mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-29 18:41:30 +00:00
efi_loader: bootmgr: support BootNext and BootCurrent variable behavior
See UEFI v2.7, section 3.1.2 for details of the specification. With efidebug command, you can run any EFI boot option as follows: => efi boot add 1 SHELL ... => efi boot add 2 HELLO ... => efi boot order 1 2 => efi bootmgr (starting SHELL ...) => efi boot next 2 => efi bootmgr (starting HELLO ...) => env print -e <snip ...> BootCurrent: {boot,run}(blob) 00000000: 02 00 .. BootOrder: {boot,run}(blob) 00000000: 01 00 02 00 .... Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
parent
b0c3c346c6
commit
37279ad3ee
1 changed files with 47 additions and 4 deletions
|
@ -141,6 +141,7 @@ static void *try_load_entry(uint16_t n, struct efi_device_path **device_path,
|
|||
efi_deserialize_load_option(&lo, load_option);
|
||||
|
||||
if (lo.attributes & LOAD_OPTION_ACTIVE) {
|
||||
u32 attributes;
|
||||
efi_status_t ret;
|
||||
|
||||
debug("%s: trying to load \"%ls\" from %pD\n",
|
||||
|
@ -151,6 +152,16 @@ static void *try_load_entry(uint16_t n, struct efi_device_path **device_path,
|
|||
if (ret != EFI_SUCCESS)
|
||||
goto error;
|
||||
|
||||
attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS;
|
||||
size = sizeof(n);
|
||||
ret = EFI_CALL(efi_set_variable(
|
||||
L"BootCurrent",
|
||||
(efi_guid_t *)&efi_global_variable_guid,
|
||||
attributes, size, &n));
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto error;
|
||||
|
||||
printf("Booting: %ls\n", lo.label);
|
||||
efi_dp_split_file_path(lo.file_path, device_path, file_path);
|
||||
}
|
||||
|
@ -162,21 +173,53 @@ error:
|
|||
}
|
||||
|
||||
/*
|
||||
* Attempt to load, in the order specified by BootOrder EFI variable, the
|
||||
* available load-options, finding and returning the first one that can
|
||||
* be loaded successfully.
|
||||
* Attempt to load from BootNext or in the order specified by BootOrder
|
||||
* EFI variable, the available load-options, finding and returning
|
||||
* the first one that can be loaded successfully.
|
||||
*/
|
||||
void *efi_bootmgr_load(struct efi_device_path **device_path,
|
||||
struct efi_device_path **file_path)
|
||||
{
|
||||
uint16_t *bootorder;
|
||||
u16 bootnext, *bootorder;
|
||||
efi_uintn_t size;
|
||||
void *image = NULL;
|
||||
int i, num;
|
||||
efi_status_t ret;
|
||||
|
||||
bs = systab.boottime;
|
||||
rs = systab.runtime;
|
||||
|
||||
/* BootNext */
|
||||
bootnext = 0;
|
||||
size = sizeof(bootnext);
|
||||
ret = EFI_CALL(efi_get_variable(L"BootNext",
|
||||
(efi_guid_t *)&efi_global_variable_guid,
|
||||
NULL, &size, &bootnext));
|
||||
if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) {
|
||||
/* BootNext does exist here */
|
||||
if (ret == EFI_BUFFER_TOO_SMALL || size != sizeof(u16))
|
||||
printf("BootNext must be 16-bit integer\n");
|
||||
|
||||
/* delete BootNext */
|
||||
ret = EFI_CALL(efi_set_variable(
|
||||
L"BootNext",
|
||||
(efi_guid_t *)&efi_global_variable_guid,
|
||||
0, 0, &bootnext));
|
||||
|
||||
/* load BootNext */
|
||||
if (ret == EFI_SUCCESS) {
|
||||
if (size == sizeof(u16)) {
|
||||
image = try_load_entry(bootnext, device_path,
|
||||
file_path);
|
||||
if (image)
|
||||
return image;
|
||||
}
|
||||
} else {
|
||||
printf("Deleting BootNext failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* BootOrder */
|
||||
bootorder = get_var(L"BootOrder", &efi_global_variable_guid, &size);
|
||||
if (!bootorder) {
|
||||
printf("BootOrder not defined\n");
|
||||
|
|
Loading…
Add table
Reference in a new issue