[PATCH v1 44/54] efi: loader: add rudimentary EFI boot manager

Ahmad Fatoum a.fatoum at pengutronix.de
Thu Dec 18 02:38:04 PST 2025


Actual efibootmgr is a bit more involved and would require evaluating
the Boot#### variables. This is planned, but for now let's only
implement the fallback when no variables have been found.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/boot.c           |  7 ++--
 efi/loader/Kconfig      | 11 ++++++
 efi/loader/Makefile     |  1 +
 efi/loader/efibootmgr.c | 79 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 95 insertions(+), 3 deletions(-)
 create mode 100644 efi/loader/efibootmgr.c

diff --git a/common/boot.c b/common/boot.c
index a8a92057844b..7b2ce4740759 100644
--- a/common/boot.c
+++ b/common/boot.c
@@ -136,9 +136,10 @@ static int init_boot(void)
 {
 	if (!global_boot_default)
 		global_boot_default = xstrdup(
-			IF_ENABLED(CONFIG_BOOT_DEFAULTS, "bootsource ")
-			IF_ENABLED(CONFIG_BOOT_DEFAULTS, "storage.builtin ")
-			IF_ENABLED(CONFIG_BOOT_DEFAULTS, "storage.removable ")
+			IF_ENABLED(CONFIG_EFI_LOADER_BOOTMGR,  "efibootmgr ")
+			IF_ENABLED(CONFIG_BOOT_DEFAULTS,       "bootsource ")
+			IF_ENABLED(CONFIG_BOOT_DEFAULTS,       "storage.builtin ")
+			IF_ENABLED(CONFIG_BOOT_DEFAULTS,       "storage.removable ")
 			"net"
 		);
 
diff --git a/efi/loader/Kconfig b/efi/loader/Kconfig
index d54783f9a084..ca0ec6b5010a 100644
--- a/efi/loader/Kconfig
+++ b/efi/loader/Kconfig
@@ -1,6 +1,17 @@
 # SPDX-License-Identifier: GPL-2.0-only
 # SPDX-Comment: Origin-URL: https://github.com/u-boot/u-boot/blob/a0fe8cedcbe8c76403a77e57eac228b8f778a3ae/lib/efi_loader/Kconfig
 
+config EFI_LOADER_BOOTMGR
+	bool "Rudimentary UEFI Boot Manager support"
+	select BOOT
+	select BOOT_DEFAULTS
+	default y
+	help
+	  This boot manager doesn't yet make use of Boot# variables, but instead
+	  hardcodes order to lookup removable and then builtin storage devices
+	  for EFI payloads located at the removable media path indicated by
+	  CONFIG_EFI_PAYLOAD_DEFAULT_PATH within their respective devices.
+
 config EFI_LOADER_DEBUG_SUPPORT
 	bool "EFI Debug Support"
 	default y
diff --git a/efi/loader/Makefile b/efi/loader/Makefile
index 84a8bf1ca229..62483057b426 100644
--- a/efi/loader/Makefile
+++ b/efi/loader/Makefile
@@ -13,3 +13,4 @@ obj-y += watchdog.o
 obj-y += pe.o
 obj-y += loadopts.o
 obj-$(CONFIG_BOOT) += bootesp.o
+obj-$(CONFIG_EFI_LOADER_BOOTMGR) += efibootmgr.o
diff --git a/efi/loader/efibootmgr.c b/efi/loader/efibootmgr.c
new file mode 100644
index 000000000000..4f8b04d8298c
--- /dev/null
+++ b/efi/loader/efibootmgr.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#define pr_fmt(fmt) "efi-loader: efibootmgr: " fmt
+
+#include <boot.h>
+#include <driver.h>
+
+struct resolve_ctx {
+	struct bootentry_provider *provider;
+	struct bootentries *entries;
+};
+
+static int populate_esp_bootentries(struct cdev *cdev, void *_ctx)
+{
+	struct resolve_ctx *ctx = _ctx;
+
+	pr_debug("processing %s\n", cdev->name);
+
+	return ctx->provider->generate(ctx->entries, cdev->name);
+}
+
+static int efibootmgr_add_entry_from_bootvars(struct bootentries *entries,
+					      const char *name)
+{
+	/* TODO: actually make use of the Boot# variables
+	 * instead of only hardcoding order
+	 */
+	return 0;
+}
+
+static int efibootmgr_add_entry_from_fallback(struct bootentries *entries,
+					      const char *name)
+{
+	struct resolve_ctx ctx;
+	int nremovable, nbuiltin;
+
+	ctx.provider = get_bootentry_provider("esp");
+	if (!ctx.provider)
+		return -ENOENT;
+
+	ctx.entries = entries;
+
+	nremovable = cdev_alias_resolve_for_each("storage.removable",
+						 populate_esp_bootentries, &ctx);
+	if (nremovable < 0)
+		return nremovable;
+
+	nbuiltin = cdev_alias_resolve_for_each("storage.builtin",
+					       populate_esp_bootentries, &ctx);
+	if (nbuiltin < 0)
+		return nbuiltin;
+
+	return nbuiltin + nremovable;
+}
+
+static int efibootmgr_add_entry(struct bootentries *entries, const char *name)
+{
+	int nentries;
+
+	if (strcmp(name, "efibootmgr"))
+		return 0;
+
+	nentries = efibootmgr_add_entry_from_bootvars(entries, name);
+	if (nentries)
+		return nentries;
+
+	return efibootmgr_add_entry_from_fallback(entries, name);
+}
+
+static struct bootentry_provider efibootmgr_entry_provider = {
+	.name = "efibootmgr",
+	.generate = efibootmgr_add_entry,
+};
+
+static int efibootmgr_init(void)
+{
+	return bootentry_register_provider(&efibootmgr_entry_provider);
+}
+device_initcall(efibootmgr_init);
-- 
2.47.3




More information about the barebox mailing list