Boot Process
The
UEFI boot process uses an EFI System Partition (ESP) to store system
bootstrap components. The ESP is a GPT or MBR partition with a specific
identifier, and contains a FAT file system with a specified hierarchy.
The boot process proceeds as follows:
- UEFI firmware runs at power up and searches for an OS loader in the EFI system partition. The path to the loader may be set by an EFI environment variable, with a default of /EFI/BOOT/BOOTX64.EFI.
- For FreeBSD, boot1.efi is installed as /EFI/BOOT/BOOTX64.EFI.
- boot1.efifat is an image of such a FAT filesystem for use by bsdinstall
- boot1.efi locates the first partition with a type of freebsd-ufs, and from it loads loader.efi. (This may be a different disk than the one holding the EFI system partition.)
- loader.efi loads and boots the kernel, as described in loader(8).
Repository
The code was merged to FreeBSD-HEAD in r264095. Development was originally done in the projects/uefi branch of the Subversion repository.
Virtualised Development Environment
If
you wish to test this code under a virtual environment, UEFI firmware
images are available for qemu. Assuming you have a version of qemu
greater than 0.9.1, you can download the OVMF images from here. Once I've downloaded the images and unpacked them, to test the code I run:
> qemu-system-x86_64 -serial stdio -bios OVMF.fd -hda fat:<path to boot directory>
Alternatively, to test UEFI CD support:
> qemu-system-x86_64 -serial stdio -bios OVMF.fd -cdrom <path to ISO image>
The boot directory contains my built loader.efi as well as any kernel I want to boot.
Real Hardware Gotchas
These are some issues I have run into when using real hardware (ie, not qemu).
- Filesystem
not seen. FreeBSD's FAT32 code appears to sometimes create filesystems
that the UEFI code can't properly read. If the filesystem is small
enough, use FAT16 or FAT12 instead.
- Please submit a PR with details if you are able to reproduce this.
Bootable UEFI memory stick
To
test UEFI booting on a memory stick, create a GPT partition table with a
small EFI partition and the rest of the space dedicated to a FreeBSD
UFS partition:
gpart create -s gpt da0 gpart add -t efi -s 800K da0 gpart add -t freebsd-ufs da0 dd if=/boot/boot1.efifat of=/dev/da0p1 newfs /dev/da0p2
Perform the install to the UFS partition, as usual:
mount /dev/da0p2 /mnt make DESTDIR=/mnt installkernel installworld distribution echo "/dev/da0p2 / ufs rw 1 1" >> /mnt/etc/fstab umount /mnt
TODO: Use a label for the root fs instead
Create etc/fstab.
umount /mnt
CD/DVD Boot under UEFI
The
approach for creating a bootable CD/DVD image for UEFI is to create a
FAT filesystem image containing your loader code as it would be laid out
in an EFI System Partition. This image is then attached to the CD/DVD
image as a non-emulation El Torito boot image. To make an image that is
bootable under both legacy BIOS and UEFI, the BIOS image is placed first
and the UEFI image is placed as an alternate. More information can be
found here.
A sample boot ISO can be created using the following steps.
Create a FAT filesystem image and place our loader in it in the default path that UEFI will look for:
> dd if=/dev/zero of=efiboot.img bs=4k count=100 > mdconfig -a -t vnode -f efiboot.img > newfs_msdos -F 12 -m 0xf8 /dev/md0 > mount -t msdosfs /dev/md0 /mnt > mkdir -p /mnt/efi/boot > cp loader.efi /mnt/efi/boot/bootx64.efi > umount /mnt > mdconfig -d -u 0
We
now have our UEFI boot image. The next step is to make the ISO image.
We assume that you have a directory called image containing the file
structure you want in your ISO.
> makefs -t cd9660 -o bootimage='i386;efiboot.img' -o no-emul-boot -o rockridge -o label="UEFItest" -o publisher="test" uefi-test.iso image
You should now have an ISO image in uefitest.iso that will boot using UEFI.
The
version that is built for FreeBSD 11 snapshots by the release scripts
has multiple boot images attached in order to support BIOS and UEFI. You
can do something similar by the following:
> makefs -t cd9660 -o 'bootimage=i386;efiboot.img' -o no-emul-boot -o 'bootimage=i386;/boot/cdboot' -o no-emul-boot -o rockridge -o label="UEFItest" -o publisher="test" uefi-test.iso image