1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
|
;/*++
; This file contains an 'Intel Peripheral Driver' and is
; licensed for Intel CPUs and chipsets under the terms of your
; license agreement with Intel or your vendor. This file may
; be modified by the user, subject to additional terms of the
; license agreement
;--*/
;------------------------------------------------------------------------------
;
; Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved
; This software and associated documentation (if any) is furnished
; under a license and may only be used or copied in accordance
; with the terms of the license. Except as permitted by such
; license, no part of this software or documentation may be
; reproduced, stored in a retrieval system, or transmitted in any
; form or by any means without the express written consent of
; Intel Corporation.
;
; Module Name:
;
; Thunk.asm
;
; Abstract:
;
; Real mode thunk
;
;------------------------------------------------------------------------------
.686p
.model flat,C
.const
EXTERNDEF mCode16Size:DWORD
mCode16Size DD _Code16End - _Code16Addr
.data
ALIGN 10h
NullSegSel DQ 0
_16CsSegSel LABEL QWORD
DW -1
DW 0
DB 0
DB 9Bh
DB 8Fh ; 16-bit segment, 4GB limit
DB 0
;_16DsSegSel LABEL QWORD
; DW -1
; DW 0
; DB 0
; DB 93h
; DB 8Fh ; 16-bit segment, 4GB limit
; DB 0
_16Gdtr LABEL FWORD
DW $ - offset NullSegSel - 1
DD offset NullSegSel
.code
IA32_REGS STRUC 4t
_EDI DD ?
_ESI DD ?
_EBP DD ?
_ESP DD ?
_EBX DD ?
_EDX DD ?
_ECX DD ?
_EAX DD ?
_DS DW ?
_ES DW ?
_FS DW ?
_GS DW ?
_EFLAGS DD ?
_EIP DD ?
_CS DW ?
_SS DW ?
IA32_REGS ENDS
_STK16 STRUC 1t
RetEip DD ?
RetCs DW ?
ThunkFlags DW ?
SavedGdtr FWORD ?
Resvd1 DW ?
SavedCr0 DD ?
SavedCr4 DD ?
_STK16 ENDS
; IA32_REGISTER_SET *
; EFIAPI
; _Thunk16 (
; IN OUT IA32_REGISTER_SET *RegisterSet,
; IN UINT32 ThunkFlags,
; IN UINT32 RealModeCs
; );
_Thunk16 PROC USES DS ES FS GS EDI ESI EBP EBX EDX ECX ; 10 dwords will be pushed
mov ebp, esp
add ebp, 40
mov ORG_SS, ss ; preserve SS & ESP
mov ORG_ESP, esp
mov esi, [ebp + 4] ; esi <- RegisterSet
movzx edx, (IA32_REGS ptr [esi])._SS ; find 16-bit stack linear address
shl edx, 4
add edx, (IA32_REGS ptr [esi])._ESP
add edx, - sizeof (IA32_REGS) - sizeof (_STK16) ; edx <- 16-bit stack linear address
mov edi, edx ; [RealMode.IA32_REGS] <- RegisterSet
push sizeof (IA32_REGS) / 4
pop ecx
rep movsd
lea eax, @F ; [RealMode._STK16.RetEip] <- ReturnOffset
stosd
mov eax, cs ; [RealMode._STK16.RetCs] <- ReturnSegment
stosw
mov eax, [ebp + 8] ; [RealMode._STK16.ThunkFlags] <- ThunkFlags
stosw
sgdt dword ptr [edi] ; [RealMode._STK16.SavedGdtr] <- GDTR
add edi, 8
mov eax, cr0 ; [RealMode._STK16.SavedCr0] <- CR0
stosd
mov esi, eax ; esi <- CR0 to set
and esi, 07FFFFFFEh ; clear BIT[24, 0]: PE & PG bits
mov eax, cr4 ; [RealMode._STK16.SavedCr4] <- CR4
stosd
push word ptr [ebp + 12] ; [STACK] <- RealModeCs, far jump address for into RealMode
pushw 0
pushd 8 ; transfer program control to a readable segment that has a limit of 64KB
pushd offset @16Bit
mov edi, edx ; edi <- 16-bit stack linear address
sidt fword ptr [ebp + 8] ; save IDTR
lgdt _16Gdtr
retf
@16Bit:
mov cr0, esi ; disable PE & PG
; db 066h
; mov ecx, 0C0000080h
; rdmsr
; and ah, NOT 1
; wrmsr ; clear LME bit
mov eax, cr4
and al, not 030h ; clear PAE & PSE
mov cr4, eax
retf
@@:
xor eax, eax
mov eax, ss
shl eax, 4
add eax, esp ; [EAX] <- RegisterSet after x86 call..to return the execution result
mov ss, cs:word ptr [ORG_SS] ; restore SS & ESP
mov esp, cs:dword ptr [ORG_ESP]
lidt fword ptr [ebp + 8] ; restore IDTR
ret
ORG_SS DW ?
ORG_ESP DD ?
_Thunk16 ENDP
ALIGN 10h
; VOID
; EFIAPI
; _Code16Addr (
; VOID
; );
_Code16Addr PROC
_Code16Addr ENDP
; Input: EDI <- 16-bit stack linear address
RealMode PROC
db 066h ; movzx esp, di
movzx esp, di
db 033h, 0FFh ; xor di, di
db 066h ; shr edi, 4
shr edi, 4
mov ss, di ; mov ss, di
db 02Eh, 00Fh, 001, 01Eh ; lidt cs:[_16Idtr]
dw (_16Idtr - _Code16Addr)
db 066h ; popad
popa
pop ds
pop es
pop fs
pop gs
add esp, 4 ; skip EFLAGS
; test if EFLAGS with _THUNK_INTERRUPT
db 067h, 00F7h, 044h, 024h, 00Eh, 001h, 000h ; test [esp + 0Eh]
jz @F
db 09Ch ; pushf
@@:
push cs
db 068h ; pushw
dw (@FarCallRet - _Code16Addr)
jz @F
db 066h, 067h
jmp fword ptr [esp + 6]
@@:
db 066h, 067h
jmp fword ptr [esp + 4]
@FarCallRet:
pushf ; pushfd actually
push gs
push fs
push es
push ds
db 066h ; pushad
pusha
cli
db 066h, 067h
lgdt (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedGdtr
db 066h, 067h
mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr4
mov cr4, eax
; db 066h
; mov ecx, 0C0000080h
; rdmsr
; or ah, 1
; wrmsr ; set LME
db 066h, 067h
mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr0
mov cr0, eax
db 066h, 067h
jmp fword ptr (_STK16 ptr [esp + sizeof(IA32_REGS)]).RetEip
RealMode ENDP
_16Idtr FWORD (1 shl 10) - 1
_Code16End:
END
|