feat: [FSP2.4] Added FSP variable serivices, Multi Phase Mem and SI. (#1901)

FSP 2.4 adds a requirement for Bootloader to respond to FSP Variable
requests in a way that is similar to UEFI variable services. This
implementation adds support for using the updated SBL VariableLib so that
the FspVariableServicesLib wrapper is no longer needed.

Additionally, support for Multi-Phase mem and SI init is added. FSP 2.4
introduces the mandatory MultiPhaseMemInit call, and makes the
MultiPhaseSiInit call mandatory where it was previously optional.

Signed-off-by: Bejean Mosher <bejean.mosher@intel.com>
This commit is contained in:
bejeanmo 2023-05-24 14:36:35 -04:00 committed by GitHub
parent 23d9187bde
commit a34e54e175
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 751 additions and 44 deletions

View File

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -10,6 +10,8 @@
#include <FspEas/FspApi.h>
typedef EFI_STATUS (EFIAPI *FSP_MULTI_PHASE_FUNCTION)(FSP_MULTI_PHASE_PARAMS *MultiPhaseInitParamPtr);
/**
This FSP API is called after TempRamInit and initializes the memory.
This FSP API accepts a pointer to a data structure that will be platform dependent
@ -39,6 +41,38 @@ CallFspMemoryInit (
VOID **HobList
);
/**
This FSP API provides multi-phase memory and silicon initialization, which brings
greater modularity to the existing FspMemoryInit() and FspSiliconInit() API. Increased
modularity is achieved by adding an extra API to FSP-M and FSP-S. This allows the
bootloader to add board specific initialization steps throughout the MemoryInit and
SiliconInit flows as needed. The FspMemoryInit() API is always called before
FspMultiPhaseMemInit(); it is the first phase of memory initialization. Similarly, the
FspSiliconInit() API is always called before FspMultiPhaseSiInit(); it is the first phase of
silicon initialization. After the first phase, subsequent phases are invoked by calling the
FspMultiPhaseMem/SiInit() API.
The FspMultiPhaseMemInit() API may only be called after the FspMemoryInit() API and
before the FspSiliconInit() API; or in the case that FSP-T is being used, before the
TempRamExit() API. The FspMultiPhaseSiInit() API may only be called after the
FspSiliconInit() API and before NotifyPhase() API; or in the case that FSP-I is being used,
before the FspSmmInit() API. The multi-phase APIs may not be called at any other time.
@param[in] MultiPhaseInitParamPtr Pointer to provide multi-phase init parameters.
@retval EFI_SUCCESS FSP execution environment was initialized successfully.
@retval EFI_INVALID_PARAMETER Input parameters are invalid.
@retval EFI_UNSUPPORTED The FSP calling conditions were not met.
@retval EFI_DEVICE_ERROR FSP initialization failed.
@retval EFI_OUT_OF_RESOURCES Stack range requested by FSP is not met.
@retval FSP_STATUS_RESET_REQUIREDx A reset is reuired. These status codes will not be returned during S3.
@retval FSP_STATUS_VARIABLE_REQUEST An FSP variable access is required.
**/
EFI_STATUS
EFIAPI
CallFspMultiPhaseMemoryInit (
IN FSP_MULTI_PHASE_PARAMS *MultiPhaseInitParamPtr
);
/**
This FSP API is called after FspMemoryInit API. This FSP API tears down the temporary
memory setup by TempRamInit API. This FSP API accepts a pointer to a data structure
@ -83,6 +117,33 @@ CallFspSiliconInit (
VOID
);
/**
This FSP API provides multi-phase memory and silicon initialization, which brings
greater modularity to the existing FspMemoryInit() and FspSiliconInit() API. Increased
modularity is achieved by adding an extra API to FSP-M and FSP-S. This allows the
bootloader to add board specific initialization steps throughout the MemoryInit and
SiliconInit flows as needed. The FspMemoryInit() API is always called before
FspMultiPhaseMemInit(); it is the first phase of memory initialization. Similarly, the
FspSiliconInit() API is always called before FspMultiPhaseSiInit(); it is the first phase of
silicon initialization. After the first phase, subsequent phases are invoked by calling the
FspMultiPhaseMem/SiInit() API.
@param[in] MultiPhaseInitParamPtr Pointer to provide multi-phase init parameters.
@retval EFI_SUCCESS FSP execution environment was initialized successfully.
@retval EFI_INVALID_PARAMETER Input parameters are invalid.
@retval EFI_UNSUPPORTED The FSP calling conditions were not met.
@retval EFI_DEVICE_ERROR FSP initialization failed.
@retval EFI_OUT_OF_RESOURCES Stack range requested by FSP is not met.
@retval FSP_STATUS_RESET_REQUIREDx A reset is reuired. These status codes will not be returned during S3.
@retval FSP_STATUS_VARIABLE_REQUEST An FSP variable access is required.
**/
EFI_STATUS
EFIAPI
CallFspMultiPhaseSiliconInit (
IN FSP_MULTI_PHASE_PARAMS *MultiPhaseInitParamPtr
);
/**
This FSP API is used to notify the FSP about the different phases in the boot process.
This allows the FSP to take appropriate actions as needed during different initialization
@ -126,6 +187,41 @@ RebaseFspComponent (
UINT32 Delta
);
/**
This function handles variable services requests from FspMemoryInit and FspSiliconInit.
This should be called immediately after returning from the respective FSP entrypoint.
@param[in] FspStatus The status returned by the FSP entry point.
@param[in] MultiPhaseFunction The Multiphase function for this FSP phase (Mem vs Si)
@retval Status
*/
EFI_STATUS
EFIAPI
FspVariableHandler (
IN EFI_STATUS FspStatus,
IN FSP_MULTI_PHASE_FUNCTION MultiPhaseFunction
);
/**
* This calls the FspMultiPhaseMemInit entry point to find out if more phases of
* memory init remain, and executes them if so.
*
* @return EFI_STATUS
*/
EFI_STATUS
EFIAPI
FspMultiPhaseMemInitHandler (VOID);
/**
* This calls the FspMultiPhaseSiliconInit entry point to find out
* if more phases of Silicon init remain, and executes them if so.
*
* @return EFI_STATUS
*/
EFI_STATUS
EFIAPI
FspMultiPhaseSiliconInitHandler (VOID);
/**
This function will handle FSP reset request.
@ -148,7 +244,7 @@ FspResetHandler (
@param[in] Param2 The second parameter to pass to 32bit code.
@param[in] ExeInMem If thunk needs to be executed from memory copy.
@return EFI_STATUS.
@return EFI_STATUS
**/
EFI_STATUS
EFIAPI

View File

@ -1,11 +1,12 @@
/** @file
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <FspApiLibInternal.h>
#include <Library/FspApiLib.h>
#include <Library/BoardInitLib.h>
#include <Library/BootloaderCoreLib.h>
@ -22,7 +23,7 @@
control after system memory is available and before the temporary RAM is torn down.
@param[in] FspmBase The base address of FSPM.
@param[out] HobListPtr Pointer to receive the address of the HOB list.
@param[out] HobList Pointer to receive the address of the HOB list.
@retval EFI_SUCCESS FSP execution environment was initialized successfully.
@retval EFI_INVALID_PARAMETER Input parameters are invalid.
@ -34,15 +35,16 @@
EFI_STATUS
EFIAPI
CallFspMemoryInit (
UINT32 FspmBase,
VOID **HobList
IN UINT32 FspmBase,
OUT VOID **HobList
)
{
UINT8 FspmUpd[FixedPcdGet32 (PcdFSPMUpdSize)];
UINT8 *DefaultMemoryInitUpd;
FSP_INFO_HEADER *FspHeader;
UINT8 *DefaultMemoryInitUpd;
FSP_INFO_HEADER *FspHeader;
FSP_MEMORY_INIT FspMemoryInit;
FSPM_UPD_COMMON *FspmUpdCommon;
FSPM_UPD_COMMON *FspmUpdCommon;
FSPM_UPD_COMMON_FSP24 *FspmUpdCommon24;
EFI_STATUS Status;
UINTN NewStack;
@ -56,10 +58,32 @@ CallFspMemoryInit (
CopyMem (&FspmUpd, DefaultMemoryInitUpd, FspHeader->CfgRegionSize);
/* Update architectural UPD fields */
FspmUpdCommon = (FSPM_UPD_COMMON *)FspmUpd;
FspmUpdCommon->FspmArchUpd.BootLoaderTolumSize = 0;
FspmUpdCommon->FspmArchUpd.BootMode = (UINT32)GetBootMode();
FspmUpdCommon->FspmArchUpd.NvsBufferPtr = (UINT32)(UINTN)FindNvsData();
if (FspHeader->SpecVersion < 0x24) {
FspmUpdCommon = (FSPM_UPD_COMMON *)FspmUpd;
FspmUpdCommon->FspmArchUpd.BootLoaderTolumSize = 0;
FspmUpdCommon->FspmArchUpd.BootMode = (UINT32)GetBootMode();
FspmUpdCommon->FspmArchUpd.NvsBufferPtr = (UINT32)(UINTN)FindNvsData();
NewStack = PcdGet32 (PcdFSPMStackTop);
if (NewStack == 0xFFFFFFFF) {
NewStack = (UINT32)FspmUpdCommon->FspmArchUpd.StackBase + (UINT32)FspmUpdCommon->FspmArchUpd.StackSize;
}
} else {
FspmUpdCommon24 = (FSPM_UPD_COMMON_FSP24 *)FspmUpd;
FspmUpdCommon24->FspmArchUpd.BootLoaderTolumSize = 0;
FspmUpdCommon24->FspmArchUpd.BootMode = (UINT32)GetBootMode();
// This must be set to NULL if ImageAttribute indicates FSP Variable support
if ((FspHeader->ImageAttribute & IMAGE_ATTRIBUTE_VAR_SERVICES_SUPPORT) == IMAGE_ATTRIBUTE_VAR_SERVICES_SUPPORT) {
FspmUpdCommon24->FspmArchUpd.NvsBufferPtr = (UINTN)NULL;
} else {
FspmUpdCommon24->FspmArchUpd.NvsBufferPtr = (UINTN)FindNvsData();
}
NewStack = PcdGet32 (PcdFSPMStackTop);
if (NewStack == 0xFFFFFFFF) {
NewStack = (UINT32)FspmUpdCommon24->FspmArchUpd.StackBase + (UINT32)FspmUpdCommon24->FspmArchUpd.StackSize;
}
}
UpdateFspConfig (FspmUpd);
@ -69,10 +93,6 @@ CallFspMemoryInit (
DEBUG ((DEBUG_INFO, "Call FspMemoryInit ... "));
NewStack = PcdGet32 (PcdFSPMStackTop);
if (NewStack == 0xFFFFFFFF) {
NewStack = FspmUpdCommon->FspmArchUpd.StackBase + FspmUpdCommon->FspmArchUpd.StackSize;
}
if (IS_X64) {
if (NewStack != 0) {
Status = FspmSwitchStack ((VOID *)(UINTN)FspMemoryInit, (VOID *)FspmUpd, (VOID *)HobList, (VOID *)NewStack);
@ -91,3 +111,112 @@ CallFspMemoryInit (
return Status;
}
/**
* This calls the FspMultiPhaseMemInit entry point to find out if more phases of
* memory init remain, and executes them if so.
*
* @return EFI_STATUS
*/
EFI_STATUS
EFIAPI
FspMultiPhaseMemInitHandler(VOID)
{
EFI_STATUS Status;
FSP_MULTI_PHASE_PARAMS MultiPhaseInitParams;
FSP_MULTI_PHASE_GET_NUMBER_OF_PHASES_PARAMS GetNumPhasesParams;
MultiPhaseInitParams.MultiPhaseAction = EnumMultiPhaseGetNumberOfPhases;
MultiPhaseInitParams.PhaseIndex = 0;
MultiPhaseInitParams.MultiPhaseParamPtr = (VOID*)&GetNumPhasesParams;
GetNumPhasesParams.PhasesExecuted = 0;
// If FSP binary doesn't support 2.4 spec, multi phase mem init will return EFI_UNSUPPORTED
Status = CallFspMultiPhaseMemoryInit(&MultiPhaseInitParams);
if (EFI_ERROR(Status)) {
return Status;
}
MultiPhaseInitParams.MultiPhaseAction = EnumMultiPhaseExecutePhase;
MultiPhaseInitParams.MultiPhaseParamPtr = NULL;
// Loop through all phases. Break on error status or FSP_STATUS_* not
// handled by variable services handler
for (MultiPhaseInitParams.PhaseIndex = 1;
MultiPhaseInitParams.PhaseIndex < GetNumPhasesParams.NumberOfPhases &&
!EFI_ERROR(Status) &&
!(Status & ENCODE_RESET_REQUEST(0));
MultiPhaseInitParams.PhaseIndex++)
{
Status = CallFspMultiPhaseMemoryInit(&MultiPhaseInitParams);
ASSERT_EFI_ERROR(Status);
Status = FspVariableHandler(Status,CallFspMultiPhaseMemoryInit);
ASSERT_EFI_ERROR(Status);
}
return Status;
}
/**
This FSP API provides multi-phase memory and silicon initialization, which brings
greater modularity to the existing FspMemoryInit() and FspSiliconInit() API. Increased
modularity is achieved by adding an extra API to FSP-M and FSP-S. This allows the
bootloader to add board specific initialization steps throughout the MemoryInit and
SiliconInit flows as needed. The FspMemoryInit() API is always called before
FspMultiPhaseMemInit(); it is the first phase of memory initialization. Similarly, the
FspSiliconInit() API is always called before FspMultiPhaseSiInit(); it is the first phase of
silicon initialization. After the first phase, subsequent phases are invoked by calling the
FspMultiPhaseMem/SiInit() API.
The FspMultiPhaseMemInit() API may only be called after the FspMemoryInit() API and
before the FspSiliconInit() API; or in the case that FSP-T is being used, before the
TempRamExit() API. The FspMultiPhaseSiInit() API may only be called after the
FspSiliconInit() API and before NotifyPhase() API; or in the case that FSP-I is being used,
before the FspSmmInit() API. The multi-phase APIs may not be called at any other time.
@param[in] MultiPhaseInitParamPtr Pointer to provide multi-phase init parameters.
@retval EFI_SUCCESS FSP execution environment was initialized successfully.
@retval EFI_INVALID_PARAMETER Input parameters are invalid.
@retval EFI_UNSUPPORTED The FSP calling conditions were not met.
@retval EFI_DEVICE_ERROR FSP initialization failed.
@retval EFI_OUT_OF_RESOURCES Stack range requested by FSP is not met.
@retval FSP_STATUS_RESET_REQUIREDx A reset is reuired. These status codes will not be returned during S3.
@retval FSP_STATUS_VARIABLE_REQUEST An FSP variable access is required.
**/
EFI_STATUS
EFIAPI
CallFspMultiPhaseMemoryInit (
IN FSP_MULTI_PHASE_PARAMS *MultiPhaseInitParamPtr
)
{
FSP_INFO_HEADER *FspHeader;
FSP_MULTI_PHASE_MEM_INIT FspMultiPhaseMemoryInit;
EFI_STATUS Status;
UINT32 FspmBase;
FspmBase = PCD_GET32_WITH_ADJUST (PcdFSPMBase);
FspHeader = (FSP_INFO_HEADER *)(UINTN)(FspmBase + FSP_INFO_HEADER_OFF);
ASSERT (FspHeader->Signature == FSP_INFO_HEADER_SIGNATURE);
ASSERT (FspHeader->ImageBase == FspmBase);
if (FspHeader->HeaderRevision < FSP24_HEADER_REVISION
|| FspHeader->FspMultiPhaseMemInitEntryOffset == 0)
{
return EFI_UNSUPPORTED;
}
FspMultiPhaseMemoryInit = (FSP_MULTI_PHASE_MEM_INIT)(UINTN)(FspHeader->ImageBase +
FspHeader->FspMultiPhaseMemInitEntryOffset);
DEBUG ((DEBUG_INFO, "Call FspMultiPhaseMemoryInit ... "));
if (IS_X64) {
Status = Execute32BitCode ((UINTN)FspMultiPhaseMemoryInit, (UINTN)MultiPhaseInitParamPtr, (UINTN)NULL, FALSE);
Status = (UINTN)LShiftU64 (Status & ((UINTN)MAX_INT32 + 1), 32) | (Status & MAX_INT32);
} else {
Status = FspMultiPhaseMemoryInit (MultiPhaseInitParamPtr);
}
DEBUG ((DEBUG_INFO, "%r\n", Status));
return Status;
}

View File

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -8,6 +8,7 @@
#include <FspApiLibInternal.h>
#include <Library/BoardInitLib.h>
#include <Library/BlMemoryAllocationLib.h>
#include <Library/FspApiLib.h>
/**
@ -27,7 +28,7 @@ CallFspSiliconInit (
VOID
)
{
VOID *FspsUpdptr;
VOID *FspsUpdptr;
UINT8 *DefaultSiliconInitUpd;
FSP_INFO_HEADER *FspHeader;
FSP_SILICON_INIT FspSiliconInit;
@ -64,3 +65,106 @@ CallFspSiliconInit (
return Status;
}
/**
* This calls the FspMultiPhaseSiliconInit entry point to find out
* if more phases of Silicon init remain, and executes them if so.
*
* @return EFI_STATUS
*/
EFI_STATUS
EFIAPI
FspMultiPhaseSiliconInitHandler(VOID)
{
EFI_STATUS Status;
FSP_MULTI_PHASE_PARAMS MultiPhaseInitParams;
FSP_MULTI_PHASE_GET_NUMBER_OF_PHASES_PARAMS GetNumPhasesParams;
MultiPhaseInitParams.MultiPhaseAction = EnumMultiPhaseGetNumberOfPhases;
MultiPhaseInitParams.PhaseIndex = 0;
MultiPhaseInitParams.MultiPhaseParamPtr = (VOID*)&GetNumPhasesParams;
GetNumPhasesParams.PhasesExecuted = 0;
Status = CallFspMultiPhaseSiliconInit(&MultiPhaseInitParams);
if (EFI_ERROR(Status)) {
return Status;
}
MultiPhaseInitParams.MultiPhaseAction = EnumMultiPhaseExecutePhase;
MultiPhaseInitParams.MultiPhaseParamPtr = NULL;
// Loop through all phases. Break on error status or FSP_STATUS_* not
// handled by variable services handler
for (MultiPhaseInitParams.PhaseIndex = 1;
MultiPhaseInitParams.PhaseIndex < GetNumPhasesParams.NumberOfPhases &&
!EFI_ERROR(Status) &&
!(Status & ENCODE_RESET_REQUEST(0));
MultiPhaseInitParams.PhaseIndex++)
{
Status = CallFspMultiPhaseSiliconInit(&MultiPhaseInitParams);
ASSERT_EFI_ERROR(Status);
Status = FspVariableHandler(Status,CallFspMultiPhaseSiliconInit);
ASSERT_EFI_ERROR(Status);
}
return Status;
}
/**
This FSP API provides multi-phase memory and silicon initialization, which brings
greater modularity to the existing FspMemoryInit() and FspSiliconInit() API. Increased
modularity is achieved by adding an extra API to FSP-M and FSP-S. This allows the
bootloader to add board specific initialization steps throughout the MemoryInit and
SiliconInit flows as needed. The FspMemoryInit() API is always called before
FspMultiPhaseMemInit(); it is the first phase of memory initialization. Similarly, the
FspSiliconInit() API is always called before FspMultiPhaseSiInit(); it is the first phase of
silicon initialization. After the first phase, subsequent phases are invoked by calling the
FspMultiPhaseMem/SiInit() API.
@param[in] MultiPhaseInitParamPtr Pointer to provide multi-phase init parameters.
@retval EFI_SUCCESS FSP execution environment was initialized successfully.
@retval EFI_INVALID_PARAMETER Input parameters are invalid.
@retval EFI_UNSUPPORTED The FSP calling conditions were not met.
@retval EFI_DEVICE_ERROR FSP initialization failed.
@retval EFI_OUT_OF_RESOURCES Stack range requested by FSP is not met.
@retval FSP_STATUS_RESET_REQUIREDx A reset is reuired. These status codes will not be returned during S3.
@retval FSP_STATUS_VARIABLE_REQUEST An FSP variable access is required.
**/
EFI_STATUS
EFIAPI
CallFspMultiPhaseSiliconInit (
IN FSP_MULTI_PHASE_PARAMS *MultiPhaseInitParamPtr
)
{
FSP_INFO_HEADER *FspHeader;
FSP_MULTI_PHASE_MEM_INIT FspMultiPhaseSiliconInit;
EFI_STATUS Status;
UINT32 FspsBase;
FspsBase = PcdGet32 (PcdFSPSBase);
FspHeader = (FSP_INFO_HEADER *)(UINTN)(FspsBase + FSP_INFO_HEADER_OFF);
ASSERT (FspHeader->Signature == FSP_INFO_HEADER_SIGNATURE);
ASSERT (FspHeader->ImageBase == FspsBase);
// Multi Phase silicon init support added in FSP 2.2
if (FspHeader->HeaderRevision < FSP22_HEADER_REVISION || FspHeader->FspMultiPhaseSiInitEntryOffset == 0) {
return EFI_UNSUPPORTED;
}
FspMultiPhaseSiliconInit = (FSP_MULTI_PHASE_MEM_INIT)(UINTN)(FspHeader->ImageBase + \
FspHeader->FspMultiPhaseSiInitEntryOffset);
DEBUG ((DEBUG_INFO, "Call FspMultiPhaseSiliconInit ... "));
if (IS_X64) {
Status = Execute32BitCode ((UINTN)FspMultiPhaseSiliconInit, (UINTN)MultiPhaseInitParamPtr, (UINTN)NULL, FALSE);
Status = (UINTN)LShiftU64 (Status & ((UINTN)MAX_INT32 + 1), 32) | (Status & MAX_INT32);
} else {
Status = FspMultiPhaseSiliconInit (MultiPhaseInitParamPtr);
}
DEBUG ((DEBUG_INFO, "%r\n", Status));
return Status;
}

View File

@ -0,0 +1,131 @@
/** @file
Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Uefi.h>
#include <FspApiLibInternal.h>
#include <Library/BootloaderCoreLib.h>
#include <Library/FspApiLib.h>
#include <Library/VariableLib.h>
/**
This function handles variable services requests from FspMemoryInit and FspSiliconInit.
This should be called immediately after returning from the respective FSP entrypoint.
@param[in] FspStatus The status returned by the FSP entry point.
@param[in] MultiPhaseFunction The Multiphase function for this FSP phase (Mem vs Si)
@retval Status
*/
EFI_STATUS
EFIAPI
FspVariableHandler(
IN EFI_STATUS FspStatus,
IN FSP_MULTI_PHASE_FUNCTION MultiPhaseFunction
)
{
EFI_STATUS Status;
FSP_MULTI_PHASE_PARAMS MultiPhaseInitParams;
FSP_MULTI_PHASE_VARIABLE_REQUEST_INFO_PARAMS *FspVarReqParams;
Status = EFI_SUCCESS;
while (FspStatus == FSP_STATUS_VARIABLE_REQUEST) {
DEBUG((DEBUG_VERBOSE, "FspVariableHandler: Got FSP_STATUS_VARIABLE_REQUEST\n"));
// Request details of variable request from Multi-phase API.
MultiPhaseInitParams.MultiPhaseAction = EnumMultiPhaseGetVariableRequestInfo;
MultiPhaseInitParams.PhaseIndex = 0;
Status = MultiPhaseFunction(&MultiPhaseInitParams);
ASSERT_EFI_ERROR(Status);
if (EFI_ERROR(Status)) {
break;
}
FspVarReqParams = (FSP_MULTI_PHASE_VARIABLE_REQUEST_INFO_PARAMS*)MultiPhaseInitParams.MultiPhaseParamPtr;
ASSERT (FspVarReqParams != NULL);
if (FspVarReqParams == NULL) {
Status = EFI_UNSUPPORTED;
break;
}
DEBUG((DEBUG_VERBOSE, "FSP Variable Request %d\n", FspVarReqParams->VariableRequest));
if (NULL != FspVarReqParams->VariableName) {
DEBUG((DEBUG_VERBOSE, "\tVariableName %s\n", FspVarReqParams->VariableName));
}
if (NULL != FspVarReqParams->VariableGuid) {
DEBUG((DEBUG_VERBOSE, "\tVariableGuid %g\n", FspVarReqParams->VariableGuid));
}
if (NULL != FspVarReqParams->DataSize) {
DEBUG((DEBUG_VERBOSE, "\tDataSize 0x%X\n", *(FspVarReqParams->DataSize)));
}
DEBUG((DEBUG_VERBOSE, "\tData ptr 0x%X\n", FspVarReqParams->Data));
switch (FspVarReqParams->VariableRequest) {
case EnumFspVariableRequestGetVariable:
Status = GetVariable(
FspVarReqParams->VariableName,
FspVarReqParams->VariableGuid,
FspVarReqParams->Attributes,
(UINTN*)FspVarReqParams->DataSize,
FspVarReqParams->Data
);
break;
case EnumFspVariableRequestGetNextVariableName:
Status = GetNextVariableName(
(UINTN*)FspVarReqParams->VariableNameSize,
FspVarReqParams->VariableName,
FspVarReqParams->VariableGuid
);
break;
case EnumFspVariableRequestSetVariable:
if (FspVarReqParams->Attributes == NULL
|| FspVarReqParams->DataSize == NULL
|| (*(FspVarReqParams->Attributes) & EFI_VARIABLE_NON_VOLATILE) == 0
|| (*(FspVarReqParams->Attributes) & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) != 0)
{
Status = EFI_INVALID_PARAMETER;
}
else {
Status = SetVariable(
FspVarReqParams->VariableName,
FspVarReqParams->VariableGuid,
*(FspVarReqParams->Attributes),
(UINTN)*(FspVarReqParams->DataSize),
FspVarReqParams->Data
);
}
break;
case EnumFspVariableRequestQueryVariableInfo:
if (FspVarReqParams->Attributes == NULL
|| (*(FspVarReqParams->Attributes) & EFI_VARIABLE_NON_VOLATILE) == 0
|| (*(FspVarReqParams->Attributes) & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) != 0)
{
Status = EFI_INVALID_PARAMETER;
}
else {
Status = QueryVariableInfo(
*(FspVarReqParams->Attributes),
FspVarReqParams->MaximumVariableStorageSize,
FspVarReqParams->RemainingVariableStorageSize,
FspVarReqParams->MaximumVariableSize
);
}
break;
default:
break;
}
FspVarReqParams->Status = Status;
MultiPhaseInitParams.MultiPhaseAction = EnumMultiPhaseCompleteVariableRequest;
Status = FspStatus = MultiPhaseFunction(&MultiPhaseInitParams);
ASSERT_EFI_ERROR(FspStatus);
if (EFI_ERROR(FspStatus)) {
return FspStatus;
}
}
return Status;
}

View File

@ -31,6 +31,7 @@
FspTempRamExit.c
FspMemoryInit.c
FspMisc.c
FspVariableServices.c
[Packages]
MdePkg/MdePkg.dec
@ -45,6 +46,8 @@
ResetSystemLib
ThunkLib
PcdLib
BootloaderLib
VariableLib
[Pcd]
gPlatformModuleTokenSpaceGuid.PcdFSPMBase

View File

@ -25,6 +25,7 @@
FspSiliconInit.c
FspNotifyPhase.c
FspMisc.c
FspVariableServices.c
[Packages]
MdePkg/MdePkg.dec
@ -39,6 +40,7 @@
ResetSystemLib
ThunkLib
PcdLib
VariableLib
[Pcd]
gPlatformModuleTokenSpaceGuid.PcdFSPSBase

View File

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -420,10 +420,24 @@ SecStartup2 (
DEBUG ((DEBUG_INIT, "Memory Init\n"));
AddMeasurePoint (0x2020);
Status = CallFspMemoryInit (PCD_GET32_WITH_ADJUST (PcdFSPMBase), &HobList);
AddMeasurePoint (0x2030);
FspResetHandler (Status);
ASSERT_EFI_ERROR (Status);
Status = FspVariableHandler(Status, CallFspMultiPhaseMemoryInit);
ASSERT_EFI_ERROR(Status);
Status = FspMultiPhaseMemInitHandler();
if (Status == EFI_UNSUPPORTED) {
DEBUG((DEBUG_INFO, "FspMultiPhaseMemInit() returned EFI_UNSUPPORTED. This is expected for FSP 2.3 and older.\n"));
} else {
ASSERT_EFI_ERROR(Status);
}
AddMeasurePoint (0x2030);
FspResetHandler (Status);
if (PcdGetBool (PcdSblResiliencyEnabled)) {
// React to TCO timer failures here as not to conflict with ACM active timer
// which is stopped at end of FSP-M

View File

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -465,9 +465,23 @@ SecStartup (
DEBUG ((DEBUG_INIT, "Silicon Init\n"));
AddMeasurePoint (0x3020);
Status = CallFspSiliconInit ();
FspResetHandler(Status);
ASSERT_EFI_ERROR (Status);
Status = FspVariableHandler(Status, CallFspMultiPhaseSiliconInit);
ASSERT_EFI_ERROR(Status);
Status = FspMultiPhaseSiliconInitHandler();
if (Status == EFI_UNSUPPORTED) {
DEBUG((DEBUG_INFO, "FspMultiPhaseSiliconInitHandler() returned EFI_UNSUPPORTED.\n"));
} else {
ASSERT_EFI_ERROR(Status);
}
AddMeasurePoint (0x3030);
FspResetHandler (Status);
ASSERT_EFI_ERROR (Status);
if (FixedPcdGetBool (PcdSmbiosEnabled)) {
InitSmbiosStringPtr ();

View File

@ -2,7 +2,7 @@
Intel FSP API definition from Intel Firmware Support Package External
Architecture Specification v2.0 - v2.2
Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2014 - 2023, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -11,19 +11,24 @@
#define _FSP_API_H_
#include <Pi/PiStatusCode.h>
#include <Base.h>
///
/// FSP Reset Status code
/// These are defined in FSP EAS v2.0 section 11.2.2 - OEM Status Code
/// These are defined in FSP EAS v2.4 section 13.2.2 - OEM Status Code
/// @{
#define FSP_STATUS_RESET_REQUIRED_COLD 0x40000001
#define FSP_STATUS_RESET_REQUIRED_WARM 0x40000002
#define FSP_STATUS_RESET_REQUIRED_3 0x40000003
#define FSP_STATUS_RESET_REQUIRED_4 0x40000004
#define FSP_STATUS_RESET_REQUIRED_5 0x40000005
#define FSP_STATUS_RESET_REQUIRED_6 0x40000006
#define FSP_STATUS_RESET_REQUIRED_7 0x40000007
#define FSP_STATUS_RESET_REQUIRED_8 0x40000008
#define ENCODE_RESET_REQUEST(ResetType) \
((EFI_STATUS)((MAX_BIT >> 1) | (ResetType)))
#define FSP_STATUS_RESET_REQUIRED_COLD ENCODE_RESET_REQUEST(1)
#define FSP_STATUS_RESET_REQUIRED_WARM ENCODE_RESET_REQUEST(2)
#define FSP_STATUS_RESET_REQUIRED_3 ENCODE_RESET_REQUEST(3)
#define FSP_STATUS_RESET_REQUIRED_4 ENCODE_RESET_REQUEST(4)
#define FSP_STATUS_RESET_REQUIRED_5 ENCODE_RESET_REQUEST(5)
#define FSP_STATUS_RESET_REQUIRED_6 ENCODE_RESET_REQUEST(6)
#define FSP_STATUS_RESET_REQUIRED_7 ENCODE_RESET_REQUEST(7)
#define FSP_STATUS_RESET_REQUIRED_8 ENCODE_RESET_REQUEST(8)
#define FSP_STATUS_VARIABLE_REQUEST ENCODE_RESET_REQUEST(10)
/// @}
///
@ -128,6 +133,27 @@ typedef struct {
UINT8 Reserved1[20];
} FSPT_ARCH_UPD;
///
/// FSPT_ARCH2_UPD Configuration.
///
typedef struct {
///
/// Revision of the structure is 2 for this version of the specification.
///
UINT8 Revision;
UINT8 Reserved[3];
///
/// Length of the structure in bytes. The current value for this field is 32.
///
UINT32 Length;
///
/// FspDebugHandler Optional debug handler for the bootloader to receive debug messages
/// occurring during FSP execution.
///
EFI_PHYSICAL_ADDRESS FspDebugHandler;
UINT8 Reserved1[16];
} FSPT_ARCH2_UPD;
///
/// FSPM_ARCH_UPD Configuration.
///
@ -169,6 +195,54 @@ typedef struct {
UINT8 Reserved1[4];
} FSPM_ARCH_UPD;
///
/// FSPM_ARCH2_UPD Configuration.
///
typedef struct {
///
/// Revision of the structure is 3 for this version of the specification.
///
UINT8 Revision;
UINT8 Reserved[3];
///
/// Length of the structure in bytes. The current value for this field is 64.
///
UINT32 Length;
///
/// Pointer to the non-volatile storage (NVS) data buffer.
/// If it is NULL it indicates the NVS data is not available.
///
EFI_PHYSICAL_ADDRESS NvsBufferPtr;
///
/// Pointer to the temporary stack base address to be
/// consumed inside FspMemoryInit() API.
///
EFI_PHYSICAL_ADDRESS StackBase;
///
/// Temporary stack size to be consumed inside
/// FspMemoryInit() API.
///
UINT64 StackSize;
///
/// Size of memory to be reserved by FSP below "top
/// of low usable memory" for bootloader usage.
///
UINT32 BootLoaderTolumSize;
///
/// Current boot mode.
///
UINT32 BootMode;
///
/// Optional event handler for the bootloader to be informed of events occurring during FSP execution.
/// This value is only valid if Revision is >= 2.
///
EFI_PHYSICAL_ADDRESS FspEventHandler;
UINT8 Reserved1[16];
} FSPM_ARCH2_UPD;
///
/// FSPS_ARCH_UPD Configuration.
///
typedef struct {
///
/// Revision Revision of the structure is 1 for this version of the specification.
@ -195,6 +269,27 @@ typedef struct {
UINT8 Reserved1[19];
} FSPS_ARCH_UPD;
///
/// FSPS_ARCH2_UPD Configuration.
///
typedef struct {
///
/// Revision of the structure is 2 for this version of the specification.
///
UINT8 Revision;
UINT8 Reserved[3];
///
/// Length of the structure in bytes. The current value for this field is 32.
///
UINT32 Length;
///
/// FspEventHandler Optional event handler for the bootloader to be informed of events
/// occurring during FSP execution.
///
EFI_PHYSICAL_ADDRESS FspEventHandler;
UINT8 Reserved1[16];
} FSPS_ARCH2_UPD;
///
/// FSPT_UPD_COMMON Configuration.
///
@ -220,6 +315,21 @@ typedef struct {
FSPT_ARCH_UPD FsptArchUpd;
} FSPT_UPD_COMMON_FSP22;
///
/// FSPT_UPD_COMMON Configuration for FSP spec. 2.4 and above.
///
typedef struct {
///
/// FSP_UPD_HEADER Configuration.
///
FSP_UPD_HEADER FspUpdHeader;
///
/// FSPT_ARCH2_UPD Configuration.
///
FSPT_ARCH2_UPD FsptArchUpd;
} FSPT_UPD_COMMON_FSP24;
///
/// FSPM_UPD_COMMON Configuration.
///
@ -234,6 +344,20 @@ typedef struct {
FSPM_ARCH_UPD FspmArchUpd;
} FSPM_UPD_COMMON;
///
/// FSPM_UPD_COMMON Configuration for FSP spec. 2.4 and above.
///
typedef struct {
///
/// FSP_UPD_HEADER Configuration.
///
FSP_UPD_HEADER FspUpdHeader;
///
/// FSPM_ARCH2_UPD Configuration.
///
FSPM_ARCH2_UPD FspmArchUpd;
} FSPM_UPD_COMMON_FSP24;
///
/// FSPS_UPD_COMMON Configuration.
///
@ -259,6 +383,21 @@ typedef struct {
FSPS_ARCH_UPD FspsArchUpd;
} FSPS_UPD_COMMON_FSP22;
///
/// FSPS_UPD_COMMON Configuration for FSP spec. 2.4 and above.
///
typedef struct {
///
/// FSP_UPD_HEADER Configuration.
///
FSP_UPD_HEADER FspUpdHeader;
///
/// FSPS_ARCH2_UPD Configuration.
///
FSPS_ARCH2_UPD FspsArchUpd;
} FSPS_UPD_COMMON_FSP24;
///
/// Enumeration of FSP_INIT_PHASE for NOTIFY_PHASE.
///
@ -296,10 +435,35 @@ typedef struct {
/// Action definition for FspMultiPhaseSiInit API
///
typedef enum {
EnumMultiPhaseGetNumberOfPhases = 0x0,
EnumMultiPhaseExecutePhase = 0x1
EnumMultiPhaseGetNumberOfPhases = 0x0,
EnumMultiPhaseExecutePhase = 0x1,
EnumMultiPhaseGetVariableRequestInfo = 0x2,
EnumMultiPhaseCompleteVariableRequest = 0x3
} FSP_MULTI_PHASE_ACTION;
typedef enum {
EnumFspVariableRequestGetVariable = 0x0,
EnumFspVariableRequestGetNextVariableName = 0x1,
EnumFspVariableRequestSetVariable = 0x2,
EnumFspVariableRequestQueryVariableInfo = 0x3
} FSP_VARIABLE_REQUEST_TYPE;
#pragma pack(16)
typedef struct {
IN FSP_VARIABLE_REQUEST_TYPE VariableRequest;
IN OUT CHAR16 *VariableName;
IN OUT UINT64 *VariableNameSize;
IN OUT EFI_GUID *VariableGuid;
IN OUT UINT32 *Attributes;
IN OUT UINT64 *DataSize;
IN OUT VOID *Data;
OUT UINT64 *MaximumVariableStorageSize;
OUT UINT64 *RemainingVariableStorageSize;
OUT UINT64 *MaximumVariableSize;
OUT EFI_STATUS Status;
} FSP_MULTI_PHASE_VARIABLE_REQUEST_INFO_PARAMS;
#pragma pack()
///
/// Data structure returned by FSP when bootloader calling
/// FspMultiPhaseSiInit API with action 0 (EnumMultiPhaseGetNumberOfPhases)
@ -323,7 +487,7 @@ typedef struct {
typedef struct {
IN FSP_MULTI_PHASE_ACTION MultiPhaseAction;
IN UINT32 PhaseIndex;
IN OUT UINT32 MultiPhaseParamPtr;
IN OUT VOID *MultiPhaseParamPtr;
} FSP_MULTI_PHASE_PARAMS;
#pragma pack()
@ -482,4 +646,30 @@ EFI_STATUS
IN FSP_MULTI_PHASE_PARAMS *MultiPhaseSiInitParamPtr
);
/**
The FspMultiPhaseMemInit() API may only be called after the FspMemoryInit() API and before the
FspSiliconInit() API; or in the case that FSP-T is being used, before the TempRamExit() API.
This FSP API provides multi-phase memory initialization; which brings greater modularity
beyond the existing FspMemoryInit() API. Increased modularity is achieved by adding an
extra API to FSP-M. This allows the bootloader to add board specific initialization steps
throughout the MemoryInit flow as needed.
@param[in,out] FSP_MULTI_PHASE_PARAMS For action - EnumMultiPhaseGetNumberOfPhases:
FSP_MULTI_PHASE_PARAMS->MultiPhaseParamPtr will contain
how many phases supported by FSP.
For action - EnumMultiPhaseExecutePhase:
FSP_MULTI_PHASE_PARAMS->MultiPhaseParamPtr shall be NULL.
@retval EFI_SUCCESS FSP execution environment was initialized successfully.
@retval EFI_INVALID_PARAMETER Input parameters are invalid.
@retval EFI_UNSUPPORTED The FSP calling conditions were not met.
@retval EFI_DEVICE_ERROR FSP initialization failed.
@retval FSP_STATUS_RESET_REQUIREDx A reset is required. These status codes will not be returned during S3.
@retval FSP_STATUS_VARIABLE_REQUEST A variable request has been made by FSP that needs boot loader handling.
**/
typedef
EFI_STATUS
(EFIAPI *FSP_MULTI_PHASE_MEM_INIT)(
IN FSP_MULTI_PHASE_PARAMS *MultiPhaseSiInitParamPtr
);
#endif

View File

@ -2,15 +2,22 @@
Intel FSP Header File definition from Intel Firmware Support Package External
Architecture Specification v2.0 and above.
Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2014 - 2023, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Base.h>
#ifndef __FSP_HEADER_FILE_H__
#define __FSP_HEADER_FILE_H__
#define FSP_HEADER_REVISION_3 3
#define FSP20_HEADER_REVISION 3
#define FSP21_HEADER_REVISION 4
#define FSP22_HEADER_REVISION 5
#define FSP23_HEADER_REVISION 6
#define FSP24_HEADER_REVISION 7
#define FSPE_HEADER_REVISION_1 1
#define FSPP_HEADER_REVISION_1 1
@ -24,6 +31,13 @@
#define FSP_INFO_HEADER_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'H')
#define IMAGE_ATTRIBUTE_GRAPHICS_SUPPORT BIT0
#define IMAGE_ATTRIBUTE_DISPATCH_MODE_SUPPORT BIT1
#define IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT BIT2
#define IMAGE_ATTRIBUTE_VAR_SERVICES_SUPPORT BIT3
#define FSP_IA32 0
#define FSP_X64 1
#pragma pack(1)
///
@ -49,7 +63,7 @@ typedef struct {
UINT8 SpecVersion;
///
/// Byte 0x0B: Revision of the FSP Information Header.
/// The Current value for this field is 0x6.
/// The Current value for this field is 0x7.
///
UINT8 HeaderRevision;
///
@ -82,6 +96,11 @@ typedef struct {
UINT32 ImageBase;
///
/// Byte 0x20: Attribute for the FSP binary.
/// Bit 0: Graphics Support - Set to 1 when FSP supports enabling Graphics Display.
/// Bit 1: Dispatch Mode Support - Set to 1 when FSP supports the optional Dispatch Mode API defined in Section 7.2 and 9. This bit is only valid if FSP HeaderRevision is >= 4.
/// Bit 2: 64-bit mode support - Set to 1 to indicate FSP supports 64-bit long mode interfaces. Set to 0 to indicate FSP supports 32-bit mode interfaces. This bit is only valid if FSP HeaderRevision is >= 7.
/// Bit 3: FSP Variable Services Support - Set to 1 to indicate FSP utilizes the FSP Variable Services defined in Section 9.6 to store non-volatile data. This bit is only valid if FSP HeaderRevision is >= 7.
/// Bits 15:4 - Reserved
///
UINT16 ImageAttribute;
///
@ -147,6 +166,10 @@ typedef struct {
/// Byte 0x4E: Reserved4.
///
UINT16 Reserved4;
///
/// Byte 0x50: Multi Phase Mem Init offset.
///
UINT32 FspMultiPhaseMemInitEntryOffset;
} FSP_INFO_HEADER;
///

View File

@ -1,6 +1,6 @@
## @ SplitFspBin.py
#
# Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@ -125,7 +125,8 @@ class FSP_INFORMATION_HEADER(Structure):
('FspSiliconInitEntryOffset', c_uint32),
('FspMultiPhaseSiInitEntryOffset', c_uint32),
('ExtendedImageRevision', c_uint16),
('Reserved4', c_uint16)
('Reserved4', c_uint16),
('FspMultiPhaseMemoryInitEntryOffset', c_uint32)
]
class FSP_PATCH_TABLE(Structure):

View File

@ -112,10 +112,10 @@ class Board(BaseBoard):
self.FSP_IMAGE_ID = '$APLFSP$'
self.STAGE1A_SIZE = 0x00008000
self.STAGE1B_SIZE = 0x00036000
self.STAGE1B_SIZE = 0x00038000
if self.ENABLE_SOURCE_DEBUG:
self.STAGE1B_SIZE += 0x2000
self.STAGE2_SIZE = 0x00032000
self.STAGE2_SIZE = 0x00033000
self.PAYLOAD_SIZE = 0x00021000
if len(self._PAYLOAD_NAME.split(';')) > 1:
@ -136,7 +136,7 @@ class Board(BaseBoard):
self.STAGE1B_XIP = 0
self.STAGE1B_LOAD_BASE = 0xFEF10000
self.STAGE1B_FD_BASE = 0xFEF80000
self.STAGE1B_FD_SIZE = 0x0006B000
self.STAGE1B_FD_SIZE = 0x0006D000
if self.ENABLE_SOURCE_DEBUG:
self.STAGE1B_FD_SIZE += 0x00001000
if self.RELEASE_MODE == 0:

View File

@ -117,7 +117,7 @@ class Board(BaseBoard):
if self.RELEASE_MODE:
self.STAGE1A_SIZE = 0x0000D000
self.STAGE1B_SIZE = 0x000B0000
self.STAGE1B_SIZE = 0x000B1000
self.STAGE2_SIZE = 0x00070000
self.STAGE2_FD_SIZE = 0x000E0000
self.PAYLOAD_SIZE = 0x00024000