Here I would like to describe the way of creating UEFI bootable USB flash drive with several Linux distributions
All you need is Linux and USB flash drive
Let’s assume you are already in Linux and have just plugged a new USB flash drive which will be mapped as /dev/sdb device We will create necessary partitions and temporarily mount them at /target later
First, I recommend to clean the beginning of the USB flash drive in order to not mess up with different partition tables
dd if=/dev/zero of=/dev/sdb bs=2M count=2
sync ; echo 1 | tee /proc/sys/vm/drop_caches
Then, create a new disklabel (partition table) of GPT type and following partitions Note: You may want to start my first partition with offset 2MB (instead of 0%) if you find your USB stick performing the best in this layout (you can use flashbench tool to find what is the best erase block size for you)
parted -a optimal /dev/sdb
mklabel gpt
unit MB
mkpart bootefi fat32 0% 200M
set 1 boot on
mkpart bootiso ext4 200M 20G
mkpart private ext4 20G 100%
unit MB
print
print free
align-check optimal 1
align-check optimal 2
align-check optimal 3
quit
Note that the boot flag parted sets is NOT the same thing as the bootable flag in the old master boot record. It’s confusing that parted choose to use the same name, but they are different. Setting the boot flag by parted in a MBR partition marks that partition bootable, while in a GPT partition it is marked as EFI System Partition (it has EF00 code if you check with gdisk -l /dev/sdb).
The EFI System Partition must be explicitly mounted at /boot/efi to properly load via the GNU GRUB2 bootloader.
Now create filesystems
mkfs.vfat -F32 -n EFIBOOT /dev/sdb1
mkfs.ext4 -L bootiso /dev/sdb2
Mount them in the following order
mkdir -p /target/boot
mount /dev/sdb2 /target/boot
mkdir /target/boot/efi
mount /dev/sdb1 /target/boot/efi
The most important moment – installing the grub2
grub-install --removable --no-uefi-secure-boot --target=x86_64-efi --efi-directory=/target/boot/efi --boot-directory=/target/boot --bootloader-id=grub --recheck /dev/sdb
This is how the data should look like after above steps have been applied
# ls -latrh /target/boot/grub/
total 48K
drwxr-xr-x 8 root root 4.0K Jun 9 17:50 ..
-rw------- 1 root root 1.3K Jun 9 18:40 grub.cfg
drwxr-xr-x 2 root root 4.0K Jun 9 18:45 fonts
-rw-r--r-- 1 root root 1.0K Jun 9 18:45 grubenv
drwx------ 5 root root 4.0K Jun 9 18:45 .
drwxr-xr-x 2 root root 12K Jun 9 19:18 x86_64-efi
drwxr-xr-x 2 root root 4.0K Jun 9 19:18 locale
# find /target/boot/efi/ -ls
1 4 drwxr-xr-x 3 root root 4096 Jan 1 1970 /target/boot/efi/
4 4 drwxr-xr-x 3 root root 4096 Jun 9 18:45 /target/boot/efi/EFI
6 4 drwxr-xr-x 2 root root 4096 Jun 9 18:45 /target/boot/efi/EFI/BOOT
9 120 -rwxr-xr-x 1 root root 119296 Jun 9 19:18 /target/boot/efi/EFI/BOOT/BOOTX64.EFI
# parted /dev/sdb print
Model: SanDisk Extreme (scsi)
Disk /dev/sdb: 62.7GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Number Start End Size File system Name Flags
1 1049kB 200MB 199MB fat32 bootefi boot
2 200MB 20.0GB 19.8GB ext4 bootiso
3 20.0GB 62.7GB 42.7GB ntfs private
# parted /dev/sdb unit s print free
Model: SanDisk Extreme (scsi)
Disk /dev/sdb: 122544516s
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Number Start End Size File system Name Flags
34s 2047s 2014s Free Space
1 2048s 391167s 389120s fat32 bootefi boot
2 391168s 39061503s 38670336s ext4 bootiso
3 39061504s 122544127s 83482624s ntfs private
122544128s 122544482s 355s Free Space
You can create any filesystem you wish on /dev/sdb3 partition, e.g.
FAT32
mkfs.vfat -F32 -n shared -v /dev/sdb3
NTFS
mkfs.ntfs -Q -L shared -I -v /dev/sdb3
EXT4
mkfs.ext4 -L shared /dev/sdb3
NOTE: if your shared partition (sdb3) will be used for NTFS, then don’t forget to set “msftdata” flag on it, otherwise Windows won’t mount it
(parted) set 3 msftdata on
Do not forget to create /target/boot/grub/grub.cfg file
You can always auto-generate it to look what it has detected and which modules does it use by default
grub-mkconfig -o /target/boot/grub/grub.cfg
But that’s not what we are here for, our goal is to upload several Linux distributions to our USB flash drive so that we can use any of them :-)
My configuration is the following
# cat /target/boot/grub/grub.cfg
set timeout=15
set default=0
# (U)EFI Graphic Protocol
insmod efi_gop
insmod efi_uga
insmod font
if loadfont ${prefix}/fonts/unicode.pf2
then
insmod gfxterm
set gfxmode=auto
set gfxpayload=keep
terminal_output gfxterm
fi
menuentry "Linux Mint 17 MATE DVD" {
loopback loop /isos/linuxmint-17-mate-dvd-64bit.iso
linux (loop)/casper/vmlinuz file=/cdrom/preseed/linuxmint.seed boot=casper iso-scan/filename=/isos/linuxmint-17-mate-dvd-64bit.iso quiet splash --
initrd (loop)/casper/initrd.lz
}
menuentry "SystemRescueCd 4.2.0" {
loopback loop /isos/systemrescuecd-x86-4.2.0.iso
linux (loop)/isolinux/rescue32 setkmap=us isoloop=/isos/systemrescuecd-x86-4.2.0.iso
initrd (loop)/isolinux/initram.igz
}
menuentry "Tails 1.0" {
loopback loop /isos/tails-i386-1.0.iso
linux (loop)/live/vmlinuz fromiso=/dev/disk/by-uuid/5e5ca198-7e43-a0dc-91eb-98ebec1274b5/isos/tails-i386-1.0.iso boot=live config live-media=removable nopersistent noprompt timezone=Etc/UTC block.events_dfl_poll_msecs=1000 splash noautologin module=Tails truecrypt quiet
initrd (loop)/live/initrd.img
}
menuentry "Kali Linux 1.0.6" {
loopback loop /isos/kali-linux-1.0.6-i386.iso
linux (loop)/live/vmlinuz fromiso=/dev/disk/by-uuid/5e5ca198-7e43-a0dc-91eb-98ebec1274b5/isos/kali-linux-1.0.6-i386.iso boot=live noconfig=sudo username=root hostname=kali
initrd (loop)/live/initrd.img
}
menuentry "Debian Live (amd64)" {
loopback loop /isos/debian-live-7.5.0-amd64-gnome-desktop.iso
linux (loop)/live/vmlinuz fromiso=/dev/disk/by-uuid/5e5ca198-7e43-a0dc-91eb-98ebec1274b5/isos/debian-live-7.5.0-amd64-gnome-desktop.iso boot=live config quiet splash
initrd (loop)/live/initrd.img
}
menuentry "Debian GNU/Linux installer boot menu" {
insmod part_gpt
insmod ext2
loopback loop /isos/debian-7.5.0-amd64-netinst.iso
linux (loop)/install.amd/vmlinuz fromiso=/dev/disk/by-uuid/5e5ca198-7e43-a0dc-91eb-98ebec1274b5/isos/debian-7.5.0-amd64-netinst.iso boot=live vga=788 -- quiet
## linux (loop)/install.amd/vmlinuz fromiso=/dev/disk/by-uuid/5e5ca198-7e43-a0dc-91eb-98ebec1274b5/isos/debian-7.5.0-amd64-netinst.iso vga=788 -- quiet
## linux (loop)/install.amd/vmlinuz fromiso=/dev/disk/by-uuid/5e5ca198-7e43-a0dc-91eb-98ebec1274b5/isos/debian-7.5.0-amd64-netinst.iso boot=live config live-media=removable nopersistent vga=788 -- quiet
initrd (loop)/install.amd/initrd.gz
}
#menuentry "Debian GNU/Linux installer boot menu (Graphical)" {
# loopback loop /isos/debian-7.5.0-amd64-netinst.iso
# linux (loop)/install.amd/vmlinuz fromiso=/dev/disk/by-uuid/5e5ca198-7e43-a0dc-91eb-98ebec1274b5/isos/debian-7.5.0-amd64-netinst.iso video=vesa:ywrap,mtrr vga=788 -- quiet
# initrd (loop)/install.amd/gtk/initrd.gz
#}
To construct linux & initrd lines I have used the contents of isolinux/menu.cfg file (in some cases it is different, but easy to find using grep) that can be accessed if you simply mount/open the .iso file
The path to /dev/disk/by-uuid/5e5ca198-7e43-a0dc-91eb-98ebec1274b5 is used in regards to the UUID of the /dev/sdb2 partition, in your case it will be different so you should replace it with yours
# ls -la /dev/disk/by-uuid/5e5ca198-7e43-a0dc-91eb-98ebec1274b5
lrwxrwxrwx 1 root root 10 Jun 9 10:36 /dev/disk/by-uuid/5e5ca198-7e43-a0dc-91eb-98ebec1274b5 -> ../../sdb2
# blkid |grep sdb2
/dev/sdb2: LABEL="boot" UUID="5e5ca198-7e43-a0dc-91eb-98ebec1274b5" TYPE="ext4"
Now you just have to create the directory (where you will put your Linux distros) on your /dev/sdb2 device that is mounted as /target/boot and copy your Linux distros there as follows
mkdir /target/boot/isos
cp ~/Downloads/linuxmint-17-mate-dvd-64bit.iso /target/boot/isos/
cp ~/Downloads/systemrescuecd-x86-4.2.0.iso /target/boot/isos/
cp ~/Downloads/tails-i386-1.0.iso /target/boot/isos/
cp ~/Downloads/kali-linux-1.0.6-i386.iso /target/boot/isos/
When you are done copying, safely unplug the USB flash drive
umount /dev/sdb1
umount /dev/sdb2
umount /dev/sdb3
sync ; echo 1 | tee /proc/sys/vm/drop_caches
udisks --detach /dev/sdb
Now you can boot any Linux distribution on your choice from your USB flash drive!