The normal FreeBSD ZFS install can build a mirrored pool which is bootable on both BIOS and UEFI machines. If you build this pool using USB disks, you have a portable system that is nearly independent of hardware. The primary machine can fail, and you can easily move the disks to another machine and go. One of the disks can fail, and you can easily replace it without shutting down your machine (assuming you have enough USB ports).

Install

Plug both drives in and use the normal FreeBSD interactive install.

If you are installing on a Mac, hold the Alt key when the system boots, and you can choose to boot from the install media.

When you get to the partitioning step, select “Auto (ZFS)”.

On the “ZFS Configuration” screen, choose:

  • Pool Type/Disks: mirror: 2 disks
  • Partition Scheme: GPT (BIOS+UEFI)
  • Mirror Swap: YES
  • Encrypt Swap: YES

When the installation finishes, reboot into the new system. (Hold the Alt key on a Mac, and select one of the “EFI Boot” disks).

At this point you should actually test both disks are bootable with BIOS and UEFI. The visible difference between BIOS and UEFI booting is that Beastie is a graphic when UEFI is used to boot.

You can also find out how a running system was booted:

# sysctl machdep.bootmethod
machdep.bootmethod: BIOS

Note [9 Apr 23] I noticed that sometimes the installer doesn’t format the EFI partition on the second disk, so you can’t boot EFI from the second disk. To fix this, format the partition and install the loaders as described in EFI loader.

/etc/fstab

The default /etc/fstab includes and entry that mounts the EFI partition on the first drive on /boot/efi.

This entry will prevent the mirrored pool from booting if the disk device names change. Device names can change if you move the disks to another machine, or if you happen to have another USB disk plugged in when you boot.

The geom subsystem and ZFS can both find their mirrors regardless of device names, but this fstab entry names a specific device that may not be correct in all circumstances.

Just unmount the EFI filesystem, and then comment or remove the EFI line in /etc/fstab.

# umount /boot/efi	
# sed -i -e /efi/s,^,#, /etc/fstab

If you need to update the loaders in the EFI partitions, mount them when needed:

# mount -t msdosfs /dev/da0p1 /mnt

or

# mount -t msdosfs /dev/da1p1 /mnt

efibootmgr

You can configure a Mac to boot from your pool devices by configuring the EFI boot manager. Boot manager settings are a function of the motherboard, so you will need to do this on any Mac you want to boot from automatically.

The procedure is you mount each EFI partition, and tell the boot manager about the loader on that partition.

Assuming you don’t want to keep any existing boot devices, you can clear the list like this:

# efibootmgr
BootCurrent: 0000
Timeout    : 5 seconds
BootOrder  : 0001, 0000
 Boot0001* USB1
+Boot0000* USB0

# efibootmgr --delete -b 1
Removing boot variable 'Boot0001'
Removing 0x1 from BootOrder
BootCurrent: 0000
Timeout    : 5 seconds
BootOrder  : 0000
+Boot0000* USB0

# efibootmgr --delete -b 0
Removing boot variable 'Boot0000'
Removing 0x0 from BootOrder
BootCurrent: 0000
Timeout    : 5 seconds

# efibootmgr
BootCurrent: 0000
Timeout    : 5 seconds

Now you can add your two drives:

# mount -t msdosfs /dev/da0p1 /mnt
# efibootmgr -a -c -l /mnt/efi/freebsd/loader.efi -L "USB0"
BootCurrent: 0000
Timeout    : 5 seconds
BootOrder  : 0000
+Boot0000* USB0
# umount /mnt

# mount -t msdosfs /dev/da1p1 /mnt
# efibootmgr -a -c -l /mnt/efi/freebsd/loader.efi -L "USB1"
BootCurrent: 0000
Timeout    : 5 seconds
BootOrder  : 0001, 0000
 Boot0001* USB1
+Boot0000* USB0
# umount /mnt

Note: you must mount the EFI partitions using their “real” device names. efibootmgr won’t understand the path to the loader if you use GPT device names. This DOESN’T work:

# mount -t msdosfs /dev/gpt/efiboot0 /mnt
# efibootmgr -a -c -l /mnt/efi/freebsd/loader.efi -L "USB0"
efibootmgr: Cannot translate unix loader path '\mnt\efi\freebsd\loader.efi' to UEFI: No such file or directory

Reboot Mac after power fail

If this system is on a Mac, and you want the system to reboot when power is restored after a power failure, there are two ways to do it:

MacOS Settings

If you have access to a bootable MacOS disk:

  • boot into MacOS
  • go to Settings -> Energy Saver
  • tick “Start up automatically after a power failure”
  • shutdown MacOS and reboot into your mirrored pool

pciconf

You can use pficonf to set the PCI configuration variable that controls boot after power failure.

This method is riskier and might be different on different Mac devices.

On my machine, this behavour is controlled by bit 0 of register 0xa4 on the PCI-ISA bridge. Yours might be completely different.

# pciconf -lv pci0:0:31:0
isab0@pci0:0:31:0:      class=0x060100 rev=0x04 hdr=0x00 vendor=0x8086 device=0x1e57 subvendor=0x8086 subdevice=0x7270
    vendor     = 'Intel Corporation'
    device     = 'HM77 Express Chipset LPC Controller'
    class      = bridge
    subclass   = PCI-ISA

Get the current value of this register:

# pciconf -r -b pci0:0:31:0 0xa4
09

Clear bit 0, and poke the result:

# pciconf -w -b pci0:0:31:0 0xa4 08

See this link for more details.