Restoring bsdinstall's boot loader

Hello!
I've managed to mess up my boot loader, after reboot I ran into "Missing boot loader" error message, and now I'd like some help to try and fix this.

My setup:

I'm using freebsd 12.1 (or maybe 12.2, not exactly sure - can figure out if it is important).
I used bsdinstall's guided ZFS setup. The pool is two mirrored disks, ada0 and ada2, using GPT and encrypted. gpart show ada0 gives something like (it is the same for both ada0 and ada2)
Code:
. . ada0 GPT (112G)
. . 1    efi (200M)
. .      - free - (1.0M)
. . 2    freebsd-swap (6.0G)
. . 3    freebsd-zfs (106G)
. .      - free - (452K)
(copied by hand, so sorry for the off formatting; I'm assuming the block start/lengths aren't relevent so replaced them with dots.)

The error:
I think I caused this problem a few months ago when I ran gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada{0,2}, assuming then that it was the right thing to do. But this might not be the cause...

The problem:
Today I rebooted the machine and got the very simple message "Missing boot loader".
What I've tried (all from a live-usb):
1. gpart bootcode -p /boot/boot1.efi -i 1 ada0
2. gpart bootcode -p /boot/boot1.efifat -i 1 ada0
3. gpart bootcode -p /boot/gptbootzfs -i 1 ada0
4. gpart bootcode -b /boot/pmbr -p /boot/gptbootzfs -i 1 ada0
There was no change with any of them except 2.; with boot1.efifat my motherboard at least detects ada0 as having a UEFI bootloader, but still gives the same error message.

I've been trying to figure out what bsdinstall actually does but no luck so far. I only have a basic grasp of the boot procedure, and this is really my first *nix system on UEFI.
Would very much appreciate some help with figuring this out.
 
Code:
newfs_msdos /dev/ada0p1
mount -t msdosfs /dev/ada0p1 /boot/efi
mkdir -p /boot/efi/efi/boot
cp /boot/loader.efi /boot/efi/efi/boot/BOOTx64.efi
umount /boot/efi

Notes:
  • You destroyed your efi partition by overwriting it with boot code (gptzfsboot) for "legacy" boot (might be a feature request for gpart(8): Refuse writing partition bootcode to any partition with a different type than freebsd-boot…)
  • the file name BOOTx64.efi is for amd64, if this doesn't match for you, see uefi(8)
  • boot1.efifat is an IMAGE of an efi partition containing boot1.efi as the efi bootloader, so writing it with gpart bootcode is technically correct for UEFI boot, but it's deprecated (already removed in FreeBSD 13) and lacks support for a few things like e.g. encrypted root. The correct way is, as seen above, to write loader.efi inside your efi partition.
 
Code:
newfs_msdos /dev/ada0p1
mount -t msdosfs /dev/ada0p1 /boot/efi
mkdir -p /boot/efi/efi/boot
cp /boot/loader.efi /boot/efi/efi/boot/BOOTx64.efi
umount /boot/efi

Notes:
  • You destroyed your efi partition by overwriting it with boot code (gptzfsboot) for "legacy" boot (might be a feature request for gpart(8): Refuse writing partition bootcode to any partition with a different type than freebsd-boot…)
  • the file name BOOTx64.efi is for amd64, if this doesn't match for you, see uefi(8)
  • boot1.efifat is an IMAGE of an efi partition containing boot1.efi as the efi bootloader, so writing it with gpart bootcode is technically correct for UEFI boot, but it's deprecated (already removed in FreeBSD 13) and lacks support for a few things like e.g. encrypted root. The correct way is, as seen above, to write loader.efi inside your efi partition.
Thank you for the extremely rapid response (at work we pay good money for much worse service than this), this worked perfectly.

Could you maybe expand a bit on what you mean with "legacy"? It would be great if you could point me to some reading here that is up to date - my googling this morning was a big slough trough anything from ancient to modern blogs posts, and I'm not qualified enough to determine what is up to date and what is not.
 
legacy as in BIOS as it was before introduction of UEFI (and still supported in many UEFI BIOS implementations with CSM = Compatibility Support Module):

The first sector of the disk (that's what's in /boot/pmbr) is just loaded and executed. This is just 512 bytes, and minus the legacy partition table stored there, you only have 446 bytes for actual code, so it can't do much. Therefore, all it does is chainload a second stage bootloader (gptzfsboot) from the first freebsd-boot partition it can find. This one has enough logic for UFS, ZFS and GELI and locates and starts the *real* bootloader (loader).

UEFI can do much more and execute a lot of stuff from an ESP (EFI system partition, the one you see with type efi on your disk). In the simplest case, it just loads and executes efi/boot/BOOTx64.efi from there, and with FreeBSD, you nowadays just put the *real* bootloader (loader.efi) there, so no multiple stages needed.
 
In practical terms, it means two things to me:

1. Legacy boot (often named BIOS) has code living on no-man's-blocks at the beginning of your hard drive, you need to do voodoo to write something useful to it, and it's easy to break. If you break it, you're in all kinds of trouble.

2. Modern boot (UEFI) has code on an EFI System Partition (ESP), which is nothing but a FAT-formatted partition with the type efi (hex: 0xef) with some folder and binaries on it. Repairing it can be as easy as replacing files on a FAT partition.

Note 1: There's something more to UEFI boot: the NVRAM, which stores some variables relevant to booting. But in many situations, you can get away without messing with them.

Note 2: There's some overlap with the concepts of MBR or GPT partitioning of disks, but it's not clear-cut. In the olden days, BIOS boot code was loaded from MBR-partitioned disks. Today, UEFI boot code is loaded from GPT-partitioned disks. It's possible to frankenstein a system into booting from some other combination, but you're better off if you don't have to.

(Edit: spelling)
 
1. Legacy boot (often named BIOS) has code living on no-man's-blocks at the beginning of your hard drive, you need to do voodoo to write something useful to it, and it's easy to break. If you break it, you're in all kinds of trouble.
Not really. The MBR (Master Boot Record) is defined to be the very first sector of the disk. An MBR partition table with 4 entries also lives there, but if you use GPT partitioning, it will still be there (and the MBR partition table will just mark the entire disk as unavailable, so MBR partitioning tools won't cause havoc).

So, it's not easy to break, and it is easy to fix, just overwrite the first 512bytes block (except when you actually use legacy MBR partitioning, then you must be careful not to destroy your partition table with that).

The drawback is the lack of space for code (446 bytes), and the lack of any flexibility. That's why multi-stage booting was used for a long time.
2. Modern boot (UEFI) has code on an EFI System Partition (ESP), which is nothing but a FAT-formatted partition with the type efi (hex: 0xef) with some folder and binaries on it. Repairing it can be as easy as replacing files on a FAT partition.
That of course is the partition type for legacy MBR partitioning. Would work as well with EFI boot, but I wouldn't recommend it (see above, partition table has only 4 entries and is stored inside the MBR). GPT uses GUIDs instead, the GUID for an EFI partition is C12A7328-F81F-11D2-BA4B-00A0C93EC93B.
Note 1: There's something more to UEFI boot: the NVRAM, which stores some variables relevant to booting. But in many situations, you can get away without messing with them.
In fact, there's a lot more to UEFI, it's kind of a complete little OS, including things like a shell, a scripting language, and so on…

But most of the time, all you need is to put a boot loader on the ESP and you're done.
Note 2: There's some overlap with the concepts of MBR or GPT partitioning of disks, but it's not clear-cut. In the olden days, BIOS boot code was loaded from MBR-partitioned disks. Today, UEFI boot code is loaded from GPT-partitioned disks.
Don't confuse the partitioning scheme with the boot method. It's perfectly fine to use legacy boot with GPT (that's what gptzfsboot supports) as GPT *does* have an MBR for backwards compatibility, see above. It's also fine (although IMHO not advisable) to UEFI-boot with MBR partitioning; also: see above.
 
  • Thanks
Reactions: mtu
Also note the 2TB size limit of MBR. Which makes it totally inadequate for today's storage capacities.
 
Thanks for the point I missed ;) Suggest to write "MBR partitioning", because there's an ambiguity with MBR meaning both the first sector of a disk and the partitioning scheme with the partition table stored inside this sector.
 
Code:
newfs_msdos /dev/ada0p1
mount -t msdosfs /dev/ada0p1 /boot/efi
mkdir -p /boot/efi/efi/boot
cp /boot/loader.efi /boot/efi/efi/boot/BOOTx64.efi
umount /boot/efi

Notes:
  • You destroyed your efi partition by overwriting it with boot code (gptzfsboot) for "legacy" boot (might be a feature request for gpart(8): Refuse writing partition bootcode to any partition with a different type than freebsd-boot…)
  • the file name BOOTx64.efi is for amd64, if this doesn't match for you, see uefi(8)
  • boot1.efifat is an IMAGE of an efi partition containing boot1.efi as the efi bootloader, so writing it with gpart bootcode is technically correct for UEFI boot, but it's deprecated (already removed in FreeBSD 13) and lacks support for a few things like e.g. encrypted root. The correct way is, as seen above, to write loader.efi inside your efi partition.
please update handbook.
 
Back
Top