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