Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Copyright (C) 2014 Intel Corporation; author Matt Fleming
0004  *
0005  * Support for invoking 32-bit EFI runtime services from a 64-bit
0006  * kernel.
0007  *
0008  * The below thunking functions are only used after ExitBootServices()
0009  * has been called. This simplifies things considerably as compared with
0010  * the early EFI thunking because we can leave all the kernel state
0011  * intact (GDT, IDT, etc) and simply invoke the 32-bit EFI runtime
0012  * services from __KERNEL32_CS. This means we can continue to service
0013  * interrupts across an EFI mixed mode call.
0014  *
0015  * We do however, need to handle the fact that we're running in a full
0016  * 64-bit virtual address space. Things like the stack and instruction
0017  * addresses need to be accessible by the 32-bit firmware, so we rely on
0018  * using the identity mappings in the EFI page table to access the stack
0019  * and kernel text (see efi_setup_page_tables()).
0020  */
0021 
0022 #include <linux/linkage.h>
0023 #include <linux/objtool.h>
0024 #include <asm/page_types.h>
0025 #include <asm/segment.h>
0026 #include <asm/nospec-branch.h>
0027 
0028     .text
0029     .code64
0030 SYM_FUNC_START(__efi64_thunk)
0031 STACK_FRAME_NON_STANDARD __efi64_thunk
0032     push    %rbp
0033     push    %rbx
0034 
0035     /*
0036      * Switch to 1:1 mapped 32-bit stack pointer.
0037      */
0038     movq    %rsp, %rax
0039     movq    efi_mixed_mode_stack_pa(%rip), %rsp
0040     push    %rax
0041 
0042     /*
0043      * Copy args passed via the stack
0044      */
0045     subq    $0x24, %rsp
0046     movq    0x18(%rax), %rbp
0047     movq    0x20(%rax), %rbx
0048     movq    0x28(%rax), %rax
0049     movl    %ebp, 0x18(%rsp)
0050     movl    %ebx, 0x1c(%rsp)
0051     movl    %eax, 0x20(%rsp)
0052 
0053     /*
0054      * Calculate the physical address of the kernel text.
0055      */
0056     movq    $__START_KERNEL_map, %rax
0057     subq    phys_base(%rip), %rax
0058 
0059     leaq    1f(%rip), %rbp
0060     leaq    2f(%rip), %rbx
0061     subq    %rax, %rbp
0062     subq    %rax, %rbx
0063 
0064     movl    %ebx, 0x0(%rsp)     /* return address */
0065     movl    %esi, 0x4(%rsp)
0066     movl    %edx, 0x8(%rsp)
0067     movl    %ecx, 0xc(%rsp)
0068     movl    %r8d, 0x10(%rsp)
0069     movl    %r9d, 0x14(%rsp)
0070 
0071     /* Switch to 32-bit descriptor */
0072     pushq   $__KERNEL32_CS
0073     pushq   %rdi            /* EFI runtime service address */
0074     lretq
0075 
0076 1:  movq    0x20(%rsp), %rsp
0077     pop %rbx
0078     pop %rbp
0079     ANNOTATE_UNRET_SAFE
0080     ret
0081     int3
0082 
0083     .code32
0084 2:  pushl   $__KERNEL_CS
0085     pushl   %ebp
0086     lret
0087 SYM_FUNC_END(__efi64_thunk)
0088 
0089     .bss
0090     .balign 8
0091 SYM_DATA(efi_mixed_mode_stack_pa, .quad 0)