Create a bootdev device for the EFI boot manager.

Signed-off-by: Heinrich Schuchardt <heinrich.schucha...@canonical.com>
---
 include/dm/uclass-id.h       |   1 +
 lib/efi_loader/Makefile      |   1 +
 lib/efi_loader/efi_bootdev.c | 102 +++++++++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+)
 create mode 100644 lib/efi_loader/efi_bootdev.c

diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 270088ad94f..d0795c13d14 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -59,6 +59,7 @@ enum uclass_id {
        UCLASS_ECDSA,           /* Elliptic curve cryptographic device */
        UCLASS_EFI_LOADER,      /* Devices created by UEFI applications */
        UCLASS_EFI_MEDIA,       /* Devices provided by UEFI firmware */
+       UCLASS_EFI_BOOT_MGR,    /* EFI boot manager */
        UCLASS_ETH,             /* Ethernet device */
        UCLASS_ETH_PHY,         /* Ethernet PHY device */
        UCLASS_EXTCON,          /* External Connector Class */
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index ab50a69e48b..c37f05d70e4 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -25,6 +25,7 @@ apps-$(CONFIG_BOOTEFI_TESTAPP_COMPILE) += testapp
 obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
 obj-$(CONFIG_EFI_BOOTMGR) += efi_bootmgr.o
 obj-$(CONFIG_EFI_BINARY_EXEC) += efi_bootbin.o
+obj-$(CONFIG_BOOTMETH_EFI_BOOTMGR) += efi_bootdev.o
 obj-y += efi_boottime.o
 obj-y += efi_helper.o
 obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
diff --git a/lib/efi_loader/efi_bootdev.c b/lib/efi_loader/efi_bootdev.c
new file mode 100644
index 00000000000..066df9462c8
--- /dev/null
+++ b/lib/efi_loader/efi_bootdev.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Bootdev for boot manager
+ *
+ * Copyright 2025, Heinrich Schuchardt <xypron.g...@gmx.de>
+ */
+
+#define LOG_CATEGORY UCLASS_BOOTSTD
+
+#include <bootdev.h>
+#include <bootflow.h>
+#include <dm.h>
+#include <dm/lists.h>
+
+static int efi_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
+                           struct bootflow *bflow)
+{
+       int ret;
+
+       ret = strcmp(iter->method->name, "efi_mgr");
+       if (!ret)
+               bflow->state = BOOTFLOWST_READY;
+
+       return ret;
+}
+
+struct bootdev_ops efi_bootdev_ops = {
+       .get_bootflow   = efi_get_bootflow,
+};
+
+static int efi_bootdev_bind(struct udevice *dev)
+{
+       struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+       ucp->prio = BOOTDEVP_6_EFI;
+
+       return 0;
+}
+
+static const struct udevice_id efi_bootdev_ids[] = {
+       { .compatible = "u-boot,bootdev-efi" },
+       { }
+};
+
+U_BOOT_DRIVER(efi_bootdev) = {
+       .name           = "efi_bootdev",
+       .id             = UCLASS_BOOTDEV,
+       .ops            = &efi_bootdev_ops,
+       .bind           = efi_bootdev_bind,
+       .of_match       = efi_bootdev_ids,
+};
+
+/**
+ * efi_bootdev_hunt() - find devices used by EFI boot manager
+ *
+ * Invoke all hunters that have not been invoked by now.
+ * This should only be the network hunter.
+ *
+ * @info:      info structure describing this hunter
+ * @show:      true to show information from the hunter
+ *
+ * Return:     0 if device found, -EINVAL otherwise
+ */
+static int efi_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+       return bootdev_hunt(NULL, 0);
+}
+
+BOOTDEV_HUNTER(efi_bootdev_hunt) = {
+       .prio           = BOOTDEVP_6_EFI,
+       .uclass         = UCLASS_EFI_BOOT_MGR,
+       .hunt           = efi_bootdev_hunt,
+       .drv            = DM_DRIVER_REF(efi_bootdev),
+};
+
+static int efi_bootdev_create(void)
+{
+       int ret;
+       struct udevice *dev_mgr;
+       struct udevice *dev;
+
+       ret = device_bind_driver(gd->dm_root, "efimgr",
+                                "efimgr", &dev_mgr);
+       if (ret)
+               return ret;
+
+       ret = device_bind_driver(dev_mgr, "efi_bootdev",
+                                "efimgr.bootdev", &dev);
+       return ret;
+}
+
+EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_R, efi_bootdev_create);
+
+U_BOOT_DRIVER(efimgr) = {
+       .name           = "efimgr",
+       .id             = UCLASS_EFI_BOOT_MGR,
+};
+
+UCLASS_DRIVER(efimgr) = {
+       .id             = UCLASS_EFI_BOOT_MGR,
+       .name           = "efimgr",
+};
-- 
2.48.1

Reply via email to