1 /** @file
2 
3   Copyright (c) 2014 - 2015, 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 <FspApi.h>
20 
21 #pragma pack(1)
22 
23 //
24 //   Cont Func Parameter 2        +0x3C
25 //   Cont Func Parameter 1        +0x38
26 //
27 //   API Parameter                +0x34
28 //   API return address           +0x30
29 //
30 //   push    FspInfoHeader        +0x2C
31 //   pushfd                       +0x28
32 //   cli
33 //   pushad                       +0x24
34 //   sub     esp, 8               +0x00
35 //   sidt    fword ptr [esp]
36 //
37 typedef struct {
38   UINT16    IdtrLimit;
39   UINT32    IdtrBase;
40   UINT16    Reserved;
41   UINT32    Edi;
42   UINT32    Esi;
43   UINT32    Ebp;
44   UINT32    Esp;
45   UINT32    Ebx;
46   UINT32    Edx;
47   UINT32    Ecx;
48   UINT32    Eax;
49   UINT16    Flags[2];
50   UINT32    FspInfoHeader;
51   UINT32    ApiRet;
52   UINT32    ApiParam;
53 } CONTEXT_STACK;
54 
55 #define CONTEXT_STACK_OFFSET(x)  (UINT32)&((CONTEXT_STACK *)(UINTN)0)->x
56 
57 #pragma pack()
58 
59 /**
60   This function sets the FSP global data pointer.
61 
62   @param[in] FspData       Fsp global data pointer.
63 
64 **/
65 VOID
66 EFIAPI
SetFspGlobalDataPointer(IN FSP_GLOBAL_DATA * FspData)67 SetFspGlobalDataPointer (
68   IN FSP_GLOBAL_DATA   *FspData
69   )
70 {
71   ASSERT (FspData != NULL);
72   *((volatile UINT32 *)(UINTN)PcdGet32(PcdGlobalDataPointerAddress)) = (UINT32)(UINTN)FspData;
73 }
74 
75 /**
76   This function gets the FSP global data pointer.
77 
78 **/
79 FSP_GLOBAL_DATA *
80 EFIAPI
GetFspGlobalDataPointer(VOID)81 GetFspGlobalDataPointer (
82   VOID
83   )
84 {
85   FSP_GLOBAL_DATA   *FspData;
86 
87   FspData = *(FSP_GLOBAL_DATA  **)(UINTN)PcdGet32(PcdGlobalDataPointerAddress);
88   return FspData;
89 }
90 
91 /**
92   This function gets back the FSP API paramter passed by the bootlaoder.
93 
94   @retval ApiParameter FSP API paramter passed by the bootlaoder.
95 **/
96 UINT32
97 EFIAPI
GetFspApiParameter(VOID)98 GetFspApiParameter (
99   VOID
100   )
101 {
102   FSP_GLOBAL_DATA  *FspData;
103 
104   FspData  = GetFspGlobalDataPointer ();
105   return *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam));
106 }
107 
108 /**
109   This function sets the FSP API paramter in the stack.
110 
111    @param[in] Value       New parameter value.
112 
113 **/
114 VOID
115 EFIAPI
SetFspApiParameter(IN UINT32 Value)116 SetFspApiParameter (
117   IN UINT32      Value
118   )
119 {
120   FSP_GLOBAL_DATA  *FspData;
121 
122   FspData  = GetFspGlobalDataPointer ();
123   *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam)) = Value;
124 }
125 
126 /**
127   This function sets the FSP continuation function parameters in the stack.
128 
129   @param[in] Value             New parameter value to set.
130   @param[in] Index             Parameter index.
131 **/
132 VOID
133 EFIAPI
SetFspContinuationFuncParameter(IN UINT32 Value,IN UINT32 Index)134 SetFspContinuationFuncParameter (
135   IN UINT32      Value,
136   IN UINT32      Index
137   )
138 {
139   FSP_GLOBAL_DATA  *FspData;
140 
141   FspData  = GetFspGlobalDataPointer ();
142   *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam) + (Index + 1) * sizeof(UINT32)) = Value;
143 }
144 
145 
146 /**
147   This function changes the BootLoader return address in stack.
148 
149   @param[in] ReturnAddress       Address to return.
150 
151 **/
152 VOID
153 EFIAPI
SetFspApiReturnAddress(IN UINT32 ReturnAddress)154 SetFspApiReturnAddress (
155   IN UINT32  ReturnAddress
156   )
157 {
158   FSP_GLOBAL_DATA  *FspData;
159 
160   FspData  = GetFspGlobalDataPointer ();
161   *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiRet)) = ReturnAddress;
162 }
163 
164 /**
165   This function set the API status code returned to the BootLoader.
166 
167   @param[in] ReturnStatus       Status code to return.
168 
169 **/
170 VOID
171 EFIAPI
SetFspApiReturnStatus(IN UINT32 ReturnStatus)172 SetFspApiReturnStatus (
173   IN UINT32  ReturnStatus
174   )
175 {
176   FSP_GLOBAL_DATA  *FspData;
177 
178   FspData  = GetFspGlobalDataPointer ();
179   *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(Eax)) = ReturnStatus;
180 }
181 
182 /**
183   This function sets the context switching stack to a new stack frame.
184 
185   @param[in] NewStackTop       New core stack to be set.
186 
187 **/
188 VOID
189 EFIAPI
SetFspCoreStackPointer(IN VOID * NewStackTop)190 SetFspCoreStackPointer (
191   IN VOID   *NewStackTop
192   )
193 {
194   FSP_GLOBAL_DATA  *FspData;
195   UINT32           *OldStack;
196   UINT32           *NewStack;
197   UINT32           StackContextLen;
198 
199   FspData  = GetFspGlobalDataPointer ();
200   StackContextLen = sizeof(CONTEXT_STACK) / sizeof(UINT32);
201 
202   //
203   // Reserve space for the ContinuationFunc two parameters
204   //
205   OldStack = (UINT32 *)FspData->CoreStack;
206   NewStack = (UINT32 *)NewStackTop - StackContextLen - 2;
207   FspData->CoreStack = (UINT32)NewStack;
208   while (StackContextLen-- != 0) {
209     *NewStack++ = *OldStack++;
210   }
211 }
212 
213 /**
214   This function sets the platform specific data pointer.
215 
216   @param[in] PlatformData       Fsp platform specific data pointer.
217 
218 **/
219 VOID
220 EFIAPI
SetFspPlatformDataPointer(IN VOID * PlatformData)221 SetFspPlatformDataPointer (
222   IN VOID   *PlatformData
223   )
224 {
225   FSP_GLOBAL_DATA  *FspData;
226 
227   FspData  = GetFspGlobalDataPointer ();
228   FspData->PlatformData.DataPtr = PlatformData;
229 }
230 
231 
232 /**
233   This function gets the platform specific data pointer.
234 
235    @param[in] PlatformData       Fsp platform specific data pointer.
236 
237 **/
238 VOID *
239 EFIAPI
GetFspPlatformDataPointer(VOID)240 GetFspPlatformDataPointer (
241   VOID
242   )
243 {
244   FSP_GLOBAL_DATA  *FspData;
245 
246   FspData  = GetFspGlobalDataPointer ();
247   return FspData->PlatformData.DataPtr;
248 }
249 
250 
251 /**
252   This function sets the UPD data pointer.
253 
254   @param[in] UpdDataRgnPtr   UPD data pointer.
255 **/
256 VOID
257 EFIAPI
SetFspUpdDataPointer(IN VOID * UpdDataRgnPtr)258 SetFspUpdDataPointer (
259   IN VOID    *UpdDataRgnPtr
260   )
261 {
262   FSP_GLOBAL_DATA  *FspData;
263 
264   //
265   // Get the Fsp Global Data Pointer
266   //
267   FspData  = GetFspGlobalDataPointer ();
268 
269   //
270   // Set the UPD pointer.
271   //
272   FspData->UpdDataRgnPtr = UpdDataRgnPtr;
273 }
274 
275 /**
276   This function gets the UPD data pointer.
277 
278   @return UpdDataRgnPtr   UPD data pointer.
279 **/
280 VOID *
281 EFIAPI
GetFspUpdDataPointer(VOID)282 GetFspUpdDataPointer (
283   VOID
284   )
285 {
286   FSP_GLOBAL_DATA  *FspData;
287 
288   FspData  = GetFspGlobalDataPointer ();
289   return FspData->UpdDataRgnPtr;
290 }
291 
292 
293 /**
294   This function sets the memory init UPD data pointer.
295 
296   @param[in] MemoryInitUpdPtr   memory init UPD data pointer.
297 **/
298 VOID
299 EFIAPI
SetFspMemoryInitUpdDataPointer(IN VOID * MemoryInitUpdPtr)300 SetFspMemoryInitUpdDataPointer (
301   IN VOID    *MemoryInitUpdPtr
302   )
303 {
304   FSP_GLOBAL_DATA  *FspData;
305 
306   //
307   // Get the Fsp Global Data Pointer
308   //
309   FspData  = GetFspGlobalDataPointer ();
310 
311   //
312   // Set the memory init UPD pointer.
313   //
314   FspData->MemoryInitUpdPtr = MemoryInitUpdPtr;
315 }
316 
317 /**
318   This function gets the memory init UPD data pointer.
319 
320   @return memory init UPD data pointer.
321 **/
322 VOID *
323 EFIAPI
GetFspMemoryInitUpdDataPointer(VOID)324 GetFspMemoryInitUpdDataPointer (
325   VOID
326   )
327 {
328   FSP_GLOBAL_DATA  *FspData;
329 
330   FspData  = GetFspGlobalDataPointer ();
331   return FspData->MemoryInitUpdPtr;
332 }
333 
334 
335 /**
336   This function sets the silicon init UPD data pointer.
337 
338   @param[in] SiliconInitUpdPtr   silicon init UPD data pointer.
339 **/
340 VOID
341 EFIAPI
SetFspSiliconInitUpdDataPointer(IN VOID * SiliconInitUpdPtr)342 SetFspSiliconInitUpdDataPointer (
343   IN VOID    *SiliconInitUpdPtr
344   )
345 {
346   FSP_GLOBAL_DATA  *FspData;
347 
348   //
349   // Get the Fsp Global Data Pointer
350   //
351   FspData  = GetFspGlobalDataPointer ();
352 
353   //
354   // Set the silicon init UPD data pointer.
355   //
356   FspData->SiliconInitUpdPtr = SiliconInitUpdPtr;
357 }
358 
359 /**
360   This function gets the silicon init UPD data pointer.
361 
362   @return silicon init UPD data pointer.
363 **/
364 VOID *
365 EFIAPI
GetFspSiliconInitUpdDataPointer(VOID)366 GetFspSiliconInitUpdDataPointer (
367   VOID
368   )
369 {
370   FSP_GLOBAL_DATA  *FspData;
371 
372   FspData  = GetFspGlobalDataPointer ();
373   return FspData->SiliconInitUpdPtr;
374 }
375 
376 
377 /**
378   Set FSP measurement point timestamp.
379 
380   @param[in] Id       Measurement point ID.
381 
382   @return performance timestamp.
383 **/
384 UINT64
385 EFIAPI
SetFspMeasurePoint(IN UINT8 Id)386 SetFspMeasurePoint (
387   IN UINT8  Id
388   )
389 {
390   FSP_GLOBAL_DATA  *FspData;
391 
392   //
393   // Bit [55: 0]  will be the timestamp
394   // Bit [63:56]  will be the ID
395   //
396   FspData  = GetFspGlobalDataPointer ();
397   if (FspData->PerfIdx < sizeof(FspData->PerfData) / sizeof(FspData->PerfData[0])) {
398     FspData->PerfData[FspData->PerfIdx] = AsmReadTsc ();
399     ((UINT8 *)(&FspData->PerfData[FspData->PerfIdx]))[7] = Id;
400   }
401 
402   return FspData->PerfData[(FspData->PerfIdx)++];
403 }
404 
405 /**
406   This function gets the FSP info header pointer.
407 
408   @retval FspInfoHeader   FSP info header pointer
409 **/
410 FSP_INFO_HEADER *
411 EFIAPI
GetFspInfoHeader(VOID)412 GetFspInfoHeader (
413   VOID
414   )
415 {
416   return  GetFspGlobalDataPointer()->FspInfoHeader;
417 }
418 
419 /**
420   This function gets the FSP info header pointer using the API stack context.
421 
422   @retval FspInfoHeader   FSP info header pointer using the API stack context
423 **/
424 FSP_INFO_HEADER *
425 EFIAPI
GetFspInfoHeaderFromApiContext(VOID)426 GetFspInfoHeaderFromApiContext (
427   VOID
428   )
429 {
430   FSP_GLOBAL_DATA  *FspData;
431 
432   FspData  = GetFspGlobalDataPointer ();
433   return  (FSP_INFO_HEADER *)(*(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(FspInfoHeader)));
434 }
435 
436 /**
437   This function gets the VPD data pointer.
438 
439   @return VpdDataRgnPtr   VPD data pointer.
440 **/
441 VOID *
442 EFIAPI
GetFspVpdDataPointer(VOID)443 GetFspVpdDataPointer (
444   VOID
445   )
446 {
447   FSP_INFO_HEADER   *FspInfoHeader;
448 
449   FspInfoHeader = GetFspInfoHeader ();
450   return (VOID *)(FspInfoHeader->ImageBase + FspInfoHeader->CfgRegionOffset);
451 }
452 
453 /**
454   This function gets FSP API calling mode.
455 
456   @retval API calling mode
457 **/
458 UINT8
459 EFIAPI
GetFspApiCallingMode(VOID)460 GetFspApiCallingMode (
461   VOID
462   )
463 {
464   return  GetFspGlobalDataPointer()->ApiMode;
465 }
466 
467 /**
468   This function sets FSP API calling mode.
469 
470   @param[in] Mode     API calling mode
471 **/
472 VOID
473 EFIAPI
SetFspApiCallingMode(UINT8 Mode)474 SetFspApiCallingMode (
475   UINT8  Mode
476   )
477 {
478   FSP_GLOBAL_DATA  *FspData;
479 
480   FspData  = GetFspGlobalDataPointer ();
481   FspData->ApiMode = Mode;
482 }
483 
484