An FDT explicitly passed to efi_bootmgr_run() is currently replaced by
the FDT referenced by the selected Boot#### load option.

A user running 'bootefi bootmgr <fdt_addr>' should be able to try another
devicetree for a single invocation, for example while debugging, without
editing the stored boot option. Boot#### still selects the EFI executable;
the explicit argument only overrides its devicetree for this invocation.
This is an input-precedence rule, not a distinction between user privilege
levels.

Only consult the load-option FDT when no FDT was passed. Document the
resulting precedence so the explicit call argument remains the
highest-priority source.

Fixes: 39bac24a48bb ("efi_loader: load device-tree specified in boot option")
Reviewed-by: Ilias Apalodimas <[email protected]>
Reviewed-by: Simon Glass <[email protected]>
Signed-off-by: Carlo Caione <[email protected]>
---
This fix was originally submitted as patch 1 of the EBBR V2 series [1]
and carried forward in V3 [2]. It is now split out for independent review
and merging, with no dependency on the firmware-devicetree work.

An FDT explicitly passed to 'bootefi bootmgr <fdt_addr>' should override
the DT referenced by the selected Boot#### option for that invocation.
The boot option still selects the EFI executable; its stored settings are
not changed.

The C change is unchanged from V2/V3, retaining the Reviewed-by tags from
Ilias and Simon. This standalone version clarifies the commit message,
documents the selection order requested by Heinrich and adds a Fixes tag.

[1] 
https://lore.kernel.org/all/[email protected]/
[2] 
https://lore.kernel.org/all/[email protected]/
---
 doc/usage/cmd/bootefi.rst    | 29 +++++++++++++++++++++++------
 lib/efi_loader/efi_bootmgr.c | 20 +++++++++++---------
 2 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/doc/usage/cmd/bootefi.rst b/doc/usage/cmd/bootefi.rst
index 8b237fd75fb..7cbf28e8b07 100644
--- a/doc/usage/cmd/bootefi.rst
+++ b/doc/usage/cmd/bootefi.rst
@@ -28,9 +28,9 @@ The *bootefi* command is used to launch a UEFI binary which 
can be any of
 
 An operating system requires a hardware description which can either be
 presented as ACPI table (CONFIG_GENERATE_ACPI_TABLE=y) or as device-tree.
-The load address of the device-tree may be provided as parameter *fdt_addr*. If
-this address is not specified, the bootefi command will try to fall back in
-sequence to:
+The load address of the device-tree may be provided as parameter *fdt_addr*.
+When launching a binary directly without this address, the bootefi command
+will try to fall back in sequence to:
 
 * the device-tree specified by environment variable *fdt_addr*
 * the device-tree specified by environment variable *fdtcontroladdr*
@@ -84,9 +84,10 @@ initrd_size
     Size of the Linux initial RAM disk.
 
 fdt_addr
-    Address of the device-tree or '-'. If no address is specified, the
-    environment variable $fdt_addr is used as first fallback, the address of
-    U-Boot's internal device-tree $fdtcontroladdr as second fallback.
+    Address of the device-tree or '-'. For direct invocation without an
+    address, the environment variable $fdt_addr is used as first fallback,
+    the address of U-Boot's internal device-tree $fdtcontroladdr as second
+    fallback. The boot manager's selection order is described below.
     When using ACPI no device-tree shall be specified.
 
 Note
@@ -109,6 +110,22 @@ option to execute next. If no binary can be loaded via 
*BootNext* the variable
 The values of these variables can be managed using the U-Boot command
 *efidebug*.
 
+When using a device-tree rather than ACPI, the boot manager selects it in
+the following order, from highest to lowest priority:
+
+1. The address explicitly passed to ``bootefi bootmgr <fdt_addr>``.
+2. The device-tree referenced by the selected *Boot####* load option.
+3. The distro device-tree loaded from the filesystem containing the EFI binary.
+4. The address in the environment variable *fdt_addr*.
+5. The address of U-Boot's internal device-tree in *fdtcontroladdr*.
+
+An explicit address overrides the stored device-tree choice for this
+invocation only. This allows trying an alternative device-tree, for example
+while debugging, without modifying the boot option. *Boot####* still selects
+the EFI binary to execute. If a load-option device-tree is selected but cannot
+be loaded, the boot manager returns an error instead of trying a lower-priority
+source.
+
 UEFI hello world application
 ''''''''''''''''''''''''''''
 
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index 8938b214ceb..6b5dad21b06 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -1294,9 +1294,9 @@ out:
  * efi_bootmgr_run() - execute EFI boot manager
  * @fdt:       Flat device tree
  *
- * 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.
+ * Invoke the EFI boot manager and execute a binary according to its boot
+ * options. The devicetree precedence, from highest to lowest, is an FDT
+ * passed in @fdt, the Boot#### load-option FDT, then the distro/ESP FDT.
  *
  * Return:     status code
  */
@@ -1305,7 +1305,7 @@ 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;
+       void *fdt_lo = NULL, *fdt_distro = NULL;
        efi_uintn_t fdt_size;
 
        /* Initialize EFI drivers */
@@ -1320,11 +1320,13 @@ 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;
+               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;

---
base-commit: ed869863c7e2aca50d57a05d843830dd843138c4
change-id: 20261015-ccaione-upstream-efi-bootmgr-passed-fdt-f3c8b760335a

Best regards,
--  
Carlo Caione <[email protected]>

Reply via email to