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