/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright ( C ) 2014 , 2015 Intel Corporation ; author Matt Fleming
*
* Early support for invoking 32 - bit EFI services from a 64 - bit kernel .
*
* Because this thunking occurs before ExitBootServices ( ) we have to
* restore the firmware ' s 32 - bit GDT and IDT before we make EFI service
* calls .
*
* On the plus side , we don ' t have to worry about mangling 64 - bit
* addresses into 32 - bits because we ' re executing with an identity
* mapped pagetable and haven ' t transitioned to 64 - bit virtual addresses
* yet .
*/
#include <linux/linkage.h>
#include <asm/desc_defs.h>
#include <asm/msr.h>
#include <asm/page_types.h>
#include <asm/pgtable_types.h>
#include <asm/processor-flags.h>
#include <asm/segment.h>
.text
.code32
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
SYM_FUNC_START(efi32_stub_entry)
call 1 f
1 : popl %ecx
/* Clear BSS */
xorl %eax, %eax
leal (_bss - 1 b)(%ecx), %edi
leal (_ebss - 1 b)(%ecx), %ecx
subl %edi, %ecx
shrl $2 , %ecx
cld
rep stosl
add $0 x4, %esp /* Discard return address */
movl 8 (%esp), %ebx /* struct boot_params pointer */
jmp efi32_startup
SYM_FUNC_END(efi32_stub_entry)
#endif
/*
* Called using a far call from _ _ efi64_thunk ( ) below , using the x86_64 SysV
* ABI ( except for R8 / R9 which are inaccessible to 32 - bit code - EAX / EBX are
* used instead ) . EBP + 16 points to the arguments passed via the stack .
*
* The first argument ( EDI ) is a pointer to the boot service or protocol , to
* which the remaining arguments are passed , each truncated to 32 bits .
*/
SYM_FUNC_START_LOCAL(efi_enter32)
/*
* Convert x86 - 64 SysV ABI params to i386 ABI
*/
pushl 32 (%ebp) /* Up to 3 args passed via the stack */
pushl 24 (%ebp)
pushl 16 (%ebp)
pushl %ebx /* R9 */
pushl %eax /* R8 */
pushl %ecx
pushl %edx
pushl %esi
/* Disable paging */
movl %cr0, %eax
btrl $X86_CR0_PG_BIT, %eax
movl %eax, %cr0
/* Disable long mode via EFER */
movl $MSR_EFER, %ecx
rdmsr
btrl $_EFER_LME, %eax
wrmsr
call *%edi
/* We must preserve return value */
movl %eax, %edi
call efi32_enable_long_mode
addl $32 , %esp
movl %edi, %eax
lret
SYM_FUNC_END(efi_enter32)
.code64
SYM_FUNC_START(__efi64_thunk)
push %rbp
movl %esp, %ebp
push %rbx
/* Move args #5 and #6 into 32-bit accessible registers */
movl %r8d, %eax
movl %r9d, %ebx
lcalll *efi32_call(%rip)
pop %rbx
pop %rbp
RET
SYM_FUNC_END(__efi64_thunk)
.code32
SYM_FUNC_START_LOCAL(efi32_enable_long_mode)
movl %cr4, %eax
btsl $(X86_CR4_PAE_BIT), %eax
movl %eax, %cr4
movl $MSR_EFER, %ecx
rdmsr
btsl $_EFER_LME, %eax
wrmsr
/* Disable interrupts - the firmware's IDT does not work in long mode */
cli
/* Enable paging */
movl %cr0, %eax
btsl $X86_CR0_PG_BIT, %eax
movl %eax, %cr0
ret
SYM_FUNC_END(efi32_enable_long_mode)
/*
* This is the common EFI stub entry point for mixed mode . It sets up the GDT
* and page tables needed for 64 - bit execution , after which it calls the
* common 64 - bit EFI entrypoint efi_stub_entry ( ) .
*
* Arguments : 0 ( % esp ) image handle
* 4 ( % esp ) EFI system table pointer
* % ebx struct boot_params pointer ( or NULL )
*
* Since this is the point of no return for ordinary execution , no registers
* are considered live except for the function parameters . [ Note that the EFI
* stub may still exit and return to the firmware using the Exit ( ) EFI boot
* service . ]
*/
SYM_FUNC_START_LOCAL(efi32_startup)
movl %esp, %ebp
subl $8 , %esp
sgdtl (%esp) /* Save GDT descriptor to the stack */
movl 2 (%esp), %esi /* Existing GDT pointer */
movzwl (%esp), %ecx /* Existing GDT limit */
inc %ecx /* Existing GDT size */
andl $~7 , %ecx /* Ensure size is multiple of 8 */
subl %ecx, %esp /* Allocate new GDT */
andl $~15 , %esp /* Realign the stack */
movl %esp, %edi /* New GDT address */
leal 7 (%ecx), %eax /* New GDT limit */
pushw %cx /* Push 64-bit CS (for LJMP below) */
pushl %edi /* Push new GDT address */
pushw %ax /* Push new GDT limit */
/* Copy GDT to the stack and add a 64-bit code segment at the end */
movl $GDT_ENTRY(DESC_CODE64, 0 , 0 xfffff) & 0 xffffffff, (%edi,%ecx)
movl $GDT_ENTRY(DESC_CODE64, 0 , 0 xfffff) >> 32 , 4 (%edi,%ecx)
shrl $2 , %ecx
cld
rep movsl /* Copy the firmware GDT */
lgdtl (%esp) /* Switch to the new GDT */
call 1 f
1 : pop %edi
/* Record mixed mode entry */
movb $0 x0, (efi_is64 - 1 b)(%edi)
/* Set up indirect far call to re-enter 32-bit mode */
leal (efi32_call - 1 b)(%edi), %eax
addl %eax, (%eax)
movw %cs, 4 (%eax)
/* Disable paging */
movl %cr0, %eax
btrl $X86_CR0_PG_BIT, %eax
movl %eax, %cr0
/* Set up 1:1 mapping */
leal (pte - 1 b)(%edi), %eax
movl $_PAGE_PRESENT | _PAGE_RW | _PAGE_PSE, %ecx
leal (_PAGE_PRESENT | _PAGE_RW)(%eax), %edx
2 : movl %ecx, (%eax)
addl $8 , %eax
addl $PMD_SIZE, %ecx
jnc 2 b
movl $PAGE_SIZE, %ecx
.irpc l, 0123
movl %edx, \l * 8 (%eax)
addl %ecx, %edx
.endr
addl %ecx, %eax
movl %edx, (%eax)
movl %eax, %cr3
call efi32_enable_long_mode
/* Set up far jump to 64-bit mode (CS is already on the stack) */
leal (efi_stub_entry - 1 b)(%edi), %eax
movl %eax, 2 (%esp)
movl 0 (%ebp), %edi
movl 4 (%ebp), %esi
movl %ebx, %edx
ljmpl *2 (%esp)
SYM_FUNC_END(efi32_startup)
/*
* efi_status_t efi32_pe_entry ( efi_handle_t image_handle ,
* efi_system_table_32_t * sys_table )
*/
SYM_FUNC_START(efi32_pe_entry)
pushl %ebx // save callee-save registers
/* Check whether the CPU supports long mode */
movl $0 x80000001, %eax // assume extended info support
cpuid
btl $29 , %edx // check long mode bit
jnc 1 f
leal 8 (%esp), %esp // preserve stack alignment
xor %ebx, %ebx // no struct boot_params pointer
jmp efi32_startup // only ESP and EBX remain live
1 : movl $0 x80000003, %eax // EFI_UNSUPPORTED
popl %ebx
RET
SYM_FUNC_END(efi32_pe_entry)
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
.org efi32_stub_entry + 0 x200
.code64
SYM_FUNC_START_NOALIGN(efi64_stub_entry)
jmp efi_handover_entry
SYM_FUNC_END(efi64_stub_entry)
#endif
.data
.balign 8
SYM_DATA_START_LOCAL(efi32_call)
.long efi_enter32 - .
.word 0 x0
SYM_DATA_END(efi32_call)
SYM_DATA(efi_is64, .byte 1 )
.bss
.balign PAGE_SIZE
SYM_DATA_LOCAL(pte, .fill 6 * PAGE_SIZE, 1 , 0 )
Messung V0.5 in Prozent C=85 H=100 G=92
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-10-01)
¤
*© Formatika GbR, Deutschland