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