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