]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseLib/Ia32/Thunk16.asm
Use #include "XXX.h" for module internal header files.
[mirror_edk2.git] / MdePkg / Library / BaseLib / Ia32 / Thunk16.asm
CommitLineData
1efcc4ae 1\r
47fc17d8 2#include "BaseLibInternals.h"\r
e1f414b6 3\r
4;------------------------------------------------------------------------------\r
5;\r
6; Copyright (c) 2006, Intel Corporation\r
7; All rights reserved. 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
25 .686p\r
26 .model flat,C\r
27\r
28EXTERNDEF C m16Start:BYTE\r
29EXTERNDEF C m16Size:WORD\r
30EXTERNDEF C mThunk16Attr:WORD\r
31EXTERNDEF C m16Gdt:WORD\r
32EXTERNDEF C m16GdtrBase:WORD\r
33EXTERNDEF C mTransition:WORD\r
34\r
35;\r
36; Here is the layout of the real mode stack. _ToUserCode() is responsible for\r
37; loading all these registers from real mode stack.\r
38;\r
39IA32_REGS STRUC 4t\r
40_EDI DD ?\r
41_ESI DD ?\r
42_EBP DD ?\r
43_ESP DD ?\r
44_EBX DD ?\r
45_EDX DD ?\r
46_ECX DD ?\r
47_EAX DD ?\r
48_DS DW ?\r
49_ES DW ?\r
50_FS DW ?\r
51_GS DW ?\r
52_EFLAGS DD ?\r
53_EIP DD ?\r
54_CS DW ?\r
55_SS DW ?\r
56IA32_REGS ENDS\r
57\r
58 .const\r
59\r
60;\r
61; These are global constant to convey information to C code.\r
62;\r
63m16Size DW InternalAsmThunk16 - m16Start\r
64mThunk16Attr DW _ThunkAttr - m16Start\r
65m16Gdt DW _NullSegDesc - m16Start\r
66m16GdtrBase DW _16GdtrBase - m16Start\r
67mTransition DW _EntryPoint - m16Start\r
68\r
69 .code\r
70\r
71m16Start LABEL BYTE\r
72\r
73SavedGdt LABEL FWORD\r
74 DW ?\r
75 DD ?\r
76;------------------------------------------------------------------------------\r
77; _BackFromUserCode() takes control in real mode after 'retf' has been executed\r
78; by user code. It will be shadowed to somewhere in memory below 1MB.\r
79;------------------------------------------------------------------------------\r
80_BackFromUserCode PROC\r
81 ;\r
82 ; The order of saved registers on the stack matches the order they appears\r
83 ; in IA32_REGS structure. This facilitates wrapper function to extract them\r
84 ; into that structure.\r
85 ;\r
86 push ss\r
87 push cs\r
88 DB 66h\r
89 call @Base ; push eip\r
90@Base:\r
91 pushf ; pushfd actually\r
92 cli ; disable interrupts\r
93 push gs\r
94 push fs\r
95 push es\r
96 push ds\r
97 pushaw ; pushad actually\r
98 DB 66h, 0bah ; mov edx, imm32\r
99_ThunkAttr DD ?\r
100 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15\r
101 jz @1\r
102 mov eax, 15cd2401h ; mov ax, 2401h & int 15h\r
103 cli ; disable interrupts\r
104 jnc @2\r
105@1:\r
106 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL\r
107 jz @2\r
108 in al, 92h\r
109 or al, 2\r
110 out 92h, al ; deactivate A20M#\r
111@2:\r
112 mov eax, ss\r
113 DB 67h\r
114 lea bp, [esp + sizeof (IA32_REGS)]\r
115 ;\r
116 ; esi's in the following 2 instructions are indeed bp in 16-bit code. Fact\r
117 ; is "esi" in 32-bit addressing mode has the same encoding of "bp" in 16-\r
118 ; bit addressing mode.\r
119 ;\r
120 mov word ptr (IA32_REGS ptr [esi - sizeof (IA32_REGS)])._ESP, bp\r
121 mov ebx, (IA32_REGS ptr [esi - sizeof (IA32_REGS)])._EIP\r
122 shl ax, 4 ; shl eax, 4\r
123 add bp, ax ; add ebp, eax\r
124 DB 66h, 0b8h ; mov eax, imm32\r
125SavedCr4 DD ?\r
126 mov cr4, eax\r
127 DB 66h\r
128 lgdt fword ptr cs:[edi + (SavedGdt - @Base)]\r
129 DB 66h, 0b8h ; mov eax, imm32\r
130SavedCr0 DD ?\r
131 mov cr0, eax\r
132 DB 0b8h ; mov ax, imm16\r
133SavedSs DW ?\r
134 mov ss, eax\r
135 DB 66h, 0bch ; mov esp, imm32\r
136SavedEsp DD ?\r
137 DB 66h\r
138 retf ; return to protected mode\r
139_BackFromUserCode ENDP\r
140\r
141_EntryPoint DD _ToUserCode - m16Start\r
142 DW 8h\r
143_16Idtr FWORD (1 SHL 10) - 1\r
144_16Gdtr LABEL FWORD\r
145 DW GdtEnd - _NullSegDesc - 1\r
146_16GdtrBase DD _NullSegDesc\r
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 PROC\r
153 mov edx, ss\r
154 mov ss, ecx ; set new segment selectors\r
155 mov ds, ecx\r
156 mov es, ecx\r
157 mov fs, ecx\r
158 mov gs, ecx\r
159 mov cr0, eax\r
160 mov cr4, ebp ; real mode starts at next instruction\r
161 mov ss, esi ; set up 16-bit stack segment\r
162 xchg sp, bx ; set up 16-bit stack pointer\r
163 DB 66h\r
164 call @Base ; push eip\r
165@Base:\r
166 pop bp ; ebp <- address of @Base\r
167 DB 67h ; address size override\r
168 push [esp + sizeof (IA32_REGS) + 2]\r
169 lea eax, [esi + (@RealMode - @Base)]\r
170 push eax\r
171 retf\r
172@RealMode:\r
173 mov cs:[esi + (SavedSs - @Base)], edx\r
174 mov cs:[esi + (SavedEsp - @Base)], bx\r
175 DB 66h\r
176 lidt fword ptr cs:[esi + (_16Idtr - @Base)]\r
177 popaw ; popad actually\r
178 pop ds\r
179 pop es\r
180 pop fs\r
181 pop gs\r
182 popf ; popfd\r
183 DB 66h ; Use 32-bit addressing for "retf" below\r
184 retf ; transfer control to user code\r
185_ToUserCode ENDP\r
186\r
187_NullSegDesc DQ 0\r
188_16CsDesc LABEL QWORD\r
189 DW -1\r
190 DW 0\r
191 DB 0\r
192 DB 9bh\r
193 DB 8fh ; 16-bit segment, 4GB limit\r
194 DB 0\r
195_16DsDesc LABEL QWORD\r
196 DW -1\r
197 DW 0\r
198 DB 0\r
199 DB 93h\r
200 DB 8fh ; 16-bit segment, 4GB limit\r
201 DB 0\r
202GdtEnd LABEL QWORD\r
203\r
204;------------------------------------------------------------------------------\r
205; IA32_REGISTER_SET *\r
206; EFIAPI\r
207; InternalAsmThunk16 (\r
208; IN IA32_REGISTER_SET *RegisterSet,\r
209; IN OUT VOID *Transition\r
210; );\r
211;------------------------------------------------------------------------------\r
212InternalAsmThunk16 PROC USES ebp ebx esi edi ds es fs gs\r
213 mov esi, [esp + 36] ; esi <- RegSet, the 1st parameter\r
214 movzx edx, (IA32_REGS ptr [esi])._SS\r
215 mov edi, (IA32_REGS ptr [esi])._ESP\r
216 add edi, - (sizeof (IA32_REGS) + 4) ; reserve stack space\r
217 mov ebx, edi ; ebx <- stack offset\r
218 imul eax, edx, 16 ; eax <- edx * 16\r
219 push sizeof (IA32_REGS) / 4\r
220 add edi, eax ; edi <- linear address of 16-bit stack\r
221 pop ecx\r
222 rep movsd ; copy RegSet\r
223 mov eax, [esp + 40] ; eax <- address of transition code\r
224 mov esi, edx ; esi <- 16-bit stack segment\r
225 lea edx, [eax + (SavedCr0 - m16Start)]\r
226 mov ecx, eax\r
227 and ecx, 0fh\r
228 shl eax, 12\r
229 lea ecx, [ecx + (_BackFromUserCode - m16Start)]\r
230 mov ax, cx\r
231 stosd ; [edi] <- return address of user code\r
232 sgdt fword ptr [edx + (SavedGdt - SavedCr0)]\r
233 sidt fword ptr [esp + 36] ; save IDT stack in argument space\r
234 mov eax, cr0\r
235 mov [edx], eax ; save CR0 in SavedCr0\r
236 and eax, 7ffffffeh ; clear PE, PG bits\r
237 mov ebp, cr4\r
238 mov [edx + (SavedCr4 - SavedCr0)], ebp\r
239 and ebp, 300h ; clear all but PCE and OSFXSR bits\r
240 push 10h\r
241 pop ecx ; ecx <- selector for data segments\r
242 lgdt fword ptr [edx + (_16Gdtr - SavedCr0)]\r
243 pushfd ; Save df/if indeed\r
244 call fword ptr [edx + (_EntryPoint - SavedCr0)]\r
245 popfd\r
246 lidt fword ptr [esp + 36] ; restore protected mode IDTR\r
247 lea eax, [ebp - sizeof (IA32_REGS)] ; eax <- the address of IA32_REGS\r
248 ret\r
249InternalAsmThunk16 ENDP\r
250\r
251 END\r