1;***************************************************************************** 2;* 3;* Copyright (c) 2006 - 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.asm 15;* 16;* Abstract: 17;* 18;* Real mode thunk 19;* 20;***************************************************************************** 21 22EXTERNDEF mCode16Size:QWORD 23 24 .const 25 26mCode16Size DQ _Code16End - _Code16Addr 27 28 .data 29 30NullSegSel DQ 0 31_16CsSegSel LABEL QWORD 32 DW -1 33 DW 0 34 DB 0 35 DB 9bh 36 DB 8fh ; 16-bit segment 37 DB 0 38_16DsSegSel LABEL QWORD 39 DW -1 40 DW 0 41 DB 0 42 DB 93h 43 DB 8fh ; 16-bit segment 44 DB 0 45 46_16Gdtr LABEL FWORD 47 DW $ - offset NullSegSel - 1 48 DQ offset NullSegSel 49 50 .code 51 52STACK_PARAM_SIZE EQU 16 53 54IA32_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 ? 71IA32_REGS ENDS 72 73_STK16 STRUC 1t 74RetEip DD ? 75RetCs DW ? 76ThunkFlags DW ? 77SavedGdtr FWORD ? 78Resvd1 DW ? 79SavedCr0 DD ? 80SavedCr4 DD ? 81_STK16 ENDS 82 83_Thunk16 PROC USES rbp rbx rsi rdi r12 r13 r14 r15 84 85 push fs 86 push gs 87 88 mov r12d, ds 89 mov r13d, es 90 mov r14d, ss 91 mov r15, rsp 92 mov rsi, rcx 93 movzx r10, (IA32_REGS ptr [rsi])._SS 94 xor rdi, rdi 95 mov edi, (IA32_REGS ptr [rsi])._ESP 96 add rdi, - sizeof (IA32_REGS) - sizeof (_STK16) 97 push rdi 98 imul rax, r10, 16 99 add rdi, rax 100 push sizeof (IA32_REGS) / 4 101 pop rcx 102 rep movsd 103 104 ; copy eflags to stack frame 105 mov rax, (IA32_REGS ptr [rsi - sizeof(IA32_REGS)])._RFLAGS 106 mov [rdi - sizeof(IA32_REGS) - STACK_PARAM_SIZE - 8], rax 107 108 pop rbx ; rbx <- 16-bit stack offset 109 lea eax, @F ; return offset 110 stosd 111 mov eax, cs ; return segment 112 stosw 113 mov eax, edx ; THUNK Flags 114 stosw 115 sgdt fword ptr [rsp + 58h] ; save GDTR 116 mov rax, [rsp + 58h] 117 stosq 118 mov rax, cr0 ; save CR0 119 mov esi, eax ; esi <- CR0 to set 120 stosd 121 mov rax, cr4 ; save CR4 122 stosd 123 sidt fword ptr [rsp + 58h] ; save IDTR 124 and esi, 07ffffffeh ; clear PE & PG bits 125 mov rdi, r10 ; rdi <- 16-bit stack segment 126 127 shl r8, 16 128 push r8 ; far jmp address 129 lea eax, @16Bit 130 push rax 131 mov word ptr [rsp + 4], 8 132 lgdt _16Gdtr 133 retf 134@16Bit: 135 DB 66h 136 mov ecx, 0c0000080h 137 mov cr0, rsi ; disable PE & PG 138 rdmsr 139 and ah, NOT 1 140 wrmsr ; clear LME bit 141 mov rax, cr4 142 and al, NOT 30h ; clear PAE & PSE 143 mov cr4, rax 144 retf 145@@: 146 xor rax, rax 147 mov ax, ss 148 shl eax, 4 149 add eax, esp ; rax <- address of 16-bit stack 150 mov rsp, r15 151 lidt fword ptr [rsp + 58h] ; restore IDTR 152 mov ds, r12d 153 mov es, r13d 154 mov ss, r14d 155 pop gs 156 pop fs 157 ret 158_Thunk16 ENDP 159 160 ALIGN 10h 161 162_Code16Addr PROC 163_Code16Addr ENDP 164 165RealMode PROC 166 mov ss, edi 167 mov sp, bx ; set up 16-bit stack 168 DB 2eh, 0fh, 1, 1eh 169 DW _16Idtr - _Code16Addr ; lidt _16Idtr 170 DB 66h, 61h ; popad 171 DB 1fh ; pop ds 172 DB 7 ; pop es 173 pop fs 174 pop gs 175 sub esp, (sizeof(IA32_REGS) - 16) + STACK_PARAM_SIZE + 8 176 177 DB 66h, 9Dh ; popfd 178 add esp, 4 ; skip high part of RFLAGS 179 DB 67h, 0f7h, 44h, 24h ; test (_STK16 ptr [esp + STACK_PARAM_SIZE + sizeof(IA32_REGS)]).ThunkFlags, 1 180 DB (STACK_PARAM_SIZE + sizeof(IA32_REGS) + 6) 181 DB 1, 0 182 jz @F 183 pushfq ; pushf, actually, when it's INT# 184@@: 185 DB 0eh ; push cs 186 DB 68h ; push /iw 187 DW @FarCallRet - _Code16Addr 188 jz @F 189 DB 66h 190 jmp fword ptr [esp + 6 + STACK_PARAM_SIZE + sizeof(IA32_REGS) - 8] 191@@: 192 DB 66h 193 jmp fword ptr [esp + 4 + STACK_PARAM_SIZE + sizeof(IA32_REGS) - 8] 194@FarCallRet: 195 add esp, (sizeof(IA32_REGS) - 16) + STACK_PARAM_SIZE + 8 196 DB 66h 197 push 0 ; push a dword of zero 198 pushf ; pushfd, actually 199 push gs 200 push fs 201 DB 6 ; push es 202 DB 1eh ; push ds 203 DB 66h, 60h ; pushad 204 cli 205 206 DB 66h 207 lgdt (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedGdtr 208 DB 66h 209 mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr4 210 mov cr4, rax 211 DB 66h 212 mov ecx, 0c0000080h 213 rdmsr 214 or ah, 1 215 wrmsr ; set LME 216 DB 66h 217 mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr0 218 mov cr0, rax 219 DB 66h 220 jmp fword ptr (_STK16 ptr [esp + sizeof(IA32_REGS)]).RetEip 221 222RealMode ENDP 223 224_16Idtr FWORD (1 SHL 10) - 1 225 226_Code16End: 227 228 END 229