]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseLib/X64/Thunk16.asm
Added an extra GDT entry to the GDT used by thunk code. SS register will always be...
[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 InternalAsmThunk16 - m16Start
51 mThunk16Attr DW _ThunkAttr - m16Start
52 m16Gdt DW _NullSeg - m16Start
53 m16GdtrBase DW _16GdtrBase - m16Start
54 mTransition DW _EntryPoint - m16Start
55
56 .code
57
58 m16Start LABEL BYTE
59
60 SavedGdt LABEL FWORD
61 DW ?
62 DQ ?
63
64 ;------------------------------------------------------------------------------
65 ; _BackFromUserCode() takes control in real mode after 'retf' has been executed
66 ; by user code. It will be shadowed to somewhere in memory below 1MB.
67 ;------------------------------------------------------------------------------
68 _BackFromUserCode PROC
69 DB 16h ; push ss
70 DB 0eh ; push cs
71 DB 66h
72 call @Base ; push eip
73 @Base:
74 DB 66h
75 push 0 ; reserved high order 32 bits of EFlags
76 pushf ; pushfd actually
77 cli ; disable interrupts
78 push gs
79 push fs
80 DB 6 ; push es
81 DB 1eh ; push ds
82 DB 66h, 60h ; pushad
83 DB 66h, 0bah ; mov edx, imm32
84 _ThunkAttr DD ?
85 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15
86 jz @1
87 mov eax, 15cd2401h ; mov ax, 2401h & int 15h
88 cli ; disable interrupts
89 jnc @2
90 @1:
91 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL
92 jz @2
93 in al, 92h
94 or al, 2
95 out 92h, al ; deactivate A20M#
96 @2:
97 mov eax, ss
98 lea bp, [esp + sizeof (IA32_REGS)]
99 mov word ptr (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._ESP, bp
100 mov ebx, (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._EIP
101 shl ax, 4 ; shl eax, 4
102 add bp, ax ; add ebp, eax
103 DB 66h, 0b8h ; mov eax, imm32
104 SavedCr4 DD ?
105 mov cr4, rax
106 DB 66h, 2eh
107 lgdt fword ptr [rdi + (SavedGdt - @Base)]
108 DB 66h
109 mov ecx, 0c0000080h
110 rdmsr
111 or ah, 1
112 wrmsr
113 DB 66h, 0b8h ; mov eax, imm32
114 SavedCr0 DD ?
115 mov cr0, rax
116 DB 0b8h ; mov ax, imm16
117 SavedSs DW ?
118 mov ss, eax
119 DB 66h, 0bch ; mov esp, imm32
120 SavedEsp DD ?
121 DB 66h
122 retf ; return to protected mode
123 _BackFromUserCode ENDP
124
125 _EntryPoint DD _ToUserCode - m16Start
126 DW CODE16
127 _16Gdtr LABEL FWORD
128 DW GDT_SIZE - 1
129 _16GdtrBase DQ _NullSeg
130 _16Idtr FWORD (1 SHL 10) - 1
131
132 ;------------------------------------------------------------------------------
133 ; _ToUserCode() takes control in real mode before passing control to user code.
134 ; It will be shadowed to somewhere in memory below 1MB.
135 ;------------------------------------------------------------------------------
136 _ToUserCode PROC
137 mov ss, edx ; set new segment selectors
138 mov ds, edx
139 mov es, edx
140 mov fs, edx
141 mov gs, edx
142 DB 66h
143 mov ecx, 0c0000080h
144 mov cr0, rax ; real mode starts at next instruction
145 rdmsr
146 and ah, NOT 1
147 wrmsr
148 mov cr4, rbp
149 mov ss, esi ; set up 16-bit stack segment
150 xchg sp, bx ; set up 16-bit stack pointer
151 DB 66h
152 call @Base ; push eip
153 @Base:
154 pop bp ; ebp <- address of @Base
155 push [esp + sizeof (IA32_REGS) + 2]
156 lea eax, [rsi + (@RealMode - @Base)]
157 push rax
158 retf
159 @RealMode:
160 DB 6ah, DATA32
161 DB 2eh ; cs:
162 pop [rsi + (SavedSs - @Base)]
163 DB 2eh ; cs:
164 mov [rsi + (SavedEsp - @Base)], bx
165 DB 66h, 2eh ; CS and operand size override
166 lidt fword ptr [rsi + (_16Idtr - @Base)]
167 DB 66h, 61h ; popad
168 DB 1fh ; pop ds
169 DB 07h ; pop es
170 pop fs
171 pop gs
172 popf ; popfd
173 lea sp, [esp + 4] ; skip high order 32 bits of EFlags
174 DB 66h
175 retf ; transfer control to user code
176 _ToUserCode ENDP
177
178 CODE16 = _16Code - $
179 DATA16 = _16Data - $
180 DATA32 = _32Data - $
181
182 _NullSeg DQ 0
183 _16Code LABEL QWORD
184 DW -1
185 DW 0
186 DB 0
187 DB 9bh
188 DB 8fh ; 16-bit segment, 4GB limit
189 DB 0
190 _16Data LABEL QWORD
191 DW -1
192 DW 0
193 DB 0
194 DB 93h
195 DB 8fh ; 16-bit segment, 4GB limit
196 DB 0
197 _32Data LABEL QWORD
198 DW -1
199 DW 0
200 DB 0
201 DB 93h
202 DB 0cfh ; 16-bit segment, 4GB limit
203 DB 0
204
205 GDT_SIZE = $ - _NullSeg
206
207 ;------------------------------------------------------------------------------
208 ; IA32_REGISTER_SET *
209 ; EFIAPI
210 ; InternalAsmThunk16 (
211 ; IN IA32_REGISTER_SET *RegisterSet,
212 ; IN OUT VOID *Transition
213 ; );
214 ;------------------------------------------------------------------------------
215 InternalAsmThunk16 PROC USES rbp rbx rsi rdi
216 mov r10d, ds
217 mov r11d, es
218 mov r9d, ss
219 push fs
220 push gs
221 mov rsi, rcx
222 movzx r8d, (IA32_REGS ptr [rsi])._SS
223 mov edi, (IA32_REGS ptr [rsi])._ESP
224 lea rdi, [edi - (sizeof (IA32_REGS) + 4)]
225 imul eax, r8d, 16 ; eax <- r8d(stack segment) * 16
226 mov ebx, edi ; ebx <- stack for 16-bit code
227 push sizeof (IA32_REGS) / 4
228 add edi, eax ; edi <- linear address of 16-bit stack
229 pop rcx
230 rep movsd ; copy RegSet
231 lea ecx, [rdx + (SavedCr4 - m16Start)]
232 mov eax, edx ; eax <- transition code address
233 and edx, 0fh
234 shl eax, 12
235 lea edx, [rdx + (_BackFromUserCode - m16Start)]
236 mov ax, dx
237 stosd ; [edi] <- return address of user code
238 sgdt fword ptr [rcx + (SavedGdt - SavedCr4)]
239 sidt fword ptr [rsp + 38h] ; save IDT stack in argument space
240 mov rax, cr0
241 mov [rcx + (SavedCr0 - SavedCr4)], eax
242 and eax, 7ffffffeh ; clear PE, PG bits
243 mov rbp, cr4
244 mov [rcx], ebp ; save CR4 in SavedCr4
245 and ebp, 300h ; clear all but PCE and OSFXSR bits
246 mov esi, r8d ; esi <- 16-bit stack segment
247 DB 6ah, DATA32 ; push DATA32
248 pop rdx ; rdx <- 32-bit data segment selector
249 lgdt fword ptr [rcx + (_16Gdtr - SavedCr4)]
250 mov ss, edx
251 pushfq
252 lea edx, [rdx + DATA16 - DATA32]
253 call fword ptr [rcx + (_EntryPoint - SavedCr4)]
254 popfq
255 lidt fword ptr [rsp + 38h] ; restore protected mode IDTR
256 lea eax, [rbp - sizeof (IA32_REGS)]
257 pop gs
258 pop fs
259 mov ss, r9d
260 mov es, r11d
261 mov ds, r10d
262 ret
263 InternalAsmThunk16 ENDP
264
265 END