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