Updating boot code failure

Hello gurus,

I'm in a bit of a bind and was hoping to be steered in the right direction. I'm running OPNsense 25.10_2-amd64 w/ FreeBSD 14.3-RELEASE-p4 on a zfs single disk decision DEC4040 appliance. As part of a recent zpool status check, I encountered a message to upgrade zpool to enable new features. Rather than doing my homework as to whether I need said features or not, I simply issued `zpool upgrade zroot` - a no-no. After reading few very helpful posts (e.g. this), I set about performing the boot loader updates prior to system reboot. But, I encountered an error (please see /b/ below) which has me stumped, and unsure as to the next steps. Help please.

Code:
zpool upgrade zroot
This system supports ZFS pool feature flags.

Enabled the following features on 'zroot':
  edonr
  zilsaxattr
  head_errlog
  blake3
  block_cloning
  vdev_zaps_v2

Pool 'zroot' has the bootfs property set, you might need to update
the boot code. See gptzfsboot(8) and loader.efi(8) for details.

Code:
Pool 'zroot' has the bootfs property set, you might need to update
the boot code. See gptzfsboot(8) and loader.efi(8) for details.

gpart output:
Code:
gpart show
=>         3  2000409253  nda0  GPT  (954G)
           3      532480     1  efi  (260M)
      532483         311     2  freebsd-boot  (156K)
      532794  1981808640     3  freebsd-zfs  (945G)
  1982341434    18067822     4  freebsd-swap  (8.6G)
Code:
sysctl machdep.bootmethod
machdep.bootmethod: UEFI
Code:
root@MorikCage:/usr/ports %# df -h
Filesystem                   Size    Used   Avail Capacity  Mounted on
zroot/ROOT/24.4.2            891G     12G    879G     1%    /
devfs                        1.0K      0B    1.0K     0%    /dev
/dev/gpt/efifs               256M    1.3M    255M     0%    /boot/efi
zroot                        879G     96K    879G     0%    /zroot
zroot/tmp                    879G    9.9M    879G     0%    /tmp
zroot/usr/home               879G     96K    879G     0%    /usr/home
zroot/var/audit              879G     96K    879G     0%    /var/audit
zroot/var/tmp                879G    116K    879G     0%    /var/tmp
zroot/var/crash              879G     96K    879G     0%    /var/crash
zroot/usr/src                879G     96K    879G     0%    /usr/src
zroot/var/mail               879G    144K    879G     0%    /var/mail
zroot/var/log                882G    2.8G    879G     0%    /var/log
zroot/usr/ports              880G    1.7G    879G     0%    /usr/ports
devfs                        1.0K      0B    1.0K     0%    /var/dhcpd/dev
devfs                        1.0K      0B    1.0K     0%    /var/unbound/dev
/usr/local/lib/python3.11    891G     12G    879G     1%    /var/unbound/usr/local/lib/python3.11
/lib                         891G     12G    879G     1%    /var/unbound/lib
Which would mean I'd have to update both a) the EFI loader and b) the BIOS bootcode øn the single disk ZFS install due to freebsd-zfs type.

/a/ seems to be okay w/ the following commands:
Code:
cp /boot/loader.efi /boot/efi/efi/boot/bootx64.efi
mkdir /boot/efi/efi/freebsd
cp /boot/loader.efi /boot/efi/efi/freebsd/loader.efi

/b/ gives this error:
Code:
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 2 nda0
gpart: /dev/nda0p2: not enough space

Adding a new disk isn't feasible (as the appliance doesn't allow for it). Perhaps a potential solution could be to erase existing nda0p2 and recreate it - but I'm not very skilled at such low-level commands, and also am unsure whether there's space to do so anymore.

If I understand the output of gpart show correctly, then freebsd-boot (on nda0p2) is only 311 bytes whereas /boot/pmbr is 512. So, deleting existing freebsd-boot partition to recreate it will not help as there isn't no larger (than 311 bytes) space available anymore? I read somewhere that manipulation of swap partition could create that extra ~250 bytes needed to delete and recreate freebsd-boot partition.
Code:
swapinfo
Device          1K-blocks     Used    Avail Capacity
/dev/gpt/swapfs   9033908        0  9033908     0%

Am I hosed?
 
it looks like your machine is booting via UEFI, whose loader you already updated, and so you don't need to update the partition bootcode on nda0p2, which is only used for BIOS boots. however, you're misreading the size markers in gpart. they're talking about 512-byte sectors — you'll note the (156K) at the end of that line. also, the swap partition is at the end of the device, so no amount of swap-device manipulation would help this problem. you'd have to move the zfs partition around, which would kinda suck.
 
If I understand the output of gpart show correctly, then freebsd-boot (on nda0p2) is only 311 bytes whereas /boot/pmbr is 512.
No, the freebsd-boot partition is 311 blocks large. The size in gpart(8) output is the number of blocks, with one block being 512 bytes. The pmbr/mbr is 512 bytes (actually the code itself is 446 bytes, that 512 byte first block also contains the partition table; Wikipedia; MBR), it has just enough code to find the freebsd-boot partition, load it in memory and execute it. PMBR is basically a fake MBR partition table, it makes GPT somewhat backwards compatible on old systems.

 
PMBR has 2 purposes.
One is to mimic as if there is legacy MBR partition table, 1 in 4 physical entry indicating the whole amount of the drive is occupied.
This is to prevent any legacy partitioning / formatting tools which desn't know aboug GPT to missingly manipulate partition table and attempt to format it.

Another is holding actual disk boot code just as legacy MBR does.
This is to allow legacy BIOS to boot GPT scheme drive. But not all BIOS'es (and legacy boot on UEFI with CSM) work sanely with this.

For example, at least some ThinkPads need special care (lenovofix attribute in gpart(8) is prepared for this purpose).
Code:
     lenovofix   Setting this attribute overwrites the Protective MBR with a
                 new one where the 0xee partition is the second, rather than
                 the first record.  This resolves a BIOS compatibility issue
                 with some Lenovo models including the X220, T420, and T520,
                 allowing them to boot from GPT partitioned disks without
                 using EFI.
 
I can not express enough my gratitude to the commenters. My takeaways:
1. Because boot method is UEFI, and that the cp commands have been executed, I don't need to update legacy partition boot code.
2. In reading through the FreeBSD booting process, I have mistakenly concluded that it is possible for the system to use different boot codes in different stages e.g. Stage 0 uses /boot/boot0,, Stage 1 (initial) could use UEFI whereas to bring up the OS (which may be on ZFS disk(s)), legacy boot code may be required.
3. I was also mistaken in how to read the output of gpart. Thank you for setting me straight.
4. I did verify the UEFI partition update using loaders-update as well. I had to do a make install from sysutil/loaders-update port (a first for me - but an excellent learning experience). As fmc000 mentioned, loaders-update does mention for the step to update legacy boot code to be performed. I wonder if there's a way to the program to know that IF boot method == UEFI, then skip gpart boot code message?
root@MorikCage:/usr/ports/sysutils/loaders-update %# loaders-update show-me
loaders-update v1.2.1

One or more efi partition(s) have been found.

Examining nda0p1...
Efi partition nda0p1 is already mounted in /boot/efi.
EFI loader /boot/efi/efi/boot/bootx64.efi is up-to-date.
EFI loader /boot/efi/efi/freebsd/loader.efi is up-to-date.

One or more freebsd-boot partition(s) have been found.
The root file system is zfs.

Examining nda0...
Would run: gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 2 nda0

-------------------------------
Your current boot method is UEFI.
Boot device: Hard Drive (TS1TMTE662T2) PciRoot(0x0)/Pci(0x1,0x3)/Pci(0x0,0x0)/NVMe(0x1,00-00-00-00-00-00-00-00)/HD(1,GPT,1c714ffc-543f-11ed-92bc-000c2905f4ec,0x3,0x82000)
Updatable BIOS loader: 1
-------------------------------


I hope that in trying to overwrite the legacy boot code using gpart bootcode I haven't damaged or left freebsd-boot partition incomplete in that it prevents boot up. In the event that such is the case, I can attempt to perform a FreeBSD 14.3 live boot, but will have to wipe out the disk completely and start anew (per atax1a 's comment)?
 
since you're uefi booting, it might be easiest for you to remove the bios-boot partition entirely with gpart delete -i 2 nda0 — this will stop loaders-update from trying to update it. that will make the drive unbootable via BIOS, but how likely is it that you'll transplant this drive into a machine that can't boot UEFI? (our answer: extremely unlikely)
 
I hope that in trying to overwrite the legacy boot code using gpart bootcode I haven't damaged or left freebsd-boot partition incomplete in that it prevents boot up. In the event that such is the case, I can attempt to perform a FreeBSD 14.3 live boot, but will have to wipe out the disk completely and start anew (per atax1a 's comment)?

In case the system needs to be bootable on a BIOS machine, there is no need to wipe out the disk completely and start anew to add a proper sized freebsd-boot. Just shrink the "efi" partition on the current setup by 1 MB to make room for freebsd-boot: delete, recreate "efi", copy loader.efi, delete, add 512k sized freebsd-boot, copy boot code.

All of the above operations can be performed from the running system.
 
Maybe not transferring the disk(s) to another system, but someone might reset the BIOS/UEFI to defaults or accidentally enable CSM, then the system won't boot at all.
 
Back
Top