efi: libstub: Factor out EFI stub entrypoint into separate file
authorArd Biesheuvel <ardb@kernel.org>
Wed, 12 Oct 2022 10:55:11 +0000 (12:55 +0200)
committerArd Biesheuvel <ardb@kernel.org>
Wed, 9 Nov 2022 11:42:03 +0000 (12:42 +0100)
In preparation for allowing the EFI zboot decompressor to reuse most of
the EFI stub machinery, factor out the actual EFI PE/COFF entrypoint
into a separate file.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
drivers/firmware/efi/libstub/Makefile
drivers/firmware/efi/libstub/efi-stub-entry.c [new file with mode: 0644]
drivers/firmware/efi/libstub/efi-stub.c
drivers/firmware/efi/libstub/efistub.h

index 4964d31..ea96405 100644 (file)
@@ -83,7 +83,7 @@ $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
        $(call if_changed_rule,cc_o_c)
 
 lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \
-                                  screen_info.o
+                                  screen_info.o efi-stub-entry.o
 
 lib-$(CONFIG_ARM)              += arm32-stub.o
 lib-$(CONFIG_ARM64)            += arm64-stub.o arm64-entry.o
diff --git a/drivers/firmware/efi/libstub/efi-stub-entry.c b/drivers/firmware/efi/libstub/efi-stub-entry.c
new file mode 100644 (file)
index 0000000..5245c4f
--- /dev/null
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/efi.h>
+#include <asm/efi.h>
+
+#include "efistub.h"
+
+/*
+ * EFI entry point for the generic EFI stub used by ARM, arm64, RISC-V and
+ * LoongArch. This is the entrypoint that is described in the PE/COFF header
+ * of the core kernel.
+ */
+efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+                                  efi_system_table_t *systab)
+{
+       efi_loaded_image_t *image;
+       efi_status_t status;
+       unsigned long image_addr;
+       unsigned long image_size = 0;
+       /* addr/point and size pairs for memory management*/
+       char *cmdline_ptr = NULL;
+       efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
+       unsigned long reserve_addr = 0;
+       unsigned long reserve_size = 0;
+
+       WRITE_ONCE(efi_system_table, systab);
+
+       /* Check if we were booted by the EFI firmware */
+       if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
+               return EFI_INVALID_PARAMETER;
+
+       /*
+        * Get a handle to the loaded image protocol.  This is used to get
+        * information about the running image, such as size and the command
+        * line.
+        */
+       status = efi_bs_call(handle_protocol, handle, &loaded_image_proto,
+                            (void *)&image);
+       if (status != EFI_SUCCESS) {
+               efi_err("Failed to get loaded image protocol\n");
+               return status;
+       }
+
+       status = efi_handle_cmdline(image, &cmdline_ptr);
+       if (status != EFI_SUCCESS)
+               return status;
+
+       efi_info("Booting Linux Kernel...\n");
+
+       status = handle_kernel_image(&image_addr, &image_size,
+                                    &reserve_addr,
+                                    &reserve_size,
+                                    image, handle);
+       if (status != EFI_SUCCESS) {
+               efi_err("Failed to relocate kernel\n");
+               return status;
+       }
+
+       status = efi_stub_common(handle, image, image_addr, cmdline_ptr);
+
+       efi_free(image_size, image_addr);
+       efi_free(reserve_size, reserve_addr);
+
+       return status;
+}
index 8521dc0..2955c1a 100644 (file)
@@ -115,61 +115,21 @@ static u32 get_supported_rt_services(void)
        return supported;
 }
 
-/*
- * EFI entry point for the arm/arm64 EFI stubs.  This is the entrypoint
- * that is described in the PE/COFF header.  Most of the code is the same
- * for both archictectures, with the arch-specific code provided in the
- * handle_kernel_image() function.
- */
-efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
-                                  efi_system_table_t *sys_table_arg)
+efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
 {
-       efi_loaded_image_t *image;
-       efi_status_t status;
-       unsigned long image_addr;
-       unsigned long image_size = 0;
-       /* addr/point and size pairs for memory management*/
-       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;
-       struct screen_info *si;
-
-       efi_system_table = sys_table_arg;
-
-       /* Check if we were booted by the EFI firmware */
-       if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
-               status = EFI_INVALID_PARAMETER;
-               goto fail;
-       }
-
-       status = check_platform_features();
-       if (status != EFI_SUCCESS)
-               goto fail;
-
-       /*
-        * Get a handle to the loaded image protocol.  This is used to get
-        * information about the running image, such as size and the command
-        * line.
-        */
-       status = efi_bs_call(handle_protocol, handle, &loaded_image_proto,
-                            (void *)&image);
-       if (status != EFI_SUCCESS) {
-               efi_err("Failed to get loaded image protocol\n");
-               goto fail;
-       }
+       efi_status_t status;
+       char *cmdline;
 
        /*
         * Get the command line from EFI, using the LOADED_IMAGE
         * protocol. We are going to copy the command line into the
         * device tree, so this can be allocated anywhere.
         */
-       cmdline_ptr = efi_convert_cmdline(image, &cmdline_size);
-       if (!cmdline_ptr) {
+       cmdline = efi_convert_cmdline(image, &cmdline_size);
+       if (!cmdline) {
                efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
-               status = EFI_OUT_OF_RESOURCES;
-               goto fail;
+               return EFI_OUT_OF_RESOURCES;
        }
 
        if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
@@ -183,25 +143,34 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
        }
 
        if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
-               status = efi_parse_options(cmdline_ptr);
+               status = efi_parse_options(cmdline);
                if (status != EFI_SUCCESS) {
                        efi_err("Failed to parse options\n");
                        goto fail_free_cmdline;
                }
        }
 
-       efi_info("Booting Linux Kernel...\n");
+       *cmdline_ptr = cmdline;
+       return EFI_SUCCESS;
 
-       si = setup_graphics();
+fail_free_cmdline:
+       efi_bs_call(free_pool, cmdline_ptr);
+       return status;
+}
 
-       status = handle_kernel_image(&image_addr, &image_size,
-                                    &reserve_addr,
-                                    &reserve_size,
-                                    image, handle);
-       if (status != EFI_SUCCESS) {
-               efi_err("Failed to relocate kernel\n");
-               goto fail_free_screeninfo;
-       }
+efi_status_t efi_stub_common(efi_handle_t handle,
+                            efi_loaded_image_t *image,
+                            unsigned long image_addr,
+                            char *cmdline_ptr)
+{
+       struct screen_info *si;
+       efi_status_t status;
+
+       status = check_platform_features();
+       if (status != EFI_SUCCESS)
+               return status;
+
+       si = setup_graphics();
 
        efi_retrieve_tpm2_eventlog();
 
@@ -221,13 +190,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
 
        status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);
 
-       efi_free(image_size, image_addr);
-       efi_free(reserve_size, reserve_addr);
-fail_free_screeninfo:
        free_screen_info(si);
-fail_free_cmdline:
-       efi_bs_call(free_pool, cmdline_ptr);
-fail:
        return status;
 }
 
index a4cb51e..fd6953e 100644 (file)
@@ -958,6 +958,14 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
                                 efi_loaded_image_t *image,
                                 efi_handle_t image_handle);
 
+/* shared entrypoint between the normal stub and the zboot stub */
+efi_status_t efi_stub_common(efi_handle_t handle,
+                            efi_loaded_image_t *image,
+                            unsigned long image_addr,
+                            char *cmdline_ptr);
+
+efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr);
+
 asmlinkage void __noreturn efi_enter_kernel(unsigned long entrypoint,
                                            unsigned long fdt_addr,
                                            unsigned long fdt_size);