On 23.04.25 14:28, Simon Glass wrote:
Hi Heinrich,

On Mon, 21 Apr 2025 at 10:26, Heinrich Schuchardt
<heinrich.schucha...@canonical.com> wrote:

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);

This recursive calling of hunting is very strange. Since bootmgr seems
to need all the hunting to be done, you could move this line to
somewhere in bootmgr.

Thank you Simon for reviewing.

I added patch 5/8 to avoid infinite recursion.

Maybe we should move this to efi_init_obj_list() because in the eficonfig and and efidebug command we also assume that all boot devices have been hunted down. If a device has not been probed you cannot create a boot option for it.


+}
+
+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


I am not seeing any tests in this series. At least we should update
the bootflow_efi() test or add something similar.

I have not looked into the tests because I first wanted to have feedback if the general direction is ok.

Unfortunately most bootstd tests are checking console output line by line instead of functional tests which makes them fail now.

The bootstd tests should better have been written in a way that would allow running them on real boards without making assumptions about the board.

Best regards

Heinrich

Reply via email to