]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdePkg/Library/BaseLib/X64/Thunk16.asm
Add volatile to modify LockValue in AcquireLockOrFail().
[mirror_edk2.git] / MdePkg / Library / BaseLib / X64 / Thunk16.asm
... / ...
CommitLineData
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
22EXTERNDEF m16Start:BYTE\r
23EXTERNDEF m16Size:WORD\r
24EXTERNDEF mThunk16Attr:WORD\r
25EXTERNDEF m16Gdt:WORD\r
26EXTERNDEF m16GdtrBase:WORD\r
27EXTERNDEF mTransition:WORD\r
28\r
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
42_EFLAGS DQ ?\r
43_EIP DD ?\r
44_CS DW ?\r
45_SS DW ?\r
46IA32_REGS ENDS\r
47\r
48 .const\r
49\r
50m16Size DW InternalAsmThunk16 - m16Start\r
51mThunk16Attr DW _ThunkAttr - m16Start\r
52m16Gdt DW _NullSeg - m16Start\r
53m16GdtrBase DW _16GdtrBase - m16Start\r
54mTransition DW _EntryPoint - m16Start\r
55\r
56 .code\r
57\r
58m16Start LABEL BYTE\r
59\r
60SavedGdt LABEL FWORD\r
61 DW ?\r
62 DQ ?\r
63\r
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
68_BackFromUserCode PROC\r
69 DB 16h ; push ss\r
70 DB 0eh ; push cs\r
71 DB 66h\r
72 call @Base ; push eip\r
73@Base:\r
74 DB 66h\r
75 push 0 ; reserved high order 32 bits of EFlags\r
76 pushf ; pushfd actually\r
77 cli ; disable interrupts\r
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
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
99 mov word ptr (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._ESP, bp\r
100 mov ebx, (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._EIP\r
101 shl ax, 4 ; shl eax, 4\r
102 add bp, ax ; add ebp, eax\r
103 mov ax, cs\r
104 shl ax, 4\r
105 lea ax, [eax + ebx + (@64BitCode - @Base)]\r
106 DB 2eh ; cs:\r
107 mov [rdi + (@64Eip - @Base)], ax\r
108 DB 66h, 0b8h ; mov eax, imm32\r
109SavedCr4 DD ?\r
110 mov cr4, rax\r
111 DB 66h, 2eh\r
112 lgdt fword ptr [rdi + (SavedGdt - @Base)]\r
113 DB 66h\r
114 mov ecx, 0c0000080h\r
115 rdmsr\r
116 or ah, 1\r
117 wrmsr\r
118 DB 66h, 0b8h ; mov eax, imm32\r
119SavedCr0 DD ?\r
120 mov cr0, rax\r
121 DB 66h, 0eah ; jmp far cs:@64Bit\r
122@64Eip DD ?\r
123SavedCs DW ?\r
124@64BitCode:\r
125 DB 48h, 0b8h ; mov rax, imm64\r
126SavedRip DQ ?\r
127 jmp rax ; return to caller\r
128_BackFromUserCode ENDP\r
129\r
130_EntryPoint DD _ToUserCode - m16Start\r
131 DW CODE16\r
132_16Gdtr LABEL FWORD\r
133 DW GDT_SIZE - 1\r
134_16GdtrBase DQ _NullSeg\r
135_16Idtr FWORD (1 SHL 10) - 1\r
136\r
137;------------------------------------------------------------------------------\r
138; _ToUserCode() takes control in real mode before passing control to user code.\r
139; It will be shadowed to somewhere in memory below 1MB.\r
140;------------------------------------------------------------------------------\r
141_ToUserCode PROC\r
142 mov ss, edx ; set new segment selectors\r
143 mov ds, edx\r
144 mov es, edx\r
145 mov fs, edx\r
146 mov gs, edx\r
147 DB 66h\r
148 mov ecx, 0c0000080h\r
149 mov cr0, rax ; real mode starts at next instruction\r
150 rdmsr\r
151 and ah, NOT 1\r
152 wrmsr\r
153 mov cr4, rbp\r
154 mov ss, esi ; set up 16-bit stack segment\r
155 mov sp, bx ; set up 16-bit stack pointer\r
156 DB 66h\r
157 call @Base ; push eip\r
158@Base:\r
159 pop bp ; ebp <- address of @Base\r
160 push [esp + sizeof (IA32_REGS) + 2]\r
161 lea eax, [rsi + (@RealMode - @Base)]\r
162 push rax\r
163 retf\r
164@RealMode:\r
165 DB 66h, 2eh ; CS and operand size override\r
166 lidt fword ptr [rsi + (_16Idtr - @Base)]\r
167 DB 66h, 61h ; popad\r
168 DB 1fh ; pop ds\r
169 DB 07h ; pop es\r
170 pop fs\r
171 pop gs\r
172 popf ; popfd\r
173 lea sp, [esp + 4] ; skip high order 32 bits of EFlags\r
174 DB 66h\r
175 retf ; transfer control to user code\r
176_ToUserCode ENDP\r
177\r
178CODE16 = _16Code - $\r
179DATA16 = _16Data - $\r
180DATA32 = _32Data - $\r
181\r
182_NullSeg DQ 0\r
183_16Code LABEL QWORD\r
184 DW -1\r
185 DW 0\r
186 DB 0\r
187 DB 9bh\r
188 DB 8fh ; 16-bit segment, 4GB limit\r
189 DB 0\r
190_16Data LABEL QWORD\r
191 DW -1\r
192 DW 0\r
193 DB 0\r
194 DB 93h\r
195 DB 8fh ; 16-bit segment, 4GB limit\r
196 DB 0\r
197_32Data LABEL QWORD\r
198 DW -1\r
199 DW 0\r
200 DB 0\r
201 DB 93h\r
202 DB 0cfh ; 16-bit segment, 4GB limit\r
203 DB 0\r
204\r
205GDT_SIZE = $ - _NullSeg\r
206\r
207;------------------------------------------------------------------------------\r
208; IA32_REGISTER_SET *\r
209; EFIAPI\r
210; InternalAsmThunk16 (\r
211; IN IA32_REGISTER_SET *RegisterSet,\r
212; IN OUT VOID *Transition\r
213; );\r
214;------------------------------------------------------------------------------\r
215InternalAsmThunk16 PROC USES rbp rbx rsi rdi\r
216 mov r10d, ds\r
217 mov r11d, es\r
218 mov r9d, ss\r
219 push fs\r
220 push gs\r
221 mov rsi, rcx\r
222 movzx r8d, (IA32_REGS ptr [rsi])._SS\r
223 mov edi, (IA32_REGS ptr [rsi])._ESP\r
224 lea rdi, [edi - (sizeof (IA32_REGS) + 4)]\r
225 imul eax, r8d, 16 ; eax <- r8d(stack segment) * 16\r
226 mov ebx, edi ; ebx <- stack for 16-bit code\r
227 push sizeof (IA32_REGS) / 4\r
228 add edi, eax ; edi <- linear address of 16-bit stack\r
229 pop rcx\r
230 rep movsd ; copy RegSet\r
231 lea ecx, [rdx + (SavedCr4 - m16Start)]\r
232 mov eax, edx ; eax <- transition code address\r
233 and edx, 0fh\r
234 shl eax, 12\r
235 lea ax, [rdx + (_BackFromUserCode - m16Start)]\r
236 stosd ; [edi] <- return address of user code\r
237 sgdt fword ptr [rcx + (SavedGdt - SavedCr4)]\r
238 sidt fword ptr [rsp + 38h] ; save IDT stack in argument space\r
239 mov rax, cr0\r
240 mov [rcx + (SavedCr0 - SavedCr4)], eax\r
241 and eax, 7ffffffeh ; clear PE, PG bits\r
242 mov rbp, cr4\r
243 mov [rcx], ebp ; save CR4 in SavedCr4\r
244 and ebp, 300h ; clear all but PCE and OSFXSR bits\r
245 mov esi, r8d ; esi <- 16-bit stack segment\r
246 DB 6ah, DATA32 ; push DATA32\r
247 pop rdx ; rdx <- 32-bit data segment selector\r
248 lgdt fword ptr [rcx + (_16Gdtr - SavedCr4)]\r
249 mov ss, edx\r
250 pushfq\r
251 lea edx, [rdx + DATA16 - DATA32]\r
252 lea r8, @RetFromRealMode\r
253 mov [rcx + (SavedRip - SavedCr4)], r8\r
254 mov r8d, cs\r
255 mov [rcx + (SavedCs - SavedCr4)], r8w\r
256 mov r8, rsp\r
257 jmp fword ptr [rcx + (_EntryPoint - SavedCr4)]\r
258@RetFromRealMode:\r
259 mov rsp, r8\r
260 popfq\r
261 lidt fword ptr [rsp + 38h] ; restore protected mode IDTR\r
262 lea eax, [rbp - sizeof (IA32_REGS)]\r
263 pop gs\r
264 pop fs\r
265 mov ss, r9d\r
266 mov es, r11d\r
267 mov ds, r10d\r
268 ret\r
269InternalAsmThunk16 ENDP\r
270\r
271 END\r