]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/BootScriptSaveOnS3SaveStateThunk/X64/AsmDispatchExecute.asm
Fix CYG GCC build fail on retf.
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / BootScriptSaveOnS3SaveStateThunk / X64 / AsmDispatchExecute.asm
1 ;
2 ; Copyright (c) 2010, 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 ; AsmDispatchExecute.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: EFI_STATUS
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 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 pop rcx ; drop param1
141 pop rcx ; drop param2
142
143 ;
144 ; restore CR4
145 ;
146 mov rax, cr4
147 bts eax, 5
148 mov cr4, rax
149
150 ;
151 ; restore CR3
152 ;
153 mov eax, ebp
154 mov cr3, rax
155
156 ;
157 ; Set EFER.LME to re-enable ia32-e
158 ;
159 mov ecx, 0C0000080h
160 rdmsr
161 bts eax, 8
162 wrmsr
163 ;
164 ; Enable paging
165 ;
166 mov rax, cr0
167 bts eax, 31
168 mov cr0, rax
169 ; Now we are in compatible mode
170
171 ;
172 ; Reload cs register
173 ;
174 retf
175 ReloadCS:
176 ;
177 ; Now we're in Long Mode
178 ;
179 ;
180 ; Restore C register and eax hold the return status from 32-bit function.
181 ; Note: Do not touch rax from now which hold the return value from IA32 function
182 ;
183 pop rbx
184 pop rbp
185 pop rsi
186 pop rdi
187 popfq
188 ;
189 ; Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.
190 ;
191 lgdt fword ptr[rsp]
192 ;
193 ; drop GDT descriptor in stack
194 ;
195 add rsp, 10h
196 ;
197 ; switch to orignal CS and GDTR
198 ;
199 pop r9 ; get CS
200 shl r9, 32 ; rcx[32..47] <- Cs
201 mov rcx, OFFSET @F
202 or rcx, r9
203 push rcx
204 retf
205 @@:
206 ;
207 ; Reload original DS/ES/SS
208 ;
209 pop rcx
210 mov ds, rcx
211 mov es, rcx
212 mov ss, rcx
213 ret
214 AsmExecute32BitCode ENDP
215
216 END