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