]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / IntelFsp2Pkg / Library / BaseFspCommonLib / FspCommonLib.c
CommitLineData
cf1d4549
JY
1/** @file\r
2\r
00aa71ce 3 Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>\r
9672cd30 4 SPDX-License-Identifier: BSD-2-Clause-Patent\r
cf1d4549
JY
5\r
6**/\r
7\r
8#include <PiPei.h>\r
9#include <Library/BaseLib.h>\r
10#include <Library/DebugLib.h>\r
11#include <Library/PcdLib.h>\r
12#include <FspGlobalData.h>\r
13#include <FspEas.h>\r
6b5677e1 14#include <Library/FspSwitchStackLib.h>\r
cf1d4549
JY
15\r
16#pragma pack(1)\r
17\r
18//\r
19// API Parameter +0x34\r
20// API return address +0x30\r
21//\r
22// push FspInfoHeader +0x2C\r
23// pushfd +0x28\r
24// cli\r
25// pushad +0x24\r
26// sub esp, 8 +0x00\r
27// sidt fword ptr [esp]\r
28//\r
29typedef struct {\r
30 UINT16 IdtrLimit;\r
31 UINT32 IdtrBase;\r
32 UINT16 Reserved;\r
ec0b5484 33 UINT32 Registers[8]; // General Purpose Registers: Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx and Eax\r
cf1d4549
JY
34 UINT16 Flags[2];\r
35 UINT32 FspInfoHeader;\r
36 UINT32 ApiRet;\r
37 UINT32 ApiParam[2];\r
38} CONTEXT_STACK;\r
39\r
ec0b5484 40//\r
00aa71ce
TK
41// API return address +0xB8\r
42// Reserved +0xB0\r
ec0b5484
KT
43// push API Parameter2 +0xA8\r
44// push API Parameter1 +0xA0\r
45// push FspInfoHeader +0x98\r
46// pushfq +0x90\r
47// cli\r
48// PUSHA_64 +0x10\r
49// sub rsp, 16 +0x00\r
50// sidt [rsp]\r
51//\r
52typedef struct {\r
53 UINT64 Idtr[2]; // IDTR Limit - bit0:bi15, IDTR Base - bit16:bit79\r
54 UINT64 Registers[16]; // General Purpose Registers: RDI, RSI, RBP, RSP, RBX, RDX, RCX, RAX, and R15 to R8\r
55 UINT32 Flags[2];\r
56 UINT64 FspInfoHeader;\r
57 UINT64 ApiParam[2];\r
00aa71ce 58 UINT64 Reserved; // The reserved QWORD is needed for stack alignment in X64.\r
ec0b5484
KT
59 UINT64 ApiRet; // 64bit stack format is different from the 32bit one due to x64 calling convention\r
60} CONTEXT_STACK_64;\r
61\r
62#define CONTEXT_STACK_OFFSET(x) (sizeof(UINTN) == sizeof (UINT32) ? (UINTN)&((CONTEXT_STACK *)(UINTN)0)->x : (UINTN)&((CONTEXT_STACK_64 *)(UINTN)0)->x)\r
cf1d4549
JY
63\r
64#pragma pack()\r
65\r
66/**\r
67 This function sets the FSP global data pointer.\r
68\r
86079a4d 69 @param[in] FspData FSP global data pointer.\r
cf1d4549
JY
70\r
71**/\r
72VOID\r
73EFIAPI\r
74SetFspGlobalDataPointer (\r
111f2228 75 IN FSP_GLOBAL_DATA *FspData\r
cf1d4549
JY
76 )\r
77{\r
78 ASSERT (FspData != NULL);\r
111f2228 79 *((volatile UINT32 *)(UINTN)PcdGet32 (PcdGlobalDataPointerAddress)) = (UINT32)(UINTN)FspData;\r
cf1d4549
JY
80}\r
81\r
82/**\r
83 This function gets the FSP global data pointer.\r
84\r
85**/\r
86FSP_GLOBAL_DATA *\r
87EFIAPI\r
88GetFspGlobalDataPointer (\r
89 VOID\r
90 )\r
91{\r
111f2228 92 FSP_GLOBAL_DATA *FspData;\r
cf1d4549 93\r
111f2228 94 FspData = *(FSP_GLOBAL_DATA **)(UINTN)PcdGet32 (PcdGlobalDataPointerAddress);\r
cf1d4549
JY
95 return FspData;\r
96}\r
97\r
98/**\r
35897da2 99 This function gets back the FSP API first parameter passed by the bootloader.\r
cf1d4549 100\r
35897da2 101 @retval ApiParameter FSP API first parameter passed by the bootloader.\r
cf1d4549 102**/\r
ec0b5484 103UINTN\r
cf1d4549
JY
104EFIAPI\r
105GetFspApiParameter (\r
106 VOID\r
107 )\r
108{\r
109 FSP_GLOBAL_DATA *FspData;\r
110\r
111f2228 111 FspData = GetFspGlobalDataPointer ();\r
ec0b5484 112 return *(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (ApiParam[0]));\r
cf1d4549
JY
113}\r
114\r
115/**\r
35897da2 116 This function returns the FSP entry stack pointer from address of the first API parameter.\r
cf1d4549 117\r
35897da2
CC
118 @retval FSP entry stack pointer.\r
119**/\r
111f2228 120VOID *\r
35897da2
CC
121EFIAPI\r
122GetFspEntryStack (\r
123 VOID\r
124 )\r
125{\r
126 FSP_GLOBAL_DATA *FspData;\r
127\r
111f2228
MK
128 FspData = GetFspGlobalDataPointer ();\r
129 return (VOID *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (ApiParam[0]));\r
35897da2
CC
130}\r
131\r
132/**\r
133 This function gets back the FSP API second parameter passed by the bootloader.\r
134\r
135 @retval ApiParameter FSP API second parameter passed by the bootloader.\r
cf1d4549 136**/\r
ec0b5484 137UINTN\r
cf1d4549
JY
138EFIAPI\r
139GetFspApiParameter2 (\r
140 VOID\r
141 )\r
142{\r
143 FSP_GLOBAL_DATA *FspData;\r
144\r
111f2228 145 FspData = GetFspGlobalDataPointer ();\r
ec0b5484 146 return *(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (ApiParam[1]));\r
cf1d4549
JY
147}\r
148\r
149/**\r
150 This function sets the FSP API parameter in the stack.\r
151\r
152 @param[in] Value New parameter value.\r
153\r
154**/\r
155VOID\r
156EFIAPI\r
157SetFspApiParameter (\r
111f2228 158 IN UINT32 Value\r
cf1d4549
JY
159 )\r
160{\r
161 FSP_GLOBAL_DATA *FspData;\r
162\r
ec0b5484
KT
163 FspData = GetFspGlobalDataPointer ();\r
164 *(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (ApiParam)) = Value;\r
cf1d4549
JY
165}\r
166\r
167/**\r
168 This function set the API status code returned to the BootLoader.\r
169\r
170 @param[in] ReturnStatus Status code to return.\r
171\r
172**/\r
173VOID\r
174EFIAPI\r
175SetFspApiReturnStatus (\r
ec0b5484 176 IN UINTN ReturnStatus\r
cf1d4549
JY
177 )\r
178{\r
179 FSP_GLOBAL_DATA *FspData;\r
180\r
ec0b5484
KT
181 FspData = GetFspGlobalDataPointer ();\r
182 *(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (Registers[7])) = ReturnStatus;\r
cf1d4549
JY
183}\r
184\r
185/**\r
186 This function sets the context switching stack to a new stack frame.\r
187\r
188 @param[in] NewStackTop New core stack to be set.\r
189\r
190**/\r
191VOID\r
192EFIAPI\r
193SetFspCoreStackPointer (\r
111f2228 194 IN VOID *NewStackTop\r
cf1d4549
JY
195 )\r
196{\r
197 FSP_GLOBAL_DATA *FspData;\r
ec0b5484
KT
198 UINTN *OldStack;\r
199 UINTN *NewStack;\r
cf1d4549
JY
200 UINT32 StackContextLen;\r
201\r
111f2228 202 FspData = GetFspGlobalDataPointer ();\r
140446cd 203 StackContextLen = sizeof (CONTEXT_STACK) / sizeof (UINTN);\r
cf1d4549
JY
204\r
205 //\r
206 // Reserve space for the ContinuationFunc two parameters\r
207 //\r
140446cd
CC
208 OldStack = (UINTN *)FspData->CoreStack;\r
209 NewStack = (UINTN *)NewStackTop - StackContextLen - 2;\r
ec0b5484 210 FspData->CoreStack = (UINTN)NewStack;\r
cf1d4549
JY
211 while (StackContextLen-- != 0) {\r
212 *NewStack++ = *OldStack++;\r
213 }\r
214}\r
215\r
216/**\r
217 This function sets the platform specific data pointer.\r
218\r
86079a4d 219 @param[in] PlatformData FSP platform specific data pointer.\r
cf1d4549
JY
220\r
221**/\r
222VOID\r
223EFIAPI\r
224SetFspPlatformDataPointer (\r
111f2228 225 IN VOID *PlatformData\r
cf1d4549
JY
226 )\r
227{\r
228 FSP_GLOBAL_DATA *FspData;\r
229\r
111f2228 230 FspData = GetFspGlobalDataPointer ();\r
cf1d4549
JY
231 FspData->PlatformData.DataPtr = PlatformData;\r
232}\r
233\r
cf1d4549
JY
234/**\r
235 This function gets the platform specific data pointer.\r
236\r
86079a4d 237 @param[in] PlatformData FSP platform specific data pointer.\r
cf1d4549
JY
238\r
239**/\r
240VOID *\r
241EFIAPI\r
242GetFspPlatformDataPointer (\r
243 VOID\r
244 )\r
245{\r
246 FSP_GLOBAL_DATA *FspData;\r
247\r
111f2228 248 FspData = GetFspGlobalDataPointer ();\r
cf1d4549
JY
249 return FspData->PlatformData.DataPtr;\r
250}\r
251\r
cf1d4549
JY
252/**\r
253 This function sets the UPD data pointer.\r
254\r
255 @param[in] UpdDataPtr UPD data pointer.\r
256**/\r
257VOID\r
258EFIAPI\r
259SetFspUpdDataPointer (\r
111f2228 260 IN VOID *UpdDataPtr\r
cf1d4549
JY
261 )\r
262{\r
263 FSP_GLOBAL_DATA *FspData;\r
264\r
265 //\r
86079a4d 266 // Get the FSP Global Data Pointer\r
cf1d4549 267 //\r
111f2228 268 FspData = GetFspGlobalDataPointer ();\r
cf1d4549
JY
269\r
270 //\r
271 // Set the UPD pointer.\r
272 //\r
273 FspData->UpdDataPtr = UpdDataPtr;\r
274}\r
275\r
276/**\r
277 This function gets the UPD data pointer.\r
278\r
279 @return UpdDataPtr UPD data pointer.\r
280**/\r
281VOID *\r
282EFIAPI\r
283GetFspUpdDataPointer (\r
284 VOID\r
285 )\r
286{\r
287 FSP_GLOBAL_DATA *FspData;\r
288\r
111f2228 289 FspData = GetFspGlobalDataPointer ();\r
cf1d4549
JY
290 return FspData->UpdDataPtr;\r
291}\r
292\r
cf1d4549 293/**\r
86079a4d 294 This function sets the FspMemoryInit UPD data pointer.\r
cf1d4549 295\r
86079a4d 296 @param[in] MemoryInitUpdPtr FspMemoryInit UPD data pointer.\r
cf1d4549
JY
297**/\r
298VOID\r
299EFIAPI\r
300SetFspMemoryInitUpdDataPointer (\r
111f2228 301 IN VOID *MemoryInitUpdPtr\r
cf1d4549
JY
302 )\r
303{\r
304 FSP_GLOBAL_DATA *FspData;\r
305\r
306 //\r
86079a4d 307 // Get the FSP Global Data Pointer\r
cf1d4549 308 //\r
111f2228 309 FspData = GetFspGlobalDataPointer ();\r
cf1d4549
JY
310\r
311 //\r
86079a4d 312 // Set the FspMemoryInit UPD pointer.\r
cf1d4549
JY
313 //\r
314 FspData->MemoryInitUpdPtr = MemoryInitUpdPtr;\r
315}\r
316\r
317/**\r
86079a4d 318 This function gets the FspMemoryInit UPD data pointer.\r
cf1d4549 319\r
86079a4d 320 @return FspMemoryInit UPD data pointer.\r
cf1d4549
JY
321**/\r
322VOID *\r
323EFIAPI\r
324GetFspMemoryInitUpdDataPointer (\r
325 VOID\r
326 )\r
327{\r
328 FSP_GLOBAL_DATA *FspData;\r
329\r
111f2228 330 FspData = GetFspGlobalDataPointer ();\r
cf1d4549
JY
331 return FspData->MemoryInitUpdPtr;\r
332}\r
333\r
cf1d4549 334/**\r
86079a4d 335 This function sets the FspSiliconInit UPD data pointer.\r
cf1d4549 336\r
86079a4d 337 @param[in] SiliconInitUpdPtr FspSiliconInit UPD data pointer.\r
cf1d4549
JY
338**/\r
339VOID\r
340EFIAPI\r
341SetFspSiliconInitUpdDataPointer (\r
111f2228 342 IN VOID *SiliconInitUpdPtr\r
cf1d4549
JY
343 )\r
344{\r
345 FSP_GLOBAL_DATA *FspData;\r
346\r
347 //\r
86079a4d 348 // Get the FSP Global Data Pointer\r
cf1d4549 349 //\r
111f2228 350 FspData = GetFspGlobalDataPointer ();\r
cf1d4549
JY
351\r
352 //\r
86079a4d 353 // Set the FspSiliconInit UPD data pointer.\r
cf1d4549
JY
354 //\r
355 FspData->SiliconInitUpdPtr = SiliconInitUpdPtr;\r
356}\r
357\r
358/**\r
86079a4d 359 This function gets the FspSiliconInit UPD data pointer.\r
cf1d4549 360\r
86079a4d 361 @return FspSiliconInit UPD data pointer.\r
cf1d4549
JY
362**/\r
363VOID *\r
364EFIAPI\r
365GetFspSiliconInitUpdDataPointer (\r
366 VOID\r
367 )\r
368{\r
369 FSP_GLOBAL_DATA *FspData;\r
370\r
111f2228 371 FspData = GetFspGlobalDataPointer ();\r
cf1d4549
JY
372 return FspData->SiliconInitUpdPtr;\r
373}\r
374\r
cf1d4549
JY
375/**\r
376 Set FSP measurement point timestamp.\r
377\r
378 @param[in] Id Measurement point ID.\r
379\r
380 @return performance timestamp.\r
381**/\r
382UINT64\r
383EFIAPI\r
384SetFspMeasurePoint (\r
385 IN UINT8 Id\r
386 )\r
387{\r
388 FSP_GLOBAL_DATA *FspData;\r
389\r
390 //\r
391 // Bit [55: 0] will be the timestamp\r
392 // Bit [63:56] will be the ID\r
393 //\r
111f2228
MK
394 FspData = GetFspGlobalDataPointer ();\r
395 if (FspData->PerfIdx < sizeof (FspData->PerfData) / sizeof (FspData->PerfData[0])) {\r
396 FspData->PerfData[FspData->PerfIdx] = AsmReadTsc ();\r
cf1d4549
JY
397 ((UINT8 *)(&FspData->PerfData[FspData->PerfIdx]))[7] = Id;\r
398 }\r
399\r
400 return FspData->PerfData[(FspData->PerfIdx)++];\r
401}\r
402\r
403/**\r
404 This function gets the FSP info header pointer.\r
405\r
406 @retval FspInfoHeader FSP info header pointer\r
407**/\r
408FSP_INFO_HEADER *\r
409EFIAPI\r
410GetFspInfoHeader (\r
411 VOID\r
412 )\r
413{\r
111f2228 414 return GetFspGlobalDataPointer ()->FspInfoHeader;\r
cf1d4549
JY
415}\r
416\r
417/**\r
418 This function sets the FSP info header pointer.\r
419\r
420 @param[in] FspInfoHeader FSP info header pointer\r
421**/\r
422VOID\r
423EFIAPI\r
424SetFspInfoHeader (\r
111f2228 425 FSP_INFO_HEADER *FspInfoHeader\r
cf1d4549
JY
426 )\r
427{\r
111f2228 428 GetFspGlobalDataPointer ()->FspInfoHeader = FspInfoHeader;\r
cf1d4549
JY
429}\r
430\r
431/**\r
432 This function gets the FSP info header pointer using the API stack context.\r
433\r
434 @retval FspInfoHeader FSP info header pointer using the API stack context\r
435**/\r
436FSP_INFO_HEADER *\r
437EFIAPI\r
438GetFspInfoHeaderFromApiContext (\r
439 VOID\r
440 )\r
441{\r
442 FSP_GLOBAL_DATA *FspData;\r
443\r
111f2228 444 FspData = GetFspGlobalDataPointer ();\r
ec0b5484 445 return (FSP_INFO_HEADER *)(*(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (FspInfoHeader)));\r
cf1d4549
JY
446}\r
447\r
448/**\r
cc0b456a 449 This function gets the CfgRegion data pointer.\r
cf1d4549 450\r
cc0b456a 451 @return CfgRegion data pointer.\r
cf1d4549
JY
452**/\r
453VOID *\r
454EFIAPI\r
cc0b456a 455GetFspCfgRegionDataPointer (\r
cf1d4549
JY
456 VOID\r
457 )\r
458{\r
111f2228 459 FSP_INFO_HEADER *FspInfoHeader;\r
cf1d4549
JY
460\r
461 FspInfoHeader = GetFspInfoHeader ();\r
ec0b5484 462 return (VOID *)(UINTN)(FspInfoHeader->ImageBase + FspInfoHeader->CfgRegionOffset);\r
cf1d4549
JY
463}\r
464\r
465/**\r
466 This function gets FSP API calling index.\r
467\r
468 @retval API calling index\r
469**/\r
470UINT8\r
471EFIAPI\r
472GetFspApiCallingIndex (\r
473 VOID\r
474 )\r
475{\r
111f2228 476 return GetFspGlobalDataPointer ()->ApiIdx;\r
cf1d4549
JY
477}\r
478\r
479/**\r
480 This function sets FSP API calling mode.\r
481\r
482 @param[in] Index API calling index\r
483**/\r
484VOID\r
485EFIAPI\r
486SetFspApiCallingIndex (\r
487 UINT8 Index\r
488 )\r
489{\r
490 FSP_GLOBAL_DATA *FspData;\r
491\r
111f2228 492 FspData = GetFspGlobalDataPointer ();\r
cf1d4549
JY
493 FspData->ApiIdx = Index;\r
494}\r
495\r
496/**\r
497 This function gets FSP Phase StatusCode.\r
498\r
499 @retval StatusCode\r
500**/\r
501UINT32\r
502EFIAPI\r
503GetPhaseStatusCode (\r
504 VOID\r
505 )\r
506{\r
111f2228 507 return GetFspGlobalDataPointer ()->StatusCode;\r
cf1d4549
JY
508}\r
509\r
510/**\r
511 This function sets FSP Phase StatusCode.\r
512\r
513 @param[in] Mode Phase StatusCode\r
514**/\r
515VOID\r
516EFIAPI\r
517SetPhaseStatusCode (\r
518 UINT32 StatusCode\r
519 )\r
520{\r
521 FSP_GLOBAL_DATA *FspData;\r
522\r
111f2228 523 FspData = GetFspGlobalDataPointer ();\r
cf1d4549
JY
524 FspData->StatusCode = StatusCode;\r
525}\r
526\r
6b5677e1
YS
527/**\r
528 This function updates the return status of the FSP API with requested reset type and returns to Boot Loader.\r
529\r
530 @param[in] FspResetType Reset type that needs to returned as API return status\r
531\r
532**/\r
533VOID\r
534EFIAPI\r
535FspApiReturnStatusReset (\r
140446cd 536 IN EFI_STATUS FspResetType\r
6b5677e1
YS
537 )\r
538{\r
539 volatile BOOLEAN LoopUntilReset;\r
e37bb20c 540\r
6b5677e1 541 LoopUntilReset = TRUE;\r
111f2228 542 DEBUG ((DEBUG_INFO, "FSP returning control to Bootloader with reset required return status %x\n", FspResetType));\r
a2e61f34
CC
543 if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) {\r
544 ///\r
545 /// Below code is not an infinite loop.The control will go back to API calling function in BootLoader each time BootLoader\r
546 /// calls the FSP API without honoring the reset request by FSP\r
547 ///\r
548 do {\r
140446cd 549 SetFspApiReturnStatus (FspResetType);\r
a2e61f34
CC
550 Pei2LoaderSwitchStack ();\r
551 DEBUG ((DEBUG_ERROR, "!!!ERROR: FSP has requested BootLoader for reset. But BootLoader has not honored the reset\n"));\r
552 DEBUG ((DEBUG_ERROR, "!!!ERROR: Please add support in BootLoader to honor the reset request from FSP\n"));\r
553 } while (LoopUntilReset);\r
554 }\r
6b5677e1 555}\r