]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseLib/Ia32/Thunk16.nasm
MdePkg/BaseLib: Support IA32 processors without CLFLUSH
[mirror_edk2.git] / MdePkg / Library / BaseLib / Ia32 / Thunk16.nasm
CommitLineData
6dab5c8a
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: resd 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
54;; .const\r
55\r
56SECTION .data\r
57\r
58;\r
59; These are global constant to convey information to C code.\r
60;\r
15f8eef7 61ASM_PFX(m16Size) DW ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start)\r
7458df40 62ASM_PFX(mThunk16Attr) DW _BackFromUserCode.ThunkAttrEnd - 4 - ASM_PFX(m16Start)\r
6dab5c8a
JJ
63ASM_PFX(m16Gdt) DW _NullSegDesc - ASM_PFX(m16Start)\r
64ASM_PFX(m16GdtrBase) DW _16GdtrBase - ASM_PFX(m16Start)\r
65ASM_PFX(mTransition) DW _EntryPoint - ASM_PFX(m16Start)\r
66\r
67SECTION .text\r
68\r
69ASM_PFX(m16Start):\r
70\r
71SavedGdt:\r
72 dw 0\r
73 dd 0\r
74\r
75;------------------------------------------------------------------------------\r
76; _BackFromUserCode() takes control in real mode after 'retf' has been executed\r
77; by user code. It will be shadowed to somewhere in memory below 1MB.\r
78;------------------------------------------------------------------------------\r
79_BackFromUserCode:\r
80 ;\r
81 ; The order of saved registers on the stack matches the order they appears\r
82 ; in IA32_REGS structure. This facilitates wrapper function to extract them\r
83 ; into that structure.\r
84 ;\r
f6888eea 85BITS 16\r
6dab5c8a
JJ
86 push ss\r
87 push cs\r
eabcdf3a
JJ
88 ;\r
89 ; Note: We can't use o32 on the next instruction because of a bug\r
90 ; in NASM 2.09.04 through 2.10rc1.\r
91 ;\r
92 call dword .Base ; push eip\r
a8458d6c 93.Base:\r
f6888eea 94 pushfd\r
6dab5c8a
JJ
95 cli ; disable interrupts\r
96 push gs\r
97 push fs\r
98 push es\r
99 push ds\r
f6888eea 100 pushad\r
7458df40
JJ
101 mov edx, strict dword 0\r
102.ThunkAttrEnd:\r
6dab5c8a 103 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15\r
a8458d6c 104 jz .1\r
f6888eea
JJ
105 mov ax, 2401h\r
106 int 15h\r
6dab5c8a 107 cli ; disable interrupts\r
a8458d6c
JJ
108 jnc .2\r
109.1:\r
6dab5c8a 110 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL\r
a8458d6c 111 jz .2\r
6dab5c8a
JJ
112 in al, 92h\r
113 or al, 2\r
114 out 92h, al ; deactivate A20M#\r
a8458d6c 115.2:\r
f6888eea
JJ
116 xor eax, eax\r
117 mov ax, ss\r
118 lea ebp, [esp + IA32_REGS.size]\r
119 mov [bp - IA32_REGS.size + IA32_REGS._ESP], ebp\r
120 mov bx, [bp - IA32_REGS.size + IA32_REGS._EIP]\r
121 shl eax, 4 ; shl eax, 4\r
122 add ebp, eax ; add ebp, eax\r
7458df40
JJ
123 mov eax, strict dword 0\r
124.SavedCr4End:\r
6dab5c8a 125 mov cr4, eax\r
f6888eea 126o32 lgdt [cs:bx + (SavedGdt - .Base)]\r
7458df40
JJ
127 mov eax, strict dword 0\r
128.SavedCr0End:\r
6dab5c8a 129 mov cr0, eax\r
7458df40
JJ
130 mov ax, strict word 0\r
131.SavedSsEnd:\r
6dab5c8a 132 mov ss, eax\r
7458df40
JJ
133 mov esp, strict dword 0\r
134.SavedEspEnd:\r
f6888eea 135o32 retf ; return to protected mode\r
6dab5c8a
JJ
136\r
137_EntryPoint:\r
138 DD _ToUserCode - ASM_PFX(m16Start)\r
139 DW 8h\r
140_16Idtr:\r
141 DW (1 << 10) - 1\r
142 DD 0\r
143_16Gdtr:\r
144 DW GdtEnd - _NullSegDesc - 1\r
145_16GdtrBase:\r
03e9db15 146 DD 0\r
6dab5c8a
JJ
147\r
148;------------------------------------------------------------------------------\r
149; _ToUserCode() takes control in real mode before passing control to user code.\r
150; It will be shadowed to somewhere in memory below 1MB.\r
151;------------------------------------------------------------------------------\r
152_ToUserCode:\r
f6888eea
JJ
153BITS 16\r
154 mov dx, ss\r
155 mov ss, cx ; set new segment selectors\r
156 mov ds, cx\r
157 mov es, cx\r
158 mov fs, cx\r
159 mov gs, cx\r
6dab5c8a
JJ
160 mov cr0, eax ; real mode starts at next instruction\r
161 ; which (per SDM) *must* be a far JMP.\r
7458df40
JJ
162 jmp 0:strict word 0\r
163.RealAddrEnd:\r
6dab5c8a 164 mov cr4, ebp\r
f6888eea
JJ
165 mov ss, si ; set up 16-bit stack segment\r
166 xchg esp, ebx ; set up 16-bit stack pointer\r
167 mov bp, [esp + IA32_REGS.size]\r
7458df40
JJ
168 mov [cs:bp + (_BackFromUserCode.SavedSsEnd - 2 - _BackFromUserCode)], dx\r
169 mov [cs:bp + (_BackFromUserCode.SavedEspEnd - 4 - _BackFromUserCode)], ebx\r
f6888eea
JJ
170 lidt [cs:bp + (_16Idtr - _BackFromUserCode)]\r
171\r
172 popad\r
6dab5c8a
JJ
173 pop ds\r
174 pop es\r
175 pop fs\r
176 pop gs\r
f6888eea 177 popfd\r
6dab5c8a 178\r
f6888eea 179o32 retf ; transfer control to user code\r
6dab5c8a
JJ
180\r
181ALIGN 16\r
182_NullSegDesc DQ 0\r
183_16CsDesc:\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_16DsDesc:\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
197GdtEnd:\r
198\r
199;------------------------------------------------------------------------------\r
200; IA32_REGISTER_SET *\r
201; EFIAPI\r
202; InternalAsmThunk16 (\r
203; IN IA32_REGISTER_SET *RegisterSet,\r
204; IN OUT VOID *Transition\r
205; );\r
206;------------------------------------------------------------------------------\r
207global ASM_PFX(InternalAsmThunk16)\r
208ASM_PFX(InternalAsmThunk16):\r
f6888eea 209BITS 32\r
6dab5c8a
JJ
210 push ebp\r
211 push ebx\r
212 push esi\r
213 push edi\r
214 push ds\r
215 push es\r
216 push fs\r
217 push gs\r
218 mov esi, [esp + 36] ; esi <- RegSet, the 1st parameter\r
219 movzx edx, word [esi + IA32_REGS._SS]\r
220 mov edi, [esi + IA32_REGS._ESP]\r
221 add edi, - (IA32_REGS.size + 4) ; reserve stack space\r
222 mov ebx, edi ; ebx <- stack offset\r
223 imul eax, edx, 16 ; eax <- edx * 16\r
224 push IA32_REGS.size / 4\r
225 add edi, eax ; edi <- linear address of 16-bit stack\r
226 pop ecx\r
227 rep movsd ; copy RegSet\r
228 mov eax, [esp + 40] ; eax <- address of transition code\r
229 mov esi, edx ; esi <- 16-bit stack segment\r
7458df40 230 lea edx, [eax + (_BackFromUserCode.SavedCr0End - ASM_PFX(m16Start))]\r
6dab5c8a
JJ
231 mov ecx, eax\r
232 and ecx, 0fh\r
233 shl eax, 12\r
234 lea ecx, [ecx + (_BackFromUserCode - ASM_PFX(m16Start))]\r
235 mov ax, cx\r
236 stosd ; [edi] <- return address of user code\r
7458df40
JJ
237 add eax, _ToUserCode.RealAddrEnd - _BackFromUserCode\r
238 mov [edx + (_ToUserCode.RealAddrEnd - 4 - _BackFromUserCode.SavedCr0End)], eax\r
239 sgdt [edx + (SavedGdt - _BackFromUserCode.SavedCr0End)]\r
6dab5c8a
JJ
240 sidt [esp + 36] ; save IDT stack in argument space\r
241 mov eax, cr0\r
7458df40 242 mov [edx - 4], eax ; save CR0 in _BackFromUserCode.SavedCr0End - 4\r
6dab5c8a
JJ
243 and eax, 7ffffffeh ; clear PE, PG bits\r
244 mov ebp, cr4\r
7458df40 245 mov [edx + (_BackFromUserCode.SavedCr4End - 4 - _BackFromUserCode.SavedCr0End)], ebp\r
6dab5c8a
JJ
246 and ebp, ~30h ; clear PAE, PSE bits\r
247 push 10h\r
248 pop ecx ; ecx <- selector for data segments\r
7458df40 249 lgdt [edx + (_16Gdtr - _BackFromUserCode.SavedCr0End)]\r
6dab5c8a 250 pushfd ; Save df/if indeed\r
7458df40 251 call dword far [edx + (_EntryPoint - _BackFromUserCode.SavedCr0End)]\r
6dab5c8a
JJ
252 popfd\r
253 lidt [esp + 36] ; restore protected mode IDTR\r
254 lea eax, [ebp - IA32_REGS.size] ; eax <- the address of IA32_REGS\r
255 pop gs\r
256 pop fs\r
257 pop es\r
258 pop ds\r
259 pop edi\r
260 pop esi\r
261 pop ebx\r
262 pop ebp\r
263 ret\r