From: Tom Rini <trini@konsulko.com>
To: Carlo Caione <ccaione@baylibre.com>, Ahmad Fatoum <a.fatoum@barebox.org>
Cc: u-boot@lists.denx.de, sjg@chromium.org, xypron.glpk@gmx.de,
ilias.apalodimas@linaro.org, dlechner@baylibre.com,
jstephan@baylibre.com, baylibre-upstreaming@groups.io
Subject: Re: [RFC] bootstd: firmware-owned OS devicetree for EBBR / SystemReady IR
Date: Tue, 30 Jun 2026 16:41:37 -0600 [thread overview]
Message-ID: <20260630224137.GF749385@bill-the-cat> (raw)
In-Reply-To: <205BD474-178D-4E91-8C41-33C46E1CCFBB@baylibre.com>
[-- Attachment #1: Type: text/plain, Size: 9461 bytes --]
On Tue, Jun 30, 2026 at 09:20:13PM +0200, Carlo Caione wrote:
> 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?
It probably shouldn't be "u-boot," because it's a more generic thing.
> 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.
I've added in Ahmad Fatoum from the barebox side, as this is a problem
that while the implementation will be bootloader specific, the details
will be generic.
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
next prev parent reply other threads:[~2026-06-30 22:41 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-30 19:20 [RFC] bootstd: firmware-owned OS devicetree for EBBR / SystemReady IR Carlo Caione
2026-06-30 22:41 ` Tom Rini [this message]
2026-07-02 13:09 ` Simon Glass
2026-07-02 14:27 ` Carlo Caione
2026-07-09 19:15 ` Simon Glass
2026-07-10 10:51 ` Carlo Caione
2026-07-13 13:14 ` Simon Glass
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260630224137.GF749385@bill-the-cat \
--to=trini@konsulko.com \
--cc=a.fatoum@barebox.org \
--cc=baylibre-upstreaming@groups.io \
--cc=ccaione@baylibre.com \
--cc=dlechner@baylibre.com \
--cc=ilias.apalodimas@linaro.org \
--cc=jstephan@baylibre.com \
--cc=sjg@chromium.org \
--cc=u-boot@lists.denx.de \
--cc=xypron.glpk@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.