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
|
;------------------------------------------------------------------------------
;
; Copyright (c) 2006, Intel Corporation
; All rights reserved. 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
;
;------------------------------------------------------------------------------
.data
NullSegSel DQ 0
_16CsSegSel LABEL QWORD
DW -1
DW 0
DB 0
DB 9bh
DB 8fh ; 16-bit segment
DB 0
_16BitDsSel LABEL QWORD
DW -1
DW 0
DB 0
DB 93h
DB 8fh ; 16-bit segment
DB 0
GdtEnd LABEL QWORD
.const
_16Gdtr LABEL FWORD
DW offset GdtEnd - offset NullSegSel - 1
DQ offset NullSegSel
_16Idtr FWORD (1 SHL 10) - 1
.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 ?
_RFLAGS DQ ?
_EIP DD ?
_CS DW ?
_SS DW ?
IA32_REGS ENDS
InternalAsmThunk16 PROC USES rbp rbx rsi rdi r12 r13 r14 r15
mov eax, ds
push rax
mov eax, es
push rax
push fs
push gs
mov rsi, rcx ; rsi <- RegSet
push sizeof (IA32_REGS)
pop rcx
movzx r8, (IA32_REGS ptr [rsi])._SS
xor rdi, rdi
mov edi, (IA32_REGS ptr [rsi])._ESP
sub rdi, rcx ; reserve space on realmode stack
push rdi ; save stack offset
imul rax, r8, 16
add rdi, rax ; rdi <- linear address of 16-bit stack
rep movsb ; copy RegSet
mov rsi, r8 ; si <- 16-bit stack segment
pop rbx ; rbx <- 16-bit stack offset
mov rdi, rdx ; rdi <- realmode patch
lea eax, @BackToThunk ; rax <- address to back from real mode
push rax ; use in a far return
mov eax, cs
mov [rsp + 4], eax ; save CS
lea eax, @16Return ; thus @Return must < 4GB
stosd ; set ret address offset
xor eax, eax
stosw ; set ret CS base to 0
mov eax, esp
stosd ; rsp must < 4GB
mov eax, ss
stosd
mov rax, cr0
mov ecx, eax ; ecx <- CR0
and ecx, 7ffffffeh ; clear PE, PG bits
stosd
mov rax, cr4
mov ebp, eax
and ebp, 300h ; clear all but PCE and OSFXSR bits
stosd
sidt fword ptr [rsp + 70h] ; use parameter space to save IDTR
sgdt fword ptr [rdi]
lea edi, _16Idtr
lea eax, @16Start ; rax <- seg:offset of @16Start
push rax
mov dword ptr [rsp + 4], 8
push 10h
pop rax ; rax <- 10h as dataseg selector
lgdt _16Gdtr
retf
@16Start: ; 16-bit starts here
mov ss, eax ; set SS to be a 16-bit segment
mov cr0, rcx ; disable protected mode
mov cr4, rbp
DB 66h
mov ecx, 0c0000080h
rdmsr
and ah, NOT 1 ; clear LME
wrmsr
mov ss, esi ; set up 16-bit stack
mov sp, bx ; mov esp, ebx actually
lidt fword ptr [edi]
DB 66h, 61h ; popad
DB 1fh ; pop ds
DB 7 ; pop es
pop fs
pop gs
add sp, 8 ; skip _RFLAGS
DB 66h
retf ; transfer control to 16-bit code
@16Return:
DB 66h
push 0 ; high order 32 bits of rflags
pushf ; pushfd actually
push gs
push fs
DB 6 ; push es
DB 1eh ; push ds
DB 66h, 60h ; pushad
DB 67h, 66h, 0c5h, 74h, 24h, 30h ; lds esi, [esp + 12*4]
DB 66h
mov eax, [esi + 12]
mov cr4, rax ; restore CR4
DB 66h
lgdt fword ptr [esi + 16]
DB 66h
mov ecx, 0c0000080h
rdmsr
or ah, 1 ; set LME
wrmsr
DB 66h
mov eax, [esi + 8]
mov cr0, rax ; restore CR0
xor ax, ax ; xor eax, eax actually
mov eax, ss
mov dword ptr (IA32_REGS ptr [esp])._SS, eax
shl ax, 4 ; shl eax, 4 actually
add ax, sp ; add eax, esp actually
add sp, sizeof (IA32_REGS) ; add esp, sizeof (IA32_REGS)
DB 66h
mov dword ptr (IA32_REGS ptr [esp - sizeof (IA32_REGS)])._ESP, esp
DB 66h
lss esp, fword ptr [esi] ; restore protected mode stack
DB 66h
retf ; go back to protected mode
@BackToThunk:
lidt fword ptr [rsp + 68h] ; restore protected mode IDTR
shl rax, 32
shr rax, 32 ; clear high order 32 bits of RAX
pop gs
pop fs
pop rcx
mov es, ecx
pop rcx
mov ds, ecx
ret
InternalAsmThunk16 ENDP
END
|