UEFI, GPT, Windows 10, FreeBSD 10, and rEFInd

Over the last few days have I experimented with UEFI and GPT in VirtualBox 4.3.26. The goal was to multiboot various operating system, in this case Windows 10 Enterprise Technical Preview 9926 x64 and FreeBSD/amd64 stable/10.

First, I thought of persuading the UEFI firmware to always present its boot menu. It sure beats remembering to press F12 each time I want to boot a different operating system. This proved impossible for a number of reasons.

Next, I came across The rEFInd Boot Manager. After a quick glance I saw this is exactly what I want, a UEFI boot manager.

Here’s what I did and learned along the way. If you attempt to recreate this, please read thoroughly and skip all the things I did wrong.

The VM was given a 64 GiB virtual harddrive. I installed Windows 10 Enterprise Technical Preview 9926 x64, and gave that OS only 32 GiB to play with.

This resulted in 4 GPT partitions layed out as follows:

  1. A recovery partition of 300 MiB
  2. An EFI System Partition (ESP) of 100 MiB
  3. A reserved partition of 128 MiB
  4. A NTFS partition of 31 GiB

The first partition begins on a 1 MiB boundary. This is a tell-tale showing that Windows 10 treats all disks almost like SSDs, and rightfully so, as this will simplify transitioning (transferring by imaging software) from mechanical harddrives to modern SSDs.

The Disk Management utility in Windows 10 will hide the presence of the 128 MiB reserved partition. Luckily, the gpart command in FreeBSD keeps nothing secret. I did notice that the Disk Management utility fails to display the GPT labels for the partitions. The Windows’ diskpart command will also show you the truth.

The first four partitions as created by the Windows 10 installer
The first four partitions as created by the Windows 10 installer

Now, it was time to install FreeBSD 10. I first attempted an automated UEFI installation. This added 3 more GPT partitions, so the list of partitions became:

  1. A recovery partition of 300 MiB
  2. An EFI System Partition (ESP) of 100 MiB
  3. A reserved partition of 128 MiB
  4. A NTFS partition of 31 GiB
  5. An EFI System Partition (ESP) of 800 KiB
  6. An UFS partition of 30 GiB
  7. A swap partition of 1.6 GiB

Although VirtualBox were happy with more than one EFI System Partition, I was not. I copied efi/boot/bootx64.efi from the second ESP (ada0p5) to EFI/Boot/bootx64-freebsd.efi on the first ESP (ada0p2). I also renamed the existing EFI/Boot/bootx64.efi on the first ESP to EFI/Boot/bootx64-windows-10.efi, still on the first ESP.

If you decide to skip the automated UEFI installation, you may copy /boot/boot1.efi off the installation media and place that file as EFI/Boot/bootx64-freebsd.efi on the first and only ESP. Remember to rename the existing EFI/Boot/bootx64.efi to EFI/Boot/bootx64-windows-10.efi.

Next, I deleted the last 3 GPT partitions, added one freebsd-ufs partition and one freebsd-swap partition, and did a manual install of FreeBSD:

gpart delete -i 5 ada0
gpart delete -i 6 ada0
gpart delete -i 7 ada0
gpart add -a 4K -l root0 -s 30G -t freebsd-ufs  ada0
gpart add -a 4K -l swap0        -t freebsd-swap ada0
newfs /dev/gpt/root0
mount /dev/gpt/root0 /mnt
cd /mnt
tar xvvf /usr/freebsd-dist/base.txz
tar xvvf /usr/freebsd-dist/kernel.txz
tar xvvf /usr/freebsd-dist/lib32.txz
# create and/or edit all relevant files in /mnt/boot and /mnt/etc
cd /
umount /mnt
reboot

Here’s what gpart thinks about the disk layout:

The first four partitions created by the Windows 10 installer, and the last two partitions created manually for FreeBSD
The first four partitions created by the Windows 10 installer, and the last two partitions created manually for FreeBSD

As a comparison, here’s what Windows’ Disk Management thinks about the same disk layout:

Windows' Disk Management doesn't reveal everything, and is less sophisticated than FreeBSD's gpart command
Windows’ Disk Management doesn’t reveal everything, and is less sophisticated than FreeBSD’s gpart command

Now I could press the F12 key whenever the VM starts to access the UEFI management interface. I added an option for booting FreeBSD to the boot manager list, and rearranged that list to suit my taste. This lets me choose booting Windows 10 or FreeBSD 10, but I wasn’t really happy.

It gets worse as anything I configure inside the UEFI management interface isn’t permanently committed to VirtualBox’ XML file for this VM.

This is where The rEFInd Boot Manager comes to the rescue.

I hacked the UEFI firmware configuration one last time, booted the installed FreeBSD 10, mounted the rEFInd CD image as /media/cdrom, mounted the ESP as /esp, and created the directory /esp/EFI/Boot/icons.

I then copied /media/cdrom/refind/refind_x64.efi to /esp/EFI/Boot/bootx64.efi, copied /media/cdrom/refind/refind.conf-sample to /esp/EFI/Boot/refind.conf, and finally copied /media/cdrom/refind/icons/* to /esp/EFI/Boot/icons.

Now it was time to edit /esp/EFI/Boot/refind.conf. I simply set timeout to 0 (zero), set screensaver to 300, set scanfor to manual, and added a couple of menu entries:

menuentry "Windows 10 Enterprise Technical Preview 9926 x64" {
	loader \EFI\Boot\bootx64-windows-10.efi
	icon \EFI\Boot\icons\os_win.png
}

menuentry "FreeBSD/amd64 stable/10" {
	loader \EFI\Boot\bootx64-freebsd.efi
	icon \EFI\Boot\icons\os_freebsd.png
}

This is what the rEFInd Boot Manager looks like when I start this VM and Windows 10 was the last OS used:

rEFInd 0.8.7 showing the menu entry for Windows 10
rEFInd 0.8.7 showing the menu entry for Windows 10

And, here I have selected the menu entry for FreeBSD 10:

rEFInd 0.8.7 showing the menu entry for FreeBSD 10
rEFInd 0.8.7 showing the menu entry for FreeBSD 10

Yes, I let rEFInd 0.8.7 do all the hard work for me:

The About page for rEFInd 0.8.7
The About page for rEFInd 0.8.7

In sum:

  1. The UEFI firmware passes control on to /EFI/Boot/bootx64.efi, which is the rEFInd Boot Manager.
  2. Then the rEFInd Boot Manager passes control on to
    1. /EFI/Boot/bootx64-windows-10.efi, or
    2. /EFI/Boot/bootx64-freebsd.efi, depending on which OS I choose to run.
  3. Finally, each UEFI boot loader locates their own partition and loads their respective OS.

Mission accomplished!

All that I’m missing at this stage is imaging software capable of understanding GPT, FAT32, NTFS, and possibly UFS, and being able to transfer an image to be created using unicast, and being able to transfer an existing image back to the clients using multicast or unicast with the former being preferred over the latter. PXE booting the client software will simplify the logistics. And yes, IPv6 capability would be a plus. Maybe Clonezilla is what I want.