SystemReady IR boots through the UEFI boot manager, which does not go through the per-device EFI bootmeth, so hooking the bootmeth alone would leave the boot-manager path (including autoboot) on the control devicetree.
Consume the firmware-FDT source in efi_bootmgr_run() too, so the firmware-owned devicetree is installed via efi_install_fdt() regardless of which EFI launch path is taken. The firmware-owned devicetree is tried before the Boot#### load-option FDT, so a stale or broken load option can neither override nor block a configured (and possibly signed) firmware devicetree. As a side effect, a devicetree passed directly to efi_bootmgr_run() now also outranks the load-option FDT, which previously overrode it: an explicitly supplied devicetree is the operator's immediate intent, and stored boot options must not replace it. Signed-off-by: Carlo Caione <[email protected]> --- lib/efi_loader/efi_bootmgr.c | 50 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 8c9a9b5eb56..8835891c003 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -14,6 +14,7 @@ #include <efi.h> #include <efi_device_path.h> #include <env.h> +#include <firmware_fdt.h> #include <log.h> #include <malloc.h> #include <net.h> @@ -1296,7 +1297,9 @@ out: * * Invoke EFI boot manager and execute a binary depending on * boot options. If @fdt is not NULL, it will be passed to - * the executed binary. + * the executed binary. Otherwise a configured firmware-owned + * devicetree source takes precedence over both a Boot#### load + * option FDT and the distro one. * * Return: status code */ @@ -1305,7 +1308,8 @@ efi_status_t efi_bootmgr_run(void *fdt) efi_handle_t handle; void *load_options; efi_status_t ret; - void *fdt_lo, *fdt_distro = NULL; + struct firmware_fdt fw = { 0 }; + void *fdt_lo = NULL, *fdt_distro = NULL; efi_uintn_t fdt_size; /* Initialize EFI drivers */ @@ -1320,11 +1324,40 @@ efi_status_t efi_bootmgr_run(void *fdt) } if (!IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) { - ret = load_fdt_from_load_option(&fdt_lo); - if (ret != EFI_SUCCESS) - return ret; - if (fdt_lo) - fdt = fdt_lo; + /* + * Prefer a firmware-owned devicetree (EBBR) over both the + * Boot#### load-option FDT and the distro/ESP one, and try it + * first, so a configured (and, in secure mode, signed) + * firmware DT can neither be overridden nor blocked by a + * stale or broken load-option FDT. An FDT explicitly passed + * to efi_bootmgr_run() (e.g. "bootefi bootmgr <addr>") still + * wins. Fail closed: a configured source that cannot be + * assembled ends the boot rather than falling back to an + * unverified devicetree. + */ + if (!fdt && CONFIG_IS_ENABLED(BOOTSTD_FIRMWARE_FDT)) { + int err; + + err = firmware_fdt_load(&fw); + if (!err) { + fdt = fw.fdt; + log_debug("Using firmware-owned devicetree\n"); + } else if (err != -ENOENT) { + log_err("Failed to assemble the firmware devicetree (err %d)\n", + err); + ret = EFI_LOAD_ERROR; + goto out; + } + } + + if (!fdt) { + ret = load_fdt_from_load_option(&fdt_lo); + if (ret != EFI_SUCCESS) + return ret; + if (fdt_lo) + fdt = fdt_lo; + } + if (!fdt) { efi_load_distro_fdt(handle, &fdt_distro, &fdt_size); fdt = fdt_distro; @@ -1337,7 +1370,10 @@ efi_status_t efi_bootmgr_run(void *fdt) */ ret = efi_install_fdt(fdt); +out: if (!IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) { + /* efi_install_fdt() has copied the devicetree */ + firmware_fdt_free(&fw); free(fdt_lo); if (fdt_distro) efi_free_pages((uintptr_t)fdt_distro, -- 2.55.0

