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