]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseLib/X64/Thunk16.asm
Fix the issue to clear the high 16-bit of EAX before use it Thunk code.
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / EdkIIGlueLib / Library / BaseLib / X64 / Thunk16.asm
1 ; Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
2 ; This program and the accompanying materials
3 ; are licensed and made available under the terms and conditions of the BSD License
4 ; which accompanies this distribution. The full text of the license may be found at
5 ; http://opensource.org/licenses/bsd-license.php
6 ;
7 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
8 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
9 ;
10 ; Module Name:
11 ;
12 ; Thunk.asm
13 ;
14 ; Abstract:
15 ;
16 ; Real mode thunk
17 ;
18 ;------------------------------------------------------------------------------
19
20 EXTERNDEF m16Start:BYTE
21 EXTERNDEF m16Size:WORD
22 EXTERNDEF mThunk16Attr:WORD
23 EXTERNDEF m16Gdt:WORD
24 EXTERNDEF m16GdtrBase:WORD
25 EXTERNDEF mTransition:WORD
26
27 THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 EQU 2
28 THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL EQU 4
29
30 IA32_REGS STRUC 4t
31 _EDI DD ?
32 _ESI DD ?
33 _EBP DD ?
34 _ESP DD ?
35 _EBX DD ?
36 _EDX DD ?
37 _ECX DD ?
38 _EAX DD ?
39 _DS DW ?
40 _ES DW ?
41 _FS DW ?
42 _GS DW ?
43 _EFLAGS DQ ?
44 _EIP DD ?
45 _CS DW ?
46 _SS DW ?
47 IA32_REGS ENDS
48
49 .const
50
51 m16Size DW InternalAsmThunk16 - m16Start
52 mThunk16Attr DW _ThunkAttr - m16Start
53 m16Gdt DW _NullSeg - m16Start
54 m16GdtrBase DW _16GdtrBase - m16Start
55 mTransition DW _EntryPoint - m16Start
56
57 .code
58
59 m16Start LABEL BYTE
60
61 SavedGdt LABEL FWORD
62 DW ?
63 DQ ?
64
65 ;------------------------------------------------------------------------------
66 ; _BackFromUserCode() takes control in real mode after 'retf' has been executed
67 ; by user code. It will be shadowed to somewhere in memory below 1MB.
68 ;------------------------------------------------------------------------------
69 _BackFromUserCode PROC
70 ;
71 ; The order of saved registers on the stack matches the order they appears
72 ; in IA32_REGS structure. This facilitates wrapper function to extract them
73 ; into that structure.
74 ;
75 ; Some instructions for manipulation of segment registers have to be written
76 ; in opcode since 64-bit MASM prevents accesses to those registers.
77 ;
78 DB 16h ; push ss
79 DB 0eh ; push cs
80 DB 66h
81 call @Base ; push eip
82 @Base:
83 DB 66h
84 push 0 ; reserved high order 32 bits of EFlags
85 pushf ; pushfd actually
86 cli ; disable interrupts
87 push gs
88 push fs
89 DB 6 ; push es
90 DB 1eh ; push ds
91 DB 66h, 60h ; pushad
92 DB 66h, 0bah ; mov edx, imm32
93 _ThunkAttr DD ?
94 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15
95 jz @1
96 mov eax, 15cd2401h ; mov ax, 2401h & int 15h
97 cli ; disable interrupts
98 jnc @2
99 @1:
100 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL
101 jz @2
102 in al, 92h
103 or al, 2
104 out 92h, al ; deactivate A20M#
105 @2:
106 xor ax, ax ; xor eax, eax
107 mov eax, ss ; mov ax, ss
108 lea bp, [esp + sizeof (IA32_REGS)]
109 ;
110 ; rsi in the following 2 instructions is indeed bp in 16-bit code
111 ;
112 mov word ptr (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._ESP, bp
113 DB 66h
114 mov ebx, (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._EIP
115 shl ax, 4 ; shl eax, 4
116 add bp, ax ; add ebp, eax
117 mov ax, cs
118 shl ax, 4
119 lea ax, [eax + ebx + (@64BitCode - @Base)]
120 DB 66h, 2eh, 89h, 87h ; mov cs:[bx + (@64Eip - @Base)], eax
121 DW @64Eip - @Base
122 DB 66h, 0b8h ; mov eax, imm32
123 SavedCr4 DD ?
124 mov cr4, rax
125 ;
126 ; rdi in the instruction below is indeed bx in 16-bit code
127 ;
128 DB 66h, 2eh ; 2eh is "cs:" segment override
129 lgdt fword ptr [rdi + (SavedGdt - @Base)]
130 DB 66h
131 mov ecx, 0c0000080h
132 rdmsr
133 or ah, 1
134 wrmsr
135 DB 66h, 0b8h ; mov eax, imm32
136 SavedCr0 DD ?
137 mov cr0, rax
138 DB 66h, 0eah ; jmp far cs:@64Bit
139 @64Eip DD ?
140 SavedCs DW ?
141 @64BitCode:
142 db 090h
143 db 067h, 0bch ; mov esp, imm32
144 SavedSp DD ? ; restore stack
145 nop
146 ret
147 _BackFromUserCode ENDP
148
149 _EntryPoint DD _ToUserCode - m16Start
150 DW CODE16
151 _16Gdtr LABEL FWORD
152 DW GDT_SIZE - 1
153 _16GdtrBase DQ _NullSeg
154 _16Idtr FWORD (1 SHL 10) - 1
155
156 ;------------------------------------------------------------------------------
157 ; _ToUserCode() takes control in real mode before passing control to user code.
158 ; It will be shadowed to somewhere in memory below 1MB.
159 ;------------------------------------------------------------------------------
160 _ToUserCode PROC
161 mov ss, edx ; set new segment selectors
162 mov ds, edx
163 mov es, edx
164 mov fs, edx
165 mov gs, edx
166 DB 66h
167 mov ecx, 0c0000080h
168 mov cr0, rax ; real mode starts at next instruction
169 rdmsr
170 and ah, NOT 1
171 wrmsr
172 mov cr4, rbp
173 mov ss, esi ; set up 16-bit stack segment
174 mov sp, bx ; set up 16-bit stack pointer
175 DB 66h ; make the following call 32-bit
176 call @Base ; push eip
177 @Base:
178 pop bp ; ebp <- address of @Base
179 push [esp + sizeof (IA32_REGS) + 2]
180 lea eax, [rsi + (@RealMode - @Base)] ; rsi is "bp" in 16-bit code
181 push rax
182 retf ; execution begins at next instruction
183 @RealMode:
184 DB 66h, 2eh ; CS and operand size override
185 lidt fword ptr [rsi + (_16Idtr - @Base)]
186 DB 66h, 61h ; popad
187 DB 1fh ; pop ds
188 DB 07h ; pop es
189 pop fs
190 pop gs
191 popf ; popfd
192 lea sp, [esp + 4] ; skip high order 32 bits of EFlags
193 DB 66h ; make the following retf 32-bit
194 retf ; transfer control to user code
195 _ToUserCode ENDP
196
197 CODE16 = _16Code - $
198 DATA16 = _16Data - $
199 DATA32 = _32Data - $
200
201 _NullSeg DQ 0
202 _16Code LABEL QWORD
203 DW -1
204 DW 0
205 DB 0
206 DB 9bh
207 DB 8fh ; 16-bit segment, 4GB limit
208 DB 0
209 _16Data LABEL QWORD
210 DW -1
211 DW 0
212 DB 0
213 DB 93h
214 DB 8fh ; 16-bit segment, 4GB limit
215 DB 0
216 _32Data LABEL QWORD
217 DW -1
218 DW 0
219 DB 0
220 DB 93h
221 DB 0cfh ; 16-bit segment, 4GB limit
222 DB 0
223
224 GDT_SIZE = $ - _NullSeg
225
226 ;------------------------------------------------------------------------------
227 ; IA32_REGISTER_SET *
228 ; EFIAPI
229 ; InternalAsmThunk16 (
230 ; IN IA32_REGISTER_SET *RegisterSet,
231 ; IN OUT VOID *Transition
232 ; );
233 ;------------------------------------------------------------------------------
234 InternalAsmThunk16 PROC USES rbp rbx rsi rdi
235 mov rbx, ds
236 push rbx ; Save ds segment register on the stack
237 mov rbx, es
238 push rbx ; Save es segment register on the stack
239 mov rbx, ss
240 push rbx ; Save ss segment register on the stack
241
242 push fs
243 push gs
244 mov rsi, rcx
245 movzx r8d, (IA32_REGS ptr [rsi])._SS
246 mov edi, (IA32_REGS ptr [rsi])._ESP
247 lea rdi, [edi - (sizeof (IA32_REGS) + 4)]
248 imul eax, r8d, 16 ; eax <- r8d(stack segment) * 16
249 mov ebx, edi ; ebx <- stack for 16-bit code
250 push sizeof (IA32_REGS) / 4
251 add edi, eax ; edi <- linear address of 16-bit stack
252 pop rcx
253 rep movsd ; copy RegSet
254 lea ecx, [rdx + (SavedCr4 - m16Start)]
255 mov eax, edx ; eax <- transition code address
256 and edx, 0fh
257 shl eax, 12 ; segment address in high order 16 bits
258 lea ax, [rdx + (_BackFromUserCode - m16Start)] ; offset address
259 stosd ; [edi] <- return address of user code
260 sgdt fword ptr [rcx + (SavedGdt - SavedCr4)]
261 sidt fword ptr [rsp + 50h] ; save IDT stack in argument space
262 mov rax, cr0
263 mov [rcx + (SavedCr0 - SavedCr4)], eax
264 and eax, 7ffffffeh ; clear PE, PG bits
265 mov rbp, cr4
266 mov [rcx], ebp ; save CR4 in SavedCr4
267 and ebp, 300h ; clear all but PCE and OSFXSR bits
268 mov esi, r8d ; esi <- 16-bit stack segment
269 DB 6ah, DATA32 ; push DATA32
270 pop rdx ; rdx <- 32-bit data segment selector
271 lgdt fword ptr [rcx + (_16Gdtr - SavedCr4)]
272 mov ss, edx
273 pushfq
274 lea edx, [rdx + DATA16 - DATA32]
275 lea r8, @RetFromRealMode
276 push r8
277 mov r8d, cs
278 mov [rcx + (SavedCs - SavedCr4)], r8w
279 mov [rcx + (SavedSp - SavedCr4)], esp
280 jmp fword ptr [rcx + (_EntryPoint - SavedCr4)]
281 @RetFromRealMode:
282 popfq
283 lidt fword ptr [rsp + 50h] ; restore protected mode IDTR
284 lea eax, [rbp - sizeof (IA32_REGS)]
285 pop gs
286 pop fs
287 pop rbx
288 mov ss, rbx
289 pop rbx
290 mov es, rbx
291 pop rbx
292 mov ds, rbx
293 ret
294 InternalAsmThunk16 ENDP
295
296 END