x86/efistub: Simplify and clean up handover entry code
authorArd Biesheuvel <ardb@kernel.org>
Mon, 7 Aug 2023 16:27:01 +0000 (18:27 +0200)
committerBorislav Petkov (AMD) <bp@alien8.de>
Mon, 7 Aug 2023 18:37:09 +0000 (20:37 +0200)
Now that the EFI entry code in assembler is only used by the optional
and deprecated EFI handover protocol, and given that the EFI stub C code
no longer returns to it, most of it can simply be dropped.

While at it, clarify the symbol naming, by merging efi_main() and
efi_stub_entry(), making the latter the shared entry point for all
different boot modes that enter via the EFI stub.

The efi32_stub_entry() and efi64_stub_entry() names are referenced
explicitly by the tooling that populates the setup header, so these must
be retained, but can be emitted as aliases of efi_stub_entry() where
appropriate.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20230807162720.545787-5-ardb@kernel.org
Documentation/arch/x86/boot.rst
arch/x86/boot/compressed/efi_mixed.S
arch/x86/boot/compressed/head_32.S
arch/x86/boot/compressed/head_64.S
drivers/firmware/efi/libstub/x86-stub.c

index 33520ec..cdbca15 100644 (file)
@@ -1417,7 +1417,7 @@ execution context provided by the EFI firmware.
 
 The function prototype for the handover entry point looks like this::
 
-    efi_main(void *handle, efi_system_table_t *table, struct boot_params *bp)
+    efi_stub_entry(void *handle, efi_system_table_t *table, struct boot_params *bp)
 
 'handle' is the EFI image handle passed to the boot loader by the EFI
 firmware, 'table' is the EFI system table - these are the first two
index 4ca70bf..dcc562c 100644 (file)
@@ -26,8 +26,8 @@
  * When booting in 64-bit mode on 32-bit EFI firmware, startup_64_mixed_mode()
  * is the first thing that runs after switching to long mode. Depending on
  * whether the EFI handover protocol or the compat entry point was used to
- * enter the kernel, it will either branch to the 64-bit EFI handover
- * entrypoint at offset 0x390 in the image, or to the 64-bit EFI PE/COFF
+ * enter the kernel, it will either branch to the common 64-bit EFI stub
+ * entrypoint efi_stub_entry() directly, or via the 64-bit EFI PE/COFF
  * entrypoint efi_pe_entry(). In the former case, the bootloader must provide a
  * struct bootparams pointer as the third argument, so the presence of such a
  * pointer is used to disambiguate.
  *  | efi32_pe_entry   |---->|            |            |       +-----------+--+
  *  +------------------+     |            |     +------+----------------+  |
  *                           | startup_32 |---->| startup_64_mixed_mode |  |
- *  +------------------+     |            |     +------+----------------+  V
- *  | efi32_stub_entry |---->|            |            |     +------------------+
- *  +------------------+     +------------+            +---->| efi64_stub_entry |
- *                                                           +-------------+----+
- *                           +------------+     +----------+               |
- *                           | startup_64 |<----| efi_main |<--------------+
- *                           +------------+     +----------+
+ *  +------------------+     |            |     +------+----------------+  |
+ *  | efi32_stub_entry |---->|            |            |                   |
+ *  +------------------+     +------------+            |                   |
+ *                                                     V                   |
+ *                           +------------+     +----------------+         |
+ *                           | startup_64 |<----| efi_stub_entry |<--------+
+ *                           +------------+     +----------------+
  */
 SYM_FUNC_START(startup_64_mixed_mode)
        lea     efi32_boot_args(%rip), %rdx
        mov     0(%rdx), %edi
        mov     4(%rdx), %esi
+#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
        mov     8(%rdx), %edx           // saved bootparams pointer
        test    %edx, %edx
-       jnz     efi64_stub_entry
+       jnz     efi_stub_entry
+#endif
        /*
         * efi_pe_entry uses MS calling convention, which requires 32 bytes of
         * shadow space on the stack even if all arguments are passed in
index 987ae72..8876ffe 100644 (file)
@@ -150,17 +150,6 @@ SYM_FUNC_START(startup_32)
        jmp     *%eax
 SYM_FUNC_END(startup_32)
 
-#ifdef CONFIG_EFI_STUB
-SYM_FUNC_START(efi32_stub_entry)
-       add     $0x4, %esp
-       movl    8(%esp), %esi   /* save boot_params pointer */
-       call    efi_main
-       /* efi_main returns the possibly relocated address of startup_32 */
-       jmp     *%eax
-SYM_FUNC_END(efi32_stub_entry)
-SYM_FUNC_ALIAS(efi_stub_entry, efi32_stub_entry)
-#endif
-
        .text
 SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
 
index f732426..e688020 100644 (file)
@@ -542,19 +542,11 @@ trampoline_return:
        jmp     *%rax
 SYM_CODE_END(startup_64)
 
-#ifdef CONFIG_EFI_STUB
-#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
+#if IS_ENABLED(CONFIG_EFI_MIXED) && IS_ENABLED(CONFIG_EFI_HANDOVER_PROTOCOL)
        .org 0x390
-#endif
 SYM_FUNC_START(efi64_stub_entry)
-       and     $~0xf, %rsp                     /* realign the stack */
-       movq    %rdx, %rbx                      /* save boot_params pointer */
-       call    efi_main
-       movq    %rbx,%rsi
-       leaq    rva(startup_64)(%rax), %rax
-       jmp     *%rax
+       jmp     efi_stub_entry
 SYM_FUNC_END(efi64_stub_entry)
-SYM_FUNC_ALIAS(efi_stub_entry, efi64_stub_entry)
 #endif
 
        .text
index 40a10db..3f3b3ed 100644 (file)
@@ -817,9 +817,9 @@ static void __noreturn enter_kernel(unsigned long kernel_addr,
  * return.  On failure, it will exit to the firmware via efi_exit() instead of
  * returning.
  */
-asmlinkage unsigned long efi_main(efi_handle_t handle,
-                                 efi_system_table_t *sys_table_arg,
-                                 struct boot_params *boot_params)
+void __noreturn efi_stub_entry(efi_handle_t handle,
+                              efi_system_table_t *sys_table_arg,
+                              struct boot_params *boot_params)
 {
        unsigned long bzimage_addr = (unsigned long)startup_32;
        unsigned long buffer_start, buffer_end;
@@ -964,7 +964,19 @@ asmlinkage unsigned long efi_main(efi_handle_t handle,
 
        enter_kernel(bzimage_addr, boot_params);
 fail:
-       efi_err("efi_main() failed!\n");
+       efi_err("efi_stub_entry() failed!\n");
 
        efi_exit(handle, status);
 }
+
+#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
+#ifndef CONFIG_EFI_MIXED
+extern __alias(efi_stub_entry)
+void efi32_stub_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
+                     struct boot_params *boot_params);
+
+extern __alias(efi_stub_entry)
+void efi64_stub_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
+                     struct boot_params *boot_params);
+#endif
+#endif