]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.nasm
bcc6d70a7383c068841976bb9f15e3b593aacb02
[mirror_edk2.git] / IntelFsp2WrapperPkg / Library / BaseFspWrapperApiLib / X64 / Thunk64To32.nasm
1 ;
2 ; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
3 ; This program and the accompanying materials
4 ; are licensed and made available under the terms and conditions of the BSD License
5 ; which accompanies this distribution. The full text of the license may be found at
6 ; http://opensource.org/licenses/bsd-license.php.
7 ;
8 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10 ;
11 ;
12 ; Module Name:
13 ;
14 ; Thunk64To32.nasm
15 ;
16 ; Abstract:
17 ;
18 ; This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then
19 ; transit back to long mode.
20 ;
21 ;-------------------------------------------------------------------------------
22 DEFAULT REL
23 SECTION .text
24 ;----------------------------------------------------------------------------
25 ; Procedure: AsmExecute32BitCode
26 ;
27 ; Input: None
28 ;
29 ; Output: None
30 ;
31 ; Prototype: UINT32
32 ; AsmExecute32BitCode (
33 ; IN UINT64 Function,
34 ; IN UINT64 Param1,
35 ; IN UINT64 Param2,
36 ; IN IA32_DESCRIPTOR *InternalGdtr
37 ; );
38 ;
39 ;
40 ; Description: A thunk function to execute 32-bit code in long mode.
41 ;
42 ;----------------------------------------------------------------------------
43 global ASM_PFX(AsmExecute32BitCode)
44 ASM_PFX(AsmExecute32BitCode):
45 ;
46 ; save IFLAG and disable it
47 ;
48 pushfq
49 cli
50
51 ;
52 ; save orignal GDTR and CS
53 ;
54 mov rax, ds
55 push rax
56 mov rax, cs
57 push rax
58 sub rsp, 0x10
59 sgdt [rsp]
60 ;
61 ; load internal GDT
62 ;
63 lgdt [r9]
64 ;
65 ; Save general purpose register and rflag register
66 ;
67 pushfq
68 push rdi
69 push rsi
70 push rbp
71 push rbx
72
73 ;
74 ; save CR3
75 ;
76 mov rax, cr3
77 mov rbp, rax
78
79 ;
80 ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode
81 ;
82 mov rax, dword 0x10 ; load long mode selector
83 shl rax, 32
84 mov r9, ReloadCS ;Assume the ReloadCS is under 4G
85 or rax, r9
86 push rax
87 ;
88 ; Save parameters for 32-bit function call
89 ;
90 mov rax, r8
91 shl rax, 32
92 or rax, rdx
93 push rax
94 ;
95 ; save the 32-bit function entry and the return address into stack which will be
96 ; retrieve in compatibility mode.
97 ;
98 mov rax, ReturnBack ;Assume the ReloadCS is under 4G
99 shl rax, 32
100 or rax, rcx
101 push rax
102
103 ;
104 ; let rax save DS
105 ;
106 mov rax, dword 0x18
107
108 ;
109 ; Change to Compatible Segment
110 ;
111 mov rcx, dword 0x8 ; load compatible mode selector
112 shl rcx, 32
113 mov rdx, Compatible ; assume address < 4G
114 or rcx, rdx
115 push rcx
116 retf
117
118 Compatible:
119 ; reload DS/ES/SS to make sure they are correct referred to current GDT
120 mov ds, ax
121 mov es, ax
122 mov ss, ax
123
124 ;
125 ; Disable paging
126 ;
127 mov rcx, cr0
128 btc ecx, 31
129 mov cr0, rcx
130 ;
131 ; Clear EFER.LME
132 ;
133 mov ecx, 0xC0000080
134 rdmsr
135 btc eax, 8
136 wrmsr
137
138 ; Now we are in protected mode
139 ;
140 ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G
141 ;
142 pop rax ; Here is the function entry
143 ;
144 ; Now the parameter is at the bottom of the stack, then call in to IA32 function.
145 ;
146 jmp rax
147 ReturnBack:
148 mov ebx, eax ; save return status
149 pop rcx ; drop param1
150 pop rcx ; drop param2
151
152 ;
153 ; restore CR4
154 ;
155 mov rax, cr4
156 bts eax, 5
157 mov cr4, rax
158
159 ;
160 ; restore CR3
161 ;
162 mov eax, ebp
163 mov cr3, rax
164
165 ;
166 ; Set EFER.LME to re-enable ia32-e
167 ;
168 mov ecx, 0xC0000080
169 rdmsr
170 bts eax, 8
171 wrmsr
172 ;
173 ; Enable paging
174 ;
175 mov rax, cr0
176 bts eax, 31
177 mov cr0, rax
178 ; Now we are in compatible mode
179
180 ;
181 ; Reload cs register
182 ;
183 retf
184 ReloadCS:
185 ;
186 ; Now we're in Long Mode
187 ;
188 ;
189 ; Restore C register and eax hold the return status from 32-bit function.
190 ; Note: Do not touch rax from now which hold the return value from IA32 function
191 ;
192 mov eax, ebx ; put return status to EAX
193 pop rbx
194 pop rbp
195 pop rsi
196 pop rdi
197 popfq
198 ;
199 ; Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.
200 ;
201 lgdt [rsp]
202 ;
203 ; drop GDT descriptor in stack
204 ;
205 add rsp, 0x10
206 ;
207 ; switch to orignal CS and GDTR
208 ;
209 pop r9 ; get CS
210 shl r9, 32 ; rcx[32..47] <- Cs
211 mov rcx, .0
212 or rcx, r9
213 push rcx
214 retf
215 .0:
216 ;
217 ; Reload original DS/ES/SS
218 ;
219 pop rcx
220 mov ds, rcx
221 mov es, rcx
222 mov ss, rcx
223
224 ;
225 ; Restore IFLAG
226 ;
227 popfq
228
229 ret
230