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]>