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
|
;*****************************************************************************
;*
;* Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
;* This program and the accompanying materials
;* are licensed and made available under the terms and conditions of the BSD License
;* which accompanies this distribution. The full text of the license may be found at
;* http://opensource.org/licenses/bsd-license.php
;*
;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
;*
;* Module Name:
;*
;* Thunk.asm
;*
;* Abstract:
;*
;* Real mode thunk
;*
;*****************************************************************************
.686p
EXTERNDEF C mCode16Size:DWORD
CONST SEGMENT FLAT "DATA" READONLY
mCode16Size DD _TEXT16SIZE
CONST ENDS
_DATA SEGMENT FLAT "DATA"
NullSegSel DQ 0
_16BitCsSel LABEL QWORD
DW -1
DW 0
DB 0
DB 9bh
DB 8fh ; 16-bit segment
DB 0
_16BitSsSel LABEL QWORD
DW -1
DW 0
DB 0
DB 93h
DB 8fh ; 16-bit segment
DB 0
_16Gdtr LABEL FWORD
DW $ - offset NullSegSel - 1
DD offset NullSegSel
_DATA ENDS
_TEXT SEGMENT FLAT "CODE" PARA
STACK_PARAM_SIZE EQU 16
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 ?
SavedEsp DD ?
SavedSs DW ?
SavedGdtr FWORD ?
SavedCr0 DD ?
SavedCr4 DD ?
_STK16 ENDS
ASSUME ds:_DATA
__Thunk16 PROC USES ebp ebx esi edi ds es fs gs
ASSUME esi:PTR IA32_REGS
mov esi, [esp + 36]
movzx edx, [esi]._SS
mov edi, [esi]._ESP
add edi, - sizeof (_STK16) - sizeof (IA32_REGS)
push edi ; save stack offset
imul eax, edx, 16 ; eax <- edx*16
add edi, eax ; edi <- linear address of 16-bit stack
push sizeof (IA32_REGS) / 4
pop ecx
rep movsd ; copy context to 16-bit stack
; copy eflags to stack frame
mov eax, [esi - sizeof(IA32_REGS)]._EFLAGS
mov [edi - sizeof(IA32_REGS) - STACK_PARAM_SIZE - 4], eax
pop ebx ; ebx <- 16-bit stack offset
mov eax, offset @F ; return offset
stosd
mov eax, cs ; return segment
stosw
mov eax, [esp + 40] ; THUNK flags
stosw
mov eax, esp
stosd ; save esp
mov eax, ss ; save ss
stosw
sgdt fword ptr [edi] ; save GDTR
sidt fword ptr [esp + 36] ; save IDTR
mov esi, cr0
mov [edi + 6], esi ; save CR0
and esi, NOT 80000001h ; esi <- CR0 to set
mov eax, cr4
mov [edi + 10], eax ; save CR4
and al, NOT 30h ; clear PAE & PSE
mov edi, edx ; edi <- 16-bit stack segment
mov edx, [esp + 44]
shl edx, 16
push edx
pop edx
mov dx, _16BitSsSel - NullSegSel
lgdt _16Gdtr ; load 16-bit GDTR
DB 0eah
DD offset @16Bit
DW _16BitCsSel - NullSegSel ; jmp far 8:@16Bit
@16Bit:
mov ss, dx
mov cr0, esi ; disable protected mode
mov cr4, eax ; disable PAE & PSE
db 67h, 0FFh, 06Ch, 024h, 0FCh ; jmp dword ptr [esp-4]
@@:
xor eax, eax
mov ax, ss
shl eax, 4
add eax, esp ; eax <- address of 16-bit stack
lss esp, fword ptr (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedEsp
lidt fword ptr [esp + 36] ; restore IDTR
ret
__Thunk16 ENDP
_TEXT ENDS
_TEXT16 SEGMENT USE16 "CODE" PARA
_Code16Addr PROC C
_Code16Addr ENDP
RealMode PROC
mov ss, di ; set up stack
mov esp, ebx
lidt fword ptr cs:[_16Idtr - _Code16Addr]
popad
pop ds
pop es
pop fs
pop gs
sub esp, (sizeof(IA32_REGS) - 12) + STACK_PARAM_SIZE + 4
popfd
test (_STK16 ptr [esp + STACK_PARAM_SIZE + sizeof(IA32_REGS)]).ThunkFlags, 1
jz @F
pushf ; push Flags when it's INT#
@@:
push cs
; push @FarCallRet - _Code16Addr
DB 68h ; push /iw
DW @FarCallRet - _Code16Addr
jz @F
jmp fword ptr [esp + 6 + STACK_PARAM_SIZE + sizeof(IA32_REGS) - 8]
@@:
jmp fword ptr [esp + 4 + STACK_PARAM_SIZE + sizeof(IA32_REGS) - 8]
@FarCallRet:
add esp, (sizeof(IA32_REGS) - 12) + STACK_PARAM_SIZE + 4
pushfd
push gs
push fs
push es
push ds
pushad
cli
DB 66h
lgdt (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedGdtr
mov eax, (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedCr4
mov cr4, eax
mov eax, (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedCr0
mov cr0, eax ; restore CR0
jmp fword ptr (_STK16 ptr [esp + sizeof (IA32_REGS)]).RetEip
RealMode ENDP
_16Idtr FWORD (1 SHL 10) - 1
_TEXT16END:
_TEXT16SIZE = _TEXT16END - _Code16Addr
_TEXT16 ENDS
END
|