summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2017-09-13 18:05:38 -0400
committerAlexander Graf <agraf@suse.de>2017-09-20 11:08:01 +0200
commit9975fe96b697b6d64bde3f77cd08612fec812b47 (patch)
treee246223b20ba06aeddbe83b7a159f1b6285a40f6 /cmd
parentad644e7c18238026fecc647f62584d87d2c5b0a3 (diff)
efi_loader: add bootmgr
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@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'cmd')
-rw-r--r--cmd/bootefi.c49
1 files changed, 47 insertions, 2 deletions
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 9f844737e5..1e2dbcc4a4 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -219,6 +219,37 @@ 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[])
{
@@ -256,7 +287,14 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return efi_selftest(&loaded_image_info, &systab);
} 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);
@@ -293,7 +331,11 @@ static char bootefi_help_text[] =
"bootefi selftest\n"
" - boot an EFI selftest application stored within U-Boot\n"
#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(
@@ -331,6 +373,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);