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