making an EFI & BIOS x86 universally bootable USB drive

a bootable operating system that could run on any computer with an x86 CPU

persistent storage to save setting across reboots

the rest of the space on the USB drive available to store music that looks like a normal USB drive with a single partition to Windows, Mac OS X, GNU/Linux desktop environments, and Pioneer CDJs

Macs have EFI firmware, and although they have a BIOS booting compatibility layer, that compatibility layer does not have a USB driver. So, it has to be EFI bootable, or it would be worthless to a lot of people. EFI firmware reads GPT partition tables, so I thought it had to have a GPT partition table.

Considering that CDJs only read the first MBR partition (and Windows XP and older do not support GPT), it needs an MBR partition table. So, to make it work with both MBR and GPT, I read every bit of information on the web I could find about hybrid MBR partition tables.

I realized that the computers in UIC’s library would let me boot from a USB drive even though the machines in the first computer lab I tried would not. So, instead of studying neuroscience or music, I spent much of my evenings after class my senior year of college hopping back and forth between Windows and Mac computers in the library with a few USB drives, booting into GNU/Linux from them to use GNU/Linux programs to set up another USB drive. After about two weeks of guessing and checking, I finally figured out how to make it all work.

At first, I used a hybrid MBR partition table. Ironically, by figuring out how to set up the hybrid MBR, I figured out that a hybrid MBR was not necessary.

For a while, my attempts to set up a hybrid MBR so that the USB drive could boot on Macs were not working. I could not have a type EE partition first in the MBR. Type EE MBR partitions normally signal to read the GPT partition table and are typically the first partition in a hybrid MBR, with up to 3 partitions after that in the MBR table. However, putting anything other than the music partition first in the MBR would cause CDJs and Windows to not recognize the music partition. I played around with including different GPT partitions in the hybrid MBR and putting partitions in different orders in the MBR and GPT tables. After a lot of trial and error, I realized that the Mac EFI implementation was not reading the GPT partition table at all when there was not a type EE partition first in the MBR partition table.

Could I make Macs EFI boot from an MBR partition table? I tried putting the EFI System Partition with GRUB installed on it in the hybrid MBR partition table, without the type EE partition first. To my surprise, that worked. Non-Mac x86 computers could still boot it, either by BIOS booting the version of GRUB installed in the MBR or EFI booting the version of GRUB installed to the EFI System Partition.

The GPT partition layout I came up with is:

GRUB BIOS partition, partition type ef02

EFI System Partition, FAT32, partition type ef00

OS root, ext4, partition type 8300

/home, ext4, partition type 8300

music up to 2 TiB boundary, FAT32, partition type a700

music beyond 2 TiB boundary, HFS+, partition type af00

The hybrid MBR table contains:

GPT partition 5 (music), partition type 0c

GPT partition 2 (EFI System Partition), partition type ef

protective MBR partition, type ee

But wait, if Macs can EFI boot from a USB drive with the EFI System Partition in the hybrid MBR, does there even need to be a GPT partition table? It turns out that no, there does not need to be a GPT partition table and a messy hybrid MBR. The missing piece of the puzzle that I did not find anywhere on the web is that Macs’ firmware will EFI boot a USB drive with an EFI System Partition in an MBR table, as long as there is not a type EE partition first in the MBR table. Perhaps this is an unintentional featurebug that Apple never anticipated, but it makes Crossfade possible.

The simpler MBR partition table is:

(1 MB post-MBR gap)

music partition, FAT32, partition type 0c

EFI System Partition, FAT32, partition type ef

OS root partition, ext4, partition type 83

/home partition, ext4, partition type 83

So, I made the Crossfade GNU/Linux installation script install the BIOS version of GRUB to the master boot record of the USB drive and install the EFI version of GRUB to the EFI System Partition in the above layout. It still sets up a GPT partition table with a hybrid MBR if it detects that the drive is larger than the maximum size that MBR supports (2 TiB).

If you want to set up a single USB drive so it can boot on Macs and non-Mac x86 PCs, plug it into a computer running GNU/Linux. Do not mount the drive. Create an MBR partition table on the USB drive. Create a partition in it with typecode ef for the EFI System Partition. Format that partition vfat/FAT32 and mount it somewhere. To install GRUB, run:

grub-install --target=i386-pc --boot-directory=/EFI-System-Partition-mount-point /dev/USB-DRIVE #The whole drive, such as /dev/sdb, not a partition on it
grub-install --target=x86_64-efi --boot-directory=/EFI-System-Partition-mount-point --efi-directory=/EFI-System-Partition-mount-point --removable
On Fedora, and likely CentOS and RHEL, replace grub-install with grub2-install.

If you are installing a 32 bit OS and want to make it bootable on the first x86 Macs with 32 bit EFI firmware, you can install the 32 bit version of EFI GRUB to the EFI System Partition too.

Create a grub.cfg file in the grub directory (or grub2, if you use Fedora) on the EFI System Partition to boot your live OS, unmount any partitions of the drive you have mounted, and there you go!

I have been focusing on contributing to Mixxx since I published Crossfade 0.90, but I do intend to update it at some point, perhaps after Mixxx 2.1 is released.