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