Remove platform-specific Firmware Volume Block Driver implementation from EdkNt32Pkg...
[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
52m16Gdt DW _NullSegDesc - m16Start\r
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
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
bbe4ba81 107 lgdt fword ptr [rdi + (SavedGdt - @Base)]\r
878ddf1f 108 DB 66h\r
109 mov ecx, 0c0000080h\r
110 rdmsr\r
97d92bda 111 or ah, 1\r
878ddf1f 112 wrmsr\r
97d92bda 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
878ddf1f 121 DB 66h\r
97d92bda 122 retf ; return to protected mode\r
123_BackFromUserCode ENDP\r
124\r
bbe4ba81 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
97d92bda 131\r
3f566587 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
97d92bda 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
878ddf1f 143 DB 66h\r
97d92bda 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
878ddf1f 152 DB 66h\r
97d92bda 153 call @Base ; push eip\r
154@Base:\r
bbe4ba81 155 pop bp ; ebp <- address of @Base\r
18c319ae 156 push [esp + sizeof (IA32_REGS) + 2]\r
bbe4ba81 157 lea eax, [rsi + (@RealMode - @Base)]\r
18c319ae 158 push rax\r
159 retf\r
160@RealMode:\r
97d92bda 161 DB 2eh ; cs:\r
bbe4ba81 162 mov [rsi + (SavedSs - @Base)], edi\r
97d92bda 163 DB 2eh ; cs:\r
bbe4ba81 164 mov [rsi + (SavedEsp - @Base)], bx\r
97d92bda 165 DB 66h, 2eh ; CS and operand size override\r
bbe4ba81 166 lidt fword ptr [rsi + (_16Idtr - @Base)]\r
97d92bda 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
878ddf1f 174 DB 66h\r
97d92bda 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
3f566587 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
97d92bda 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
bbe4ba81 213 mov ebx, edi ; ebx <- stack for 16-bit code\r
97d92bda 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
bbe4ba81 218 lea ecx, [rdx + (SavedCr4 - m16Start)]\r
97d92bda 219 mov eax, edx ; eax <- transition code address\r
220 and edx, 0fh\r
221 shl eax, 12\r
bbe4ba81 222 lea edx, [rdx + (_BackFromUserCode - m16Start)]\r
97d92bda 223 mov ax, dx\r
224 stosd ; [edi] <- return address of user code\r
bbe4ba81 225 sgdt fword ptr [rcx + (SavedGdt - SavedCr4)]\r
97d92bda 226 sidt fword ptr [rsp + 38h] ; save IDT stack in argument space\r
227 mov rax, cr0\r
bbe4ba81 228 mov [rcx + (SavedCr0 - SavedCr4)], eax\r
97d92bda 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
bbe4ba81 236 lgdt fword ptr [rcx + (_16Gdtr - SavedCr4)]\r
18c319ae 237 pushfq\r
bbe4ba81 238 call fword ptr [rcx + (_EntryPoint - SavedCr4)]\r
18c319ae 239 popfq\r
97d92bda 240 lidt fword ptr [rsp + 38h] ; restore protected mode IDTR\r
241 lea eax, [rbp - sizeof (IA32_REGS)]\r
878ddf1f 242 pop gs\r
243 pop fs\r
97d92bda 244 mov es, r11d\r
245 mov ds, r10d\r
878ddf1f 246 ret\r
247InternalAsmThunk16 ENDP\r
248\r
249 END\r