]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseLib/X64/Thunk16.asm
Update the comments.
[mirror_edk2.git] / MdePkg / Library / BaseLib / X64 / Thunk16.asm
1 //
2 // Include common header file for this module.
3 //
4 #include <BaseLibInternals.h>
5
6 ;------------------------------------------------------------------------------
7 ;
8 ; Copyright (c) 2006, Intel Corporation
9 ; All rights reserved. This program and the accompanying materials
10 ; are licensed and made available under the terms and conditions of the BSD License
11 ; which accompanies this distribution. The full text of the license may be found at
12 ; http://opensource.org/licenses/bsd-license.php
13 ;
14 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 ;
17 ; Module Name:
18 ;
19 ; Thunk.asm
20 ;
21 ; Abstract:
22 ;
23 ; Real mode thunk
24 ;
25 ;------------------------------------------------------------------------------
26
27 EXTERNDEF m16Start:BYTE
28 EXTERNDEF m16Size:WORD
29 EXTERNDEF mThunk16Attr:WORD
30 EXTERNDEF m16Gdt:WORD
31 EXTERNDEF m16GdtrBase:WORD
32 EXTERNDEF mTransition:WORD
33
34 IA32_REGS STRUC 4t
35 _EDI DD ?
36 _ESI DD ?
37 _EBP DD ?
38 _ESP DD ?
39 _EBX DD ?
40 _EDX DD ?
41 _ECX DD ?
42 _EAX DD ?
43 _DS DW ?
44 _ES DW ?
45 _FS DW ?
46 _GS DW ?
47 _EFLAGS DQ ?
48 _EIP DD ?
49 _CS DW ?
50 _SS DW ?
51 IA32_REGS ENDS
52
53 .const
54
55 m16Size DW InternalAsmThunk16 - m16Start
56 mThunk16Attr DW _ThunkAttr - m16Start
57 m16Gdt DW _NullSeg - m16Start
58 m16GdtrBase DW _16GdtrBase - m16Start
59 mTransition DW _EntryPoint - m16Start
60
61 .code
62
63 m16Start LABEL BYTE
64
65 SavedGdt LABEL FWORD
66 DW ?
67 DQ ?
68
69 ;------------------------------------------------------------------------------
70 ; _BackFromUserCode() takes control in real mode after 'retf' has been executed
71 ; by user code. It will be shadowed to somewhere in memory below 1MB.
72 ;------------------------------------------------------------------------------
73 _BackFromUserCode PROC
74 ;
75 ; The order of saved registers on the stack matches the order they appears
76 ; in IA32_REGS structure. This facilitates wrapper function to extract them
77 ; into that structure.
78 ;
79 ; Some instructions for manipulation of segment registers have to be written
80 ; in opcode since 64-bit MASM prevents accesses to those registers.
81 ;
82 DB 16h ; push ss
83 DB 0eh ; push cs
84 DB 66h
85 call @Base ; push eip
86 @Base:
87 DB 66h
88 push 0 ; reserved high order 32 bits of EFlags
89 pushf ; pushfd actually
90 cli ; disable interrupts
91 push gs
92 push fs
93 DB 6 ; push es
94 DB 1eh ; push ds
95 DB 66h, 60h ; pushad
96 DB 66h, 0bah ; mov edx, imm32
97 _ThunkAttr DD ?
98 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15
99 jz @1
100 mov eax, 15cd2401h ; mov ax, 2401h & int 15h
101 cli ; disable interrupts
102 jnc @2
103 @1:
104 test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL
105 jz @2
106 in al, 92h
107 or al, 2
108 out 92h, al ; deactivate A20M#
109 @2:
110 mov eax, ss
111 lea bp, [esp + sizeof (IA32_REGS)]
112 ;
113 ; rsi in the following 2 instructions is indeed bp in 16-bit code
114 ;
115 mov word ptr (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._ESP, bp
116 DB 66h
117 mov ebx, (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._EIP
118 shl ax, 4 ; shl eax, 4
119 add bp, ax ; add ebp, eax
120 mov ax, cs
121 shl ax, 4
122 lea ax, [eax + ebx + (@64BitCode - @Base)]
123 DB 66h, 2eh, 89h, 87h ; mov cs:[bx + (@64Eip - @Base)], eax
124 DW @64Eip - @Base
125 DB 66h, 0b8h ; mov eax, imm32
126 SavedCr4 DD ?
127 mov cr4, rax
128 ;
129 ; rdi in the instruction below is indeed bx in 16-bit code
130 ;
131 DB 66h, 2eh ; 2eh is "cs:" segment override
132 lgdt fword ptr [rdi + (SavedGdt - @Base)]
133 DB 66h
134 mov ecx, 0c0000080h
135 rdmsr
136 or ah, 1
137 wrmsr
138 DB 66h, 0b8h ; mov eax, imm32
139 SavedCr0 DD ?
140 mov cr0, rax
141 DB 66h, 0eah ; jmp far cs:@64Bit
142 @64Eip DD ?
143 SavedCs DW ?
144 @64BitCode:
145 mov rsp, r8 ; restore stack
146 ret
147 _BackFromUserCode ENDP
148
149 _EntryPoint DD _ToUserCode - m16Start
150 DW CODE16
151 _16Gdtr LABEL FWORD
152 DW GDT_SIZE - 1
153 _16GdtrBase DQ _NullSeg
154 _16Idtr FWORD (1 SHL 10) - 1
155
156 ;------------------------------------------------------------------------------
157 ; _ToUserCode() takes control in real mode before passing control to user code.
158 ; It will be shadowed to somewhere in memory below 1MB.
159 ;------------------------------------------------------------------------------
160 _ToUserCode PROC
161 mov ss, edx ; set new segment selectors
162 mov ds, edx
163 mov es, edx
164 mov fs, edx
165 mov gs, edx
166 DB 66h
167 mov ecx, 0c0000080h
168 mov cr0, rax ; real mode starts at next instruction
169 rdmsr
170 and ah, NOT 1
171 wrmsr
172 mov cr4, rbp
173 mov ss, esi ; set up 16-bit stack segment
174 mov sp, bx ; set up 16-bit stack pointer
175 DB 66h ; make the following call 32-bit
176 call @Base ; push eip
177 @Base:
178 pop bp ; ebp <- address of @Base
179 push [esp + sizeof (IA32_REGS) + 2]
180 lea eax, [rsi + (@RealMode - @Base)] ; rsi is "bp" in 16-bit code
181 push rax
182 retf ; execution begins at next instruction
183 @RealMode:
184 DB 66h, 2eh ; CS and operand size override
185 lidt fword ptr [rsi + (_16Idtr - @Base)]
186 DB 66h, 61h ; popad
187 DB 1fh ; pop ds
188 DB 07h ; pop es
189 pop fs
190 pop gs
191 popf ; popfd
192 lea sp, [esp + 4] ; skip high order 32 bits of EFlags
193 DB 66h ; make the following retf 32-bit
194 retf ; transfer control to user code
195 _ToUserCode ENDP
196
197 CODE16 = _16Code - $
198 DATA16 = _16Data - $
199 DATA32 = _32Data - $
200
201 _NullSeg DQ 0
202 _16Code LABEL QWORD
203 DW -1
204 DW 0
205 DB 0
206 DB 9bh
207 DB 8fh ; 16-bit segment, 4GB limit
208 DB 0
209 _16Data LABEL QWORD
210 DW -1
211 DW 0
212 DB 0
213 DB 93h
214 DB 8fh ; 16-bit segment, 4GB limit
215 DB 0
216 _32Data LABEL QWORD
217 DW -1
218 DW 0
219 DB 0
220 DB 93h
221 DB 0cfh ; 16-bit segment, 4GB limit
222 DB 0
223
224 GDT_SIZE = $ - _NullSeg
225
226 ;------------------------------------------------------------------------------
227 ; IA32_REGISTER_SET *
228 ; EFIAPI
229 ; InternalAsmThunk16 (
230 ; IN IA32_REGISTER_SET *RegisterSet,
231 ; IN OUT VOID *Transition
232 ; );
233 ;------------------------------------------------------------------------------
234 InternalAsmThunk16 PROC USES rbp rbx rsi rdi
235 mov r10d, ds ; r9 ~ r11 are not accessible in 16-bit
236 mov r11d, es ; so use them for saving seg registers
237 mov r9d, ss
238 push fs
239 push gs
240 mov rsi, rcx
241 movzx r8d, (IA32_REGS ptr [rsi])._SS
242 mov edi, (IA32_REGS ptr [rsi])._ESP
243 lea rdi, [edi - (sizeof (IA32_REGS) + 4)]
244 imul eax, r8d, 16 ; eax <- r8d(stack segment) * 16
245 mov ebx, edi ; ebx <- stack for 16-bit code
246 push sizeof (IA32_REGS) / 4
247 add edi, eax ; edi <- linear address of 16-bit stack
248 pop rcx
249 rep movsd ; copy RegSet
250 lea ecx, [rdx + (SavedCr4 - m16Start)]
251 mov eax, edx ; eax <- transition code address
252 and edx, 0fh
253 shl eax, 12 ; segment address in high order 16 bits
254 lea ax, [rdx + (_BackFromUserCode - m16Start)] ; offset address
255 stosd ; [edi] <- return address of user code
256 sgdt fword ptr [rcx + (SavedGdt - SavedCr4)]
257 sidt fword ptr [rsp + 38h] ; save IDT stack in argument space
258 mov rax, cr0
259 mov [rcx + (SavedCr0 - SavedCr4)], eax
260 and eax, 7ffffffeh ; clear PE, PG bits
261 mov rbp, cr4
262 mov [rcx], ebp ; save CR4 in SavedCr4
263 and ebp, 300h ; clear all but PCE and OSFXSR bits
264 mov esi, r8d ; esi <- 16-bit stack segment
265 DB 6ah, DATA32 ; push DATA32
266 pop rdx ; rdx <- 32-bit data segment selector
267 lgdt fword ptr [rcx + (_16Gdtr - SavedCr4)]
268 mov ss, edx
269 pushfq
270 lea edx, [rdx + DATA16 - DATA32]
271 lea r8, @RetFromRealMode
272 push r8
273 mov r8d, cs
274 mov [rcx + (SavedCs - SavedCr4)], r8w
275 mov r8, rsp
276 jmp fword ptr [rcx + (_EntryPoint - SavedCr4)]
277 @RetFromRealMode:
278 popfq
279 lidt fword ptr [rsp + 38h] ; restore protected mode IDTR
280 lea eax, [rbp - sizeof (IA32_REGS)]
281 pop gs
282 pop fs
283 mov ss, r9d
284 mov es, r11d
285 mov ds, r10d
286 ret
287 InternalAsmThunk16 ENDP
288
289 END