[RFC v2] bootstd: firmware-owned OS devicetree for EBBR / SystemReady IR

Carlo Caione ccaione at baylibre.com
Fri Jul 3 11:40:22 CEST 2026


Hi all,

This is v2 of a design RFC, not a patch series. v1 [1] proposed a mechanism
for sourcing the OS devicetree from a firmware-owned partition; v2 refines the
same design. The main change is that the devicetree set is now described by a
firmware-owned FIT manifest carried on that partition, instead of by environment
variables.

This text is self-contained; you do not need to have read v1.

A working implementation exists, with sandbox tests, and has been validated end
to end on hardware in both the plain and the secure (signed) setup.

1. The problem
==============

Platforms that follow EBBR / Arm SystemReady IR treat the OS devicetree as part
of the firmware rather than part of the OS: the base DTB and its overlays live
on a firmware-owned partition and are updated independently of the operating
system, instead of being shipped in the OS image or on the EFI System Partition
(ESP). The firmware is expected to load that devicetree and hand it to the OS
(via the EFI configuration table).

U-Boot today can source the OS devicetree from its own control DT, from the ESP,
or from an EFI Boot#### load option, but it has no generic way to assemble it
from a firmware-owned partition. As a result vendors carry out-of-tree machinery
for exactly this.

For example, MediaTek ships downstream 'dtbprobe' (assemble the DT from a
partition) and 'fdt authndtb' (authenticate it) commands. The goal of this
work is to provide one reusable, vendor-neutral mechanism in mainline so those
downstream commands can be dropped.


2. What a solution has to do
============================

  - Assemble the OS devicetree (a base DTB plus a list of overlays) from a
    firmware-owned partition and install it for the OS.
  - Install it on *every* EFI launch path, not just one. SystemReady IR boots
    through the UEFI boot manager, which in U-Boot does not go through the
    per-device EFI bootmeth, so a per-device-only hook is not enough.
  - Support secure boot: when the firmware devicetree is signed, verify it, and
    never silently fall back to an unverified devicetree.
  - Support A/B firmware partitions and per-SKU devicetree variants.


3. Proposed design
==================

A bootstd helper, firmware_fdt_load() (CONFIG_BOOTSTD_FIRMWARE_FDT), assembles
the devicetree from a FIT manifest on the firmware partition and returns it;
the EFI launch paths install the result via efi_install_fdt(), exactly like any
other devicetree source.

3.1 The manifest: describe and carry in one artefact
----------------------------------------------------

The partition carries one FIT image (by default 'fdt.itb'). Its images hold
the base DTB and the overlays; each of its configurations names one bootable
combination through the standard 'fdt' property:

	/dts-v1/;
	/ {
		description = "Firmware-owned OS devicetree";
		#address-cells = <1>;

		images {
			fdt-base {
				data = /incbin/("board.dtb");
				type = "flat_dt";
				arch = "arm64";
				compression = "none";
				hash-1 { algo = "sha256"; };
			};
			fdt-panel {
				data = /incbin/("panel.dtbo");
				type = "flat_dt";
				arch = "arm64";
				compression = "none";
				hash-1 { algo = "sha256"; };
			};
		};

		configurations {
			default = "conf-panel";
			conf-panel {
				fdt = "fdt-base", "fdt-panel";
			};
			conf-base {
				fdt = "fdt-base";
			};
		};
	};

The helper selects a configuration, verifies it, and assembles the devicetree
by reusing boot_get_fdt_fit(), the same code path bootm already uses for
FIT-carried devicetrees: multi-configuration selection, per-image verification,
overlay application in the listed order, and packing of the result. No new
format, parser, or crypto is introduced.

The manifest must be self-contained: images must be 'flat_dt' with embedded
data (external-data FITs are rejected) and must not carry a 'load' property
(rejected, so a misbuilt manifest cannot overwrite arbitrary memory).

3.2 Where the partition is described (new binding)
--------------------------------------------------

The *location* is described in the control devicetree. The bootstd node carries
a 'firmware-fdt-source' phandle to a node that is a child of the media device
that owns the partition:

	bootstd {
		compatible = "u-boot,boot-std";
		firmware-fdt-source = <&fw_fdt>;
	};

	&mmc0 {
		fw_fdt: firmware-fdt {
			compatible = "u-boot,firmware-fdt-block";
			partition-type-uuid = "....";	/* GPT type UUID */
			partition-name = "firmware";	/* optional */
			filename = "fdt.itb";		/* optional, the default */
		};
	};

The '-block' suffix names the backend: a block device with a GPT partition
holding a filesystem. It leaves room for sibling backends later, e.g. an UBI/MTD
variant for NOR-based boards.

The partition is matched by GPT type UUID and/or name; when both are configured,
both must match, so a misprovisioned disk fails instead of silently selecting
whichever same-type (A/B) partition comes first.

3.3 Configuration selection: by compatible, not by filename
-----------------------------------------------------------

The primary selection mechanism is the compatible string, the way the
FDT spec intends: with FIT_BEST_MATCH, the configuration whose devicetree
best matches the compatible of U-Boot's control devicetree is chosen
(fit_conf_find_compat()), falling back to the manifest's 'default'
configuration. No filename names a devicetree anywhere; the only filename in
the design is the manifest container itself, a fixed convention in the same way
EFI/BOOT/BOOTAA64.EFI is.

On top of that, two optional environment variables can override the choice:

  - 'fw_fdt_config' names a specific FIT configuration (SKU selection);
  - 'boot_dtb' pins a partition number, for A/B firmware partitions.

All selection paths only choose among combinations the firmware author
shipped; with signed configurations, a tampered value cannot select an unsigned
combination. There is no other environment dependency: the description lives
in the manifest and is updated atomically with the devicetrees it describes, so
'env default -a' cannot break the boot.

3.4 Where it is installed (every EFI launch path)
-------------------------------------------------

The helper is consumed by:

  - the per-device EFI bootmeth (bootmeth_efi), on both its disk and its
    network (PXE/DHCP) bootflow paths, so a TFTP server cannot substitute the OS
    devicetree either; and
  - the EFI boot manager (efi_bootmgr_run()), where the firmware devicetree is
    tried first and outranks a Boot#### load-option FDT, so a stale or broken
    load option can neither replace nor block it. An FDT explicitly passed on
    the command line still wins.

Each path installs the result through efi_install_fdt(), the convergence
point all EFI launches pass through, so the firmware devicetree is installed
regardless of how the EFI application is started, including the boot-manager
autoboot path that SystemReady IR uses.

This is transparent to the EFI application: the devicetree sits in the EFI
configuration table before the application starts. In particular, booting GRUB
works unchanged: GRUB does not touch the table entry and the kernel's EFI stub
consumes it.

The assembled firmware devicetree is complete and authoritative: no other
devicetree source is layered on top of it. In particular, extension-board
(extension_scan()) overlays are intentionally not applied, since modifying
the assembled (and, in secure mode, signed) devicetree would defeat the
authenticated-combination model; such combinations should be shipped as manifest
configurations instead.

3.5 Fail-closed error semantics
-------------------------------

Once a source is configured (the node is present), the result is deterministic.
-ENOENT means *only* that no source is configured, in which case the caller
falls back to its normal devicetree. Any other failure to assemble a configured
source (unresolvable device, no matching partition, read error, invalid
manifest, missing configuration, failed signature) is fatal for that EFI launch
path: a missing or bad firmware devicetree is never silently replaced by another
source. Error codes from inner layers that happen to be -ENOENT (for example
a missing FIT configuration) are remapped before returning, so the fallback
sentinel stays unambiguous.

3.6 Secure boot
---------------

Signing a FIT configuration authenticates the whole combination: the base, the
overlay set and its ordering are the signed unit. With FIT_SIGNATURE enabled
and a required key in U-Boot's control devicetree, verification is enforced
by the existing FIT policy code: an unsigned or tampered manifest is rejected,
and because a configured source never falls back, the boot fails closed. There
is no separate Kconfig option for this: FIT is the mechanism, and the usual
verified-boot configuration turns enforcement on.

Thanks for any feedback. I will follow up with the patch series once the
binding and approach are agreed (or in a few days anyway :)

Cheers,

[1] https://lists.denx.de/pipermail/u-boot/2026-June/623429.html

—
Carlo Caione



More information about the U-Boot mailing list