GitHub - losfair/bsdloader: Minimal (~123KB), reproducible x86_64 FreeBSD UEFI loader

2 min read Original article ↗

bsdloader

Minimal (~123KB), reproducible x86_64 FreeBSD UEFI loader. Supports preloaded memory disk and UEFI TPM2.0 measured boot.

Usage

# Directory layout: /base /kernel /bsdloader
# 'base' contains extracted FreeBSD base.txz - ideally a minimal one like mfsBSD
# 'kernel' contains extracted FreeBSD kernel.txz

# Build bsdloader
mkdir -p esp/efi/boot
cd bsdloader
cargo build --release
cp ./target/x86_64-unknown-uefi/release/bsdloader.efi ../esp/efi/boot/bootx64.efi
cd ..

# Build UFS2 rootfs memory disk image
makefs -t ffs base.ufs base

# Write the rootfs memory disk image into the ".memdisk" section of `kernel.elf`.
#
# bsdloader reads this section and preloads the memory disk as `/dev/md0`. The FreeBSD
# kernel will automatically boot from it.
llvm-objcopy --add-section .memdisk=base.ufs kernel/boot/kernel/kernel esp/kernel.elf

# Optionally, add some kernel environment variables
echo -e 'hw.uart.console=io:0x3f8,br:115200\nconsole=efi comconsole' > ./esp/kenv

# Copy the contents of `esp/` into a FAT32-formatted partition. It's now bootable!

Measured boot

If TPM2 is present, bsdloader measures kernel.elf and kenv into PCR9 as EV_IPL events, and mounts the TPM2 event log as the second memory disk accessible at /dev/md1. Measurements and the event log can be accessed from userspace:

kldload tpm

# Read PCRs
tpm2_pcrread

# Show the event log
tpm2_eventlog /dev/md1

Note: If kenv does not exist or is empty, the measurement is taken on the string with a single newline: \n.

Signing kernel.elf and kenv

bsdloader supports verifying Ed25519 signatures on kernel.elf and kenv and measuring the public key into PCR14. The public key and signature should be hex-encoded and written to a file named siginfo. The first line of the file is the 32-byte public key, and the second line is the 64-byte signature. An example:

28ebc78dc763971bf56dde160f8e30f7e9e98ad358d9add73245f05d1b3337fc
6133c1fea385f900f5cf0835838665f616bb725090a93aa6276288319b8c2c43909b4acee0f8457351212d35c614d95d238a69ac5e5409ffa9e78067af0dc349

PCR14 is always extended. If the siginfo file does not exist, a fake "public key" of 32 zeros is used.

To construct the payload for signing, use the following script as a reference:

sha256sum kernel.elf > payload
sha256sum kenv >> payload
cat payload

The payload should look like:

1f825899d834c8132c05a95d70e1544367a35208c275f4af608fd633d9cf0b31  kernel.elf
f87dd3bf8425f28aa1b17888c67d64314cd0609dd39ecdef83fcbcc3c53abf76  kenv

Note that there is a \n character at the end of each line.