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