Multi-boot from ISO on USB with Grub 2
Last time we've talked about how to Manually UEFI Boot Linux and Windows 10 USB from Grub, today we'd like to talk about creating a multi-boot usb stick with grub 2.
Sometimes we need to create multiple linux distribution installation media or bootable usb stick. However, it is always so annoying to re-flush the usb stick again and again.
However, grub actually enables us to boot most of the linux distributions through loop format or iso image files. The iso image format is known for its original design for CD disks or DVD disks so that the distributions are bootable through your CD-ROM drivers. If the distribution is bootable through the CD-ROM drivers and the CD or DVD media is not writable, which it effectively means that we can actually boot from the non-writable iso image file as well.
Requirements
Since we need to boot multiple ISO image files directly from USB, we do really need a large USB stick. Secondly, we need to use a UEFI compatible system to avoid issues and maximize flexibility. Finally, we need to have a working linux distribution to work on which currently I'm using Ubuntu 18.04.2 demoing this tutorial.
- Large USB stick
- UEFI compatible system
- A Linux distribution to work on
We need to create the USB stick's partition table as gpt format and further make two partitions. We may refer to the following partition layout as an example.
$ sudo parted /dev/sdb print free
Model: SanDisk Ultra USB 3.0 (scsi)
Disk /dev/sdb: 61.5GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
17.4kB 1049kB 1031kB Free Space
1 1049kB 256MB 255MB fat32 ESP boot, esp
2 256MB 61.5GB 61.3GB ext4 OS-Images
We have created an ext4 filesystem partition named OS-Images
for ISO image files because fat32 has a maximum file size limit of 4GB.
We now should create separate directories to mount these two partitions and copy over the ISO image files into OS-Images partition which should look very similar to the following layout.
.
├── ESP
└── OS-Images
├── ArchLinux
│ └── archlinux-2019.06.01-x86_64.iso
├── CentOS
│ ├── CentOS-7-x86_64-DVD-7.5.1804.iso
│ └── CentOS-7-x86_64-DVD-7.6.1810.iso
├── Fedora
│ └── Fedora-Workstation-Live-x86_64-30-1.2.iso
├── Redhat
│ ├── RHEL-7.7-20190702.0-Workstation-x86_64-dvd1.iso
│ └── RHEL-8.0.0-20190404.2-x86_64-dvd1-GA.iso
├── SLE
│ ├── SLE-15-Installer-DVD-x86_64-GM-DVD1.iso
│ └── SLE-15-SP1-Installer-DVD-x86_64-GMC-DVD1.iso
└── Ubuntu
├── ubuntu-16.04.6-desktop-amd64.iso
├── ubuntu-18.04.2-desktop-amd64.iso
└── ubuntu-19.04-desktop-amd64.iso
Create grub bootloader
We need to create a bootx64.efi
to make sure the USB is bootable on a UEFI platform. Use the following command to generate a working grub bootloader.
$ grub-mkimage -o bootx64.efi -p /efi/boot -O x86_64-efi \
all_videobootbtrfs cat chain configfile echo efi_gop \
efi_uga efifwsetup exfat ext2 fat gfxterm \
gfxterm_background gfxterm_menu hfsplus iso9660 \
linux linuxefi loadenv loopback ls lsefi normal ntfs \
part_gpt part_msdos search search_fs_file \
search_fs_uuid search_label test udf usb
We need to further move the bootx64.efi
to ESP/EFI/BOOT
directory, backup it in the ESP/backup
directory, and create a grub configuration file named grub.cfg
.
Afterwards, the ESP partition should look like as following.
ESP
├── backup
│ └── bootx64.efi
└── EFI
└── BOOT
├── bootx64.efi
└── grub.cfg
Grub Boot Parameters in Detail
In grub.cfg
, we can specify multiple menu entries to boot different ISO media files. Taking ubuntu 18.04.2 as an example:
insmod part_gpt
insmod ext2
insmod gzio
insmod efi_uga
insmod efi_gop
menuentry "Boot Ubuntu 18.04.2 from ISO" {
set root=hd0,gpt2
set isofile="/Ubuntu/ubuntu-18.04.2-desktop-amd64.iso"
loopback loop $isofile
linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=$isofile noprompt noeject debug text
initrd (loop)/casper/initrd
}
Ubuntu
menuentry "Boot Ubuntu 18.04.2 from ISO" {
set root=hd0,gpt2
set isofile="/Ubuntu/ubuntu-18.04.2-desktop-amd64.iso"
loopback loop $isofile
linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=$isofile noprompt noeject debug text
initrd (loop)/casper/initrd
}
Redhat
menuentry "Boot Redhat 7.7 (20190702) from ISO" {
set root=hd0,gpt2
set isofile="/Redhat/RHEL-7.7-20190702.0-Workstation-x86_64-dvd1.iso"
loopback loop $isofile
# BUG: Does not boot with LABEL
# linuxefi (loop)/images/pxeboot/vmlinuz inst.stage2=cdrom:LABEL=OS-Images:$isofile rd.live.check debug
linuxefi (loop)/images/pxeboot/vmlinuz inst.stage2=cdrom:sda2:$isofile rd.live.check debug
initrdefi (loop)/images/pxeboot/initrd.img
}
CentOS
menuentry "Boot CentOS 7.6.1810 from ISO" {
set root=hd0,gpt2
set isofile="/CentOS/CentOS-7-x86_64-DVD-7.6.1810.iso"
loopback loop $isofile
# BUG: Does not boot with LABEL
# linuxefi (loop)/images/pxeboot/vmlinuz inst.stage2=cdrom:LABEL=OS-Images:$isofile rd.live.check debug
linuxefi (loop)/images/pxeboot/vmlinuz inst.stage2=cdrom:sda2:$isofile rd.live.check debug
initrdefi (loop)/images/pxeboot/initrd.img
}
SUSE Linux Enterprise
menuentry "Boot SUSE 15-SP1-GMC from ISO" {
set root=hd0,gpt2
set isofile="/SLE/SLE-15-SP1-Installer-DVD-x86_64-GMC-DVD1.iso"
loopback loop $isofile
linuxefi (loop)/boot/x86_64/loader/linux splash=silent
initrdefi (loop)/boot/x86_64/loader/initrd
}
Fedora
menuentry "Boot Fedora Workstation 30 from ISO" {
set root=hd0,gpt2
set isofile="/Fedora/Fedora-Workstation-Live-x86_64-30-1.2.iso"
loopback loop $isofile
linuxefi (loop)/images/pxeboot/vmlinuz root=live:CDLABEL=Fedora-WS-Live-30-1-2 rd.live.image iso-scan/filename=$isofile $iso_params debug text $_extra
initrdefi (loop)/images/pxeboot/initrd.img
}
Archlinux
menuentry "Boot Archlinux 2019-06-01 from ISO" {
set root=hd0,gpt2
set isofile="/ArchLinux/archlinux-2019.06.01-x86_64.iso"
loopback loop $isofile
set imgdevpath='/dev/disk/by-partlabel/OS-Image'
linux (loop)/arch/boot/x86_64/vmlinuz img_dev=$imgdevpath img_loop=$isofile earlymodules=loop debug text $_extra
initrd (loop)/arch/boot/amd_ucode.img (loop)/arch/boot/intel_ucode.img (loop)/arch/boot/x86_64/archiso.img
}
Fixing a grub boot
After installing an OS, it is possible that the bootloader is corrupted after some hacking.
We can boot to a live CD using our USB stick and then follow the commands listed below to fix the grub bootloader.
sudo mount /dev/sdXY /mnt
sudo mount /dev/sdXZ /mnt/boot/efi
sudo mount --bind /dev /mnt/dev
sudo mount --bind /dev/pts /mnt/dev/pts
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys /mnt/sys
sudo chroot /mnt
grub-install --efi-directory /boot/efi /dev/sdX
grub-install --efi-directory /boot/efi --recheck /dev/sdX
# In case `update-grub` command is not found,
# use the following command to generate the grub configuration file.
# `grub-mkconfig -o /boot/grub/grub.cfg`
update-grub
exit
sudo umount /mnt/sys
sudo umount /mnt/proc
sudo umount /mnt/dev/pts
sudo umount /mnt/dev
sudo umount /mnt
Comments
Comments powered by Disqus