]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/Thunk16/X64/Thunk16.asm
Sync all bug fixes between EDK1.04 and EDK1.06 into EdkCompatibilityPkg.
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Thunk16 / X64 / Thunk16.asm
1 ;*****************************************************************************
2 ;*
3 ;* Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
4 ;* 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 mCode16Size:QWORD
23
24 .const
25
26 mCode16Size DQ _Code16End - _Code16Addr
27
28 .data
29
30 NullSegSel DQ 0
31 _16CsSegSel LABEL QWORD
32 DW -1
33 DW 0
34 DB 0
35 DB 9bh
36 DB 8fh ; 16-bit segment
37 DB 0
38 _16DsSegSel LABEL QWORD
39 DW -1
40 DW 0
41 DB 0
42 DB 93h
43 DB 8fh ; 16-bit segment
44 DB 0
45
46 _16Gdtr LABEL FWORD
47 DW $ - offset NullSegSel - 1
48 DQ offset NullSegSel
49
50 .code
51
52 STACK_PARAM_SIZE EQU 16
53
54 IA32_REGS STRUC 4t
55 _EDI DD ?
56 _ESI DD ?
57 _EBP DD ?
58 _ESP DD ?
59 _EBX DD ?
60 _EDX DD ?
61 _ECX DD ?
62 _EAX DD ?
63 _DS DW ?
64 _ES DW ?
65 _FS DW ?
66 _GS DW ?
67 _RFLAGS DQ ?
68 _EIP DD ?
69 _CS DW ?
70 _SS DW ?
71 IA32_REGS ENDS
72
73 _STK16 STRUC 1t
74 RetEip DD ?
75 RetCs DW ?
76 ThunkFlags DW ?
77 SavedGdtr FWORD ?
78 Resvd1 DW ?
79 SavedCr0 DD ?
80 SavedCr4 DD ?
81 _STK16 ENDS
82
83 _Thunk16 PROC USES rbp rbx rsi rdi r12 r13 r14 r15
84
85 push fs
86 push gs
87
88 mov r12d, ds
89 mov r13d, es
90 mov r14d, ss
91 mov r15, rsp
92 mov rsi, rcx
93 movzx r10, (IA32_REGS ptr [rsi])._SS
94 xor rdi, rdi
95 mov edi, (IA32_REGS ptr [rsi])._ESP
96 add rdi, - sizeof (IA32_REGS) - sizeof (_STK16)
97 push rdi
98 imul rax, r10, 16
99 add rdi, rax
100 push sizeof (IA32_REGS) / 4
101 pop rcx
102 rep movsd
103
104 ; copy eflags to stack frame
105 mov rax, (IA32_REGS ptr [rsi - sizeof(IA32_REGS)])._RFLAGS
106 mov [rdi - sizeof(IA32_REGS) - STACK_PARAM_SIZE - 8], rax
107
108 pop rbx ; rbx <- 16-bit stack offset
109 lea eax, @F ; return offset
110 stosd
111 mov eax, cs ; return segment
112 stosw
113 mov eax, edx ; THUNK Flags
114 stosw
115 sgdt fword ptr [rsp + 58h] ; save GDTR
116 mov rax, [rsp + 58h]
117 stosq
118 mov rax, cr0 ; save CR0
119 mov esi, eax ; esi <- CR0 to set
120 stosd
121 mov rax, cr4 ; save CR4
122 stosd
123 sidt fword ptr [rsp + 58h] ; save IDTR
124 and esi, 07ffffffeh ; clear PE & PG bits
125 mov rdi, r10 ; rdi <- 16-bit stack segment
126
127 shl r8, 16
128 push r8 ; far jmp address
129 lea eax, @16Bit
130 push rax
131 mov word ptr [rsp + 4], 8
132 lgdt _16Gdtr
133 retf
134 @16Bit:
135 DB 66h
136 mov ecx, 0c0000080h
137 mov cr0, rsi ; disable PE & PG
138 rdmsr
139 and ah, NOT 1
140 wrmsr ; clear LME bit
141 mov rax, cr4
142 and al, NOT 30h ; clear PAE & PSE
143 mov cr4, rax
144 retf
145 @@:
146 xor rax, rax
147 mov eax, ss
148 shl eax, 4
149 add eax, esp ; rax <- address of 16-bit stack
150 mov rsp, r15
151 lidt fword ptr [rsp + 58h] ; restore IDTR
152 mov ds, r12d
153 mov es, r13d
154 mov ss, r14d
155 pop gs
156 pop fs
157 ret
158 _Thunk16 ENDP
159
160 ALIGN 10h
161
162 _Code16Addr PROC
163 _Code16Addr ENDP
164
165 RealMode PROC
166 mov ss, edi
167 mov sp, bx ; set up 16-bit stack
168 DB 2eh, 0fh, 1, 1eh
169 DW _16Idtr - _Code16Addr ; lidt _16Idtr
170 DB 66h, 61h ; popad
171 DB 1fh ; pop ds
172 DB 7 ; pop es
173 pop fs
174 pop gs
175 sub esp, (sizeof(IA32_REGS) - 16) + STACK_PARAM_SIZE + 8
176
177 DB 66h, 9Dh ; popfd
178 add esp, 4 ; skip high part of RFLAGS
179 DB 67h, 0f7h, 44h, 24h ; test (_STK16 ptr [esp + STACK_PARAM_SIZE + sizeof(IA32_REGS)]).ThunkFlags, 1
180 DB (STACK_PARAM_SIZE + sizeof(IA32_REGS) + 6)
181 DB 1, 0
182 jz @F
183 pushfq ; pushf, actually, when it's INT#
184 @@:
185 DB 0eh ; push cs
186 DB 68h ; push /iw
187 DW @FarCallRet - _Code16Addr
188 jz @F
189 DB 66h
190 jmp fword ptr [esp + 6 + STACK_PARAM_SIZE + sizeof(IA32_REGS) - 8]
191 @@:
192 DB 66h
193 jmp fword ptr [esp + 4 + STACK_PARAM_SIZE + sizeof(IA32_REGS) - 8]
194 @FarCallRet:
195 add esp, (sizeof(IA32_REGS) - 16) + STACK_PARAM_SIZE + 8
196 DB 66h
197 push 0 ; push a dword of zero
198 pushf ; pushfd, actually
199 push gs
200 push fs
201 DB 6 ; push es
202 DB 1eh ; push ds
203 DB 66h, 60h ; pushad
204 cli
205
206 DB 66h
207 lgdt (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedGdtr
208 DB 66h
209 mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr4
210 mov cr4, rax
211 DB 66h
212 mov ecx, 0c0000080h
213 rdmsr
214 or ah, 1
215 wrmsr ; set LME
216 DB 66h
217 mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr0
218 mov cr0, rax
219 DB 66h
220 jmp fword ptr (_STK16 ptr [esp + sizeof(IA32_REGS)]).RetEip
221
222 RealMode ENDP
223
224 _16Idtr FWORD (1 SHL 10) - 1
225
226 _Code16End:
227
228 END