]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdePkg/Library/BaseLib/X64/Thunk16.asm
Remove platform-specific Firmware Volume Block Driver implementation from EdkNt32Pkg...
[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 _NullSegDesc - 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 DB 66h, 0b8h ; mov eax, imm32\r
104SavedCr4 DD ?\r
105 mov cr4, rax\r
106 DB 66h, 2eh\r
107 lgdt fword ptr [rdi + (SavedGdt - @Base)]\r
108 DB 66h\r
109 mov ecx, 0c0000080h\r
110 rdmsr\r
111 or ah, 1\r
112 wrmsr\r
113 DB 66h, 0b8h ; mov eax, imm32\r
114SavedCr0 DD ?\r
115 mov cr0, rax\r
116 DB 0b8h ; mov ax, imm16\r
117SavedSs DW ?\r
118 mov ss, eax\r
119 DB 66h, 0bch ; mov esp, imm32\r
120SavedEsp DD ?\r
121 DB 66h\r
122 retf ; return to protected mode\r
123_BackFromUserCode ENDP\r
124\r
125_EntryPoint DD _ToUserCode - m16Start\r
126 DW 8h\r
127_16Gdtr LABEL FWORD\r
128 DW GdtEnd - _NullSegDesc - 1\r
129_16GdtrBase DQ _NullSegDesc\r
130_16Idtr FWORD (1 SHL 10) - 1\r
131\r
132;------------------------------------------------------------------------------\r
133; _ToUserCode() takes control in real mode before passing control to user code.\r
134; It will be shadowed to somewhere in memory below 1MB.\r
135;------------------------------------------------------------------------------\r
136_ToUserCode PROC\r
137 mov edi, ss\r
138 mov ss, edx ; set new segment selectors\r
139 mov ds, edx\r
140 mov es, edx\r
141 mov fs, edx\r
142 mov gs, edx\r
143 DB 66h\r
144 mov ecx, 0c0000080h\r
145 mov cr0, rax ; real mode starts at next instruction\r
146 rdmsr\r
147 and ah, NOT 1\r
148 wrmsr\r
149 mov cr4, rbp\r
150 mov ss, esi ; set up 16-bit stack segment\r
151 xchg sp, bx ; set up 16-bit stack pointer\r
152 DB 66h\r
153 call @Base ; push eip\r
154@Base:\r
155 pop bp ; ebp <- address of @Base\r
156 push [esp + sizeof (IA32_REGS) + 2]\r
157 lea eax, [rsi + (@RealMode - @Base)]\r
158 push rax\r
159 retf\r
160@RealMode:\r
161 DB 2eh ; cs:\r
162 mov [rsi + (SavedSs - @Base)], edi\r
163 DB 2eh ; cs:\r
164 mov [rsi + (SavedEsp - @Base)], bx\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
178_NullSegDesc DQ 0\r
179_16CsDesc LABEL QWORD\r
180 DW -1\r
181 DW 0\r
182 DB 0\r
183 DB 9bh\r
184 DB 8fh ; 16-bit segment, 4GB limit\r
185 DB 0\r
186_16DsDesc LABEL QWORD\r
187 DW -1\r
188 DW 0\r
189 DB 0\r
190 DB 93h\r
191 DB 8fh ; 16-bit segment, 4GB limit\r
192 DB 0\r
193GdtEnd LABEL QWORD\r
194\r
195;------------------------------------------------------------------------------\r
196; IA32_REGISTER_SET *\r
197; EFIAPI\r
198; InternalAsmThunk16 (\r
199; IN IA32_REGISTER_SET *RegisterSet,\r
200; IN OUT VOID *Transition\r
201; );\r
202;------------------------------------------------------------------------------\r
203InternalAsmThunk16 PROC USES rbp rbx rsi rdi\r
204 mov r10d, ds\r
205 mov r11d, es\r
206 push fs\r
207 push gs\r
208 mov rsi, rcx\r
209 movzx r8d, (IA32_REGS ptr [rsi])._SS\r
210 mov edi, (IA32_REGS ptr [rsi])._ESP\r
211 lea rdi, [edi - (sizeof (IA32_REGS) + 4)]\r
212 imul eax, r8d, 16 ; eax <- r8d(stack segment) * 16\r
213 mov ebx, edi ; ebx <- stack for 16-bit code\r
214 push sizeof (IA32_REGS) / 4\r
215 add edi, eax ; edi <- linear address of 16-bit stack\r
216 pop rcx\r
217 rep movsd ; copy RegSet\r
218 lea ecx, [rdx + (SavedCr4 - m16Start)]\r
219 mov eax, edx ; eax <- transition code address\r
220 and edx, 0fh\r
221 shl eax, 12\r
222 lea edx, [rdx + (_BackFromUserCode - m16Start)]\r
223 mov ax, dx\r
224 stosd ; [edi] <- return address of user code\r
225 sgdt fword ptr [rcx + (SavedGdt - SavedCr4)]\r
226 sidt fword ptr [rsp + 38h] ; save IDT stack in argument space\r
227 mov rax, cr0\r
228 mov [rcx + (SavedCr0 - SavedCr4)], eax\r
229 and eax, 7ffffffeh ; clear PE, PG bits\r
230 mov rbp, cr4\r
231 mov [rcx], ebp ; save CR4 in SavedCr4\r
232 and ebp, 300h ; clear all but PCE and OSFXSR bits\r
233 mov esi, r8d ; esi <- 16-bit stack segment\r
234 push 10h\r
235 pop rdx ; rdx <- selector for data segments\r
236 lgdt fword ptr [rcx + (_16Gdtr - SavedCr4)]\r
237 pushfq\r
238 call fword ptr [rcx + (_EntryPoint - SavedCr4)]\r
239 popfq\r
240 lidt fword ptr [rsp + 38h] ; restore protected mode IDTR\r
241 lea eax, [rbp - sizeof (IA32_REGS)]\r
242 pop gs\r
243 pop fs\r
244 mov es, r11d\r
245 mov ds, r10d\r
246 ret\r
247InternalAsmThunk16 ENDP\r
248\r
249 END\r