Multi-boot + data + multi-partition = octopus flash drive 2.0?
A while ago, I posted about a multi-boot flash drive. That approach has served me well, but I got a new flash drive a while ago - and for some reason I could never get it to be bootable in the same way.
After a frustrating experience trying to image a yet another machine and not being able to find a free flash drive, I decided that enough was enough and that I'd do something about it. My requirements are as follows:
- It has to be bootable via legacy BIOS
- It has to be bootable via (U)EFI
- I don't want multiple configuration files for each booting method
- I want to be able to store other files on it too
- I want it to be recognised by all major operating systems
- I want to be able to fiddle with the grub configuration without manually mounting a partition
Quite the list! I can confirm that this is all technically achievable - it just takes a bit of work to do so. In this post, I'll outline how you can do it too - with reasoning at each step as to why it's necessary.
Start by finding a completely free flash drive. Note that you'll lose all the data that's currently stored on it, because we need to re-partition it.
I used the excellent GParted for this purpose, which is included in the Ubuntu live CD for those without a supported operating system.
Start by creating a brand-new gpt
partition table. We're using GPT here because I believe it's required for (U)EFI booting. I haven't run into a machine that doesn't understand it yet, but there's always a hybrid partition that you can look into if you have issues.
Once done, create a FAT32
partition that fills all but the last 128MiB or so of the disk. Let's call this one DATA
.
Next, create another partition that fills the remaining ~128MiB of the disk. Let's call this one EFI
.
Write these to disk. Once done, right click on each partition in turn and click "manage flags". Set them as such:
Partition | Filesystem | Flags |
---|---|---|
DATA |
FAT32 |
msftdata |
EFI |
FAT32 |
esp , boot |
This is important, because only partitions marked with the boot
flag can be booted from via EFI. Partitions marked boot
also have to be marked esp
apparently, which is mutually exclusive with the msftdata
flag. The other problem is that only partitions marked with msftdata
will be auto-detected by operating systems in a GPT partition table.
It is for this reason that we need to have a separate partition marked as esp
and boot
- otherwise operating systems wouldn't detect and automount our flash drive.
Once you've finished setting the flags, close GParted and mount the partitions. Windows users may have to use a Linux virtual machine and pass the flash drive in via USB passthrough.
Next, we'll need to copy a pair of binary files to the EFI
partition to allow it to boot via EFI. These can be found in this zip archive, which is part of this tutorial that I linked to in my previous post I linked to above. Extract the EFI
directory from the zip archive to the EFI
partition we created, and leave the rest.
Next, we need to install grub to the EFI
partition. We need to do this twice:
- Once for (U)EFI booting
- Once for legacy bios booting
Before you continue, make sure that your host machine is not Ubuntu 19.10. This is really important - as there's a bug in the grub 2.04 version used in Ubuntu 19.10 that basically renders the loopback
command (used for booting ISOs) useless when booting via UEFI! Try Ubuntu 18.04 - hopefully it'll get fixed soon.
This can be done like so:
# Install for UEFI boot:
sudo grub-install --target x86_64-efi --force --removable --boot-directory=/media/sbrl/EFI --efi-directory=/media/sbrl/EFI /dev/sdb
# Install for legacy BIOS boot:
sudo grub-install --target=i386-pc --force --removable --boot-directory=/media/sbrl/EFI /dev/sdb --removable
It might complain a bit, but you should be able to (mostly) ignore it.
This is actually ok - as this Unix Stack Exchange post explains - as the two installations don't actually clash with each other and just happen to load and use the same configuration file in the end.
If you have trouble, make sure that you've got the right packages installed with your package manager (apt
on Linux-based systems). Most systems will be missing 1 of the following, as it seems that the installer will only install the one that's required for your system:
- For BIOS booting,
grub-pc-bin
needs to be installed via apt. - For UEFI booting
grub-efi-amd64-bin
needs to be installed via apt.
Note that installing these packages won't mess with the booting of your host machine you're working on - it's the grub-pc
and grub-efi-amd64
packages that do that.
Next, we can configure grub. This is a 2-step process, as we don't want the main grub configuration file on the EFI
partition because of requirement #6 above.
Thankfully, we can achieve this by getting grub to dynamically load a second configuration file, in which we will store our actual configuration.
Create the file grub/grub.cfg
on the EFI partition, and paste this inside:
# Load the configfile on the main partition
configfile (hd0,gpt1)/images/grub.cfg
In grub, partitioned block devices are called hdX
, where X
is a number indexed from 0. Partitions on a block device are specified by a comma, followed by the partition type and the number of the partition (which starts from 1, oddly enough). The block device grub booted from is always device 0.
In the above, we specify that we want to dynamically load the configuration file that's located on the first partition (the DATA
partition) of the disk that it booted from. I did it this way around, because I suspect that Windows still has that age-old bug where it will only look at the first partition of a flash drive - which would be marked as esp
+ boot
and thus hidden if we had them the other way around. I haven't tested this though, so I could be wrong.
Now, we can create that other grub configuration file on the DATA
partition. I'm storing all my ISOs and the grub configuration file in question in a folder called images
(specifically my main grub configuration file is located at /images/grub.cfg
on the DATA
partition), but you can put it wherever you like - just remember to edit above the grub configuration file on the EFI
partition - otherwise grub will get confused and complain it can't find the configuration file on the DATA
partition.
For example, here's a (cut-down) portion of my grub configuration file:
# Ref https://askubuntu.com/q/1186040/139735
# As far as I can tell, this bug only affects UEFI / EFI
rmmod tpm
# Just a header message - selecting this basically has no effect
menuentry "*** Bootable Images ***" { true }
submenu "Ubuntu" {
set isofile="/images/ubuntu-18.04.3-desktop-amd64.iso"
set isoversion="18.04 Bionic Beaver"
#echo "ISO file: ${isofile}, version: ${isoversion}";
loopback loop $isofile
menuentry "[x64] Ubuntu Desktop ${isoversion}" {
linux (loop)/casper/vmlinuz boot=casper setkmap=uk eject noprompt splash iso-scan/filename=${isofile} --
initrd (loop)/casper/initrd
}
menuentry "[x64] [ejectable] Ubuntu Desktop ${isoversion}" {
linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=$isofile setkmap=uk eject noprompt splash toram iso-scan/filename=${isofile} --
initrd (loop)/casper/initrd
}
menuentry "[x64] [install] Ubuntu Desktop ${isoversion}" {
linux (loop)/capser/vmlinuz file=/cdrom/preseed/ubuntu.seed only-ubiquity quiet iso-scan/filename=${isofile} --
initrd (loop)/install/initrd
}
}
# Artix Linux
menuentry "Artix Linux" {
set isofile="/images/artix-lxqt-openrc-20181008-x86_64.iso"
probe -u $root --set=rootuuid
set imgdevpath="/dev/disk/by-uuid/$rootuuid"
loopback loop $isofile
probe -l loop --set=isolabel
linux (loop)/arch/boot/x86_64/vmlinuz archisodevice=/dev/loop0 img_dev=$imgdevpath img_loop=$isofile archisolabel=$isolabel earlymodules=loop
initrd (loop)/arch/boot/x86_64/archiso.img
}
menuentry "Fedora Workstation 31" {
set isofile="/images/Fedora-Workstation-Live-x86_64-31-1.9.iso"
echo "Setting up loopback"
loopback loop "${isofile}"
probe -l loop --set=isolabel
echo "ISO Label is ${isolabel}"
echo "Booting...."
linux (loop)/isolinux/vmlinuz iso-scan/filename="${isofile}" root=live:CDLABEL=$isolabel rd.live.image
initrd (loop)/isolinux/initrd.img
}
menuentry "Offline Password Changer [01/02/2014]" {
loopback loop /images/offline_password_changer.iso
linux (loop)/VMLINUZ setkmap=uk isoloop=$isofile
# initrd (loop)/initrd.cgz
initrd (loop)/initrd
}
menuentry "Memtest 86+ 5.01" {
linux16 /images/memtest86+.bin
}
submenu "Boot from Hard Drive" {
menuentry "Hard Drive 0" {
set root=(hd0)
chainloader +1
}
menuentry "Hard Drive 1" {
set root=(hd1)
chainloader +1
}
menuentry "Hard Drive 2" {
set root=(hd2)
chainloader +1
}
menuentry "Hard Drive 3" {
set root=(hd3)
chainloader +1
}
}
If you're really interested in building on your grub configuration file, I'll include some useful links at the bottom of this post. Specifically, having an understanding of the Linux boot process can be helpful for figuring out how to boot a specific Linux ISO if you can't find any instructions on how to do so. These steps might help if you are having issues figuring out the right parameters to boot a specific ISO:
- Use your favourite search engine and search for
Boot DISTRO_NAME_HERE iso with grub
or something similar - Try the links at the bottom of this post to see if they have the parameters you need
- Try looking for a configuration for a more recent version of the distribution
- Try using the configuration from a similar distribution (e.g. Artix is similar to Manjaro - it's the successor to Manjaro OpenRC, which is derived from Arch Linux)
- Open the ISO up and look for the grub configuration file for a clue
- Try booting it with memdisk
- Ask on the distribution's forums
Memdisk is a tool that copies a given ISO into RAM, and then chainloads it (as far as I'm aware). It can actually be used with grub (despite the fact that you might read that it's only compatible with syslinux):
menuentry "Title" {
linux16 /images/memdisk iso
initrd16 /path/to/linux.iso
}
Sometimes it can help with particularly stubborn ISOs. If you're struggling to find a copy of it out on the web, here's the version I use - though I don't remember where I got it from (if you know, post a comment below and I'll give you attribution).
That concludes this (quite lengthly!) tutorial on creating the, in my opinion, ultimate multi-boot everything flash drive. My future efforts with respect to my flash drive will be directed in the following areas:
- Building a complete portable environment for running practically all the software I need when out and about
- Finding useful ISOs to include on my flash drive
- Anything else that increases the usefulness of flash drive that I haven't thought of yet
If you've got any cool suggestions (or questions about the process) - comment below!
Sources and Further Reading
- My previous post about a multi-boot flash drive
- Bug report about loopback ISO booting with grub on flash drives installed by a Ubuntu 19.10 host
- Unix Stack Exchange on multiple grub installs
- Grub command list and reference - not quite as complete as entering the grub command line on a real machine and entering
help
it would seem - More multiboot iso configurations
- Even more multiboot iso configurations
- Customising grub colours