Update of the bootcodes for a GPT scheme (x64 architecture)

This how-to is about the update of the bootcodes on FreeBSD as it's little to no documented. It only covers the GPT scheme and is intended for people with little knowledge of FreeBSD.

When to update?
At each upgrade of the system whenever it's a minor or a major one.

In general, the system is compatible with the bootcodes of version-1. So personally, I do it just after the upgrade is finished.

GPT or MBR?
The command gpart show will answer to this. You will see either GPT or MBR at the first line of output. If you are on a MBR scheme, you can leave this how-to (and think about a reinstallation with GPT).

What is/are my booting partitions?
Again, gpart show will give you the answers. You can have only efi booting or only legacy BIOS booting or both.

In this example, the root disk has both booting capabilities:
Code:
gpart show -p
=>       40  104857520    ada0  GPT  (50G)
         40     409600  ada0p1  efi  (200M)
     409640       1024  ada0p2  freebsd-boot  (512K)
     410664        984          - free -  (492K)
     411648    4194304  ada0p3  freebsd-swap  (2.0G)
    4605952  100249600  ada0p4  freebsd-zfs  (48G)
  104855552       2008          - free -  (1.0M)

Here, you see the disk-name (ada0) and the partition scheme (GPT). You have an efi partition for efi booting and a freebsd-boot partition for BIOS booting. Note the partition-name (under disk-name) you have to update and its partition-number. In the example, it's ada0p1 (partition-number is 1) & ada0p2 (partition-number is 2).

Note also the root partition type, whether it is a zfs (freebsd-zfs) or an ufs one (freebsd-ufs). It's a zfs root partition in this example.

Here we go:

Update of the efi bootcode on a GPT scheme with an installation that was made before 13.0-RELEASE (root user):

Code:
mount -t msdosfs /dev/partition-name /mnt
cp /boot/loader.efi /mnt/efi/boot/bootx64.efi
umount /mnt

So, following the example, it's: mount -t msdosfs /dev/ada0p1 /mnt

This annoyance happens if the system has been installed from a 12.0 or previous RELEASE disk. It's the way loader.efi was copied into this partition. You legacy a FAT12 msdosfs that doesn't take all the available space (200 MiB).

So, you must change the file system, reformat it in Windows terms. You need first to unmount the partition:
umount /mnt
Then:
Code:
newfs_msdos -F16 /dev/partition-name
mount -t msdosfs /dev/partition-name /mnt
mkdir -p /mnt/efi/boot
cp /boot/loader.efi /mnt/efi/boot/bootx64.efi
umount /mnt
Where partition-name is ada0p1 in the example.

DO NOT REBOOT BEFORE loader.efi IS ACTUALLY COPIED AT THE RIGHT PLACE

Important note: if you started with a 13.0-RELEASE installation, the partition where the efi loader resides is mounted on /boot/efi. In this case, you cannot mount the partition on /mnt. mount will answer "Device is busy".

So, the procedure becomes:
Code:
cp /boot/loader.efi /boot/efi/efi/boot/bootx64.efi

Very important note: if you started with FreeBSD 14, the installer has activated a EFI boot entry that refers to this loader: /efi/freebsd/loader.efi. It means the system won't boot anymore on the default /efi/boot/bootx64.efi. So, update the file bootx64.efi will have no effect. I think it's safer to update both bootcodes.
Code:
cp /boot/loader.efi /boot/efi/efi/freebsd/loader.efi


Update of the BIOS bootcode on a GPT scheme if the root partition is a freebsd-zfs type (root user):

gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i partition-number disk-name
Following the given example, it's: gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 2 ada0


Update of the BIOS bootcode on a GPT scheme if the root partition is a freebsd-ufs type (root user):

gpart bootcode -b /boot/pmbr -p /boot/gptboot -i partition-number disk-name


I have now to speak about the case of a zfs mirror. This is what you get with a guided installation (Auto (ZFS) with "mirror" selected). Here is an example, a mirror on two disks:

Code:
gpart show                                                 
=>        40  3907029088  ada0  GPT  (1.8T)                                  
          40        1024     1  freebsd-boot  (512K)                        
        1064         984        - free -  (492K)                            
        2048     4194304     2  freebsd-swap  (2.0G)                        
     4196352  3902832640     3  freebsd-zfs  (1.8T)                          
  3907028992         136        - free -  (68K)                              
                                                                             
=>        40  3907029088  ada1  GPT  (1.8T)                                  
          40        1024     1  freebsd-boot  (512K)                        
        1064         984        - free -  (492K)                            
        2048     4194304     2  freebsd-swap  (2.0G)                        
     4196352  3902832640     3  freebsd-zfs  (1.8T)                          
3907028992 136 - free - (68K)

zpool status                                               
  pool: zroot                                                                
state: ONLINE                                                                                   
config:                                                                      
                                                                             
        NAME        STATE     READ WRITE CKSUM                               
        zroot       ONLINE       0     0     0                               
          mirror-0  ONLINE       0     0     0                               
            ada0p3  ONLINE       0     0     0                               
            ada1p3  ONLINE       0     0     0

If your zfs root system is on a mirror, you have to update bootcodes on all disks that belonging to this mirror. Because in case of failure of the main disk, the others disks have to provide the booting.

In this example, there is no efi booting, just BIOS booting. So, at each upgrade I will execute:
Code:
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada1
 
Last edited:
Thank you very much for the detailed description of how to update bootcode.
I have a clarifying question recording efi bootcode and mirrored zfs-root as described above.

I have installed Freebsd 13/stable on a zfs-mirror (using the auto setting during install), the efi boot partition is therefore mirrored on both drives in the mirror, but the installer only seems to install boot code into the first drive. The efi portion on the second drive is not a msdosfs partion.

Code:
# gpart show nvd0 nvd1
=>        40  1875384928  nvd0  GPT  (894G)
          40      532480     1  efi  (260M)
      532520        1024     2  freebsd-boot  (512K)
      533544         984        - free -  (492K)
      534528    16777216     3  freebsd-swap  (8.0G)
    17311744  1858072576     4  freebsd-zfs  (886G)
  1875384320         648        - free -  (324K)

=>        40  1875384928  nvd1  GPT  (894G)
          40      532480     1  efi  (260M)
      532520        1024     2  freebsd-boot  (512K)
      533544         984        - free -  (492K)
      534528    16777216     3  freebsd-swap  (8.0G)
    17311744  1858072576     4  freebsd-zfs  (886G)
  1875384320         648        - free -  (324K)

# file -s /dev/nvd0p1 /dev/nvd1p1
/dev/nvd0p1: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "BSD4.4  ", sectors/cluster 32, root entries 512, sectors/FAT 65, sectors/track 63, heads 255, sectors 532480 (volumes > 32 MB), serial number 0xf4bb07f6, unlabeled, FAT (16 bit)
/dev/nvd1p1: data

Is there any reason for not having the bootcode on the second disk in the mirror, I would assume that I would not be able to boot if the first disk goes away for some reason?
Do I need to create this by myself?

Thank you very much for the help
 
Seems the nvd1p1 partition isn't formated. So you have to do it, create the directories and copy the loader:

Code:
newfs_msdos -F16 /dev/nvd1p1
mount -t msdosfs /dev/nvd1p1 /mnt
mkdir -p /mnt/efi/boot
cp /boot/loader.efi /mnt/efi/boot/bootx64.efi
umount /mnt
 
In general, the system is compatible with the bootcodes of version-1. So personally, I do it just after the upgrade is finished.
But what if the system is upgraded from a very old version. I assume that you need to update the bootcode before the first shutdown, which occurs after freebsd-update upgrade -r <release>; freebsd-update install. Is it right?
 
Yes. But, if it is a very old version, maybe you won't have enough room in the corresponding partitions.

In some cases, it's simpler to reinstall the whole system (and not only for this specific problem).
 
In some cases, it's simpler to reinstall the whole system (and not only for this specific problem).
In the past, I often reinstalled the whole system due to certain circumstances, such as moving to a new computer, HDD failure, changing the partition scheme, switching to a different type of filesystem, etc.

Are there any other cases when it's easier to reainstall the whole system instead of upgrading?
 
Are there any other cases when it's easier to reainstall the whole system instead of upgrading?
VMs, Cloud images. Those are typically installed and configured with automated tools anyway. Make sure you disconnect your data from the OS. As long as your data is on another disk (or partition, pool, SAN/NAS, whatever) you could just wipe the OS, reinstall, configure what you need, reattach the data and be up and running again.
 
… a mere list of manpages is not what I expect from a handbook.

I feel the same.

A few months ago, when reports of bootcode-related problems were frequent, I might have had an idea what to write. Now it's like a distant memory, my mind's on other things.

bsduck Emrion if you can think of a suitable addition to 24.3, maybe add a patch file (as a suggestion) to the bug before it closes.
 
Seems the nvd1p1 partition isn't formated. So you have to do it, create the directories and copy the loader:

Code:
newfs_msdos -F16 /dev/nvd1p1
mount -t msdosfs /dev/nvd1p1 /mnt
mkdir -p /mnt/efi/boot
cp /boot/loader.efi /mnt/efi/boot/bootx64.efi
umount /mnt
i installed 13.2 first, then (source) upgraded to 14.0
should i create both folders/files efi/boot/bootx64.efi and efi/freebsd/loader.efi


Code:
newfs_msdos -F16 /dev/ada1p1
mount -t msdosfs /dev/ada1p1 /mnt
mkdir -p /mnt/efi/boot
cp /boot/loader.efi /mnt/efi/boot/bootx64.efi
mkdir -p /mnt/efi/freebsd
cp /boot/loader.efi /mnt/efi/freebsd/loader.efi
umount /mnt

file -s /dev/ada0p1 /dev/ada1p1
/dev/ada0p1: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "BSD4.4  ", sectors/cluster 32, root entries 512, sectors/FAT 65, sectors/track 63, heads 16, sectors 532480 (volumes > 32 MB), serial number 0x9cc41c01, unlabeled, FAT (16 bit)
/dev/ada1p1: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "BSD4.4  ", sectors/cluster 32, root entries 512, sectors/FAT 65, sectors/track 63, heads 16, sectors 532480 (volumes > 32 MB), serial number 0x3875130e, unlabeled, FAT (16 bit)
 
i installed 13.2 first, then (source) upgraded to 14.0
should i create both folders/files efi/boot/bootx64.efi and efi/freebsd/loader.efi
Yes. For the shake of curiosity, what's the output of # efibootmgr -v?
 
Yes. For the shake of curiosity, what's the output of # efibootmgr -v?

Code:
efibootmgr -v
Boot to FW : false
BootCurrent: 0000
Timeout    : 5 seconds
BootOrder  : 0000, 0002, 0003, 0004, 0005
+Boot0000* FreeBSD HD(1,GPT,a95f81b0-3560-11ee-bb6b-a036bcc8b189,0x28,0x82000)/File(\EFI\FREEBSD\LOADER.EFI)
                      gpt/efiboot0:/EFI/FREEBSD/LOADER.EFI /boot/efi//EFI/FREEBSD/LOADER.EFI
 Boot0002* UEFI OS HD(1,GPT,a95f81b0-3560-11ee-bb6b-a036bcc8b189,0x28,0x82000)/File(\EFI\BOOT\BOOTX64.EFI)
                      gpt/efiboot0:/EFI/BOOT/BOOTX64.EFI /boot/efi//EFI/BOOT/BOOTX64.EFI
 Boot0003* UEFI:CD/DVD Drive BBS(0x81,,0x0)
 Boot0004* UEFI:Removable Device BBS(0x82,,0x0)
 Boot0005* UEFI:Network Device BBS(0x83,,0x0)
Unreferenced Variables:
 
Ok, so the upgrade to 14.0-RELEASE promoted the /EFI/FREEBSD/LOADER.EFI loader. It did the same on a bare metal machine I recently upgraded (with some mess apparently...) but didn't touch the boot entries on several VMs (VirtualBox on Windows).

Thank you very much.
 
Back
Top