]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm
IntelFsp2Pkg/FspSecCore: Add FSP-I API for SMM support.
[mirror_edk2.git] / IntelFsp2Pkg / FspSecCore / X64 / FspApiEntryM.nasm
CommitLineData
00aa71ce
TK
1;; @file\r
2; Provide FSP API entry points.\r
3;\r
4; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
5; SPDX-License-Identifier: BSD-2-Clause-Patent\r
6;;\r
7\r
8 SECTION .text\r
9\r
10%include "PushPopRegsNasm.inc"\r
11\r
12;\r
13; Following are fixed PCDs\r
14;\r
15extern ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))\r
16\r
17struc FSPM_UPD_COMMON_FSP24\r
18 ; FSP_UPD_HEADER {\r
19 .FspUpdHeader: resd 8\r
20 ; }\r
21 ; FSPM_ARCH2_UPD {\r
22 .Revision: resb 1\r
23 .Reserved: resb 3\r
24 .Length resd 1\r
25 .StackBase: resq 1\r
26 .StackSize: resq 1\r
27 .BootLoaderTolumSize: resd 1\r
28 .BootMode: resd 1\r
29 .FspEventHandler resq 1\r
30 .Reserved1: resb 24\r
31 ; }\r
32 .size:\r
33endstruc\r
34\r
35;\r
36; Following functions will be provided in C\r
37;\r
38extern ASM_PFX(SecStartup)\r
39extern ASM_PFX(FspApiCommon)\r
40\r
41;\r
42; Following functions will be provided in PlatformSecLib\r
43;\r
44extern ASM_PFX(AsmGetFspBaseAddress)\r
45extern ASM_PFX(AsmGetFspInfoHeader)\r
46\r
47FSP_HEADER_IMGBASE_OFFSET EQU 1Ch\r
48FSP_HEADER_CFGREG_OFFSET EQU 24h\r
49\r
50;----------------------------------------------------------------------------\r
51; FspMemoryInit API\r
52;\r
53; This FSP API is called after TempRamInit and initializes the memory.\r
54;\r
55;----------------------------------------------------------------------------\r
56global ASM_PFX(FspMemoryInitApi)\r
57ASM_PFX(FspMemoryInitApi):\r
48249243 58 mov rax, 3 ; FSP_API_INDEX.FspMemoryInitApiIndex\r
00aa71ce
TK
59 jmp ASM_PFX(FspApiCommon)\r
60\r
61;----------------------------------------------------------------------------\r
62; TempRamExitApi API\r
63;\r
64; This API tears down temporary RAM\r
65;\r
66;----------------------------------------------------------------------------\r
67global ASM_PFX(TempRamExitApi)\r
68ASM_PFX(TempRamExitApi):\r
48249243 69 mov rax, 4 ; FSP_API_INDEX.TempRamExitApiIndex\r
00aa71ce
TK
70 jmp ASM_PFX(FspApiCommon)\r
71\r
72;----------------------------------------------------------------------------\r
73; FspApiCommonContinue API\r
74;\r
75; This is the FSP API common entry point to resume the FSP execution\r
76;\r
77;----------------------------------------------------------------------------\r
78global ASM_PFX(FspApiCommonContinue)\r
79ASM_PFX(FspApiCommonContinue):\r
80 ;\r
81 ; RAX holds the API index\r
82 ; Push RDX and RCX to form CONTEXT_STACK_64\r
83 ;\r
84 push rdx ; Push a QWORD data for stack alignment\r
85 push rdx ; Push API Parameter2 on stack\r
86 push rcx ; Push API Parameter1 on stack\r
87\r
88 ;\r
89 ; FspMemoryInit API setup the initial stack frame\r
90 ;\r
91\r
92 ;\r
93 ; Place holder to store the FspInfoHeader pointer\r
94 ;\r
95 push rax\r
96\r
97 ;\r
98 ; Update the FspInfoHeader pointer\r
99 ;\r
100 push rax\r
101 call ASM_PFX(AsmGetFspInfoHeader)\r
102 mov [rsp + 8], rax\r
103 pop rax\r
104\r
105 ;\r
106 ; Create a Task Frame in the stack for the Boot Loader\r
107 ;\r
108 pushfq\r
109 cli\r
110 PUSHA_64\r
111\r
112 ; Reserve 16 bytes for IDT save/restore\r
113 sub rsp, 16\r
114 sidt [rsp]\r
115\r
116 ; Get Stackbase and StackSize from FSPM_UPD Param\r
117 mov rdx, rcx ; Put FSPM_UPD Param to rdx\r
118 cmp rdx, 0\r
119 jnz FspStackSetup\r
120\r
121 ; Get UPD default values if FspmUpdDataPtr (ApiParam1) is null\r
122 xchg rbx, rax\r
123 call ASM_PFX(AsmGetFspInfoHeader)\r
124 mov edx, [rax + FSP_HEADER_IMGBASE_OFFSET]\r
125 add edx, [rax + FSP_HEADER_CFGREG_OFFSET]\r
126 xchg rbx, rax\r
127\r
128FspStackSetup:\r
129 mov cl, [rdx + FSPM_UPD_COMMON_FSP24.Revision]\r
130 cmp cl, 3\r
131 jae FspmUpdCommonFsp24\r
132\r
133 mov rax, 08000000000000002h ; RETURN_INVALID_PARAMETER\r
134 sub rsp, 0b8h\r
135 ret\r
136\r
137FspmUpdCommonFsp24:\r
138 ;\r
139 ; StackBase = temp memory base, StackSize = temp memory size\r
140 ;\r
141 mov rdi, [rdx + FSPM_UPD_COMMON_FSP24.StackBase]\r
142 mov ecx, [rdx + FSPM_UPD_COMMON_FSP24.StackSize]\r
143\r
144 ;\r
145 ; Keep using bootloader stack if heap size % is 0\r
146 ;\r
147 mov rbx, ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))\r
148 mov bl, BYTE [rbx]\r
149 cmp bl, 0\r
150 jz SkipStackSwitch\r
151\r
152 ;\r
153 ; Set up a dedicated temp ram stack for FSP if FSP heap size % doesn't equal 0\r
154 ;\r
155 add rdi, rcx\r
156 ;\r
157 ; Switch to new FSP stack\r
158 ;\r
159 xchg rdi, rsp ; Exchange rdi and rsp, rdi will be assigned to the current rsp pointer and rsp will be Stack base + Stack size\r
160\r
161SkipStackSwitch:\r
162 ;\r
163 ; If heap size % is 0:\r
164 ; EDI is FSPM_UPD_COMMON_FSP24.StackBase and will hold ESP later (boot loader stack pointer)\r
165 ; ECX is FSPM_UPD_COMMON_FSP24.StackSize\r
166 ; ESP is boot loader stack pointer (no stack switch)\r
167 ; BL is 0 to indicate no stack switch (EBX will hold FSPM_UPD_COMMON_FSP24.StackBase later)\r
168 ;\r
169 ; If heap size % is not 0\r
170 ; EDI is boot loader stack pointer\r
171 ; ECX is FSPM_UPD_COMMON_FSP24.StackSize\r
172 ; ESP is new stack (FSPM_UPD_COMMON_FSP24.StackBase + FSPM_UPD_COMMON_FSP24.StackSize)\r
173 ; BL is NOT 0 to indicate stack has switched\r
174 ;\r
175 cmp bl, 0\r
176 jnz StackHasBeenSwitched\r
177\r
178 mov rbx, rdi ; Put FSPM_UPD_COMMON_FSP24.StackBase to rbx as temp memory base\r
179 mov rdi, rsp ; Put boot loader stack pointer to rdi\r
180 jmp StackSetupDone\r
181\r
182StackHasBeenSwitched:\r
183 mov rbx, rsp ; Put Stack base + Stack size in ebx\r
184 sub rbx, rcx ; Stack base + Stack size - Stack size as temp memory base\r
185\r
186StackSetupDone:\r
187\r
188 ;\r
189 ; Per X64 calling convention, make sure RSP is 16-byte aligned.\r
190 ;\r
191 mov rdx, rsp\r
192 and rdx, 0fh\r
193 sub rsp, rdx\r
194\r
195 ;\r
196 ; Pass the API Idx to SecStartup\r
197 ;\r
198 push rax\r
199\r
200 ;\r
201 ; Pass the BootLoader stack to SecStartup\r
202 ;\r
203 push rdi\r
204\r
205 ;\r
206 ; Pass BFV into the PEI Core\r
207 ; It uses relative address to calculate the actual boot FV base\r
208 ; For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and\r
209 ; PcdFspAreaBaseAddress are the same. For FSP with multiple FVs,\r
210 ; they are different. The code below can handle both cases.\r
211 ;\r
212 call ASM_PFX(AsmGetFspBaseAddress)\r
213 mov r8, rax\r
214\r
215 ;\r
216 ; Pass entry point of the PEI core\r
217 ;\r
218 call ASM_PFX(AsmGetPeiCoreOffset)\r
219 lea r9, [r8 + rax]\r
220\r
221 ;\r
222 ; Pass stack base and size into the PEI Core\r
223 ;\r
224 mov rcx, rcx\r
225 mov rdx, rbx\r
226\r
227 ;\r
228 ; Pass Control into the PEI Core\r
229 ; RCX = SizeOfRam, RDX = TempRamBase, R8 = BFV, R9 = PeiCoreEntry, Last 1 Stack = BL stack, Last 2 Stack = API index\r
230 ; According to X64 calling convention, caller has to allocate 32 bytes as a shadow store on call stack right before\r
231 ; calling the function.\r
232 ;\r
233 sub rsp, 20h\r
234 call ASM_PFX(SecStartup)\r
235 add rsp, 20h\r
236exit:\r
237 ret\r
238\r
239global ASM_PFX(FspPeiCoreEntryOff)\r
240ASM_PFX(FspPeiCoreEntryOff):\r
241 ;\r
242 ; This value will be patched by the build script\r
243 ;\r
244 DD 0x12345678\r
245\r
246global ASM_PFX(AsmGetPeiCoreOffset)\r
247ASM_PFX(AsmGetPeiCoreOffset):\r
248 push rbx\r
249 mov rbx, ASM_PFX(FspPeiCoreEntryOff)\r
250 mov eax, dword[ebx]\r
251 pop rbx\r
252 ret\r
253\r
254;----------------------------------------------------------------------------\r
255; TempRamInit API\r
256;\r
257; Empty function for WHOLEARCHIVE build option\r
258;\r
259;----------------------------------------------------------------------------\r
260global ASM_PFX(TempRamInitApi)\r
261ASM_PFX(TempRamInitApi):\r
262 jmp $\r
263 ret\r
264\r
265;----------------------------------------------------------------------------\r
266; Module Entrypoint API\r
267;----------------------------------------------------------------------------\r
268global ASM_PFX(_ModuleEntryPoint)\r
269ASM_PFX(_ModuleEntryPoint):\r
270 jmp $\r
271\r