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