U-Boot is a ubiquitous late stage boot loader used primarily for embedded devices with ARM processors. It also provides an early stage boot loader that can be loaded into SRAM, which then loads U-Boot into system RAM.
It is used by most chip manufacturers for their BSPs and presumably used by most of their customers. My experience is only with Marvell and Xilinx processors. That experience has led me to seek out alternatives.
Although Buildroot provides configuration support for U-Boot I’ve found it better to store defconfigs in-tree rather than in a br2_external repository so that changes to the defconfig will require bumping the version with a new tag in our U-Boot repository. This is important because unlike Linux, which we ship in the rootfs, U-Boot is copied to persistent storage on the device. And upgrading it requires a new version.
The U-Boot environment consists of a binary blob containing variables and a short header. The header consists of 4 bytes containing a hash of the blob followed by an optional byte to store a counter if redundant environments are enabled.
The environment is stored in numerous places. It is statically compiled into the U-Boot binary and Linux userspace tools. It may be built as a standalone binary to be shipped separately. That standalone binary may be stored in persistent storage on the device. It is possible to generate the binary from a text file containing key/value pairs.
Configuration of the environment is stored in the U-Boot binary and
/etc/fw_env.config
. That includes where the environment is
stored (e.g. flash, EEPROM, within a binary on a filesystem) and the
size.
Ideally the header would include the following:
During a talk about adding UEFI support to U-Boot at ELC 2019 the presenter, who was an employee of ARM, explained that U-Boot’s design made it hard to support the UEFI specification of an environment.
U-Boot ends up duplicating a lot of functionality provided by Linux, which results in code getting copied from the kernel.
Projects like LinuxBoot use a stripped down kernel to boot a runtime kernel.
Additionally, there was a discussion on the U-Boot mailing list about creating a firmware repository like linux-firmware, but for boot firmware that is only available as a binary.1
Ping-pong or A/B partitioning consists of two partitions, one active and the other inactive. This allows for atomic image based upgrades. Image based upgrades is far simpler at the cost of additional network bandwidth and writes to persistent storage than alternatives like package based updates or os-tree.
U-Boot does not have a standard way to support this and it is up to the user to figure it out independently.
At IDEXX I’ve written two patches for U-Boot.
The first patch updates the Linux utilities to print an error and exit when they fail to read the environment rather than printing the environment statically compiled into the utility (see patchwork).
The second patch fixes loading a redundant environment from EEPROM, which appears to have suffered from code rot.