From bc06aa035d8f78a713a3d339d45f3d05ef0f0d67 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 30 Jul 2022 15:52:21 -0600 Subject: [PATCH] bootstd: Allow bootmeths to be marked as global The current way of handling things like EFI bootmgr is a bit odd, since that bootmeth handles selection of the bootdev itself. VBE needs to work the same way, so we should support it properly. Add a flag that indicates that the bootmeth is global, rather than being invoked on each bootdev. Provide a helper to read a bootflow from the bootmeth. Signed-off-by: Simon Glass --- boot/Kconfig | 7 +++++++ boot/bootmeth-uclass.c | 14 ++++++++++++++ boot/bootmeth_efi_mgr.c | 3 ++- cmd/bootmeth.c | 4 +++- include/bootmeth.h | 23 +++++++++++++++++++++++ lib/efi_loader/Kconfig | 1 + 6 files changed, 50 insertions(+), 2 deletions(-) diff --git a/boot/Kconfig b/boot/Kconfig index a294ad769e..b8db8cd796 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -349,6 +349,13 @@ config BOOTSTD_BOOTCOMMAND standard boot does not support all of the features of distro boot yet. +config BOOTMETH_GLOBAL + bool + help + Add support for global bootmeths. This feature is used by VBE and + EFI bootmgr, since they take full control over which bootdevs are + selected to boot. + config BOOTMETH_DISTRO bool "Bootdev support for distro boot" select PXE_UTILS diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c index 1e276c0f26..88bbb32c47 100644 --- a/boot/bootmeth-uclass.c +++ b/boot/bootmeth-uclass.c @@ -71,6 +71,20 @@ int bootmeth_read_file(struct udevice *dev, struct bootflow *bflow, return ops->read_file(dev, bflow, file_path, addr, sizep); } +int bootmeth_get_bootflow(struct udevice *dev, struct bootflow *bflow) +{ + const struct bootmeth_ops *ops = bootmeth_get_ops(dev); + + if (!ops->read_bootflow) + return -ENOSYS; + memset(bflow, '\0', sizeof(*bflow)); + bflow->dev = NULL; + bflow->method = dev; + bflow->state = BOOTFLOWST_BASE; + + return ops->read_bootflow(dev, bflow); +} + /** * bootmeth_setup_iter_order() - Set up the ordering of bootmeths to scan * diff --git a/boot/bootmeth_efi_mgr.c b/boot/bootmeth_efi_mgr.c index a6914466db..08d9328af4 100644 --- a/boot/bootmeth_efi_mgr.c +++ b/boot/bootmeth_efi_mgr.c @@ -61,6 +61,7 @@ static int bootmeth_efi_mgr_bind(struct udevice *dev) struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); plat->desc = "EFI bootmgr flow"; + plat->flags = BOOTMETHF_GLOBAL; return 0; } @@ -77,7 +78,7 @@ static const struct udevice_id efi_mgr_bootmeth_ids[] = { { } }; -U_BOOT_DRIVER(bootmeth_zefi_mgr) = { +U_BOOT_DRIVER(bootmeth_efi_mgr) = { .name = "bootmeth_efi_mgr", .id = UCLASS_BOOTMETH, .of_match = efi_mgr_bootmeth_ids, diff --git a/cmd/bootmeth.c b/cmd/bootmeth.c index c9a27fe8ac..9fbcccdba7 100644 --- a/cmd/bootmeth.c +++ b/cmd/bootmeth.c @@ -69,7 +69,9 @@ static int do_bootmeth_list(struct cmd_tbl *cmdtp, int flag, int argc, } } - if (order == -1) + if (ucp->flags & BOOTMETHF_GLOBAL) + printf("%5s", "glob"); + else if (order == -1) printf("%5s", "-"); else printf("%5x", order); diff --git a/include/bootmeth.h b/include/bootmeth.h index 4967031a0a..c93367b099 100644 --- a/include/bootmeth.h +++ b/include/bootmeth.h @@ -12,13 +12,24 @@ struct bootflow; struct bootflow_iter; struct udevice; +/** + * enum bootmeth_flags - Flags for bootmeths + * + * @BOOTMETHF_GLOBAL: bootmeth handles bootdev selection automatically + */ +enum bootmeth_flags { + BOOTMETHF_GLOBAL = BIT(0), +}; + /** * struct bootmeth_uc_plat - information the uclass keeps about each bootmeth * * @desc: A long description of the bootmeth + * @flags: Flags for this bootmeth (enum bootmeth_flags) */ struct bootmeth_uc_plat { const char *desc; + int flags; }; /** struct bootmeth_ops - Operations for boot methods */ @@ -267,4 +278,16 @@ int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align); int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow, const char *file_path, ulong addr, ulong *sizep); +/** + * bootmeth_get_bootflow() - Get a bootflow from a global bootmeth + * + * Check the bootmeth for a bootflow which can be used. In this case the + * bootmeth handles all bootdev selection, etc. + * + * @dev: bootmeth device to read from + * @bflow: Bootflow information + * @return 0 on success, -ve if a bootflow could not be found or had an error + */ +int bootmeth_get_bootflow(struct udevice *dev, struct bootflow *bflow); + #endif diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index e3f2402d0e..5cfff8c56b 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -37,6 +37,7 @@ if EFI_LOADER config CMD_BOOTEFI_BOOTMGR bool "UEFI Boot Manager" default y + select BOOTMETH_GLOBAL if BOOTSTD help Select this option if you want to select the UEFI binary to be booted via UEFI variables Boot####, BootOrder, and BootNext. This enables the