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