1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming 4 * 5 * Early support for invoking 32-bit EFI services from a 64-bit kernel. 6 * 7 * Because this thunking occurs before ExitBootServices() we have to 8 * restore the firmware's 32-bit GDT and IDT before we make EFI service 9 * calls. 10 * 11 * On the plus side, we don't have to worry about mangling 64-bit 12 * addresses into 32-bits because we're executing with an identity 13 * mapped pagetable and haven't transitioned to 64-bit virtual addresses 14 * yet. 15 */ 16 17#include <linux/linkage.h> 18#include <asm/msr.h> 19#include <asm/page_types.h> 20#include <asm/processor-flags.h> 21#include <asm/segment.h> 22 23 .code64 24 .text 25/* 26 * When booting in 64-bit mode on 32-bit EFI firmware, startup_64_mixed_mode() 27 * is the first thing that runs after switching to long mode. Depending on 28 * whether the EFI handover protocol or the compat entry point was used to 29 * enter the kernel, it will either branch to the 64-bit EFI handover 30 * entrypoint at offset 0x390 in the image, or to the 64-bit EFI PE/COFF 31 * entrypoint efi_pe_entry(). In the former case, the bootloader must provide a 32 * struct bootparams pointer as the third argument, so the presence of such a 33 * pointer is used to disambiguate. 34 * 35 * +--------------+ 36 * +------------------+ +------------+ +------>| efi_pe_entry | 37 * | efi32_pe_entry |---->| | | +-----------+--+ 38 * +------------------+ | | +------+----------------+ | 39 * | startup_32 |---->| startup_64_mixed_mode | | 40 * +------------------+ | | +------+----------------+ V 41 * | efi32_stub_entry |---->| | | +------------------+ 42 * +------------------+ +------------+ +---->| efi64_stub_entry | 43 * +-------------+----+ 44 * +------------+ +----------+ | 45 * | startup_64 |<----| efi_main |<--------------+ 46 * +------------+ +----------+ 47 */ 48SYM_FUNC_START(startup_64_mixed_mode) 49 lea efi32_boot_args(%rip), %rdx 50 mov 0(%rdx), %edi 51 mov 4(%rdx), %esi 52 mov 8(%rdx), %edx // saved bootparams pointer 53 test %edx, %edx 54 jnz efi64_stub_entry 55 /* 56 * efi_pe_entry uses MS calling convention, which requires 32 bytes of 57 * shadow space on the stack even if all arguments are passed in 58 * registers. We also need an additional 8 bytes for the space that 59 * would be occupied by the return address, and this also results in 60 * the correct stack alignment for entry. 61 */ 62 sub $40, %rsp 63 mov %rdi, %rcx // MS calling convention 64 mov %rsi, %rdx 65 jmp efi_pe_entry 66SYM_FUNC_END(startup_64_mixed_mode) 67 68SYM_FUNC_START(__efi64_thunk) 69 push %rbp 70 push %rbx 71 72 movl %ds, %eax 73 push %rax 74 movl %es, %eax 75 push %rax 76 movl %ss, %eax 77 push %rax 78 79 /* Copy args passed on stack */ 80 movq 0x30(%rsp), %rbp 81 movq 0x38(%rsp), %rbx 82 movq 0x40(%rsp), %rax 83 84 /* 85 * Convert x86-64 ABI params to i386 ABI 86 */ 87 subq $64, %rsp 88 movl %esi, 0x0(%rsp) 89 movl %edx, 0x4(%rsp) 90 movl %ecx, 0x8(%rsp) 91 movl %r8d, 0xc(%rsp) 92 movl %r9d, 0x10(%rsp) 93 movl %ebp, 0x14(%rsp) 94 movl %ebx, 0x18(%rsp) 95 movl %eax, 0x1c(%rsp) 96 97 leaq 0x20(%rsp), %rbx 98 sgdt (%rbx) 99 sidt 16(%rbx) 100 101 leaq 1f(%rip), %rbp 102 103 /* 104 * Switch to IDT and GDT with 32-bit segments. These are the firmware 105 * GDT and IDT that were installed when the kernel started executing. 106 * The pointers were saved by the efi32_entry() routine below. 107 * 108 * Pass the saved DS selector to the 32-bit code, and use far return to 109 * restore the saved CS selector. 110 */ 111 lidt efi32_boot_idt(%rip) 112 lgdt efi32_boot_gdt(%rip) 113 114 movzwl efi32_boot_ds(%rip), %edx 115 movzwq efi32_boot_cs(%rip), %rax 116 pushq %rax 117 leaq efi_enter32(%rip), %rax 118 pushq %rax 119 lretq 120 1211: addq $64, %rsp 122 movq %rdi, %rax 123 124 pop %rbx 125 movl %ebx, %ss 126 pop %rbx 127 movl %ebx, %es 128 pop %rbx 129 movl %ebx, %ds 130 /* Clear out 32-bit selector from FS and GS */ 131 xorl %ebx, %ebx 132 movl %ebx, %fs 133 movl %ebx, %gs 134 135 pop %rbx 136 pop %rbp 137 RET 138SYM_FUNC_END(__efi64_thunk) 139 140 .code32 141/* 142 * EFI service pointer must be in %edi. 143 * 144 * The stack should represent the 32-bit calling convention. 145 */ 146SYM_FUNC_START_LOCAL(efi_enter32) 147 /* Load firmware selector into data and stack segment registers */ 148 movl %edx, %ds 149 movl %edx, %es 150 movl %edx, %fs 151 movl %edx, %gs 152 movl %edx, %ss 153 154 /* Reload pgtables */ 155 movl %cr3, %eax 156 movl %eax, %cr3 157 158 /* Disable paging */ 159 movl %cr0, %eax 160 btrl $X86_CR0_PG_BIT, %eax 161 movl %eax, %cr0 162 163 /* Disable long mode via EFER */ 164 movl $MSR_EFER, %ecx 165 rdmsr 166 btrl $_EFER_LME, %eax 167 wrmsr 168 169 call *%edi 170 171 /* We must preserve return value */ 172 movl %eax, %edi 173 174 /* 175 * Some firmware will return with interrupts enabled. Be sure to 176 * disable them before we switch GDTs and IDTs. 177 */ 178 cli 179 180 lidtl 16(%ebx) 181 lgdtl (%ebx) 182 183 movl %cr4, %eax 184 btsl $(X86_CR4_PAE_BIT), %eax 185 movl %eax, %cr4 186 187 movl %cr3, %eax 188 movl %eax, %cr3 189 190 movl $MSR_EFER, %ecx 191 rdmsr 192 btsl $_EFER_LME, %eax 193 wrmsr 194 195 xorl %eax, %eax 196 lldt %ax 197 198 pushl $__KERNEL_CS 199 pushl %ebp 200 201 /* Enable paging */ 202 movl %cr0, %eax 203 btsl $X86_CR0_PG_BIT, %eax 204 movl %eax, %cr0 205 lret 206SYM_FUNC_END(efi_enter32) 207 208/* 209 * This is the common EFI stub entry point for mixed mode. 210 * 211 * Arguments: %ecx image handle 212 * %edx EFI system table pointer 213 * %esi struct bootparams pointer (or NULL when not using 214 * the EFI handover protocol) 215 * 216 * Since this is the point of no return for ordinary execution, no registers 217 * are considered live except for the function parameters. [Note that the EFI 218 * stub may still exit and return to the firmware using the Exit() EFI boot 219 * service.] 220 */ 221SYM_FUNC_START(efi32_entry) 222 call 1f 2231: pop %ebx 224 225 /* Save firmware GDTR and code/data selectors */ 226 sgdtl (efi32_boot_gdt - 1b)(%ebx) 227 movw %cs, (efi32_boot_cs - 1b)(%ebx) 228 movw %ds, (efi32_boot_ds - 1b)(%ebx) 229 230 /* Store firmware IDT descriptor */ 231 sidtl (efi32_boot_idt - 1b)(%ebx) 232 233 /* Store boot arguments */ 234 leal (efi32_boot_args - 1b)(%ebx), %ebx 235 movl %ecx, 0(%ebx) 236 movl %edx, 4(%ebx) 237 movl %esi, 8(%ebx) 238 movb $0x0, 12(%ebx) // efi_is64 239 240 /* Disable paging */ 241 movl %cr0, %eax 242 btrl $X86_CR0_PG_BIT, %eax 243 movl %eax, %cr0 244 245 jmp startup_32 246SYM_FUNC_END(efi32_entry) 247 248#define ST32_boottime 60 // offsetof(efi_system_table_32_t, boottime) 249#define BS32_handle_protocol 88 // offsetof(efi_boot_services_32_t, handle_protocol) 250#define LI32_image_base 32 // offsetof(efi_loaded_image_32_t, image_base) 251 252/* 253 * efi_status_t efi32_pe_entry(efi_handle_t image_handle, 254 * efi_system_table_32_t *sys_table) 255 */ 256SYM_FUNC_START(efi32_pe_entry) 257 pushl %ebp 258 movl %esp, %ebp 259 pushl %eax // dummy push to allocate loaded_image 260 261 pushl %ebx // save callee-save registers 262 pushl %edi 263 264 call verify_cpu // check for long mode support 265 testl %eax, %eax 266 movl $0x80000003, %eax // EFI_UNSUPPORTED 267 jnz 2f 268 269 call 1f 2701: pop %ebx 271 272 /* Get the loaded image protocol pointer from the image handle */ 273 leal -4(%ebp), %eax 274 pushl %eax // &loaded_image 275 leal (loaded_image_proto - 1b)(%ebx), %eax 276 pushl %eax // pass the GUID address 277 pushl 8(%ebp) // pass the image handle 278 279 /* 280 * Note the alignment of the stack frame. 281 * sys_table 282 * handle <-- 16-byte aligned on entry by ABI 283 * return address 284 * frame pointer 285 * loaded_image <-- local variable 286 * saved %ebx <-- 16-byte aligned here 287 * saved %edi 288 * &loaded_image 289 * &loaded_image_proto 290 * handle <-- 16-byte aligned for call to handle_protocol 291 */ 292 293 movl 12(%ebp), %eax // sys_table 294 movl ST32_boottime(%eax), %eax // sys_table->boottime 295 call *BS32_handle_protocol(%eax) // sys_table->boottime->handle_protocol 296 addl $12, %esp // restore argument space 297 testl %eax, %eax 298 jnz 2f 299 300 movl 8(%ebp), %ecx // image_handle 301 movl 12(%ebp), %edx // sys_table 302 movl -4(%ebp), %esi // loaded_image 303 movl LI32_image_base(%esi), %esi // loaded_image->image_base 304 leal (startup_32 - 1b)(%ebx), %ebp // runtime address of startup_32 305 /* 306 * We need to set the image_offset variable here since startup_32() will 307 * use it before we get to the 64-bit efi_pe_entry() in C code. 308 */ 309 subl %esi, %ebp // calculate image_offset 310 movl %ebp, (image_offset - 1b)(%ebx) // save image_offset 311 xorl %esi, %esi 312 jmp efi32_entry // pass %ecx, %edx, %esi 313 // no other registers remain live 314 3152: popl %edi // restore callee-save registers 316 popl %ebx 317 leave 318 RET 319SYM_FUNC_END(efi32_pe_entry) 320 321 .section ".rodata" 322 /* EFI loaded image protocol GUID */ 323 .balign 4 324SYM_DATA_START_LOCAL(loaded_image_proto) 325 .long 0x5b1b31a1 326 .word 0x9562, 0x11d2 327 .byte 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b 328SYM_DATA_END(loaded_image_proto) 329 330 .data 331 .balign 8 332SYM_DATA_START_LOCAL(efi32_boot_gdt) 333 .word 0 334 .quad 0 335SYM_DATA_END(efi32_boot_gdt) 336 337SYM_DATA_START_LOCAL(efi32_boot_idt) 338 .word 0 339 .quad 0 340SYM_DATA_END(efi32_boot_idt) 341 342SYM_DATA_LOCAL(efi32_boot_cs, .word 0) 343SYM_DATA_LOCAL(efi32_boot_ds, .word 0) 344SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0) 345SYM_DATA(efi_is64, .byte 1) 346