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