1 #***************************************************************************** 2 #* 3 #* Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR> 4 #* This program and the accompanying materials 5 #* are licensed and made available under the terms and conditions of the BSD License 6 #* which accompanies this distribution. The full text of the license may be found at 7 #* http://opensource.org/licenses/bsd-license.php 8 #* 9 #* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 #* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 #* 12 #* Module Name: 13 #* 14 #* Thunk.S 15 #* 16 #* Abstract: 17 #* 18 #* Real mode thunk 19 #* 20 #***************************************************************************** 21 #include <EfiBind.h> 22 23 #ifndef __APPLE__ 24 25 .data 26 27 .globl ASM_PFX(mCode16Size) 28 29 .data 30 mCode16Size: .long _Code16End - _Code16Addr 31 32 33 NullSegSel: .quad 0 34 _16CsSegSel: 35 .word -1 36 .word 0 37 .byte 0 38 .byte 0x9b 39 .byte 0x8f #16-bit segment 40 .byte 0 41 _16DsSegSel: 42 .word -1 43 .word 0 44 .byte 0 45 .byte 0x93 46 .byte 0x8f #16-bit segment 47 .byte 0 48 49 _16Gdtr: 50 .word _16Gdtr - NullSegSel - 1 51 .long NullSegSel 52 .code: 53 54 #IA32_REGS STRUC 4t 55 #_EDI DD ? 56 #_ESI DD ? 57 #_EBP DD ? 58 #_ESP DD ? 59 #_EBX DD ? 60 #_EDX DD ? 61 #_ECX DD ? 62 #_EAX DD ? 63 #_DS DW ? 64 #_ES DW ? 65 #_FS DW ? 66 #_GS DW ? 67 #_RFLAGS DQ ? 68 #_EIP DD ? 69 #_CS DW ? 70 #_SS DW ? 71 #IA32_REGS ENDS 72 73 #_STK16 STRUC 1t 74 #RetEip DD ? 75 #RetCs DW ? 76 #ThunkFlags DW ? 77 #SavedGdtr FWORD ? 78 #Resvd1 DW ? 79 #SavedCr0 DD ? 80 #SavedCr4 DD ? 81 #_STK16 ENDS 82 83 ASM_PFX(Thunk16): 84 push %rbp 85 push %rbx 86 push %rsi 87 push %rdi 88 push %r12 89 push %r13 90 push %r14 91 push %r15 92 pushq %fs 93 pushq %gs 94 movl %ds,%r12d 95 movl %es,%r13d 96 movl %ss,%r14d 97 mov %rsp,%r15 98 mov %rcx,%rsi 99 movzwq 0x36(%rsi),%r10 #movzx r10, (IA32_REGS ptr [rsi])._SS 100 xor %rdi,%rdi 101 mov 0xc(%rsi),%edi #mov edi, (IA32_REGS ptr [rsi])._ESP 102 add $0xffffffffffffffb0,%rdi #add rdi, - sizeof (IA32_REGS) - sizeof (_STK16) 103 push %rdi 104 imul $0x10,%r10,%rax 105 add %rax,%rdi 106 pushq $0xe #push sizeof (IA32_REGS) / 4 107 pop %rcx 108 rep movsl %ds:(%rsi),%es:(%rdi) 109 #; copy eflags to stack frame 110 mov -16(%rsi), %rax 111 mov %rax, -80(%rsi) 112 pop %rbx #rbx <- 16-bit stack offset 113 lea Label,%eax #42 <_Thunk16+0x42> 114 stos %eax,%es:(%rdi) 115 movl %cs,%eax #return segment 116 stos %ax,%es:(%rdi) 117 mov %edx,%eax #THUNK Flags 118 stos %ax,%es:(%rdi) 119 sgdt 0x58(%rsp) #save GDTR 120 mov 0x58(%rsp),%rax 121 stos %rax,%es:(%rdi) 122 mov %cr0,%rax #save CR0 123 mov %eax,%esi #esi <- CR0 to set 124 stos %eax,%es:(%rdi) 125 mov %cr4,%rax #save CR4 126 stos %eax,%es:(%rdi) 127 sidt 0x58(%rsp) #save IDTR 128 and $0x7ffffffe,%esi #clear PE & PG bits 129 mov %r10,%rdi #rdi <- 16-bit stack segment 130 shl $0x10,%r8 131 push %r8 #far jmp address 132 lea Label_16Bit,%eax 133 push %rax 134 movw $0x8,0x4(%rsp) 135 lgdt _16Gdtr #bugbug: may not match. 136 lret 137 Label_16Bit: 138 .byte 0x66 139 movl $0xc0000080,%ecx 140 mov %rsi,%cr0 #disable PE & PG 141 rdmsr 142 and $0xfe,%ah 143 wrmsr #clear LME bit 144 mov %cr4,%rax 145 and $0xcf,%al #clear PAE & PSE 146 mov %rax,%cr4 147 lret 148 149 Label: 150 xor %rax,%rax 151 movw %ss,%ax 152 shl $0x4,%eax 153 add %esp,%eax 154 mov %r15,%rsp 155 lidt 0x58(%rsp) 156 movl %r12d,%ds 157 movl %r13d,%es 158 movl %r14d,%ss 159 popq %gs 160 popq %fs 161 pop %r15 162 pop %r14 163 pop %r13 164 pop %r12 165 pop %rdi 166 pop %rsi 167 pop %rbx 168 pop %rbp 169 retq 170 171 172 .p2align 4 173 174 _Code16Addr: 175 ASM_PFX(RealMode): 176 movl %edi,%ss 177 mov %bx,%sp #set up 16-bit stack 178 .byte 0x2e 179 .byte 0x0f 180 .byte 0x01 181 .byte 0x1e 182 .word _16Idtr - _Code16Addr #lidt _16Idtr 183 .byte 0x66 184 .byte 0x61 #popad 185 .byte 0x1f #pop ds 186 .byte 0x07 #pop es 187 popq %fs 188 popq %gs 189 sub 64, %esp 190 .byte 0x66, 0x9d #popfd 191 add $0x4,%esp #skip high part of RFLAGS 192 .byte 0x67 #; test (_STK16 ptr [esp + STACK_PARAM_SIZE + sizeof(IA32_REGS)]).ThunkFlags, 1 193 .byte 0xf7 194 .byte 0x44 195 .byte 0x24 196 .byte 0x4e 197 .byte 0x01 198 .byte 0x00 199 jz 1f 200 pushfq #pushf, actually, when it's INT# 201 1: 202 .byte 0x0e #push cs 203 .byte 0x68 #push /iw 204 .word FarCallRet - _Code16Addr 205 jz 2f 206 .byte 0x66 207 ljmp *70(%esp) 208 2: 209 .byte 0x66 210 ljmp *68(%esp) 211 FarCallRet: 212 add 64, %esp 213 .byte 0x66 214 push $0x00 #push a dword of zero 215 .byte 0x66 216 pushf #pushfd, actually 217 pushq %gs 218 pushq %fs 219 .byte 0x06 #push %es 220 .byte 0x1e #push %ds 221 .byte 0x66 222 .byte 0x60 223 cli 224 .byte 0x66 #sizeof (IA32_REGS) = 13 * 4 = 52 225 lgdt 64(%esp) #lgdt (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedGdtr 226 .byte 0x66 227 mov 76(%esp), %eax 228 mov %rax, %cr4 229 .byte 0x66 230 mov $0xc0000080, %ecx 231 rdmsr 232 orb $1, %ah 233 wrmsr 234 .byte 0x66 235 mov 72(%esp), %eax 236 mov %rax, %cr0 #restore CR0 237 .byte 0x66 238 ljmpl *52(%esp) 239 240 _16Idtr: 241 .word 0x3ff #FWORD (1 SHL 10) - 1 242 .byte 0x00 243 244 #endif 245