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