Symptom
On a bootc-composefs system that:
- Was installed via
bootc install to-filesystem (writes a systemd-boot /
BLS layout to the ESP: /boot/loader/entries/*.conf and
/boot/EFI/Linux/…)
- Boots via a non-EFI mechanism at runtime (Raspberry Pi 4/5 direct-kernel
boot from Pi firmware, U-Boot chained to a bare kernel, coreboot with a
linux payload, etc.) — i.e. /sys/firmware/efi does not exist
… every bootc verb that touches storage fails at initialization:
$ sudo bootc status
error: Status: Prepending custom prefix to EFI and BLS entries: \
Getting sorted Type1 boot entries: No such file or directory (os error 2)
$ sudo bootc upgrade --check
error: Initializing storage: Prepending custom prefix to EFI and BLS entries: \
Getting sorted Type1 boot entries: No such file or directory (os error 2)
$ sudo bootc switch --transport=registry <target>
error: Switching: Initializing storage: … (same)
bootc usr-overlay still works (doesn't go through the same storage-init
path), which is what surfaces this as a partial regression rather than a
full brick.
Root cause
crates/lib/src/bootc_composefs/status.rs::get_bootloader() reads
EFI_LOADER_INFO via read_uefi_var. When there are no EFI vars
(EfiError::SystemNotUEFI or EfiError::MissingVar) it unconditionally
returns Bootloader::Grub.
Bootloader::Grub.kind() returns BootloaderKind::GRUBClassic. In
storage::new (crates/lib/src/store/mod.rs), that drives:
let boot_dir = match get_bootloader()?.kind()? {
BootloaderKind::GRUBClassic => {
physical_root.open_dir("boot").context("Opening boot")?
}
BootloaderKind::BLSCompatible => {
esp_mount.fd.try_clone().context("Cloning fd")?
}
};
On a system where /boot is a separate partition (the ESP mounted at
/boot via systemd.mount-extra=UUID=<ESP>:/boot:auto:ro in the
deployment cmdline — which bootc install to-filesystem itself writes),
/sysroot/boot/ is empty. All subsequent BLS reads via
boot_dir.read_dir("loader/entries") then ENOENT — including the
idempotent prepend_custom_prefix() backwards-compat migration invoked
from storage::new itself.
Environment where this reproduces
- aarch64 Raspberry Pi 5 with
bootc 1.16.7
- Booted directly from Pi firmware →
config.txt → kernel_2712.img (no
U-Boot, no systemd-boot, no GRUB at runtime)
- Image installed via
bootc install to-filesystem — laid down a valid
BLS layout on the ESP (/boot/loader/entries/bootc_composefs-<sha>-1.conf,
/boot/EFI/Linux/bootc_composefs-<sha>/{vmlinuz,initrd})
/sys/firmware/efi absent
The same code path would fire on any non-EFI ARM board or embedded x86
setup that uses BLS entries for boot metadata but doesn't advertise a
bootloader via EFI variables.
This bug was likely masked before #2356 (merged 2026-08-04) by an earlier
EBUSY error from the pre-mounted ESP path. With #2356's proper handling
of an already-mounted ESP, execution now reaches prepend_custom_prefix
— which is where the wrong boot_dir gets used. #2356 didn't cause this
bug; it just exposed it.
Proposed fix
get_bootloader() should probe the filesystem for a BLS layout when there
are no EFI vars, before falling back to Grub. PR attached.
Symptom
On a bootc-composefs system that:
bootc install to-filesystem(writes a systemd-boot /BLS layout to the ESP:
/boot/loader/entries/*.confand/boot/EFI/Linux/…)boot from Pi firmware, U-Boot chained to a bare kernel, coreboot with a
linux payload, etc.) — i.e.
/sys/firmware/efidoes not exist… every
bootcverb that touches storage fails at initialization:bootc usr-overlaystill works (doesn't go through the same storage-initpath), which is what surfaces this as a partial regression rather than a
full brick.
Root cause
crates/lib/src/bootc_composefs/status.rs::get_bootloader()readsEFI_LOADER_INFOviaread_uefi_var. When there are no EFI vars(
EfiError::SystemNotUEFIorEfiError::MissingVar) it unconditionallyreturns
Bootloader::Grub.Bootloader::Grub.kind()returnsBootloaderKind::GRUBClassic. Instorage::new(crates/lib/src/store/mod.rs), that drives:On a system where
/bootis a separate partition (the ESP mounted at/bootviasystemd.mount-extra=UUID=<ESP>:/boot:auto:roin thedeployment cmdline — which
bootc install to-filesystemitself writes),/sysroot/boot/is empty. All subsequent BLS reads viaboot_dir.read_dir("loader/entries")then ENOENT — including theidempotent
prepend_custom_prefix()backwards-compat migration invokedfrom
storage::newitself.Environment where this reproduces
bootc1.16.7config.txt→kernel_2712.img(noU-Boot, no systemd-boot, no GRUB at runtime)
bootc install to-filesystem— laid down a validBLS layout on the ESP (
/boot/loader/entries/bootc_composefs-<sha>-1.conf,/boot/EFI/Linux/bootc_composefs-<sha>/{vmlinuz,initrd})/sys/firmware/efiabsentThe same code path would fire on any non-EFI ARM board or embedded x86
setup that uses BLS entries for boot metadata but doesn't advertise a
bootloader via EFI variables.
Note on #2356
This bug was likely masked before #2356 (merged 2026-08-04) by an earlier
EBUSYerror from the pre-mounted ESP path. With #2356's proper handlingof an already-mounted ESP, execution now reaches
prepend_custom_prefix— which is where the wrong
boot_dirgets used. #2356 didn't cause thisbug; it just exposed it.
Proposed fix
get_bootloader()should probe the filesystem for a BLS layout when thereare no EFI vars, before falling back to
Grub. PR attached.