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 <sjg@chromium.org>
This commit is contained in:
Simon Glass 2022-07-30 15:52:21 -06:00 committed by Tom Rini
parent a18686cda1
commit bc06aa035d
6 changed files with 50 additions and 2 deletions

View File

@ -349,6 +349,13 @@ config BOOTSTD_BOOTCOMMAND
standard boot does not support all of the features of distro boot standard boot does not support all of the features of distro boot
yet. 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 config BOOTMETH_DISTRO
bool "Bootdev support for distro boot" bool "Bootdev support for distro boot"
select PXE_UTILS select PXE_UTILS

View File

@ -71,6 +71,20 @@ int bootmeth_read_file(struct udevice *dev, struct bootflow *bflow,
return ops->read_file(dev, bflow, file_path, addr, sizep); 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 * bootmeth_setup_iter_order() - Set up the ordering of bootmeths to scan
* *

View File

@ -61,6 +61,7 @@ static int bootmeth_efi_mgr_bind(struct udevice *dev)
struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
plat->desc = "EFI bootmgr flow"; plat->desc = "EFI bootmgr flow";
plat->flags = BOOTMETHF_GLOBAL;
return 0; 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", .name = "bootmeth_efi_mgr",
.id = UCLASS_BOOTMETH, .id = UCLASS_BOOTMETH,
.of_match = efi_mgr_bootmeth_ids, .of_match = efi_mgr_bootmeth_ids,

View File

@ -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", "-"); printf("%5s", "-");
else else
printf("%5x", order); printf("%5x", order);

View File

@ -12,13 +12,24 @@ struct bootflow;
struct bootflow_iter; struct bootflow_iter;
struct udevice; 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 * struct bootmeth_uc_plat - information the uclass keeps about each bootmeth
* *
* @desc: A long description of the bootmeth * @desc: A long description of the bootmeth
* @flags: Flags for this bootmeth (enum bootmeth_flags)
*/ */
struct bootmeth_uc_plat { struct bootmeth_uc_plat {
const char *desc; const char *desc;
int flags;
}; };
/** struct bootmeth_ops - Operations for boot methods */ /** 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, int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow,
const char *file_path, ulong addr, ulong *sizep); 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 #endif

View File

@ -37,6 +37,7 @@ if EFI_LOADER
config CMD_BOOTEFI_BOOTMGR config CMD_BOOTEFI_BOOTMGR
bool "UEFI Boot Manager" bool "UEFI Boot Manager"
default y default y
select BOOTMETH_GLOBAL if BOOTSTD
help help
Select this option if you want to select the UEFI binary to be booted Select this option if you want to select the UEFI binary to be booted
via UEFI variables Boot####, BootOrder, and BootNext. This enables the via UEFI variables Boot####, BootOrder, and BootNext. This enables the