efi: libstub: remove DT dependency from generic stub
authorArd Biesheuvel <ardb@kernel.org>
Fri, 16 Sep 2022 16:51:36 +0000 (18:51 +0200)
committerArd Biesheuvel <ardb@kernel.org>
Tue, 27 Sep 2022 11:22:47 +0000 (13:22 +0200)
Refactor the generic EFI stub entry code so that all the dependencies on
device tree are abstracted and hidden behind a generic efi_boot_kernel()
routine that can also be implemented in other ways. This allows users of
the generic stub to avoid using FDT for passing information to the core
kernel.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
drivers/firmware/efi/libstub/efi-stub.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/fdt.c

index 72826bc..80a1c72 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/efi.h>
-#include <linux/libfdt.h>
 #include <asm/efi.h>
 
 #include "efistub.h"
@@ -132,14 +131,11 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
        unsigned long image_addr;
        unsigned long image_size = 0;
        /* addr/point and size pairs for memory management*/
-       unsigned long fdt_addr = 0;  /* Original DTB */
-       unsigned long fdt_size = 0;
        char *cmdline_ptr = NULL;
        int cmdline_size = 0;
        efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
        unsigned long reserve_addr = 0;
        unsigned long reserve_size = 0;
-       enum efi_secureboot_mode secure_boot;
        struct screen_info *si;
        efi_properties_table_t *prop_tbl;
 
@@ -215,38 +211,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
        /* Ask the firmware to clear memory on unclean shutdown */
        efi_enable_reset_attack_mitigation();
 
-       secure_boot = efi_get_secureboot();
-
-       /*
-        * Unauthenticated device tree data is a security hazard, so ignore
-        * 'dtb=' unless UEFI Secure Boot is disabled.  We assume that secure
-        * boot is enabled if we can't determine its state.
-        */
-       if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) ||
-            secure_boot != efi_secureboot_mode_disabled) {
-               if (strstr(cmdline_ptr, "dtb="))
-                       efi_err("Ignoring DTB from command line.\n");
-       } else {
-               status = efi_load_dtb(image, &fdt_addr, &fdt_size);
-
-               if (status != EFI_SUCCESS && status != EFI_NOT_READY) {
-                       efi_err("Failed to load device tree!\n");
-                       goto fail_free_image;
-               }
-       }
-
-       if (fdt_addr) {
-               efi_info("Using DTB from command line\n");
-       } else {
-               /* Look for a device tree configuration table entry. */
-               fdt_addr = (uintptr_t)get_fdt(&fdt_size);
-               if (fdt_addr)
-                       efi_info("Using DTB from configuration table\n");
-       }
-
-       if (!fdt_addr)
-               efi_info("Generating empty DTB\n");
-
        efi_load_initrd(image, ULONG_MAX, efi_get_max_initrd_addr(image_addr),
                        NULL);
 
@@ -290,23 +254,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
 
        install_memreserve_table();
 
-       status = allocate_new_fdt_and_exit_boot(handle, &fdt_addr, cmdline_ptr,
-                                               fdt_addr, fdt_size);
-       if (status != EFI_SUCCESS)
-               goto fail_free_fdt;
-
-       if (IS_ENABLED(CONFIG_ARM))
-               efi_handle_post_ebs_state();
-
-       efi_enter_kernel(image_addr, fdt_addr, fdt_totalsize((void *)fdt_addr));
-       /* not reached */
-
-fail_free_fdt:
-       efi_err("Failed to update FDT and exit boot services\n");
-
-       efi_free(fdt_size, fdt_addr);
+       status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);
 
-fail_free_image:
        efi_free(image_size, image_addr);
        efi_free(reserve_size, reserve_addr);
 fail_free_screeninfo:
index 38ec809..f06d753 100644 (file)
@@ -844,11 +844,8 @@ typedef efi_status_t (*efi_exit_boot_map_processing)(
 efi_status_t efi_exit_boot_services(void *handle, void *priv,
                                    efi_exit_boot_map_processing priv_func);
 
-efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
-                                           unsigned long *new_fdt_addr,
-                                           char *cmdline_ptr,
-                                           unsigned long fdt_addr,
-                                           unsigned long fdt_size);
+efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
+                            unsigned long kernel_addr, char *cmdline_ptr);
 
 void *get_fdt(unsigned long *fdt_size);
 
index afed0aa..4f4d98e 100644 (file)
@@ -219,17 +219,18 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
  * exit_boot_services() call, so the exiting of boot services is very tightly
  * tied to the creation of the FDT with the final memory map in it.
  */
-
+static
 efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
+                                           efi_loaded_image_t *image,
                                            unsigned long *new_fdt_addr,
-                                           char *cmdline_ptr,
-                                           unsigned long fdt_addr,
-                                           unsigned long fdt_size)
+                                           char *cmdline_ptr)
 {
        unsigned long desc_size;
        u32 desc_ver;
        efi_status_t status;
        struct exit_boot_struct priv;
+       unsigned long fdt_addr = 0;
+       unsigned long fdt_size = 0;
 
        if (!efi_novamap) {
                status = efi_alloc_virtmap(&priv.runtime_map, &desc_size,
@@ -240,6 +241,36 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
                }
        }
 
+       /*
+        * Unauthenticated device tree data is a security hazard, so ignore
+        * 'dtb=' unless UEFI Secure Boot is disabled.  We assume that secure
+        * boot is enabled if we can't determine its state.
+        */
+       if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) ||
+           efi_get_secureboot() != efi_secureboot_mode_disabled) {
+               if (strstr(cmdline_ptr, "dtb="))
+                       efi_err("Ignoring DTB from command line.\n");
+       } else {
+               status = efi_load_dtb(image, &fdt_addr, &fdt_size);
+
+               if (status != EFI_SUCCESS && status != EFI_NOT_READY) {
+                       efi_err("Failed to load device tree!\n");
+                       goto fail;
+               }
+       }
+
+       if (fdt_addr) {
+               efi_info("Using DTB from command line\n");
+       } else {
+               /* Look for a device tree configuration table entry. */
+               fdt_addr = (uintptr_t)get_fdt(&fdt_size);
+               if (fdt_addr)
+                       efi_info("Using DTB from configuration table\n");
+       }
+
+       if (!fdt_addr)
+               efi_info("Generating empty DTB\n");
+
        efi_info("Exiting boot services...\n");
 
        status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, ULONG_MAX);
@@ -303,11 +334,33 @@ fail_free_new_fdt:
        efi_free(MAX_FDT_SIZE, *new_fdt_addr);
 
 fail:
+       efi_free(fdt_size, fdt_addr);
+
        efi_bs_call(free_pool, priv.runtime_map);
 
        return EFI_LOAD_ERROR;
 }
 
+efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
+                            unsigned long kernel_addr, char *cmdline_ptr)
+{
+       unsigned long fdt_addr;
+       efi_status_t status;
+
+       status = allocate_new_fdt_and_exit_boot(handle, image, &fdt_addr,
+                                               cmdline_ptr);
+       if (status != EFI_SUCCESS) {
+               efi_err("Failed to update FDT and exit boot services\n");
+               return status;
+       }
+
+       if (IS_ENABLED(CONFIG_ARM))
+               efi_handle_post_ebs_state();
+
+       efi_enter_kernel(kernel_addr, fdt_addr, fdt_totalsize((void *)fdt_addr));
+       /* not reached */
+}
+
 void *get_fdt(unsigned long *fdt_size)
 {
        void *fdt;