Home | History | Annotate | Download | only in BaseFspCommonLib
      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
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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