Modified coding style, removed unnecessary comments and "offset" key words.
[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
64_BackFromUserCode PROC\r
65 DB 16h ; push ss\r
66 DB 0eh ; push cs\r
878ddf1f 67 DB 66h\r
97d92bda 68 call @Base ; push eip\r
69@Base:\r
878ddf1f 70 DB 66h\r
97d92bda 71 push 0 ; reserved high order 32 bits of EFlags\r
878ddf1f 72 pushf ; pushfd actually\r
97d92bda 73 cli ; disable interrupts\r
878ddf1f 74 push gs\r
75 push fs\r
76 DB 6 ; push es\r
77 DB 1eh ; push ds\r
78 DB 66h, 60h ; pushad\r
97d92bda 79 DB 66h, 0bah ; mov edx, imm32\r
80_ThunkAttr DD ?\r
81 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15\r
82 jz @1\r
83 mov eax, 15cd2401h ; mov ax, 2401h & int 15h\r
84 cli ; disable interrupts\r
85 jnc @2\r
86@1:\r
87 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL\r
88 jz @2\r
89 in al, 92h\r
90 or al, 2\r
91 out 92h, al ; deactivate A20M#\r
92@2:\r
93 mov eax, ss\r
94 lea bp, [esp + sizeof (IA32_REGS)]\r
95 mov word ptr (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._ESP, bp\r
96 mov ebx, (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._EIP\r
97 shl ax, 4 ; shl eax, 4\r
98 add bp, ax ; add ebp, eax\r
99 DB 66h, 0b8h ; mov eax, imm32\r
100SavedCr4 DD ?\r
101 mov cr4, rax\r
102 DB 66h, 2eh\r
bbe4ba81 103 lgdt fword ptr [rdi + (SavedGdt - @Base)]\r
878ddf1f 104 DB 66h\r
105 mov ecx, 0c0000080h\r
106 rdmsr\r
97d92bda 107 or ah, 1\r
878ddf1f 108 wrmsr\r
97d92bda 109 DB 66h, 0b8h ; mov eax, imm32\r
110SavedCr0 DD ?\r
111 mov cr0, rax\r
112 DB 0b8h ; mov ax, imm16\r
113SavedSs DW ?\r
114 mov ss, eax\r
115 DB 66h, 0bch ; mov esp, imm32\r
116SavedEsp DD ?\r
878ddf1f 117 DB 66h\r
97d92bda 118 retf ; return to protected mode\r
119_BackFromUserCode ENDP\r
120\r
bbe4ba81 121_EntryPoint DD _ToUserCode - m16Start\r
122 DW 8h\r
123_16Gdtr LABEL FWORD\r
124 DW GdtEnd - _NullSegDesc - 1\r
125_16GdtrBase DQ _NullSegDesc\r
126_16Idtr FWORD (1 SHL 10) - 1\r
97d92bda 127\r
128_ToUserCode PROC\r
129 mov edi, ss\r
130 mov ss, edx ; set new segment selectors\r
131 mov ds, edx\r
132 mov es, edx\r
133 mov fs, edx\r
134 mov gs, edx\r
878ddf1f 135 DB 66h\r
97d92bda 136 mov ecx, 0c0000080h\r
137 mov cr0, rax ; real mode starts at next instruction\r
138 rdmsr\r
139 and ah, NOT 1\r
140 wrmsr\r
141 mov cr4, rbp\r
142 mov ss, esi ; set up 16-bit stack segment\r
143 xchg sp, bx ; set up 16-bit stack pointer\r
878ddf1f 144 DB 66h\r
97d92bda 145 call @Base ; push eip\r
146@Base:\r
bbe4ba81 147 pop bp ; ebp <- address of @Base\r
18c319ae 148 push [esp + sizeof (IA32_REGS) + 2]\r
bbe4ba81 149 lea eax, [rsi + (@RealMode - @Base)]\r
18c319ae 150 push rax\r
151 retf\r
152@RealMode:\r
97d92bda 153 DB 2eh ; cs:\r
bbe4ba81 154 mov [rsi + (SavedSs - @Base)], edi\r
97d92bda 155 DB 2eh ; cs:\r
bbe4ba81 156 mov [rsi + (SavedEsp - @Base)], bx\r
97d92bda 157 DB 66h, 2eh ; CS and operand size override\r
bbe4ba81 158 lidt fword ptr [rsi + (_16Idtr - @Base)]\r
97d92bda 159 DB 66h, 61h ; popad\r
160 DB 1fh ; pop ds\r
161 DB 07h ; pop es\r
162 pop fs\r
163 pop gs\r
164 popf ; popfd\r
165 lea sp, [esp + 4] ; skip high order 32 bits of EFlags\r
878ddf1f 166 DB 66h\r
97d92bda 167 retf ; transfer control to user code\r
168_ToUserCode ENDP\r
169\r
170_NullSegDesc DQ 0\r
171_16CsDesc LABEL QWORD\r
172 DW -1\r
173 DW 0\r
174 DB 0\r
175 DB 9bh\r
176 DB 8fh ; 16-bit segment, 4GB limit\r
177 DB 0\r
178_16DsDesc LABEL QWORD\r
179 DW -1\r
180 DW 0\r
181 DB 0\r
182 DB 93h\r
183 DB 8fh ; 16-bit segment, 4GB limit\r
184 DB 0\r
185GdtEnd LABEL QWORD\r
186\r
187;\r
188; @param RegSet Pointer to a IA32_DWORD_REGS structure\r
189; @param Transition Pointer to the transition code\r
190; @return The address of the 16-bit stack after returning from user code\r
191;\r
192InternalAsmThunk16 PROC USES rbp rbx rsi rdi\r
193 mov r10d, ds\r
194 mov r11d, es\r
195 push fs\r
196 push gs\r
197 mov rsi, rcx\r
198 movzx r8d, (IA32_REGS ptr [rsi])._SS\r
199 mov edi, (IA32_REGS ptr [rsi])._ESP\r
200 lea rdi, [edi - (sizeof (IA32_REGS) + 4)]\r
201 imul eax, r8d, 16 ; eax <- r8d(stack segment) * 16\r
bbe4ba81 202 mov ebx, edi ; ebx <- stack for 16-bit code\r
97d92bda 203 push sizeof (IA32_REGS) / 4\r
204 add edi, eax ; edi <- linear address of 16-bit stack\r
205 pop rcx\r
206 rep movsd ; copy RegSet\r
bbe4ba81 207 lea ecx, [rdx + (SavedCr4 - m16Start)]\r
97d92bda 208 mov eax, edx ; eax <- transition code address\r
209 and edx, 0fh\r
210 shl eax, 12\r
bbe4ba81 211 lea edx, [rdx + (_BackFromUserCode - m16Start)]\r
97d92bda 212 mov ax, dx\r
213 stosd ; [edi] <- return address of user code\r
bbe4ba81 214 sgdt fword ptr [rcx + (SavedGdt - SavedCr4)]\r
97d92bda 215 sidt fword ptr [rsp + 38h] ; save IDT stack in argument space\r
216 mov rax, cr0\r
bbe4ba81 217 mov [rcx + (SavedCr0 - SavedCr4)], eax\r
97d92bda 218 and eax, 7ffffffeh ; clear PE, PG bits\r
219 mov rbp, cr4\r
220 mov [rcx], ebp ; save CR4 in SavedCr4\r
221 and ebp, 300h ; clear all but PCE and OSFXSR bits\r
222 mov esi, r8d ; esi <- 16-bit stack segment\r
223 push 10h\r
224 pop rdx ; rdx <- selector for data segments\r
bbe4ba81 225 lgdt fword ptr [rcx + (_16Gdtr - SavedCr4)]\r
18c319ae 226 pushfq\r
bbe4ba81 227 call fword ptr [rcx + (_EntryPoint - SavedCr4)]\r
18c319ae 228 popfq\r
97d92bda 229 lidt fword ptr [rsp + 38h] ; restore protected mode IDTR\r
230 lea eax, [rbp - sizeof (IA32_REGS)]\r
878ddf1f 231 pop gs\r
232 pop fs\r
97d92bda 233 mov es, r11d\r
234 mov ds, r10d\r
878ddf1f 235 ret\r
236InternalAsmThunk16 ENDP\r
237\r
238 END\r