Commit c3710de5 authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Ingo Molnar

efi/libstub/x86: Drop __efi_early() export and efi_config struct

The various pointers we stash in the efi_config struct which we
retrieve using __efi_early() are simply copies of the ones in
the EFI system table, which we have started accessing directly
in the previous patch. So drop all the __efi_early() related
plumbing, as well as all the assembly code dealing with efi_config,
which allows us to move the PE/COFF entry point to C code as well.
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
Cc: Arvind Sankar <nivedita@alum.mit.edu>
Cc: Borislav Petkov <bp@alien8.de>
Cc: James Morse <james.morse@arm.com>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-efi@vger.kernel.org
Link: https://lkml.kernel.org/r/20191224151025.32482-18-ardb@kernel.orgSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent dc29da14
...@@ -19,32 +19,17 @@ ...@@ -19,32 +19,17 @@
#include "eboot.h" #include "eboot.h"
static efi_system_table_t *sys_table; static efi_system_table_t *sys_table;
static bool efi_is64 = IS_ENABLED(CONFIG_X86_64);
static struct efi_config *efi_early;
__pure const struct efi_config *__efi_early(void)
{
return efi_early;
}
__pure efi_system_table_t *efi_system_table(void) __pure efi_system_table_t *efi_system_table(void)
{ {
return sys_table; return sys_table;
} }
#define BOOT_SERVICES(bits) \ __pure bool efi_is_64bit(void)
static void setup_boot_services##bits(struct efi_config *c) \ {
{ \ return efi_is64;
efi_system_table_##bits##_t *table; \
\
table = (typeof(table))sys_table; \
\
c->runtime_services = table->runtime; \
c->boot_services = table->boottime; \
c->text_output = table->con_out; \
} }
BOOT_SERVICES(32);
BOOT_SERVICES(64);
static efi_status_t static efi_status_t
preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom) preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
...@@ -367,21 +352,24 @@ void setup_graphics(struct boot_params *boot_params) ...@@ -367,21 +352,24 @@ void setup_graphics(struct boot_params *boot_params)
} }
} }
void startup_32(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);
/* /*
* Because the x86 boot code expects to be passed a boot_params we * Because the x86 boot code expects to be passed a boot_params we
* need to create one ourselves (usually the bootloader would create * need to create one ourselves (usually the bootloader would create
* one for us). * one for us).
*
* The caller is responsible for filling out ->code32_start in the
* returned boot_params.
*/ */
struct boot_params *make_boot_params(struct efi_config *c) efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_system_table_t *sys_table_arg)
{ {
struct boot_params *boot_params; struct boot_params *boot_params;
struct apm_bios_info *bi; struct apm_bios_info *bi;
struct setup_header *hdr; struct setup_header *hdr;
efi_loaded_image_t *image; efi_loaded_image_t *image;
void *handle;
efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID; efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
int options_size = 0; int options_size = 0;
efi_status_t status; efi_status_t status;
...@@ -389,31 +377,24 @@ struct boot_params *make_boot_params(struct efi_config *c) ...@@ -389,31 +377,24 @@ struct boot_params *make_boot_params(struct efi_config *c)
unsigned long ramdisk_addr; unsigned long ramdisk_addr;
unsigned long ramdisk_size; unsigned long ramdisk_size;
efi_early = c; sys_table = sys_table_arg;
sys_table = (efi_system_table_t *)(unsigned long)efi_early->table;
handle = (void *)(unsigned long)efi_early->image_handle;
/* Check if we were booted by the EFI firmware */ /* Check if we were booted by the EFI firmware */
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
return NULL; return EFI_INVALID_PARAMETER;
if (efi_is_64bit())
setup_boot_services64(efi_early);
else
setup_boot_services32(efi_early);
status = efi_call_early(handle_protocol, handle, status = efi_call_early(handle_protocol, handle,
&proto, (void *)&image); &proto, (void *)&image);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_printk(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n"); efi_printk(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
return NULL; return status;
} }
status = efi_low_alloc(sys_table, 0x4000, 1, status = efi_low_alloc(sys_table, 0x4000, 1,
(unsigned long *)&boot_params); (unsigned long *)&boot_params);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_printk(sys_table, "Failed to allocate lowmem for boot params\n"); efi_printk(sys_table, "Failed to allocate lowmem for boot params\n");
return NULL; return status;
} }
memset(boot_params, 0x0, 0x4000); memset(boot_params, 0x0, 0x4000);
...@@ -474,14 +455,17 @@ struct boot_params *make_boot_params(struct efi_config *c) ...@@ -474,14 +455,17 @@ struct boot_params *make_boot_params(struct efi_config *c)
boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32; boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32;
boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32; boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32;
return boot_params; hdr->code32_start = (u32)(unsigned long)startup_32;
efi_stub_entry(handle, sys_table, boot_params);
/* not reached */
fail2: fail2:
efi_free(sys_table, options_size, hdr->cmd_line_ptr); efi_free(sys_table, options_size, hdr->cmd_line_ptr);
fail: fail:
efi_free(sys_table, 0x4000, (unsigned long)boot_params); efi_free(sys_table, 0x4000, (unsigned long)boot_params);
return NULL; return status;
} }
static void add_e820ext(struct boot_params *params, static void add_e820ext(struct boot_params *params,
...@@ -737,33 +721,26 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle) ...@@ -737,33 +721,26 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
* On success we return a pointer to a boot_params structure, and NULL * On success we return a pointer to a boot_params structure, and NULL
* on failure. * on failure.
*/ */
struct boot_params * struct boot_params *efi_main(efi_handle_t handle,
efi_main(struct efi_config *c, struct boot_params *boot_params) efi_system_table_t *sys_table_arg,
struct boot_params *boot_params,
bool is64)
{ {
struct desc_ptr *gdt = NULL; struct desc_ptr *gdt = NULL;
struct setup_header *hdr = &boot_params->hdr; struct setup_header *hdr = &boot_params->hdr;
efi_status_t status; efi_status_t status;
struct desc_struct *desc; struct desc_struct *desc;
void *handle;
efi_system_table_t *_table;
unsigned long cmdline_paddr; unsigned long cmdline_paddr;
efi_early = c; sys_table = sys_table_arg;
_table = (efi_system_table_t *)(unsigned long)efi_early->table;
handle = (void *)(unsigned long)efi_early->image_handle;
sys_table = _table; if (IS_ENABLED(CONFIG_EFI_MIXED))
efi_is64 = is64;
/* Check if we were booted by the EFI firmware */ /* Check if we were booted by the EFI firmware */
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
goto fail; goto fail;
if (efi_is_64bit())
setup_boot_services64(efi_early);
else
setup_boot_services32(efi_early);
/* /*
* make_boot_params() may have been called before efi_main(), in which * make_boot_params() may have been called before efi_main(), in which
* case this is the second time we parse the cmdline. This is ok, * case this is the second time we parse the cmdline. This is ok,
...@@ -925,5 +902,6 @@ efi_main(struct efi_config *c, struct boot_params *boot_params) ...@@ -925,5 +902,6 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
fail: fail:
efi_printk(sys_table, "efi_main() failed!\n"); efi_printk(sys_table, "efi_main() failed!\n");
return NULL; for (;;)
asm("hlt");
} }
...@@ -145,63 +145,16 @@ SYM_FUNC_START(startup_32) ...@@ -145,63 +145,16 @@ SYM_FUNC_START(startup_32)
SYM_FUNC_END(startup_32) SYM_FUNC_END(startup_32)
#ifdef CONFIG_EFI_STUB #ifdef CONFIG_EFI_STUB
/*
* We don't need the return address, so set up the stack so efi_main() can find
* its arguments.
*/
SYM_FUNC_START(efi_pe_entry)
add $0x4, %esp
call 1f
1: popl %esi
subl $1b, %esi
popl %ecx
movl %ecx, efi32_config(%esi) /* Handle */
popl %ecx
movl %ecx, efi32_config+8(%esi) /* EFI System table pointer */
leal efi32_config(%esi), %eax
pushl %eax
call make_boot_params
cmpl $0, %eax
je fail
movl %esi, BP_code32_start(%eax)
popl %ecx
pushl %eax
pushl %ecx
jmp 2f /* Skip efi_config initialization */
SYM_FUNC_END(efi_pe_entry)
SYM_FUNC_START(efi32_stub_entry) SYM_FUNC_START(efi32_stub_entry)
SYM_FUNC_START_ALIAS(efi_stub_entry)
add $0x4, %esp add $0x4, %esp
popl %ecx
popl %edx
call 1f
1: popl %esi
subl $1b, %esi
movl %ecx, efi32_config(%esi) /* Handle */
movl %edx, efi32_config+8(%esi) /* EFI System table pointer */
leal efi32_config(%esi), %eax
pushl %eax
2:
call efi_main call efi_main
cmpl $0, %eax
movl %eax, %esi movl %eax, %esi
jne 2f
fail:
/* EFI init failed, so hang. */
hlt
jmp fail
2:
movl BP_code32_start(%esi), %eax movl BP_code32_start(%esi), %eax
leal startup_32(%eax), %eax leal startup_32(%eax), %eax
jmp *%eax jmp *%eax
SYM_FUNC_END(efi32_stub_entry) SYM_FUNC_END(efi32_stub_entry)
SYM_FUNC_END_ALIAS(efi_stub_entry)
#endif #endif
.text .text
...@@ -258,13 +211,6 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated) ...@@ -258,13 +211,6 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
jmp *%eax jmp *%eax
SYM_FUNC_END(.Lrelocated) SYM_FUNC_END(.Lrelocated)
#ifdef CONFIG_EFI_STUB
.data
efi32_config:
.fill 5,8,0
.byte 0
#endif
/* /*
* Stack and heap for uncompression * Stack and heap for uncompression
*/ */
......
...@@ -208,10 +208,14 @@ SYM_FUNC_START(startup_32) ...@@ -208,10 +208,14 @@ SYM_FUNC_START(startup_32)
pushl $__KERNEL_CS pushl $__KERNEL_CS
leal startup_64(%ebp), %eax leal startup_64(%ebp), %eax
#ifdef CONFIG_EFI_MIXED #ifdef CONFIG_EFI_MIXED
movl efi32_config(%ebp), %ebx movl efi32_boot_args(%ebp), %ebx
cmp $0, %ebx cmp $0, %ebx
jz 1f jz 1f
leal handover_entry(%ebp), %eax leal handover_entry(%ebp), %eax
movl 0(%ebx), %edi
movl 4(%ebx), %esi
movl 8(%ebx), %edx
movl $0x0, %ecx
1: 1:
#endif #endif
pushl %eax pushl %eax
...@@ -228,22 +232,14 @@ SYM_FUNC_END(startup_32) ...@@ -228,22 +232,14 @@ SYM_FUNC_END(startup_32)
.org 0x190 .org 0x190
SYM_FUNC_START(efi32_stub_entry) SYM_FUNC_START(efi32_stub_entry)
add $0x4, %esp /* Discard return address */ add $0x4, %esp /* Discard return address */
popl %ecx
popl %edx
popl %esi
leal (BP_scratch+4)(%esi), %esp
call 1f call 1f
1: pop %ebp 1: pop %ebp
subl $1b, %ebp subl $1b, %ebp
movl %ecx, efi32_config(%ebp) movl %esp, efi32_boot_args(%ebp)
movl %edx, efi32_config+8(%ebp)
sgdtl efi32_boot_gdt(%ebp) sgdtl efi32_boot_gdt(%ebp)
leal efi32_config(%ebp), %eax
movl %eax, efi_config(%ebp)
/* Disable paging */ /* Disable paging */
movl %cr0, %eax movl %cr0, %eax
btrl $X86_CR0_PG_BIT, %eax btrl $X86_CR0_PG_BIT, %eax
...@@ -450,51 +446,19 @@ trampoline_return: ...@@ -450,51 +446,19 @@ trampoline_return:
SYM_CODE_END(startup_64) SYM_CODE_END(startup_64)
#ifdef CONFIG_EFI_STUB #ifdef CONFIG_EFI_STUB
.org 0x390
/* The entry point for the PE/COFF executable is efi_pe_entry. */ SYM_FUNC_START(efi64_stub_entry)
SYM_FUNC_START(efi_pe_entry) SYM_FUNC_START_ALIAS(efi_stub_entry)
movq %rcx, efi64_config(%rip) /* Handle */ movq $1, %rcx
movq %rdx, efi64_config+8(%rip) /* EFI System table pointer */ SYM_INNER_LABEL(handover_entry, SYM_L_LOCAL)
leaq efi64_config(%rip), %rax
movq %rax, efi_config(%rip)
movq %rax, %rdi
call make_boot_params
cmpq $0,%rax
je fail
mov %rax, %rsi
leaq startup_32(%rip), %rax
movl %eax, BP_code32_start(%rsi)
handover_entry:
movq efi_config(%rip), %rdi
and $~0xf, %rsp /* realign the stack */ and $~0xf, %rsp /* realign the stack */
call efi_main call efi_main
movq %rax,%rsi movq %rax,%rsi
cmpq $0,%rax
jne 2f
fail:
/* EFI init failed, so hang. */
hlt
jmp fail
2:
movl BP_code32_start(%esi), %eax movl BP_code32_start(%esi), %eax
leaq startup_64(%rax), %rax leaq startup_64(%rax), %rax
jmp *%rax jmp *%rax
SYM_FUNC_END(efi_pe_entry)
.org 0x390
SYM_FUNC_START(efi64_stub_entry)
movq %rdi, efi64_config(%rip) /* Handle */
movq %rsi, efi64_config+8(%rip) /* EFI System table pointer */
leaq efi64_config(%rip), %rax
movq %rax, efi_config(%rip)
movq %rdx, %rsi
jmp handover_entry
SYM_FUNC_END(efi64_stub_entry) SYM_FUNC_END(efi64_stub_entry)
SYM_FUNC_END_ALIAS(efi_stub_entry)
#endif #endif
.text .text
...@@ -663,22 +627,10 @@ SYM_DATA_START_LOCAL(gdt) ...@@ -663,22 +627,10 @@ SYM_DATA_START_LOCAL(gdt)
.quad 0x0000000000000000 /* TS continued */ .quad 0x0000000000000000 /* TS continued */
SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end) SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end)
#ifdef CONFIG_EFI_STUB
SYM_DATA_LOCAL(efi_config, .quad 0)
#ifdef CONFIG_EFI_MIXED #ifdef CONFIG_EFI_MIXED
SYM_DATA_START(efi32_config) SYM_DATA_LOCAL(efi32_boot_args, .long 0)
.fill 5,8,0
.byte 0
SYM_DATA_END(efi32_config)
#endif #endif
SYM_DATA_START(efi64_config)
.fill 5,8,0
.byte 1
SYM_DATA_END(efi64_config)
#endif /* CONFIG_EFI_STUB */
/* /*
* Stack and heap for uncompression * Stack and heap for uncompression
*/ */
......
...@@ -200,32 +200,14 @@ static inline efi_status_t efi_thunk_set_virtual_address_map( ...@@ -200,32 +200,14 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
/* arch specific definitions used by the stub code */ /* arch specific definitions used by the stub code */
struct efi_config { __pure bool efi_is_64bit(void);
u64 image_handle;
u64 table;
u64 runtime_services;
u64 boot_services;
u64 text_output;
bool is64;
} __packed;
__pure const struct efi_config *__efi_early(void);
static inline bool efi_is_64bit(void)
{
if (!IS_ENABLED(CONFIG_X86_64))
return false;
if (!IS_ENABLED(CONFIG_EFI_MIXED))
return true;
return __efi_early()->is64;
}
static inline bool efi_is_native(void) static inline bool efi_is_native(void)
{ {
if (!IS_ENABLED(CONFIG_X86_64)) if (!IS_ENABLED(CONFIG_X86_64))
return true; return true;
if (!IS_ENABLED(CONFIG_EFI_MIXED))
return true;
return efi_is_64bit(); return efi_is_64bit();
} }
...@@ -252,18 +234,16 @@ static inline bool efi_is_native(void) ...@@ -252,18 +234,16 @@ static inline bool efi_is_native(void)
#define efi_call_early(f, ...) \ #define efi_call_early(f, ...) \
(efi_is_native() \ (efi_is_native() \
? ((efi_boot_services_t *)(unsigned long) \ ? efi_system_table()->boottime->f(__VA_ARGS__) \
__efi_early()->boot_services)->f(__VA_ARGS__) \ : efi64_thunk(efi_table_attr(efi_boot_services, \
: efi64_thunk(((efi_boot_services_t *)(unsigned long) \ boottime, efi_system_table())->mixed_mode.f, \
__efi_early()->boot_services)->mixed_mode.f, \
__VA_ARGS__)) __VA_ARGS__))
#define efi_call_runtime(f, ...) \ #define efi_call_runtime(f, ...) \
(efi_is_native() \ (efi_is_native() \
? ((efi_runtime_services_t *)(unsigned long) \ ? efi_system_table()->runtime->f(__VA_ARGS__) \
__efi_early()->runtime_services)->f(__VA_ARGS__)\ : efi64_thunk(efi_table_attr(efi_runtime_services, \
: efi64_thunk(((efi_runtime_services_t *)(unsigned long)\ runtime, efi_system_table())->mixed_mode.f, \
__efi_early()->runtime_services)->mixed_mode.f, \
__VA_ARGS__)) __VA_ARGS__))
extern bool efi_reboot_required(void); extern bool efi_reboot_required(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment