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 <[email protected]>
---
 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


Reply via email to