diff options
Diffstat (limited to 'drivers/firmware/efi/libstub/x86-mixed.S')
-rw-r--r-- | drivers/firmware/efi/libstub/x86-mixed.S | 253 |
1 files changed, 0 insertions, 253 deletions
diff --git a/drivers/firmware/efi/libstub/x86-mixed.S b/drivers/firmware/efi/libstub/x86-mixed.S deleted file mode 100644 index e04ed99bc449..000000000000 --- a/drivers/firmware/efi/libstub/x86-mixed.S +++ /dev/null @@ -1,253 +0,0 @@ -/* 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 1f -1: popl %ecx - - /* Clear BSS */ - xorl %eax, %eax - leal (_bss - 1b)(%ecx), %edi - leal (_ebss - 1b)(%ecx), %ecx - subl %edi, %ecx - shrl $2, %ecx - cld - rep stosl - - add $0x4, %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, 0xfffff) & 0xffffffff, (%edi,%ecx) - movl $GDT_ENTRY(DESC_CODE64, 0, 0xfffff) >> 32, 4(%edi,%ecx) - shrl $2, %ecx - cld - rep movsl /* Copy the firmware GDT */ - lgdtl (%esp) /* Switch to the new GDT */ - - call 1f -1: pop %edi - - /* Record mixed mode entry */ - movb $0x0, (efi_is64 - 1b)(%edi) - - /* Set up indirect far call to re-enter 32-bit mode */ - leal (efi32_call - 1b)(%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 - 1b)(%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 2b - - 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 - 1b)(%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 $0x80000001, %eax // assume extended info support - cpuid - btl $29, %edx // check long mode bit - jnc 1f - 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 $0x80000003, %eax // EFI_UNSUPPORTED - popl %ebx - RET -SYM_FUNC_END(efi32_pe_entry) - -#ifdef CONFIG_EFI_HANDOVER_PROTOCOL - .org efi32_stub_entry + 0x200 - .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 0x0 -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) |