--- /dev/null
+/** @file\r
+ Support FSP Wrapper MultiPhase process.\r
+\r
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/FspWrapperApiLib.h>\r
+#include <Library/FspWrapperPlatformLib.h>\r
+#include <FspEas.h>\r
+#include <FspGlobalData.h>\r
+#include <Ppi/ReadOnlyVariable2.h>\r
+#include <Ppi/Variable.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/FspWrapperMultiPhaseProcessLib.h>\r
+\r
+/**\r
+ Execute 32-bit FSP API entry code.\r
+\r
+ @param[in] Function The 32bit code entry to be executed.\r
+ @param[in] Param1 The first parameter to pass to 32bit code.\r
+ @param[in] Param2 The second parameter to pass to 32bit code.\r
+\r
+ @return EFI_STATUS.\r
+**/\r
+EFI_STATUS\r
+Execute32BitCode (\r
+ IN UINT64 Function,\r
+ IN UINT64 Param1,\r
+ IN UINT64 Param2\r
+ );\r
+\r
+/**\r
+ Execute 64-bit FSP API entry code.\r
+\r
+ @param[in] Function The 64bit code entry to be executed.\r
+ @param[in] Param1 The first parameter to pass to 64bit code.\r
+ @param[in] Param2 The second parameter to pass to 64bit code.\r
+\r
+ @return EFI_STATUS.\r
+**/\r
+EFI_STATUS\r
+Execute64BitCode (\r
+ IN UINT64 Function,\r
+ IN UINT64 Param1,\r
+ IN UINT64 Param2\r
+ );\r
+\r
+/**\r
+ Call FspsMultiPhase API.\r
+\r
+ @param[in] FspsMultiPhaseParams - Parameters for MultiPhase API.\r
+ @param[in] FspHobListPtr - Pointer to FSP HobList (valid after FSP-M completed)\r
+ @param[in] ComponentIndex - FSP Component which executing MultiPhase initialization.\r
+\r
+ @return EFI_UNSUPPORTED - the requested FspsMultiPhase API is not supported.\r
+ @return EFI_DEVICE_ERROR - the FSP header was not found.\r
+ @return EFI status returned by FspsMultiPhase API.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CallFspMultiPhaseEntry (\r
+ IN VOID *FspMultiPhaseParams,\r
+ IN OUT VOID **FspHobListPtr,\r
+ IN UINT8 ComponentIndex\r
+ )\r
+{\r
+ FSP_INFO_HEADER *FspHeader;\r
+ //\r
+ // FSP_MULTI_PHASE_INIT and FSP_MULTI_PHASE_SI_INIT API functions having same prototype.\r
+ //\r
+ UINTN FspMultiPhaseApiEntry;\r
+ UINTN FspMultiPhaseApiOffset;\r
+ EFI_STATUS Status;\r
+ BOOLEAN InterruptState;\r
+\r
+ if (ComponentIndex == FspMultiPhaseMemInitApiIndex) {\r
+ FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspmBaseAddress));\r
+ if (FspHeader == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ FspMultiPhaseApiOffset = FspHeader->FspMultiPhaseMemInitEntryOffset;\r
+ } else if (ComponentIndex == FspMultiPhaseSiInitApiIndex) {\r
+ FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspsBaseAddress));\r
+ if (FspHeader == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ FspMultiPhaseApiOffset = FspHeader->FspMultiPhaseSiInitEntryOffset;\r
+ }\r
+\r
+ if (FspMultiPhaseApiOffset == 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ FspMultiPhaseApiEntry = FspHeader->ImageBase + FspMultiPhaseApiOffset;\r
+ InterruptState = SaveAndDisableInterrupts ();\r
+ if ((FspHeader->ImageAttribute & BIT2) == 0) {\r
+ // BIT2: IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT\r
+ Status = Execute32BitCode ((UINTN)FspMultiPhaseApiEntry, (UINTN)FspMultiPhaseParams, (UINTN)NULL);\r
+ } else {\r
+ Status = Execute64BitCode ((UINTN)FspMultiPhaseApiEntry, (UINTN)FspMultiPhaseParams, (UINTN)NULL);\r
+ }\r
+\r
+ SetInterruptState (InterruptState);\r
+\r
+ DEBUG ((DEBUG_ERROR, "CallFspMultiPhaseEntry return Status %r \n", Status));\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ FSP Wrapper Variable Request Handler\r
+\r
+ @param[in] FspHobListPtr - Pointer to FSP HobList (valid after FSP-M completed)\r
+ @param[in] ComponentIndex - FSP Component which executing MultiPhase initialization.\r
+\r
+ @retval EFI_UNSUPPORTED FSP Wrapper cannot support the specific variable request\r
+ @retval EFI_STATUS Return FSP returned status\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FspWrapperVariableRequestHandler (\r
+ IN OUT VOID **FspHobListPtr,\r
+ IN UINT8 ComponentIndex\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ FSP_MULTI_PHASE_PARAMS FspMultiPhaseParams;\r
+ FSP_MULTI_PHASE_VARIABLE_REQUEST_INFO_PARAMS *FspVariableRequestParams;\r
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadOnlyVariablePpi;\r
+ EDKII_PEI_VARIABLE_PPI *VariablePpi;\r
+ BOOLEAN WriteVariableSupport;\r
+ FSP_MULTI_PHASE_COMPLETE_VARIABLE_REQUEST_PARAMS CompleteVariableRequestParams;\r
+\r
+ WriteVariableSupport = TRUE;\r
+ Status = PeiServicesLocatePpi (\r
+ &gEdkiiPeiVariablePpiGuid,\r
+ 0,\r
+ NULL,\r
+ (VOID **)&VariablePpi\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ WriteVariableSupport = FALSE;\r
+ Status = PeiServicesLocatePpi (\r
+ &gEfiPeiReadOnlyVariable2PpiGuid,\r
+ 0,\r
+ NULL,\r
+ (VOID **)&ReadOnlyVariablePpi\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ Status = FSP_STATUS_VARIABLE_REQUEST;\r
+ while (Status == FSP_STATUS_VARIABLE_REQUEST) {\r
+ //\r
+ // Get the variable request information from FSP.\r
+ //\r
+ FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseGetVariableRequestInfo;\r
+ FspMultiPhaseParams.PhaseIndex = 0;\r
+ Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);\r
+ ASSERT_EFI_ERROR (Status);\r
+ //\r
+ // FSP should output this pointer for variable request information.\r
+ //\r
+ FspVariableRequestParams = (FSP_MULTI_PHASE_VARIABLE_REQUEST_INFO_PARAMS *)FspMultiPhaseParams.MultiPhaseParamPtr;\r
+ switch (FspVariableRequestParams->VariableRequest) {\r
+ case EnumFspVariableRequestGetVariable:\r
+ if (WriteVariableSupport) {\r
+ Status = VariablePpi->GetVariable (\r
+ VariablePpi,\r
+ FspVariableRequestParams->VariableName,\r
+ FspVariableRequestParams->VariableGuid,\r
+ FspVariableRequestParams->Attributes,\r
+ (UINTN *)FspVariableRequestParams->DataSize,\r
+ FspVariableRequestParams->Data\r
+ );\r
+ } else {\r
+ Status = ReadOnlyVariablePpi->GetVariable (\r
+ ReadOnlyVariablePpi,\r
+ FspVariableRequestParams->VariableName,\r
+ FspVariableRequestParams->VariableGuid,\r
+ FspVariableRequestParams->Attributes,\r
+ (UINTN *)FspVariableRequestParams->DataSize,\r
+ FspVariableRequestParams->Data\r
+ );\r
+ }\r
+\r
+ CompleteVariableRequestParams.VariableRequestStatus = Status;\r
+ FspMultiPhaseParams.MultiPhaseParamPtr = (VOID *)&CompleteVariableRequestParams;\r
+ FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseCompleteVariableRequest;\r
+ Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);\r
+ break;\r
+\r
+ case EnumFspVariableRequestSetVariable:\r
+ if (WriteVariableSupport) {\r
+ Status = VariablePpi->SetVariable (\r
+ VariablePpi,\r
+ FspVariableRequestParams->VariableName,\r
+ FspVariableRequestParams->VariableGuid,\r
+ *FspVariableRequestParams->Attributes,\r
+ (UINTN)*FspVariableRequestParams->DataSize,\r
+ FspVariableRequestParams->Data\r
+ );\r
+ } else {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ CompleteVariableRequestParams.VariableRequestStatus = Status;\r
+ FspMultiPhaseParams.MultiPhaseParamPtr = (VOID *)&CompleteVariableRequestParams;\r
+ FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseCompleteVariableRequest;\r
+ Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);\r
+ break;\r
+\r
+ case EnumFspVariableRequestGetNextVariableName:\r
+ if (WriteVariableSupport) {\r
+ Status = VariablePpi->GetNextVariableName (\r
+ VariablePpi,\r
+ (UINTN *)FspVariableRequestParams->VariableNameSize,\r
+ FspVariableRequestParams->VariableName,\r
+ FspVariableRequestParams->VariableGuid\r
+ );\r
+ } else {\r
+ Status = ReadOnlyVariablePpi->NextVariableName (\r
+ ReadOnlyVariablePpi,\r
+ (UINTN *)FspVariableRequestParams->VariableNameSize,\r
+ FspVariableRequestParams->VariableName,\r
+ FspVariableRequestParams->VariableGuid\r
+ );\r
+ }\r
+\r
+ CompleteVariableRequestParams.VariableRequestStatus = Status;\r
+ FspMultiPhaseParams.MultiPhaseParamPtr = (VOID *)&CompleteVariableRequestParams;\r
+ FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseCompleteVariableRequest;\r
+ Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);\r
+ break;\r
+\r
+ case EnumFspVariableRequestQueryVariableInfo:\r
+ if (WriteVariableSupport) {\r
+ Status = VariablePpi->QueryVariableInfo (\r
+ VariablePpi,\r
+ *FspVariableRequestParams->Attributes,\r
+ FspVariableRequestParams->MaximumVariableStorageSize,\r
+ FspVariableRequestParams->RemainingVariableStorageSize,\r
+ FspVariableRequestParams->MaximumVariableSize\r
+ );\r
+ } else {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ CompleteVariableRequestParams.VariableRequestStatus = Status;\r
+ FspMultiPhaseParams.MultiPhaseParamPtr = (VOID *)&CompleteVariableRequestParams;\r
+ FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseCompleteVariableRequest;\r
+ Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);\r
+ break;\r
+\r
+ default:\r
+ DEBUG ((DEBUG_ERROR, "Unknown VariableRequest type!\n"));\r
+ Status = EFI_UNSUPPORTED;\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status\r
+ //\r
+ if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {\r
+ DEBUG ((DEBUG_INFO, "FspMultiPhaseApi-0x%x requested reset %r\n", ComponentIndex, Status));\r
+ CallFspWrapperResetSystem ((UINTN)Status);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ FSP Wrapper MultiPhase Handler\r
+\r
+ @param[in] FspHobListPtr - Pointer to FSP HobList (valid after FSP-M completed)\r
+ @param[in] ComponentIndex - FSP Component which executing MultiPhase initialization.\r
+\r
+ @retval EFI_STATUS Always return EFI_SUCCESS\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FspWrapperMultiPhaseHandler (\r
+ IN OUT VOID **FspHobListPtr,\r
+ IN UINT8 ComponentIndex\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ FSP_MULTI_PHASE_PARAMS FspMultiPhaseParams;\r
+ FSP_MULTI_PHASE_GET_NUMBER_OF_PHASES_PARAMS FspMultiPhaseGetNumber;\r
+ UINT32 Index;\r
+ UINT32 NumOfPhases;\r
+\r
+ //\r
+ // Query FSP for the number of phases supported.\r
+ //\r
+ FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseGetNumberOfPhases;\r
+ FspMultiPhaseParams.PhaseIndex = 0;\r
+ FspMultiPhaseParams.MultiPhaseParamPtr = (VOID *)&FspMultiPhaseGetNumber;\r
+ Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ //\r
+ // MultiPhase API was not supported\r
+ //\r
+ return Status;\r
+ } else {\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ NumOfPhases = FspMultiPhaseGetNumber.NumberOfPhases;\r
+\r
+ for (Index = 1; Index <= NumOfPhases; Index++) {\r
+ DEBUG ((DEBUG_ERROR, "MultiPhase Index/NumOfPhases = %d of %d\n", Index, NumOfPhases));\r
+ //\r
+ // Platform actions can be added in below function for each component and phase before returning control back to FSP.\r
+ //\r
+ FspWrapperPlatformMultiPhaseHandler (FspHobListPtr, ComponentIndex, Index);\r
+\r
+ FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseExecutePhase;\r
+ FspMultiPhaseParams.PhaseIndex = Index;\r
+ FspMultiPhaseParams.MultiPhaseParamPtr = NULL;\r
+ Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);\r
+\r
+ if (Status == FSP_STATUS_VARIABLE_REQUEST) {\r
+ //\r
+ // call to Variable request handler\r
+ //\r
+ FspWrapperVariableRequestHandler (FspHobListPtr, ComponentIndex);\r
+ }\r
+\r
+ //\r
+ // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status\r
+ //\r
+ if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {\r
+ DEBUG ((DEBUG_INFO, "FspMultiPhaseApi-0x%x requested reset %r\n", ComponentIndex, Status));\r
+ CallFspWrapperResetSystem ((UINTN)Status);\r
+ }\r
+\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r