| /** @file | |
| Copyright (c) 2014 - 2025, 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) | |
| typedef struct { | |
| UINT16 IdtrLimit; | |
| UINT32 IdtrBase; | |
| UINT16 Reserved; | |
| UINT32 Cr0; | |
| UINT32 Cr3; | |
| UINT32 Cr4; | |
| UINT32 Efer; // lower 32-bit of EFER since only NXE bit (BIT11) need to be restored. | |
| 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; | |
| typedef struct { | |
| UINT64 Idtr[2]; // IDTR Limit - bit0:bit15, IDTR Base - bit16:bit79 | |
| UINT64 Gdtr[2]; // GDTR Limit - bit0:bit15, GDTR Base - bit16:bit79 | |
| UINT64 Segment[6]; // Segment Registers: CS, DS, ES, FS, GS, SS | |
| UINT64 Cr0; | |
| UINT64 Cr3; | |
| UINT64 Cr4; | |
| UINT64 Efer; | |
| 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 Reserved; // The reserved QWORD is needed for stack alignment in X64. | |
| 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 | |
| ) | |
| { | |
| UINT32 FspDataAddress; | |
| FspDataAddress = *(UINT32 *)(UINTN)PcdGet32 (PcdGlobalDataPointerAddress); | |
| return (FSP_GLOBAL_DATA *)(UINTN)FspDataAddress; | |
| } | |
| /** | |
| 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 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; | |
| } | |
| /** | |
| This function sets the FspSmmInit UPD data pointer. | |
| @param[in] SmmInitUpdPtr FspSmmInit UPD data pointer. | |
| **/ | |
| VOID | |
| EFIAPI | |
| SetFspSmmInitUpdDataPointer ( | |
| IN VOID *SmmInitUpdPtr | |
| ) | |
| { | |
| FSP_GLOBAL_DATA *FspData; | |
| // | |
| // Get the FSP Global Data Pointer | |
| // | |
| FspData = GetFspGlobalDataPointer (); | |
| // | |
| // Set the FspSmmInit UPD data pointer. | |
| // | |
| FspData->SmmInitUpdPtr = SmmInitUpdPtr; | |
| } | |
| /** | |
| This function gets the FspSmmInit UPD data pointer. | |
| @return FspSmmInit UPD data pointer. | |
| **/ | |
| VOID * | |
| EFIAPI | |
| GetFspSmmInitUpdDataPointer ( | |
| VOID | |
| ) | |
| { | |
| FSP_GLOBAL_DATA *FspData; | |
| FspData = GetFspGlobalDataPointer (); | |
| return FspData->SmmInitUpdPtr; | |
| } | |
| /** | |
| Set FSP measurement point timestamp. | |
| @param[in] Id Measurement point ID. | |
| @return performance timestamp if current PerfIdx is valid, | |
| else return 0 as invalid 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)++]; | |
| } | |
| return 0; | |
| } | |
| /** | |
| 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; | |
| } |