b3c0769f1f36099c9e703e85fb900575a3296232
[mirror_edk2.git] / MdePkg / Library / BaseLib / X64 / Thunk16.asm
1 ;------------------------------------------------------------------------------
2 ;
3 ; Copyright (c) 2006, Intel Corporation
4 ; All rights reserved. This program and the accompanying materials
5 ; are licensed and made available under the terms and conditions of the BSD License
6 ; which accompanies this distribution. The full text of the license may be found at
7 ; http://opensource.org/licenses/bsd-license.php
8 ;
9 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 ;
12 ; Module Name:
13 ;
14 ; Thunk.asm
15 ;
16 ; Abstract:
17 ;
18 ; Real mode thunk
19 ;
20 ;------------------------------------------------------------------------------
21
22 EXTERNDEF m16Start:BYTE
23 EXTERNDEF m16Size:WORD
24 EXTERNDEF mThunk16Attr:WORD
25 EXTERNDEF m16Gdt:WORD
26 EXTERNDEF m16GdtrBase:WORD
27 EXTERNDEF mTransition:WORD
28
29 ;THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 EQU 2
30 ;THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL EQU 4
31
32 IA32_REGS STRUC 4t
33 _EDI DD ?
34 _ESI DD ?
35 _EBP DD ?
36 _ESP DD ?
37 _EBX DD ?
38 _EDX DD ?
39 _ECX DD ?
40 _EAX DD ?
41 _DS DW ?
42 _ES DW ?
43 _FS DW ?
44 _GS DW ?
45 _EFLAGS DQ ?
46 _EIP DD ?
47 _CS DW ?
48 _SS DW ?
49 IA32_REGS ENDS
50
51 .const
52
53 m16Size DW offset InternalAsmThunk16 - offset m16Start
54 mThunk16Attr DW offset _ThunkAttr - offset m16Start
55 m16Gdt DW offset _NullSegDesc - offset m16Start
56 m16GdtrBase DW offset _16GdtrBase - offset m16Start
57 mTransition DW offset _EntryPoint - offset m16Start
58
59 .code
60
61 m16Start LABEL BYTE
62
63 SavedGdt LABEL FWORD
64 DW ?
65 DQ ?
66
67 _BackFromUserCode PROC
68 DB 16h ; push ss
69 DB 0eh ; push cs
70 DB 66h
71 call @Base ; push eip
72 @Base:
73 DB 66h
74 push 0 ; reserved high order 32 bits of EFlags
75 pushf ; pushfd actually
76 cli ; disable interrupts
77 push gs
78 push fs
79 DB 6 ; push es
80 DB 1eh ; push ds
81 DB 66h, 60h ; pushad
82 DB 66h, 0bah ; mov edx, imm32
83 _ThunkAttr DD ?
84 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15
85 jz @1
86 mov eax, 15cd2401h ; mov ax, 2401h & int 15h
87 cli ; disable interrupts
88 jnc @2
89 @1:
90 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL
91 jz @2
92 in al, 92h
93 or al, 2
94 out 92h, al ; deactivate A20M#
95 @2:
96 mov eax, ss
97 lea bp, [esp + sizeof (IA32_REGS)]
98 mov word ptr (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._ESP, bp
99 mov ebx, (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._EIP
100 shl ax, 4 ; shl eax, 4
101 add bp, ax ; add ebp, eax
102 DB 66h, 0b8h ; mov eax, imm32
103 SavedCr4 DD ?
104 mov cr4, rax
105 DB 66h, 2eh
106 lgdt fword ptr [rdi + (offset SavedGdt - offset @Base)]
107 DB 66h
108 mov ecx, 0c0000080h
109 rdmsr
110 or ah, 1
111 wrmsr
112 DB 66h, 0b8h ; mov eax, imm32
113 SavedCr0 DD ?
114 mov cr0, rax
115 DB 0b8h ; mov ax, imm16
116 SavedSs DW ?
117 mov ss, eax
118 DB 66h, 0bch ; mov esp, imm32
119 SavedEsp DD ?
120 DB 66h
121 retf ; return to protected mode
122 _BackFromUserCode ENDP
123
124 _EntryPoint DD offset _ToUserCode - offset m16Start
125 DW 8h
126 _16Gdtr LABEL FWORD
127 DW offset GdtEnd - offset _NullSegDesc - 1
128 _16GdtrBase DQ offset _NullSegDesc
129 _16Idtr FWORD (1 SHL 10) - 1
130
131 _ToUserCode PROC
132 mov edi, ss
133 mov ss, edx ; set new segment selectors
134 mov ds, edx
135 mov es, edx
136 mov fs, edx
137 mov gs, edx
138 DB 66h
139 mov ecx, 0c0000080h
140 mov cr0, rax ; real mode starts at next instruction
141 rdmsr
142 and ah, NOT 1
143 wrmsr
144 mov cr4, rbp
145 mov ss, esi ; set up 16-bit stack segment
146 xchg sp, bx ; set up 16-bit stack pointer
147 DB 66h
148 call @Base ; push eip
149 @Base:
150 pop bp ; ebp <- offset @Base
151 push [esp + sizeof (IA32_REGS) + 2]
152 lea eax, [rsi + (offset @RealMode - offset @Base)]
153 push rax
154 retf
155 @RealMode:
156 DB 2eh ; cs:
157 mov [rsi + (offset SavedSs - offset @Base)], edi
158 DB 2eh ; cs:
159 mov [rsi + (offset SavedEsp - offset @Base)], bx
160 DB 66h, 2eh ; CS and operand size override
161 lidt fword ptr [rsi + (offset _16Idtr - offset @Base)]
162 DB 66h, 61h ; popad
163 DB 1fh ; pop ds
164 DB 07h ; pop es
165 pop fs
166 pop gs
167 popf ; popfd
168 lea sp, [esp + 4] ; skip high order 32 bits of EFlags
169 DB 66h
170 retf ; transfer control to user code
171 _ToUserCode ENDP
172
173 _NullSegDesc DQ 0
174 _16CsDesc LABEL QWORD
175 DW -1
176 DW 0
177 DB 0
178 DB 9bh
179 DB 8fh ; 16-bit segment, 4GB limit
180 DB 0
181 _16DsDesc LABEL QWORD
182 DW -1
183 DW 0
184 DB 0
185 DB 93h
186 DB 8fh ; 16-bit segment, 4GB limit
187 DB 0
188 GdtEnd LABEL QWORD
189
190 ;
191 ; @param RegSet Pointer to a IA32_DWORD_REGS structure
192 ; @param Transition Pointer to the transition code
193 ; @return The address of the 16-bit stack after returning from user code
194 ;
195 InternalAsmThunk16 PROC USES rbp rbx rsi rdi
196 mov r10d, ds
197 mov r11d, es
198 push fs
199 push gs
200 mov rsi, rcx
201 movzx r8d, (IA32_REGS ptr [rsi])._SS
202 mov edi, (IA32_REGS ptr [rsi])._ESP
203 lea rdi, [edi - (sizeof (IA32_REGS) + 4)]
204 imul eax, r8d, 16 ; eax <- r8d(stack segment) * 16
205 mov ebx, edi ; ebx <- stack offset for 16-bit code
206 push sizeof (IA32_REGS) / 4
207 add edi, eax ; edi <- linear address of 16-bit stack
208 pop rcx
209 rep movsd ; copy RegSet
210 lea ecx, [rdx + (offset SavedCr4 - offset m16Start)]
211 mov eax, edx ; eax <- transition code address
212 and edx, 0fh
213 shl eax, 12
214 lea edx, [rdx + (offset _BackFromUserCode - offset m16Start)]
215 mov ax, dx
216 stosd ; [edi] <- return address of user code
217 sgdt fword ptr [rcx + (offset SavedGdt - offset SavedCr4)]
218 sidt fword ptr [rsp + 38h] ; save IDT stack in argument space
219 mov rax, cr0
220 mov [rcx + (offset SavedCr0 - offset SavedCr4)], eax
221 and eax, 7ffffffeh ; clear PE, PG bits
222 mov rbp, cr4
223 mov [rcx], ebp ; save CR4 in SavedCr4
224 and ebp, 300h ; clear all but PCE and OSFXSR bits
225 mov esi, r8d ; esi <- 16-bit stack segment
226 push 10h
227 pop rdx ; rdx <- selector for data segments
228 lgdt fword ptr [rcx + (offset _16Gdtr - offset SavedCr4)]
229 pushfq
230 call fword ptr [rcx + (offset _EntryPoint - offset SavedCr4)]
231 popfq
232 lidt fword ptr [rsp + 38h] ; restore protected mode IDTR
233 lea eax, [rbp - sizeof (IA32_REGS)]
234 pop gs
235 pop fs
236 mov es, r11d
237 mov ds, r10d
238 ret
239 InternalAsmThunk16 ENDP
240
241 END