U-Boot Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] bootstd: firmware-owned OS devicetree for EBBR / SystemReady IR
@ 2026-06-30 19:20 Carlo Caione
  2026-06-30 22:41 ` Tom Rini
  2026-07-02 13:09 ` Simon Glass
  0 siblings, 2 replies; 4+ messages in thread
From: Carlo Caione @ 2026-06-30 19:20 UTC (permalink / raw)
  To: u-boot
  Cc: sjg, xypron.glpk, ilias.apalodimas, trini, dlechner, jstephan,
	baylibre-upstreaming

Hi all,

This is a design RFC, not a patch series. I would like to agree the approach
and the devicetree binding on the list before posting code, because the
mechanism touches both bootstd and the EFI loader and introduces a new binding.

A working implementation exists and has been validated on hardware (details at
the end); I will post it as patches once the design here is acceptable.


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.


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

A new bootstd helper, `firmware_fdt_load()` (`CONFIG_BOOTSTD_FIRMWARE_FDT`),
assembles the devicetree and returns it; the EFI launch paths install it via
`efi_install_fdt()`, exactly like any other devicetree source.

3.1 Where the source 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, and identifies the partition by GPT type UUID and/or
name:

	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 */
			extra-size = <0x3000>;		/* overlay headroom */
		};
	};

3.2 The dynamic parameters (environment) and board defaults
-----------------------------------------------------------

The source and its partition policy stay in the control devicetree (section
3.1). The values that change with the OS image rather than with the hardware are
layered:

  - the control DT describes the source and the partition policy;
  - the board default environment carries factory defaults for the static values
    (`fdtfile` and `dtb_path` for the base DTB, and the `fdt_addr_r` /
    `fdtoverlay_addr_r` working addresses), so a from-source build boots and
    `env default` restores a loadable configuration;
  - the (firmware-owned) stored environment overrides those at runtime, and
    carries the genuinely dynamic values: the overlay list (`list_dtbo`) and the
    A/B partition pin (`boot_dtb`).

As an alternative, the stable defaults (`fdtfile` and the path) could instead be
expressed as optional properties on the source node, keeping them in the control
devicetree rather than in the board default environment. See the open questions.

3.3 Where it is installed (both EFI paths)
------------------------------------------

The helper is consumed by both:

  - the per-device EFI bootmeth (`bootmeth_efi`), and
  - the EFI boot manager (`efi_bootmgr_run()`),

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

3.4 Fail-closed error semantics
-------------------------------

Once a source is configured (the node is present), the result must be
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 blob, failed signature) is fatal for that EFI launch path: a
missing or bad firmware devicetree is never silently replaced by another source.
Missing environment metadata for a configured source is treated as a
configuration error (fail closed, or satisfied from the board default), never as
"no source".

3.5 Optional secure boot
------------------------

With `CONFIG_BOOTSTD_FIRMWARE_FDT_FIT` the base DTB and overlays are signed FIT
images. Each is verified by reusing U-Boot's existing verified-boot policy
(`fit_image_load()` with verification enabled and a required key in the control
FDT), and the verified flat devicetree is extracted in place. A non-FIT file is
rejected so an unsigned devicetree cannot be installed. This reuses the existing
trust model rather than adding new crypto, and replaces the downstream
`fdt authndtb`.


4. Why these choices
====================

  - Describing the source in the control DT, as a child of the media device,
    follows the existing bootstd guidance ("if a bootdev needs configuration,
    add it to the DT as a child of the media device") and the VBE precedent. It
    keeps the mechanism generic: no GPT UUID or board constant in the C code.
  - Splitting identity (control DT) from dynamic values (environment) and static
    defaults (board default env) keeps the firmware in control of what changes
    per OS image, while still letting a plain `make <board>_defconfig` build
    boot.
  - Installing at `efi_install_fdt()` rather than in one bootmeth is what makes
    this SystemReady-IR-grade: the boot-manager path carries the firmware
    devicetree too. A per-device-only hook leaves the autoboot path on the
    control DT.
  - Fail-closed is required for secure boot: there must be no path where a
    configured, signed devicetree silently degrades to an unverified one.
  - Reusing `fit_image_load()` keeps a single, reviewed verified-boot path.


5. Alternatives considered
==========================

  - A global bootmeth ordered ahead of the EFI boot manager (a structure used in
    an earlier proof of concept). It works for autoboot but does not converge
    all launch paths; `efi_install_fdt()` is the real single point.
  - A per-device bootmeth hook only. Simpler, but misses the boot-manager
    autoboot path, which is the one SystemReady IR uses.
  - Keeping the mechanism vendor-specific (the status quo). Does not help anyone
    else and keeps the command out of tree.


6. Open questions for the list
==============================

  1. Binding naming: are `firmware-fdt-source` and the `u-boot,firmware-fdt-block`
     compatible acceptable, and is the control-DT-described-source shape the one
     you want?
  2. The configuration boundary. The proposal keeps the source and partition
     policy in the control DT, puts factory defaults for the filenames and the
     working addresses in the board default environment, and lets the
     firmware-owned stored environment override at runtime (and hold the dynamic
     `list_dtbo` / `boot_dtb`). An alternative is to express the stable defaults
     (`fdtfile`, a path) as optional properties on the source node, so they live
     in the control DT rather than the board environment. Which does the project
     prefer?
  3. The `efi_bootmgr_run()` hook: is installing the firmware devicetree on the
     boot-manager path acceptable to the EFI maintainers, and is that the right
     place?
  4. The fail-closed semantics: a configured source that cannot be assembled is
     fatal; only an absent source falls back. Agree?
  5. Should the signed-FIT verification be part of this series or a follow-up?

Thanks for any feedback. I will follow up with the patch series once the binding
and approach are agreed.

Cheers,

—
Carlo Caione


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-07-02 14:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-30 19:20 [RFC] bootstd: firmware-owned OS devicetree for EBBR / SystemReady IR Carlo Caione
2026-06-30 22:41 ` Tom Rini
2026-07-02 13:09 ` Simon Glass
2026-07-02 14:27   ` Carlo Caione

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox