REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3867 Add BaseFspCommonLib Support for X64. Cc: Chasel Chiu <chasel.chiu@intel.com> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com> Cc: Star Zeng <star.zeng@intel.com> Cc: Ashraf Ali S <ashraf.ali.s@intel.com> Signed-off-by: Ted Kuo <ted.kuo@intel.com> Reviewed-by: Chasel Chiu <chasel.chiu@intel.com>
		
			
				
	
	
		
			554 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			554 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| 
 | |
|   Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include <PiPei.h>
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/PcdLib.h>
 | |
| #include <FspGlobalData.h>
 | |
| #include <FspEas.h>
 | |
| #include <Library/FspSwitchStackLib.h>
 | |
| 
 | |
| #pragma pack(1)
 | |
| 
 | |
| //
 | |
| //   API Parameter                +0x34
 | |
| //   API return address           +0x30
 | |
| //
 | |
| //   push    FspInfoHeader        +0x2C
 | |
| //   pushfd                       +0x28
 | |
| //   cli
 | |
| //   pushad                       +0x24
 | |
| //   sub     esp, 8               +0x00
 | |
| //   sidt    fword ptr [esp]
 | |
| //
 | |
| typedef struct {
 | |
|   UINT16    IdtrLimit;
 | |
|   UINT32    IdtrBase;
 | |
|   UINT16    Reserved;
 | |
|   UINT32    Registers[8];   // General Purpose Registers: Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx and Eax
 | |
|   UINT16    Flags[2];
 | |
|   UINT32    FspInfoHeader;
 | |
|   UINT32    ApiRet;
 | |
|   UINT32    ApiParam[2];
 | |
| } CONTEXT_STACK;
 | |
| 
 | |
| //
 | |
| //   API return address           +0xB0
 | |
| //   push    API Parameter2       +0xA8
 | |
| //   push    API Parameter1       +0xA0
 | |
| //   push    FspInfoHeader        +0x98
 | |
| //   pushfq                       +0x90
 | |
| //   cli
 | |
| //   PUSHA_64                     +0x10
 | |
| //   sub     rsp, 16              +0x00
 | |
| //   sidt    [rsp]
 | |
| //
 | |
| typedef struct {
 | |
|   UINT64    Idtr[2];        // IDTR Limit - bit0:bi15, IDTR Base - bit16:bit79
 | |
|   UINT64    Registers[16];  // General Purpose Registers: RDI, RSI, RBP, RSP, RBX, RDX, RCX, RAX, and R15 to R8
 | |
|   UINT32    Flags[2];
 | |
|   UINT64    FspInfoHeader;
 | |
|   UINT64    ApiParam[2];
 | |
|   UINT64    ApiRet;         // 64bit stack format is different from the 32bit one due to x64 calling convention
 | |
| } CONTEXT_STACK_64;
 | |
| 
 | |
| #define CONTEXT_STACK_OFFSET(x)  (sizeof(UINTN) == sizeof (UINT32) ? (UINTN)&((CONTEXT_STACK *)(UINTN)0)->x : (UINTN)&((CONTEXT_STACK_64 *)(UINTN)0)->x)
 | |
| 
 | |
| #pragma pack()
 | |
| 
 | |
| /**
 | |
|   This function sets the FSP global data pointer.
 | |
| 
 | |
|   @param[in] FspData       FSP global data pointer.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SetFspGlobalDataPointer (
 | |
|   IN FSP_GLOBAL_DATA  *FspData
 | |
|   )
 | |
| {
 | |
|   ASSERT (FspData != NULL);
 | |
|   *((volatile UINT32 *)(UINTN)PcdGet32 (PcdGlobalDataPointerAddress)) = (UINT32)(UINTN)FspData;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets the FSP global data pointer.
 | |
| 
 | |
| **/
 | |
| FSP_GLOBAL_DATA *
 | |
| EFIAPI
 | |
| GetFspGlobalDataPointer (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData = *(FSP_GLOBAL_DATA  **)(UINTN)PcdGet32 (PcdGlobalDataPointerAddress);
 | |
|   return FspData;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets back the FSP API first parameter passed by the bootloader.
 | |
| 
 | |
|   @retval ApiParameter FSP API first parameter passed by the bootloader.
 | |
| **/
 | |
| UINTN
 | |
| EFIAPI
 | |
| GetFspApiParameter (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData = GetFspGlobalDataPointer ();
 | |
|   return *(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (ApiParam[0]));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function returns the FSP entry stack pointer from address of the first API parameter.
 | |
| 
 | |
|   @retval FSP entry stack pointer.
 | |
| **/
 | |
| VOID *
 | |
| EFIAPI
 | |
| GetFspEntryStack (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData = GetFspGlobalDataPointer ();
 | |
|   return (VOID *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (ApiParam[0]));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets back the FSP API second parameter passed by the bootloader.
 | |
| 
 | |
|   @retval ApiParameter FSP API second parameter passed by the bootloader.
 | |
| **/
 | |
| UINTN
 | |
| EFIAPI
 | |
| GetFspApiParameter2 (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData = GetFspGlobalDataPointer ();
 | |
|   return *(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (ApiParam[1]));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function sets the FSP API parameter in the stack.
 | |
| 
 | |
|    @param[in] Value       New parameter value.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SetFspApiParameter (
 | |
|   IN UINT32  Value
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData                                                          = GetFspGlobalDataPointer ();
 | |
|   *(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (ApiParam)) = Value;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function set the API status code returned to the BootLoader.
 | |
| 
 | |
|   @param[in] ReturnStatus       Status code to return.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SetFspApiReturnStatus (
 | |
|   IN UINTN  ReturnStatus
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData                                                              = GetFspGlobalDataPointer ();
 | |
|   *(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (Registers[7])) = ReturnStatus;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function sets the context switching stack to a new stack frame.
 | |
| 
 | |
|   @param[in] NewStackTop       New core stack to be set.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SetFspCoreStackPointer (
 | |
|   IN VOID  *NewStackTop
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
|   UINTN            *OldStack;
 | |
|   UINTN            *NewStack;
 | |
|   UINT32           StackContextLen;
 | |
| 
 | |
|   FspData         = GetFspGlobalDataPointer ();
 | |
|   StackContextLen = sizeof(CONTEXT_STACK) / sizeof(UINTN);
 | |
| 
 | |
|   //
 | |
|   // Reserve space for the ContinuationFunc two parameters
 | |
|   //
 | |
|   OldStack = (UINTN *)FspData->CoreStack;
 | |
|   NewStack = (UINTN *)NewStackTop - StackContextLen - 2;
 | |
|   FspData->CoreStack = (UINTN)NewStack;
 | |
|   while (StackContextLen-- != 0) {
 | |
|     *NewStack++ = *OldStack++;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function sets the platform specific data pointer.
 | |
| 
 | |
|   @param[in] PlatformData       FSP platform specific data pointer.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SetFspPlatformDataPointer (
 | |
|   IN VOID  *PlatformData
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData                       = GetFspGlobalDataPointer ();
 | |
|   FspData->PlatformData.DataPtr = PlatformData;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets the platform specific data pointer.
 | |
| 
 | |
|    @param[in] PlatformData       FSP platform specific data pointer.
 | |
| 
 | |
| **/
 | |
| VOID *
 | |
| EFIAPI
 | |
| GetFspPlatformDataPointer (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData = GetFspGlobalDataPointer ();
 | |
|   return FspData->PlatformData.DataPtr;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function sets the UPD data pointer.
 | |
| 
 | |
|   @param[in] UpdDataPtr   UPD data pointer.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SetFspUpdDataPointer (
 | |
|   IN VOID  *UpdDataPtr
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   //
 | |
|   // Get the FSP Global Data Pointer
 | |
|   //
 | |
|   FspData = GetFspGlobalDataPointer ();
 | |
| 
 | |
|   //
 | |
|   // Set the UPD pointer.
 | |
|   //
 | |
|   FspData->UpdDataPtr = UpdDataPtr;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets the UPD data pointer.
 | |
| 
 | |
|   @return UpdDataPtr   UPD data pointer.
 | |
| **/
 | |
| VOID *
 | |
| EFIAPI
 | |
| GetFspUpdDataPointer (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData = GetFspGlobalDataPointer ();
 | |
|   return FspData->UpdDataPtr;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function sets the FspMemoryInit UPD data pointer.
 | |
| 
 | |
|   @param[in] MemoryInitUpdPtr   FspMemoryInit UPD data pointer.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SetFspMemoryInitUpdDataPointer (
 | |
|   IN VOID  *MemoryInitUpdPtr
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   //
 | |
|   // Get the FSP Global Data Pointer
 | |
|   //
 | |
|   FspData = GetFspGlobalDataPointer ();
 | |
| 
 | |
|   //
 | |
|   // Set the FspMemoryInit UPD pointer.
 | |
|   //
 | |
|   FspData->MemoryInitUpdPtr = MemoryInitUpdPtr;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets the FspMemoryInit UPD data pointer.
 | |
| 
 | |
|   @return FspMemoryInit UPD data pointer.
 | |
| **/
 | |
| VOID *
 | |
| EFIAPI
 | |
| GetFspMemoryInitUpdDataPointer (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData = GetFspGlobalDataPointer ();
 | |
|   return FspData->MemoryInitUpdPtr;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function sets the FspSiliconInit UPD data pointer.
 | |
| 
 | |
|   @param[in] SiliconInitUpdPtr   FspSiliconInit UPD data pointer.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SetFspSiliconInitUpdDataPointer (
 | |
|   IN VOID  *SiliconInitUpdPtr
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   //
 | |
|   // Get the FSP Global Data Pointer
 | |
|   //
 | |
|   FspData = GetFspGlobalDataPointer ();
 | |
| 
 | |
|   //
 | |
|   // Set the FspSiliconInit UPD data pointer.
 | |
|   //
 | |
|   FspData->SiliconInitUpdPtr = SiliconInitUpdPtr;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets the FspSiliconInit UPD data pointer.
 | |
| 
 | |
|   @return FspSiliconInit UPD data pointer.
 | |
| **/
 | |
| VOID *
 | |
| EFIAPI
 | |
| GetFspSiliconInitUpdDataPointer (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData = GetFspGlobalDataPointer ();
 | |
|   return FspData->SiliconInitUpdPtr;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set FSP measurement point timestamp.
 | |
| 
 | |
|   @param[in] Id       Measurement point ID.
 | |
| 
 | |
|   @return performance timestamp.
 | |
| **/
 | |
| UINT64
 | |
| EFIAPI
 | |
| SetFspMeasurePoint (
 | |
|   IN UINT8  Id
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   //
 | |
|   // Bit [55: 0]  will be the timestamp
 | |
|   // Bit [63:56]  will be the ID
 | |
|   //
 | |
|   FspData = GetFspGlobalDataPointer ();
 | |
|   if (FspData->PerfIdx < sizeof (FspData->PerfData) / sizeof (FspData->PerfData[0])) {
 | |
|     FspData->PerfData[FspData->PerfIdx]                  = AsmReadTsc ();
 | |
|     ((UINT8 *)(&FspData->PerfData[FspData->PerfIdx]))[7] = Id;
 | |
|   }
 | |
| 
 | |
|   return FspData->PerfData[(FspData->PerfIdx)++];
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets the FSP info header pointer.
 | |
| 
 | |
|   @retval FspInfoHeader   FSP info header pointer
 | |
| **/
 | |
| FSP_INFO_HEADER *
 | |
| EFIAPI
 | |
| GetFspInfoHeader (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   return GetFspGlobalDataPointer ()->FspInfoHeader;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function sets the FSP info header pointer.
 | |
| 
 | |
|   @param[in] FspInfoHeader   FSP info header pointer
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SetFspInfoHeader (
 | |
|   FSP_INFO_HEADER  *FspInfoHeader
 | |
|   )
 | |
| {
 | |
|   GetFspGlobalDataPointer ()->FspInfoHeader = FspInfoHeader;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets the FSP info header pointer using the API stack context.
 | |
| 
 | |
|   @retval FspInfoHeader   FSP info header pointer using the API stack context
 | |
| **/
 | |
| FSP_INFO_HEADER *
 | |
| EFIAPI
 | |
| GetFspInfoHeaderFromApiContext (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData = GetFspGlobalDataPointer ();
 | |
|   return (FSP_INFO_HEADER *)(*(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (FspInfoHeader)));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets the CfgRegion data pointer.
 | |
| 
 | |
|   @return CfgRegion data pointer.
 | |
| **/
 | |
| VOID *
 | |
| EFIAPI
 | |
| GetFspCfgRegionDataPointer (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   FSP_INFO_HEADER  *FspInfoHeader;
 | |
| 
 | |
|   FspInfoHeader = GetFspInfoHeader ();
 | |
|   return (VOID *)(UINTN)(FspInfoHeader->ImageBase + FspInfoHeader->CfgRegionOffset);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets FSP API calling index.
 | |
| 
 | |
|   @retval API calling index
 | |
| **/
 | |
| UINT8
 | |
| EFIAPI
 | |
| GetFspApiCallingIndex (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   return GetFspGlobalDataPointer ()->ApiIdx;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function sets FSP API calling mode.
 | |
| 
 | |
|   @param[in] Index     API calling index
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SetFspApiCallingIndex (
 | |
|   UINT8  Index
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData         = GetFspGlobalDataPointer ();
 | |
|   FspData->ApiIdx = Index;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets FSP Phase StatusCode.
 | |
| 
 | |
|   @retval StatusCode
 | |
| **/
 | |
| UINT32
 | |
| EFIAPI
 | |
| GetPhaseStatusCode (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   return GetFspGlobalDataPointer ()->StatusCode;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function sets FSP Phase StatusCode.
 | |
| 
 | |
|   @param[in] Mode     Phase StatusCode
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SetPhaseStatusCode (
 | |
|   UINT32  StatusCode
 | |
|   )
 | |
| {
 | |
|   FSP_GLOBAL_DATA  *FspData;
 | |
| 
 | |
|   FspData             = GetFspGlobalDataPointer ();
 | |
|   FspData->StatusCode = StatusCode;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function updates the return status of the FSP API with requested reset type and returns to Boot Loader.
 | |
| 
 | |
|   @param[in] FspResetType     Reset type that needs to returned as API return status
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| FspApiReturnStatusReset (
 | |
|   IN UINT32  FspResetType
 | |
|   )
 | |
| {
 | |
|   volatile BOOLEAN  LoopUntilReset;
 | |
| 
 | |
|   LoopUntilReset = TRUE;
 | |
|   DEBUG ((DEBUG_INFO, "FSP returning control to Bootloader with reset required return status %x\n", FspResetType));
 | |
|   if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) {
 | |
|     ///
 | |
|     /// Below code is not an infinite loop.The control will go back to API calling function in BootLoader each time BootLoader
 | |
|     /// calls the FSP API without honoring the reset request by FSP
 | |
|     ///
 | |
|     do {
 | |
|       SetFspApiReturnStatus ((EFI_STATUS)FspResetType);
 | |
|       Pei2LoaderSwitchStack ();
 | |
|       DEBUG ((DEBUG_ERROR, "!!!ERROR: FSP has requested BootLoader for reset. But BootLoader has not honored the reset\n"));
 | |
|       DEBUG ((DEBUG_ERROR, "!!!ERROR: Please add support in BootLoader to honor the reset request from FSP\n"));
 | |
|     } while (LoopUntilReset);
 | |
|   }
 | |
| }
 |