Merge branch '2022-05-05-assorted-cleanups-and-fixes'
[platform/kernel/u-boot.git] / cmd / bootefi.c
index 94d18ca..d80353f 100644 (file)
@@ -265,8 +265,8 @@ efi_status_t efi_install_fdt(void *fdt)
         */
 #if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
        if (fdt) {
-               log_err("ERROR: can't have ACPI table and device tree.\n");
-               return EFI_LOAD_ERROR;
+               log_warning("WARNING: Can't have ACPI table and device tree - ignoring DT.\n");
+               return EFI_SUCCESS;
        }
 #else
        bootm_headers_t img = { 0 };
@@ -353,6 +353,19 @@ static efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options)
        /* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
        switch_to_non_secure_mode();
 
+       /*
+        * The UEFI standard requires that the watchdog timer is set to five
+        * minutes when invoking an EFI boot option.
+        *
+        * Unified Extensible Firmware Interface (UEFI), version 2.7 Errata A
+        * 7.5. Miscellaneous Boot Services - EFI_BOOT_SERVICES.SetWatchdogTimer
+        */
+       ret = efi_set_watchdog(300);
+       if (ret != EFI_SUCCESS) {
+               log_err("ERROR: Failed to set watchdog timer\n");
+               goto out;
+       }
+
        /* Call our payload! */
        ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data));
        if (ret != EFI_SUCCESS) {
@@ -366,11 +379,15 @@ static efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options)
 
        efi_restore_gd();
 
+out:
        free(load_options);
 
        if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD))
                efi_initrd_deregister();
 
+       /* Control is returned to U-Boot, disable EFI watchdog */
+       efi_set_watchdog(0);
+
        return ret;
 }
 
@@ -405,10 +422,11 @@ static int do_efibootmgr(void)
  * Set up memory image for the binary to be loaded, prepare device path, and
  * then call do_bootefi_exec() to execute it.
  *
- * @image_opt: string of image start address
+ * @image_opt: string with image start address
+ * @size_opt:  string with image size or NULL
  * Return:     status code
  */
-static int do_bootefi_image(const char *image_opt)
+static int do_bootefi_image(const char *image_opt, const char *size_opt)
 {
        void *image_buf;
        unsigned long addr, size;
@@ -426,14 +444,21 @@ static int do_bootefi_image(const char *image_opt)
                /* Check that a numeric value was passed */
                if (!addr)
                        return CMD_RET_USAGE;
-
                image_buf = map_sysmem(addr, 0);
 
-               if (image_buf != image_addr) {
-                       log_err("No UEFI binary known at %s\n", image_opt);
-                       return CMD_RET_FAILURE;
+               if (size_opt) {
+                       size = strtoul(size_opt, NULL, 16);
+                       if (!size)
+                               return CMD_RET_USAGE;
+                       efi_clear_bootdev();
+               } else {
+                       if (image_buf != image_addr) {
+                               log_err("No UEFI binary known at %s\n",
+                                       image_opt);
+                               return CMD_RET_FAILURE;
+                       }
+                       size = image_size;
                }
-               size = image_size;
        }
        ret = efi_run_image(image_buf, size);
 
@@ -637,7 +662,7 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc,
                return CMD_RET_FAILURE;
        }
 
-       if (argc > 2) {
+       if (argc > 2 && strcmp(argv[2], "-")) {
                uintptr_t fdt_addr;
 
                fdt_addr = hextoul(argv[2], NULL);
@@ -660,15 +685,15 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc,
                return do_efi_selftest();
 #endif
 
-       return do_bootefi_image(argv[1]);
+       return do_bootefi_image(argv[1], argc > 3 ? argv[3] : NULL);
 }
 
 #ifdef CONFIG_SYS_LONGHELP
 static char bootefi_help_text[] =
-       "<image address> [fdt address]\n"
-       "  - boot EFI payload stored at address <image address>.\n"
-       "    If specified, the device tree located at <fdt address> gets\n"
-       "    exposed as EFI configuration table.\n"
+       "<image address> [fdt address [image size]]\n"
+       "  - boot EFI payload stored at <image address>\n"
+       "    fdt address, address of device-tree or '-'\n"
+       "    image size, required if image not preloaded\n"
 #ifdef CONFIG_CMD_BOOTEFI_HELLO
        "bootefi hello\n"
        "  - boot a sample Hello World application stored within U-Boot\n"
@@ -690,7 +715,7 @@ static char bootefi_help_text[] =
 #endif
 
 U_BOOT_CMD(
-       bootefi, 3, 0, do_bootefi,
+       bootefi, 4, 0, do_bootefi,
        "Boots an EFI payload from memory",
        bootefi_help_text
 );