mirror of https://github.com/acidanthera/audk.git
375 lines
15 KiB
C
375 lines
15 KiB
C
/** @file
|
|
Support FSP Wrapper MultiPhase process.
|
|
|
|
Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Library/FspWrapperApiLib.h>
|
|
#include <Library/FspWrapperPlatformLib.h>
|
|
#include <FspEas.h>
|
|
#include <FspGlobalData.h>
|
|
#include <Ppi/ReadOnlyVariable2.h>
|
|
#include <Ppi/Variable.h>
|
|
#include <Library/PeiServicesLib.h>
|
|
#include <Library/FspWrapperPlatformMultiPhaseLib.h>
|
|
|
|
/**
|
|
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;
|
|
}
|