--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <FspGlobalData.h>\r
+#include <FspApi.h>\r
+\r
+#pragma pack(1)\r
+\r
+//\r
+// Cont Func Parameter 2 +0x3C\r
+// Cont Func Parameter 1 +0x38\r
+//\r
+// API Parameter +0x34\r
+// API return address +0x30\r
+//\r
+// push offset exit +0x2C\r
+// pushfd +0x28\r
+// cli\r
+// pushad +0x24\r
+// sub esp, 8 +0x00\r
+// sidt fword ptr [esp]\r
+//\r
+typedef struct {\r
+ UINT16 IdtrLimit;\r
+ UINT32 IdtrBase;\r
+ UINT16 Reserved;\r
+ UINT32 Edi;\r
+ UINT32 Esi;\r
+ UINT32 Ebp;\r
+ UINT32 Esp;\r
+ UINT32 Ebx;\r
+ UINT32 Edx;\r
+ UINT32 Ecx;\r
+ UINT32 Eax;\r
+ UINT16 Flags[2];\r
+ UINT32 ExitOff;\r
+ UINT32 ApiRet;\r
+ UINT32 ApiParam;\r
+} CONTEXT_STACK;\r
+\r
+#define CONTEXT_STACK_OFFSET(x) (UINT32)&((CONTEXT_STACK *)(UINTN)0)->x\r
+\r
+#pragma pack()\r
+\r
+/**\r
+ This function sets the FSP global data pointer.\r
+\r
+ @param[in] FspData Fsp global data pointer.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SetFspGlobalDataPointer (\r
+ IN FSP_GLOBAL_DATA *FspData\r
+ )\r
+{\r
+ ASSERT (FspData != NULL);\r
+ *((volatile UINT32 *)(UINTN)PcdGet32(PcdGlobalDataPointerAddress)) = (UINT32)(UINTN)FspData;\r
+}\r
+\r
+/**\r
+ This function gets the FSP global data pointer.\r
+\r
+**/\r
+FSP_GLOBAL_DATA *\r
+EFIAPI\r
+GetFspGlobalDataPointer (\r
+ VOID\r
+ )\r
+{\r
+ FSP_GLOBAL_DATA *FspData;\r
+\r
+ FspData = *(FSP_GLOBAL_DATA **)(UINTN)PcdGet32(PcdGlobalDataPointerAddress);\r
+ return FspData;\r
+}\r
+\r
+/**\r
+ This function gets back the FSP API paramter passed by the bootlaoder.\r
+\r
+ @retval ApiParameter FSP API paramter passed by the bootlaoder.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetFspApiParameter (\r
+ VOID\r
+ )\r
+{\r
+ FSP_GLOBAL_DATA *FspData;\r
+\r
+ FspData = GetFspGlobalDataPointer ();\r
+ return *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam));\r
+}\r
+\r
+/**\r
+ This function sets the FSP API paramter in the stack.\r
+\r
+ @param[in] Value New parameter value.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SetFspApiParameter (\r
+ IN UINT32 Value\r
+ )\r
+{\r
+ FSP_GLOBAL_DATA *FspData;\r
+\r
+ FspData = GetFspGlobalDataPointer ();\r
+ *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam)) = Value;\r
+}\r
+\r
+/**\r
+ This function sets the FSP continuation function parameters in the stack.\r
+\r
+ @param[in] Value New parameter value to set.\r
+ @param[in] Index Parameter index.\r
+**/\r
+VOID\r
+EFIAPI\r
+SetFspContinuationFuncParameter (\r
+ IN UINT32 Value,\r
+ IN UINT32 Index\r
+ )\r
+{\r
+ FSP_GLOBAL_DATA *FspData;\r
+\r
+ FspData = GetFspGlobalDataPointer ();\r
+ *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam) + (Index + 1) * sizeof(UINT32)) = Value;\r
+}\r
+\r
+\r
+/**\r
+ This function changes the Bootloader return address in stack.\r
+\r
+ @param[in] ReturnAddress Address to return.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SetFspApiReturnAddress (\r
+ IN UINT32 ReturnAddress\r
+ )\r
+{\r
+ FSP_GLOBAL_DATA *FspData;\r
+\r
+ FspData = GetFspGlobalDataPointer ();\r
+ *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiRet)) = ReturnAddress;\r
+}\r
+\r
+/**\r
+ This function set the API status code returned to the bootloader.\r
+\r
+ @param[in] ReturnStatus Status code to return.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SetFspApiReturnStatus (\r
+ IN UINT32 ReturnStatus\r
+ )\r
+{\r
+ FSP_GLOBAL_DATA *FspData;\r
+\r
+ FspData = GetFspGlobalDataPointer ();\r
+ *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(Eax)) = ReturnStatus;\r
+}\r
+\r
+/**\r
+ This function sets the context switching stack to a new stack frame.\r
+\r
+ @param[in] NewStackTop New core stack to be set.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SetFspCoreStackPointer (\r
+ IN VOID *NewStackTop\r
+ )\r
+{\r
+ FSP_GLOBAL_DATA *FspData;\r
+ UINT32 *OldStack;\r
+ UINT32 *NewStack;\r
+ UINT32 StackContextLen;\r
+\r
+ FspData = GetFspGlobalDataPointer ();\r
+ StackContextLen = sizeof(CONTEXT_STACK) / sizeof(UINT32);\r
+\r
+ //\r
+ // Reserve space for the ContinuationFunc two parameters\r
+ //\r
+ OldStack = (UINT32 *)FspData->CoreStack;\r
+ NewStack = (UINT32 *)NewStackTop - StackContextLen - 2;\r
+ FspData->CoreStack = (UINT32)NewStack;\r
+ while (StackContextLen-- != 0) {\r
+ *NewStack++ = *OldStack++;\r
+ }\r
+}\r
+\r
+/**\r
+ This function sets the platform specific data pointer.\r
+\r
+ @param[in] PlatformData Fsp platform specific data pointer.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SetFspPlatformDataPointer (\r
+ IN VOID *PlatformData\r
+ )\r
+{\r
+ FSP_GLOBAL_DATA *FspData;\r
+\r
+ FspData = GetFspGlobalDataPointer ();\r
+ FspData->PlatformData.DataPtr = PlatformData;\r
+}\r
+\r
+\r
+/**\r
+ This function gets the platform specific data pointer.\r
+\r
+ @param[in] PlatformData Fsp platform specific data pointer.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+GetFspPlatformDataPointer (\r
+ VOID\r
+ )\r
+{\r
+ FSP_GLOBAL_DATA *FspData;\r
+\r
+ FspData = GetFspGlobalDataPointer ();\r
+ return FspData->PlatformData.DataPtr;\r
+}\r
+\r
+\r
+/**\r
+ This function sets the UPD data pointer.\r
+\r
+ @param[in] UpdDataRgnPtr UPD data pointer.\r
+**/\r
+VOID\r
+EFIAPI\r
+SetFspUpdDataPointer (\r
+ IN VOID *UpdDataRgnPtr\r
+ )\r
+{\r
+ FSP_GLOBAL_DATA *FspData;\r
+\r
+ //\r
+ // Get the Fsp Global Data Pointer\r
+ //\r
+ FspData = GetFspGlobalDataPointer ();\r
+\r
+ //\r
+ // Set the UPD pointer.\r
+ //\r
+ FspData->UpdDataRgnPtr = UpdDataRgnPtr;\r
+}\r
+\r
+/**\r
+ This function gets the UPD data pointer.\r
+\r
+ @return UpdDataRgnPtr UPD data pointer.\r
+**/\r
+VOID *\r
+EFIAPI\r
+GetFspUpdDataPointer (\r
+ VOID\r
+ )\r
+{\r
+ FSP_GLOBAL_DATA *FspData;\r
+\r
+ FspData = GetFspGlobalDataPointer ();\r
+ return FspData->UpdDataRgnPtr;\r
+}\r
+\r
+/**\r
+ Set FSP measurement point timestamp.\r
+\r
+ @param[in] Id Measurement point ID.\r
+\r
+ @return performance timestamp.\r
+**/\r
+UINT64\r
+EFIAPI\r
+SetFspMeasurePoint (\r
+ IN UINT8 Id\r
+ )\r
+{\r
+ FSP_GLOBAL_DATA *FspData;\r
+\r
+ //\r
+ // Bit [55: 0] will be the timestamp\r
+ // Bit [63:56] will be the ID\r
+ //\r
+ FspData = GetFspGlobalDataPointer ();\r
+ if (FspData->PerfIdx < sizeof(FspData->PerfData) / sizeof(FspData->PerfData[0])) {\r
+ FspData->PerfData[FspData->PerfIdx] = AsmReadTsc ();\r
+ ((UINT8 *)(&FspData->PerfData[FspData->PerfIdx]))[7] = Id;\r
+ }\r
+\r
+ return FspData->PerfData[(FspData->PerfIdx)++];\r
+}\r