Booting Linux under UEFI and Legacy BIOS

The overall problem.

Work have given me a MacBook Pro to use, although they’re not too enamoured at the thought of me putting Linux on the internal SSD. I must haz Linux.

The overall answer.

I had a 128GB M2 SSD in my Acer Chromebook 15 at home, so I purchased a USB M2 SSD enclosure/adapter, with a view to using Linux via it and my SSD on the MacBook Pro, and it being fast.

The problem MKII.

Once I had Linux on said SSD in said enclosure/adapter, and booting on said MacBook Pro, I was unable to boot it on my Acer Chromebook 15 running SeaBIOS. I guess a secondary reason for me wanting the SSD in the enclosure, would be that I could take my OS, boot it “anywhere”, and it would be fast (i.e close to the theoretical maximum of USB 3.0 with very low latency, at least on a device with USB 3.0). The basic problem is that the Mac uses UEFI and the Chromebook uses “legacy” BIOS. Both have differing mechanisms for boot.

The answer MKII.

So, the answer turned out to be putting a “bios_boot” partition on the SSD in the first one meg (obviously not over the mbr and partition table), installing Grub again, and fiddling with the grub config a little. In this way the external SSD boots on both UEFI and Legacy BIOS systems.

How did you do that?

I referenced an article I wrote 5 years ago and did a little sideways thinking:

The commands would be as follows, assuming the internal SSD is /dev/sda and the external SSD/enclosure is /dev/sdb:

  1. Backup the existing first 1 MB of the drive – sudo dd count=2048 if=/dev/sdb of=mbr.gpt.bak
  2. sudo gdisk /dev/sdb
  3. Type n
  4. Type 3 (assuming that partition number is available)
  5. Type 34 (this is the starting sector of the partition we’re creating)
  6. Type 2047 (this takes the partition up to the one meg boundary)
  7. Type ef02 (this makes the partition the “bios_boot” type)
  8. Type w to save and quit.

I then reinstalled Grub to the SSD:

sudo grub2-install --target i386-pc /dev/sdb

For some reason it wouldn’t work without the target specified. Then I had to get around the Grub config.

The primary difference between Linux booted on UEFI, and Linux booted on Legacy BIOS, is the command to load the kernel/initrd. In UEFI this is “linuxefi” and “initrdefi”, in Legacy BIOS it’s “linux” and “initrd”, or “linux16” and “initrd16”. So, the easiest thing to do was create a custom Grub config to deal with booting none UEFI. In /etc/grub.d/40_custom I put:

menuentry 'Fedora (4.2.7-300.fc23.x86_64) 23 (SeaBIOS Mode)' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-4.2.7-300.fc23.x86_64-advanced-a2c26bf5-3f1b-436f-8291-8ee94f8dc7b4' {
 set gfxpayload=keep
 insmod gzio
 insmod part_gpt
 insmod ext2
 set root='hd1,gpt2'
 if [ x$feature_platform_search_hint = xy ]; then
 search --no-floppy --fs-uuid --set=root --hint-bios=hd1,gpt2 --hint-efi=hd1,gpt2 --hint-baremetal=ahci1,gpt2 a2c26bf5-3f1b-436f-8291-8ee94f8dc7b4
 search --no-floppy --fs-uuid --set=root a2c26bf5-3f1b-436f-8291-8ee94f8dc7b4
 linux /boot/vmlinuz-4.2.7-300.fc23.x86_64 root=UUID=a2c26bf5-3f1b-436f-8291-8ee94f8dc7b4 ro rhgb quiet
 initrd /boot/initramfs-4.2.7-300.fc23.x86_64.img

Then run su -c “grub2-mkconfig > /boot/grub2/grub.cfg” and you will be able to boot Linux both under UEFI *and* Legacy BIOS.

Bear in mind, that if you upgrade the kernel while booted under Legacy BIOS, the prober/autoconfig will automatically change the primary menu options from linuxefi to linux16, so watch out for that.

Also, the usual disclaimers apply – you broke it you bought it, YMMV, etc, etc.

Leave a comment