[U-Boot] [PATCH v1 15/15] efi_loader: add bootmgr

Alexander Graf agraf at suse.de
Sat Aug 12 13:10:44 UTC 2017



On 10.08.17 20:29, Rob Clark wrote:
> Similar to a "real" UEFI implementation, the bootmgr looks at the
> BootOrder and BootXXXX variables to try to find an EFI payload to load
> and boot.  This is added as a sub-command of bootefi.
> 
> The idea is that the distro bootcmd would first try loading a payload
> via the bootmgr, and then if that fails (ie. first boot or corrupted
> EFI variables) it would fallback to loading bootaa64.efi.  (Which
> would then load fallback.efi which would look for \EFI\*\boot.csv and
> populate BootOrder and BootXXXX based on what it found.)
> 
> Signed-off-by: Rob Clark <robdclark at gmail.com>
> ---
>   cmd/bootefi.c                     |  48 ++++++++++-
>   include/config_distro_bootcmd.h   |   5 ++
>   include/efi_api.h                 |   4 +
>   include/efi_loader.h              |   6 ++
>   lib/efi_loader/Makefile           |   2 +-
>   lib/efi_loader/efi_bootmgr.c      | 169 ++++++++++++++++++++++++++++++++++++++
>   lib/efi_loader/efi_boottime.c     |   6 +-
>   lib/efi_loader/efi_image_loader.c |   1 +
>   8 files changed, 235 insertions(+), 6 deletions(-)
>   create mode 100644 lib/efi_loader/efi_bootmgr.c
> 
> diff --git a/cmd/bootefi.c b/cmd/bootefi.c
> index 80f52e9e35..02a0dd159b 100644
> --- a/cmd/bootefi.c
> +++ b/cmd/bootefi.c
> @@ -219,6 +219,36 @@ exit:
>   	return ret;
>   }
>   
> +static int do_bootefi_bootmgr_exec(unsigned long fdt_addr)
> +{
> +	struct efi_device_path *device_path, *file_path;
> +	void *addr;
> +	efi_status_t r;
> +
> +	/* Initialize and populate EFI object list */
> +	if (!efi_obj_list_initalized)
> +		efi_init_obj_list();
> +
> +	/*
> +	 * gd lives in a fixed register which may get clobbered while we execute
> +	 * the payload. So save it here and restore it on every callback entry
> +	 */
> +	efi_save_gd();
> +
> +	addr = efi_bootmgr_load(&device_path, &file_path);
> +	if (!addr)
> +		return 1;
> +
> +	printf("## Starting EFI application at %p ...\n", addr);
> +	r = do_bootefi_exec(addr, (void*)fdt_addr, device_path, file_path);
> +	printf("## Application terminated, r = %lu\n",
> +	       r & ~EFI_ERROR_MASK);
> +
> +	if (r != EFI_SUCCESS)
> +		return 1;
> +
> +	return 0;
> +}
>   
>   /* Interpreter command to boot an arbitrary EFI image from memory */
>   static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> @@ -237,7 +267,14 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>   		memcpy((char *)addr, __efi_hello_world_begin, size);
>   	} else
>   #endif
> -	{
> +	if (!strcmp(argv[1], "bootmgr")) {
> +		unsigned long fdt_addr = 0;
> +
> +		if (argc > 2)
> +			fdt_addr = simple_strtoul(argv[2], NULL, 16);
> +
> +		return do_bootefi_bootmgr_exec(fdt_addr);
> +	} else {
>   		saddr = argv[1];
>   
>   		addr = simple_strtoul(saddr, NULL, 16);
> @@ -270,7 +307,11 @@ static char bootefi_help_text[] =
>   	"hello\n"
>   	"  - boot a sample Hello World application stored within U-Boot"
>   #endif
> -	;
> +	"bootmgr [fdt addr]\n"
> +	"  - load and boot EFI payload based on BootOrder/BootXXXX variables.\n"
> +	"\n"
> +	"    If specified, the device tree located at <fdt address> gets\n"
> +	"    exposed as EFI configuration table.\n";
>   #endif
>   
>   U_BOOT_CMD(
> @@ -308,6 +349,9 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
>   #endif
>   	}
>   
> +	if (!path)
> +		return;
> +
>   	if (strcmp(dev, "Net")) {
>   		/* Add leading / to fs paths, because they're absolute */
>   		snprintf(filename, sizeof(filename), "/%s", path);
> diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
> index d8dab8e46a..94ccab02d2 100644
> --- a/include/config_distro_bootcmd.h
> +++ b/include/config_distro_bootcmd.h
> @@ -112,6 +112,11 @@
>   
>   #define BOOTENV_SHARED_EFI                                                \
>   	"boot_efi_binary="                                                \
> +		"if fdt addr ${fdt_addr_r}; then "                        \
> +			"bootefi bootmgr ${fdt_addr_r};"                  \

This is too late. At this point you already checked that there indeed is 
a fallback binary. Since the bootmgr target actually knows which device 
it loads itself from, it can occur way before in the boot chain.

Maybe we should just add a new boot_target for bootmgr. That way it 
naturally fits into the distro boot flow. You could then add a 
BOOTENV_DEV_BOOTMGR and simply run it from there.

The only thing missing in that case is the device tree override - hmm...

Oh well, if you need that I'm fine to leave it as hacky as it is here, 
but this boot protocol is definitely not what the UEFI guys had 
envisioned ;).


Alex



More information about the U-Boot mailing list