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