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