U-Boot EFI Variable Files: Why a Successful Set May Not Survive Reboot

An EFI variable changes, reads back correctly and then reverts after
restart. In U-Boot v2025.01’s file-backed implementation, this can
happen without the setter reporting the filesystem failure to its
caller. The in-memory update and its persistence attempt have different
error paths. A Buildroot product using this backend should qualify
both.

This analysis covers ordinary non-volatile variables handled inside
U-Boot before the runtime-service transition. It excludes
secure-variable enrollment and the trusted-world backend selected
through EFI_MM_COMM_TEE. It is also separate from U-Boot’s
ordinary environment storage.

Establish which store was
built

EFI_VARIABLE_FILE_STORE selects storage in
/ubootefi.var on the EFI system partition and depends on
FAT write support. It is a configuration choice, not an automatic
property of every U-Boot EFI build. The trusted-world option dispatches
variable operations through another implementation, so conclusions about
a filesystem file must not be applied to that backend. Tagged
variable-store configuration
.

The file helper selects storage from the recorded EFI system
partition’s interface class, device number and partition number. An
invalid selection or a failed filesystem selection produces
EFI_DEVICE_ERROR. Thus a visible FAT partition somewhere on
the board is insufficient evidence that this helper has selected a
usable destination. File-store
implementation
.

In-memory variable update, file persistence and next-boot restoration have separate success boundaries.

Trace the setter
beyond its memory update

efi_set_variable_int() validates arguments and
attributes, then updates the in-memory variable representation. Those
operations can return errors normally. After a successful update, the
function calls efi_var_to_file() when the variable’s
attributes include non-volatility.

The important detail is the call site: it does not inspect the file
helper’s return value before returning EFI_SUCCESS. A
successful setter response therefore cannot, by itself, certify a
successful file write. An immediate readback may simply observe the new
in-memory value. Variable-service
implementation
.

The helper itself does check persistence errors. It collects the
non-volatile variables, selects the system partition and calls
fs_write(). A write error or an actual byte count different
from the requested length becomes EFI_DEVICE_ERROR. Missing
system-partition selection also has a warning path. This is not an
absence of error detection; it is an error-propagation boundary between
the helper and its caller. Persistence
helper
.

That distinction changes the diagnostic target. Repeating the
variable read in the same session does not test the failing layer.
Observe the selected backing partition and persistence diagnostics, then
validate restoration across a restart in a controlled fixture.

Successful
initialization can tolerate missing state

The next-boot path is deliberately tolerant.
efi_var_from_file() returns success for a missing file or a
corrupt variable file so those conditions do not necessarily stop boot.
Allocation failure is a separate error case. The restore helper checks
the file’s header conditions and CRC, and file restoration does not
overwrite a variable already present in memory.

It also filters security-related and volatile variables from an
ordinary file restore; this file is not a general mechanism for
importing all EFI state. These rules explain why “EFI initialized
successfully” is too weak an assertion that a particular expected value
was restored. Check that value and its intended source explicitly. Restore
and load paths
.

Keep runtime
writes out of the same assumption

After the runtime-service transition, a different setter is
installed. The file-store configuration can optionally enable RAM-backed
runtime changes with EFI_RT_VOLATILE_STORE; its help text
assigns file synchronization to the operating system if those changes
must persist. A successful runtime operation is therefore a different
test from the pre-transition file-writing path discussed above. Runtime-store
configuration
.

Use an ordinary test variable in an isolated, recoverable
qualification image. Compare three observations: the setter’s result,
the current-session value and the value restored after restart. Include
unavailable backing storage, a file-write failure and an invalid-file
fixture where safely supported. Keep security databases and production
boot policy outside this test.

No variable was changed or restart test executed for this article.
The acceptance criterion is that the intended value crosses the storage
and restore boundaries, rather than merely surviving an in-memory
readback.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *