As far as I know, /boot is an ordinary directory in the root dataset, so each BE has it's own /boot.
That is correct.
Are you saying that if /boot is corrupted on the default BE, the boot process can't fall back to the other versions of /boot?
That's exactly the case.
The loader can probe only the active BE. If no kernel can be found there, the boot process stops at the loader, presenting the user a loader prompt.
There is no logic in the loader built in to probe other BEs if no kernel is found in the active BE. In such a case the user must tell the loader explicitly an alternate BE to use.
Example:
Assuming OPs UEFI system,
loader.efi(8) would be the kernel loader, and "currdev" the variable to set a different BE (for "currdev" see
loader_simp(8)). See [1] for BIOS.
Code:
# kenv
...
bootenv_autolist="YES"
bootenvs[0]="zfs:zroot/ROOT/14.3-RELEASE_2025-06-29-10:14:05"
bootenvs[1]="zfs:zroot/ROOT/14.3-RELEASE_2025-06-29-10:14:01"
bootenvs[2]="zfs:zroot/ROOT/14.3-RELEASE_2025-06-29-10:13:56"
bootenvs[3]="zfs:zroot/ROOT/14.3-RELEASE_2025-06-29-10:13:46"
bootenvs[4]="zfs:zroot/ROOT/14.3-RELEASE_2025-06-29-10:13:39"
bootenvs[5]="zfs:zroot/ROOT/14.3-RELEASE_2025-06-29-10:13:33"
bootenvs[6]="zfs:zroot/ROOT/14.3-RELEASE_2025-06-29-10:03:25"
bootenvs[7]="zfs:zroot/ROOT/default"
bootenvs_count="8"
bootfile="kernel"
...
currdev="zfs:zroot/ROOT/default:"
In this VM setup are 8 BEs, 1 activated default and 7 (simulated)
freebsd-update(8) created BEs. The default device to loader the kernel from is set to
currdev="zfs:zroot/ROOT/default:"
.
To override a corrupted BE, the user must specify at the loader prompt a different BE with an intact file system to boot a kernel from, i.e.:
Code:
OK set currdev=zfs:zroot/ROOT/14.3-RELEASE_2025-06-29-10:13:33:
After setting the BE, the file system can be inspected with "ls". Then, to boot the system, load .../kernel, load .../zfs.ko, boot.
In the OPs system setup,
geli(8) encrypted Root-on-ZFS is involved, which makes it impossible to view other BEs from the loader prompt. If the user has no knowledge of the exact BEs name (which is usually the case of freebsd-update created BEs), a installer medias live system must be booted, the Root-on-ZFS
geli(8) provider attached, the pool imported, to "zfs list" BE snapshots.
Cloning a BE snapshot with an easier-to-remember name (zroot/ROOT/rescue in the example in post # 14) is for user convenience, instead of making a note or memorizing the exact BE name, which includes year/month/day/hour/minute/second, underscore, hyphens, colons as part of the name.
[1]
On BIOS,
gptzfsboot(8) is the loader probing ZFS partition for an kernel. The setting format for another pool is
[zfs:pool/filesystem:][/path/to/loader]
, i.e.:
Code:
boot: zfs:zroot/ROOT/rescue:/boot/zfsloader
It looks like,
gptzfsboot(8) doesn't understand BE names containing underscore, hyphens, colons (like
zfs:zroot/ROOT/14.3-RELEASE_2025-06-29-10:13:33:
). An alternate BE should be cloned from a snapshot with a simple name when on a live rescue system.