[U-Boot] [PATCH v4 0/1] efi_loader: support BootNext and BootCurrent

This patch was originally posted as a single one, but then was merged in my "run -e." Now I would like to post it on its own.
With this patch, EFI Boot Manager will handles BootNext and BootCurrent variable as UEFI specification describes.
Changes in v4 (Mar 20, 2019) * strictly check the size of BootNext
Changes in v3 (Mar 8, 2019) * add error messages around BootNext * delete BootNext anyway when processing BootOrder
Changes in v2 (Mar 5, 2019) * extract this patch from my "run -e" patch set * use efi_[get|set]_variable instead of 'rs->*' * add EFI_CALL * cosmetic changes
AKASHI Takahiro (1): efi_loader: bootmgr: support BootNext and BootCurrent variable behavior
lib/efi_loader/efi_bootmgr.c | 51 +++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-)

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 --- lib/efi_loader/efi_bootmgr.c | 51 +++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-)
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 417016102b48..4fccadc5483d 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -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");

On 3/20/19 1:07 AM, AKASHI Takahiro wrote:
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

On 3/20/19 8:01 AM, Heinrich Schuchardt wrote:
On 3/20/19 1:07 AM, AKASHI Takahiro wrote:
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
Added to efi-2019-07 branch.

On 3/20/19 1:07 AM, AKASHI Takahiro wrote:
This patch was originally posted as a single one, but then was merged in my "run -e." Now I would like to post it on its own.
With this patch, EFI Boot Manager will handles BootNext and BootCurrent variable as UEFI specification describes.
Changes in v4 (Mar 20, 2019)
- strictly check the size of BootNext
Changes in v3 (Mar 8, 2019)
- add error messages around BootNext
- delete BootNext anyway when processing BootOrder
Changes in v2 (Mar 5, 2019)
- extract this patch from my "run -e" patch set
- use efi_[get|set]_variable instead of 'rs->*'
- add EFI_CALL
- cosmetic changes
AKASHI Takahiro (1): efi_loader: bootmgr: support BootNext and BootCurrent variable behavior
lib/efi_loader/efi_bootmgr.c | 51 +++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-)
Thanks a lot for the patch. It is rather late in the release cycle. So expect this in v2019.07.
In the long run we will have to devise a way for automated testing of the boot manager. It think this will have to comprise generating a disk image with an EFI partition with multiple EFI binaries.
Best regards
Heinrich
participants (2)
-
AKASHI Takahiro
-
Heinrich Schuchardt