Skip to content

Commit dac628e

Browse files
committed
x86/efistub: Merge PE and handover entrypoints
The difference between the PE and handover entrypoints in the EFI stub is that the former allocates a struct boot_params whereas the latter expects one from the caller. Currently, these are two completely separate entrypoints, duplicating some logic and both relying of efi_exit() to return straight back to the firmware on an error. Simplify this by making the PE entrypoint call the handover entrypoint with NULL as the argument for the struct boot_params parameter. This makes the code easier to follow, and removes the need to support two different calling conventions in the mixed mode asm code. While at it, move the assignment of boot_params_ptr into the function that actually calls into the legacy decompressor, which is where its value is required. Acked-by: Ingo Molnar <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]>
1 parent 2014c95 commit dac628e

File tree

2 files changed

+30
-38
lines changed

2 files changed

+30
-38
lines changed

arch/x86/boot/compressed/efi_mixed.S

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,8 @@ SYM_FUNC_START(startup_64_mixed_mode)
5656
movl efi32_boot_sp(%rip), %esp
5757
andl $~7, %esp
5858

59-
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
6059
mov 8(%rdx), %edx // saved bootparams pointer
61-
test %edx, %edx
62-
jnz efi_stub_entry
63-
#endif
64-
/*
65-
* efi_pe_entry uses MS calling convention, which requires 32 bytes of
66-
* shadow space on the stack even if all arguments are passed in
67-
* registers. We also need an additional 8 bytes for the space that
68-
* would be occupied by the return address, and this also results in
69-
* the correct stack alignment for entry.
70-
*/
71-
sub $40, %rsp
72-
mov %rdi, %rcx // MS calling convention
73-
mov %rsi, %rdx
74-
jmp efi_pe_entry
60+
call efi_stub_entry
7561
SYM_FUNC_END(startup_64_mixed_mode)
7662

7763
SYM_FUNC_START(__efi64_thunk)

drivers/firmware/efi/libstub/x86-stub.c

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -397,17 +397,13 @@ static void __noreturn efi_exit(efi_handle_t handle, efi_status_t status)
397397
asm("hlt");
398398
}
399399

400-
void __noreturn efi_stub_entry(efi_handle_t handle,
401-
efi_system_table_t *sys_table_arg,
402-
struct boot_params *boot_params);
403-
404400
/*
405401
* Because the x86 boot code expects to be passed a boot_params we
406402
* need to create one ourselves (usually the bootloader would create
407403
* one for us).
408404
*/
409-
efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
410-
efi_system_table_t *sys_table_arg)
405+
static efi_status_t efi_allocate_bootparams(efi_handle_t handle,
406+
struct boot_params **bp)
411407
{
412408
efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
413409
struct boot_params *boot_params;
@@ -416,21 +412,15 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
416412
unsigned long alloc;
417413
char *cmdline_ptr;
418414

419-
efi_system_table = sys_table_arg;
420-
421-
/* Check if we were booted by the EFI firmware */
422-
if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
423-
efi_exit(handle, EFI_INVALID_PARAMETER);
424-
425415
status = efi_bs_call(handle_protocol, handle, &proto, (void **)&image);
426416
if (status != EFI_SUCCESS) {
427417
efi_err("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
428-
efi_exit(handle, status);
418+
return status;
429419
}
430420

431421
status = efi_allocate_pages(PARAM_SIZE, &alloc, ULONG_MAX);
432422
if (status != EFI_SUCCESS)
433-
efi_exit(handle, status);
423+
return status;
434424

435425
boot_params = memset((void *)alloc, 0x0, PARAM_SIZE);
436426
hdr = &boot_params->hdr;
@@ -446,14 +436,14 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
446436
cmdline_ptr = efi_convert_cmdline(image);
447437
if (!cmdline_ptr) {
448438
efi_free(PARAM_SIZE, alloc);
449-
efi_exit(handle, EFI_OUT_OF_RESOURCES);
439+
return EFI_OUT_OF_RESOURCES;
450440
}
451441

452442
efi_set_u64_split((unsigned long)cmdline_ptr, &hdr->cmd_line_ptr,
453443
&boot_params->ext_cmd_line_ptr);
454444

455-
efi_stub_entry(handle, sys_table_arg, boot_params);
456-
/* not reached */
445+
*bp = boot_params;
446+
return EFI_SUCCESS;
457447
}
458448

459449
static void add_e820ext(struct boot_params *params,
@@ -740,13 +730,16 @@ static efi_status_t parse_options(const char *cmdline)
740730
return efi_parse_options(cmdline);
741731
}
742732

743-
static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
733+
static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry,
734+
struct boot_params *boot_params)
744735
{
745736
unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
746737
unsigned long addr, alloc_size, entry;
747738
efi_status_t status;
748739
u32 seed[2] = {};
749740

741+
boot_params_ptr = boot_params;
742+
750743
/* determine the required size of the allocation */
751744
alloc_size = ALIGN(max_t(unsigned long, output_len, kernel_total_size),
752745
MIN_KERNEL_ALIGN);
@@ -777,7 +770,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
777770
seed[0] = 0;
778771
}
779772

780-
boot_params_ptr->hdr.loadflags |= KASLR_FLAG;
773+
boot_params->hdr.loadflags |= KASLR_FLAG;
781774
}
782775

783776
status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr,
@@ -815,20 +808,27 @@ static void __noreturn enter_kernel(unsigned long kernel_addr,
815808
void __noreturn efi_stub_entry(efi_handle_t handle,
816809
efi_system_table_t *sys_table_arg,
817810
struct boot_params *boot_params)
811+
818812
{
819813
efi_guid_t guid = EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;
820-
struct setup_header *hdr = &boot_params->hdr;
821814
const struct linux_efi_initrd *initrd = NULL;
822815
unsigned long kernel_entry;
816+
struct setup_header *hdr;
823817
efi_status_t status;
824818

825-
boot_params_ptr = boot_params;
826-
827819
efi_system_table = sys_table_arg;
828820
/* Check if we were booted by the EFI firmware */
829821
if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
830822
efi_exit(handle, EFI_INVALID_PARAMETER);
831823

824+
if (!IS_ENABLED(CONFIG_EFI_HANDOVER_PROTOCOL) || !boot_params) {
825+
status = efi_allocate_bootparams(handle, &boot_params);
826+
if (status != EFI_SUCCESS)
827+
efi_exit(handle, status);
828+
}
829+
830+
hdr = &boot_params->hdr;
831+
832832
if (have_unsupported_snp_features())
833833
efi_exit(handle, EFI_UNSUPPORTED);
834834

@@ -870,7 +870,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
870870
if (efi_mem_encrypt > 0)
871871
hdr->xloadflags |= XLF_MEM_ENCRYPTION;
872872

873-
status = efi_decompress_kernel(&kernel_entry);
873+
status = efi_decompress_kernel(&kernel_entry, boot_params);
874874
if (status != EFI_SUCCESS) {
875875
efi_err("Failed to decompress kernel\n");
876876
goto fail;
@@ -940,6 +940,12 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
940940
efi_exit(handle, status);
941941
}
942942

943+
efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
944+
efi_system_table_t *sys_table_arg)
945+
{
946+
efi_stub_entry(handle, sys_table_arg, NULL);
947+
}
948+
943949
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
944950
void efi_handover_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
945951
struct boot_params *boot_params)

0 commit comments

Comments
 (0)