x86/efi: Firmware agnostic handover entry points
The EFI handover code only works if the "bitness" of the firmware and the kernel match, i.e. 64-bit firmware and 64-bit kernel - it is not possible to mix the two. This goes against the tradition that a 32-bit kernel can be loaded on a 64-bit BIOS platform without having to do anything special in the boot loader. Linux distributions, for one thing, regularly run only 32-bit kernels on their live media. Despite having only one 'handover_offset' field in the kernel header, EFI boot loaders use two separate entry points to enter the kernel based on the architecture the boot loader was compiled for, (1) 32-bit loader: handover_offset (2) 64-bit loader: handover_offset + 512 Since we already have two entry points, we can leverage them to infer the bitness of the firmware we're running on, without requiring any boot loader modifications, by making (1) and (2) valid entry points for both CONFIG_X86_32 and CONFIG_X86_64 kernels. To be clear, a 32-bit boot loader will always use (1) and a 64-bit boot loader will always use (2). It's just that, if a single kernel image supports (1) and (2) that image can be used with both 32-bit and 64-bit boot loaders, and hence both 32-bit and 64-bit EFI. (1) and (2) must be 512 bytes apart at all times, but that is already part of the boot ABI and we could never change that delta without breaking existing boot loaders anyhow. Signed-off-by: Matt Fleming <matt.fleming@intel.com>
This commit is contained in:
@@ -178,6 +178,13 @@ ENTRY(startup_32)
|
||||
*/
|
||||
pushl $__KERNEL_CS
|
||||
leal startup_64(%ebp), %eax
|
||||
#ifdef CONFIG_EFI_MIXED
|
||||
movl efi32_config(%ebp), %ebx
|
||||
cmp $0, %ebx
|
||||
jz 1f
|
||||
leal handover_entry(%ebp), %eax
|
||||
1:
|
||||
#endif
|
||||
pushl %eax
|
||||
|
||||
/* Enter paged protected Mode, activating Long Mode */
|
||||
@@ -188,6 +195,30 @@ ENTRY(startup_32)
|
||||
lret
|
||||
ENDPROC(startup_32)
|
||||
|
||||
#ifdef CONFIG_EFI_MIXED
|
||||
.org 0x190
|
||||
ENTRY(efi32_stub_entry)
|
||||
add $0x4, %esp /* Discard return address */
|
||||
popl %ecx
|
||||
popl %edx
|
||||
popl %esi
|
||||
|
||||
leal (BP_scratch+4)(%esi), %esp
|
||||
call 1f
|
||||
1: pop %ebp
|
||||
subl $1b, %ebp
|
||||
|
||||
movl %ecx, efi32_config(%ebp)
|
||||
movl %edx, efi32_config+8(%ebp)
|
||||
sgdtl efi32_boot_gdt(%ebp)
|
||||
|
||||
leal efi32_config(%ebp), %eax
|
||||
movl %eax, efi_config(%ebp)
|
||||
|
||||
jmp startup_32
|
||||
ENDPROC(efi32_stub_entry)
|
||||
#endif
|
||||
|
||||
.code64
|
||||
.org 0x200
|
||||
ENTRY(startup_64)
|
||||
@@ -231,13 +262,7 @@ ENTRY(efi_pe_entry)
|
||||
mov %rax, %rsi
|
||||
jmp 2f /* Skip the relocation */
|
||||
|
||||
ENTRY(efi_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)
|
||||
|
||||
handover_entry:
|
||||
call 1f
|
||||
1: popq %rbp
|
||||
subq $1b, %rbp
|
||||
@@ -247,7 +272,6 @@ ENTRY(efi_stub_entry)
|
||||
*/
|
||||
movq efi_config(%rip), %rax
|
||||
addq %rbp, 88(%rax)
|
||||
movq %rdx, %rsi
|
||||
2:
|
||||
movq efi_config(%rip), %rdi
|
||||
call efi_main
|
||||
@@ -336,6 +360,20 @@ preferred_addr:
|
||||
leaq relocated(%rbx), %rax
|
||||
jmp *%rax
|
||||
|
||||
#ifdef CONFIG_EFI_STUB
|
||||
.org 0x390
|
||||
ENTRY(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
|
||||
ENDPROC(efi64_stub_entry)
|
||||
#endif
|
||||
|
||||
.text
|
||||
relocated:
|
||||
|
||||
@@ -404,6 +442,14 @@ gdt_end:
|
||||
efi_config:
|
||||
.quad 0
|
||||
|
||||
#ifdef CONFIG_EFI_MIXED
|
||||
.global efi32_config
|
||||
efi32_config:
|
||||
.fill 11,8,0
|
||||
.quad efi64_thunk
|
||||
.byte 0
|
||||
#endif
|
||||
|
||||
.global efi64_config
|
||||
efi64_config:
|
||||
.fill 11,8,0
|
||||
|
مرجع در شماره جدید
Block a user