]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseLib/X64/Thunk16.asm
Updated BaseLib for THUNK functions and some CPU functions
[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
97d92bda 29THUNK_ATTRIBUTE_BIG_REAL_MODE EQU 1\r
30THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 EQU 2\r
31THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL EQU 4\r
878ddf1f 32\r
33IA32_REGS STRUC 4t\r
34_EDI DD ?\r
35_ESI DD ?\r
36_EBP DD ?\r
37_ESP DD ?\r
38_EBX DD ?\r
39_EDX DD ?\r
40_ECX DD ?\r
41_EAX DD ?\r
42_DS DW ?\r
43_ES DW ?\r
44_FS DW ?\r
45_GS DW ?\r
97d92bda 46_EFLAGS DQ ?\r
878ddf1f 47_EIP DD ?\r
48_CS DW ?\r
49_SS DW ?\r
50IA32_REGS ENDS\r
51\r
97d92bda 52 .const\r
53\r
54m16Size DW offset InternalAsmThunk16 - offset m16Start\r
55mThunk16Attr DW offset _ThunkAttr - offset m16Start\r
56m16Gdt DW offset _NullSegDesc - offset m16Start\r
57m16GdtrBase DW offset _16GdtrBase - offset m16Start\r
58mTransition DW offset _EntryPoint - offset m16Start\r
59\r
60 .code\r
61\r
62m16Start LABEL BYTE\r
63\r
64SavedGdt LABEL FWORD\r
65 DW ?\r
66 DQ ?\r
67\r
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
107 lgdt fword ptr [rdi + (offset SavedGdt - offset @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
125_EntryPoint DD offset _ToUserCode - offset m16Start\r
126 DW 8h\r
127_16Gdtr LABEL FWORD\r
128 DW offset GdtEnd - offset _NullSegDesc - 1\r
129_16GdtrBase DQ offset _NullSegDesc\r
130_16Idtr FWORD (1 SHL 10) - 1\r
131\r
132_ToUserCode PROC\r
133 mov edi, ss\r
134 mov ss, edx ; set new segment selectors\r
135 mov ds, edx\r
136 mov es, edx\r
137 mov fs, edx\r
138 mov gs, edx\r
878ddf1f 139 DB 66h\r
97d92bda 140 mov ecx, 0c0000080h\r
141 mov cr0, rax ; real mode starts at next instruction\r
142 rdmsr\r
143 and ah, NOT 1\r
144 wrmsr\r
145 mov cr4, rbp\r
146 mov ss, esi ; set up 16-bit stack segment\r
147 xchg sp, bx ; set up 16-bit stack pointer\r
878ddf1f 148 DB 66h\r
97d92bda 149 call @Base ; push eip\r
150@Base:\r
151 pop bp ; ebp <- offset @Base\r
152 DB 2eh ; cs:\r
153 mov [rsi + (offset SavedSs - offset @Base)], edi\r
154 DB 2eh ; cs:\r
155 mov [rsi + (offset SavedEsp - offset @Base)], bx\r
156 DB 66h, 2eh ; CS and operand size override\r
157 lidt fword ptr [rsi + (offset _16Idtr - offset @Base)]\r
158 DB 66h, 61h ; popad\r
159 DB 1fh ; pop ds\r
160 DB 07h ; pop es\r
161 pop fs\r
162 pop gs\r
163 popf ; popfd\r
164 lea sp, [esp + 4] ; skip high order 32 bits of EFlags\r
878ddf1f 165 DB 66h\r
97d92bda 166 retf ; transfer control to user code\r
167_ToUserCode ENDP\r
168\r
169_NullSegDesc DQ 0\r
170_16CsDesc LABEL QWORD\r
171 DW -1\r
172 DW 0\r
173 DB 0\r
174 DB 9bh\r
175 DB 8fh ; 16-bit segment, 4GB limit\r
176 DB 0\r
177_16DsDesc LABEL QWORD\r
178 DW -1\r
179 DW 0\r
180 DB 0\r
181 DB 93h\r
182 DB 8fh ; 16-bit segment, 4GB limit\r
183 DB 0\r
184GdtEnd LABEL QWORD\r
185\r
186;\r
187; @param RegSet Pointer to a IA32_DWORD_REGS structure\r
188; @param Transition Pointer to the transition code\r
189; @return The address of the 16-bit stack after returning from user code\r
190;\r
191InternalAsmThunk16 PROC USES rbp rbx rsi rdi\r
192 mov r10d, ds\r
193 mov r11d, es\r
194 push fs\r
195 push gs\r
196 mov rsi, rcx\r
197 movzx r8d, (IA32_REGS ptr [rsi])._SS\r
198 mov edi, (IA32_REGS ptr [rsi])._ESP\r
199 lea rdi, [edi - (sizeof (IA32_REGS) + 4)]\r
200 imul eax, r8d, 16 ; eax <- r8d(stack segment) * 16\r
201 mov ebx, edi ; ebx <- stack offset for 16-bit code\r
202 push sizeof (IA32_REGS) / 4\r
203 add edi, eax ; edi <- linear address of 16-bit stack\r
204 pop rcx\r
205 rep movsd ; copy RegSet\r
206 lea ecx, [rdx + (offset SavedCr4 - offset m16Start)]\r
207 mov eax, edx ; eax <- transition code address\r
208 and edx, 0fh\r
209 shl eax, 12\r
210 lea edx, [rdx + (offset _BackFromUserCode - offset m16Start)]\r
211 mov ax, dx\r
212 stosd ; [edi] <- return address of user code\r
213 sgdt fword ptr [rcx + (offset SavedGdt - offset SavedCr4)]\r
214 sidt fword ptr [rsp + 38h] ; save IDT stack in argument space\r
215 mov rax, cr0\r
216 mov [rcx + (offset SavedCr0 - offset SavedCr4)], eax\r
217 and eax, 7ffffffeh ; clear PE, PG bits\r
218 mov rbp, cr4\r
219 mov [rcx], ebp ; save CR4 in SavedCr4\r
220 and ebp, 300h ; clear all but PCE and OSFXSR bits\r
221 mov esi, r8d ; esi <- 16-bit stack segment\r
222 push 10h\r
223 pop rdx ; rdx <- selector for data segments\r
224 lgdt fword ptr [rcx + (offset _16Gdtr - offset SavedCr4)]\r
225 call fword ptr [rcx + (offset _EntryPoint - offset SavedCr4)]\r
226 lidt fword ptr [rsp + 38h] ; restore protected mode IDTR\r
227 lea eax, [rbp - sizeof (IA32_REGS)]\r
878ddf1f 228 pop gs\r
229 pop fs\r
97d92bda 230 mov es, r11d\r
231 mov ds, r10d\r
878ddf1f 232 ret\r
233InternalAsmThunk16 ENDP\r
234\r
235 END\r