diff --git a/IntelFsp2Pkg/Include/FspStatusCode.h b/IntelFsp2Pkg/Include/FspStatusCode.h
index e294aa343565..c7afff5cf943 100644
--- a/IntelFsp2Pkg/Include/FspStatusCode.h
+++ b/IntelFsp2Pkg/Include/FspStatusCode.h
@@ -16,6 +16,7 @@
#define FSP_STATUS_CODE_MEMORY_INIT 0xD000
#define FSP_STATUS_CODE_TEMP_RAM_EXIT 0xB000
#define FSP_STATUS_CODE_SILICON_INIT 0x9000
+#define FSP_STATUS_CODE_FSPSMM_INIT 0x7000
#define FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION 0x6000
#define FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION 0x4000
#define FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION 0x2000
diff --git a/IntelFsp2WrapperPkg/FspiWrapperPeim/FspiWrapperPeim.c b/IntelFsp2WrapperPkg/FspiWrapperPeim/FspiWrapperPeim.c
new file mode 100644
index 000000000000..211dd26060f7
--- /dev/null
+++ b/IntelFsp2WrapperPkg/FspiWrapperPeim/FspiWrapperPeim.c
@@ -0,0 +1,269 @@
+/** @file
+ This will be invoked only once. It will call FspSmmInit API,
+ to call MmIplPei to load MM Core and dispatch all Standalone
+ MM drivers.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/**
+ Call FspSmmInit API.
+
+ @return Status returned by FspSmmInit API.
+**/
+EFI_STATUS
+FspiWrapperInitApiMode (
+ VOID
+ )
+{
+ FSP_INFO_HEADER *FspiHeaderPtr;
+ EFI_STATUS Status;
+ UINT64 TimeStampCounterStart;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ VOID *FspHobListPtr;
+ VOID *FspiUpdDataPtr;
+ UINTN *SourceData;
+
+ DEBUG ((DEBUG_INFO, "PeiFspSmmInit enter\n"));
+
+ FspHobListPtr = NULL;
+ FspiUpdDataPtr = NULL;
+
+ FspiHeaderPtr = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspiBaseAddress));
+ DEBUG ((DEBUG_INFO, "FspiHeaderPtr - 0x%x\n", FspiHeaderPtr));
+ if (FspiHeaderPtr == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((PcdGet64 (PcdFspiUpdDataAddress) == 0) && (FspiHeaderPtr->CfgRegionSize != 0) && (FspiHeaderPtr->CfgRegionOffset != 0)) {
+ //
+ // Copy default FSP-I UPD data from Flash
+ //
+ FspiUpdDataPtr = AllocateZeroPool ((UINTN)FspiHeaderPtr->CfgRegionSize);
+ ASSERT (FspiUpdDataPtr != NULL);
+ SourceData = (UINTN *)((UINTN)FspiHeaderPtr->ImageBase + (UINTN)FspiHeaderPtr->CfgRegionOffset);
+ CopyMem (FspiUpdDataPtr, SourceData, (UINTN)FspiHeaderPtr->CfgRegionSize);
+ } else {
+ //
+ // External UPD is ready, get the buffer from PCD pointer.
+ //
+ FspiUpdDataPtr = (VOID *)(UINTN)PcdGet64 (PcdFspiUpdDataAddress);
+ ASSERT (FspiUpdDataPtr != NULL);
+ }
+
+ DEBUG ((DEBUG_INFO, "UpdateFspiUpdData enter\n"));
+ UpdateFspiUpdData (FspiUpdDataPtr);
+ DEBUG ((DEBUG_INFO, " BootloaderSmmFvBaseAddress - 0x%lx\n", ((FSPI_UPD_COMMON *)FspiUpdDataPtr)->FspiArchUpd.BootloaderSmmFvBaseAddress));
+ DEBUG ((DEBUG_INFO, " BootloaderSmmFvLength - 0x%lx\n", ((FSPI_UPD_COMMON *)FspiUpdDataPtr)->FspiArchUpd.BootloaderSmmFvLength));
+ DEBUG ((DEBUG_INFO, " BootloaderSmmFvContextData - 0x%lx\n", ((FSPI_UPD_COMMON *)FspiUpdDataPtr)->FspiArchUpd.BootloaderSmmFvContextData));
+ DEBUG ((DEBUG_INFO, " BootloaderSmmFvContextDataLength - 0x%lx\n", ((FSPI_UPD_COMMON *)FspiUpdDataPtr)->FspiArchUpd.BootloaderSmmFvContextDataLength));
+
+ //
+ // Get FspHobList
+ //
+ GuidHob = GetFirstGuidHob (&gFspHobGuid);
+ ASSERT (GuidHob != NULL);
+ FspHobListPtr = *(VOID **)GET_GUID_HOB_DATA (GuidHob);
+ DEBUG ((DEBUG_INFO, " HobListPtr - 0x%x\n", &FspHobListPtr));
+
+ TimeStampCounterStart = AsmReadTsc ();
+ Status = CallFspSmmInit (FspiUpdDataPtr);
+
+ //
+ // 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, "FspSmmInitApi requested reset %r\n", Status));
+ CallFspWrapperResetSystem (Status);
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ERROR - Failed to execute FspSmmInitApi(), Status = %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ DEBUG ((DEBUG_INFO, "FspSmmInit status: %r\n", Status));
+ //
+ // Create hobs after FspSmmInit. Hence passing the recorded timestamp here
+ //
+ PERF_START_EX (&gFspApiPerformanceGuid, "EventRec", NULL, TimeStampCounterStart, FSP_STATUS_CODE_FSPSMM_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ PERF_END_EX (&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_FSPSMM_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ DEBUG ((DEBUG_INFO, "Total time spent executing FspSmmInitApi: %d millisecond\n", DivU64x32 (GetTimeInNanoSecond (AsmReadTsc () - TimeStampCounterStart), 1000000)));
+
+ Status = TestFspSmmInitApiOutput (FspiUpdDataPtr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ERROR - TestFspSmmInitApiOutput () fail, Status = %r\n", Status));
+ }
+
+ DEBUG ((DEBUG_INFO, " FspHobListPtr (returned) - 0x%x\n", FspHobListPtr));
+ ASSERT (FspHobListPtr != NULL);
+
+ PostFspiHobProcess (FspHobListPtr);
+
+ return Status;
+}
+
+/**
+ Do FSP SMM initialization in Dispatch mode.
+
+ @retval FSP SMM initialization status.
+**/
+EFI_STATUS
+EFIAPI
+FspiWrapperInitDispatchMode (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *MeasurementExcludedFvPpi;
+ EFI_PEI_PPI_DESCRIPTOR *MeasurementExcludedPpiList;
+
+ MeasurementExcludedFvPpi = AllocatePool (sizeof (*MeasurementExcludedFvPpi));
+ if (MeasurementExcludedFvPpi != NULL) {
+ MeasurementExcludedFvPpi->Count = 1;
+ MeasurementExcludedFvPpi->Fv[0].FvBase = PcdGet32 (PcdFspiBaseAddress);
+ MeasurementExcludedFvPpi->Fv[0].FvLength = ((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdFspiBaseAddress))->FvLength;
+ } else {
+ ASSERT (MeasurementExcludedFvPpi != NULL);
+ }
+
+ MeasurementExcludedPpiList = AllocatePool (sizeof (*MeasurementExcludedPpiList));
+ if (MeasurementExcludedPpiList != NULL) {
+ MeasurementExcludedPpiList->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ MeasurementExcludedPpiList->Guid = &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid;
+ MeasurementExcludedPpiList->Ppi = MeasurementExcludedFvPpi;
+
+ Status = PeiServicesInstallPpi (MeasurementExcludedPpiList);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ ASSERT (MeasurementExcludedPpiList != NULL);
+ }
+
+ //
+ // FSP-I Wrapper running in Dispatch mode and reports FSP-I FV to PEI dispatcher.
+ //
+ PeiServicesInstallFvInfoPpi (
+ &((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdFspiBaseAddress))->FileSystemGuid,
+ (VOID *)(UINTN)PcdGet32 (PcdFspiBaseAddress),
+ (UINT32)((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdFspiBaseAddress))->FvLength,
+ NULL,
+ NULL
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is called after TCG installed PPI.
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_STATUS Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+TcgPpiNotify (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
+ );
+
+EFI_PEI_NOTIFY_DESCRIPTOR mTcgPpiNotifyDesc = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEdkiiTcgPpiGuid,
+ TcgPpiNotify
+};
+
+/**
+ This function is called after TCG installed PPI.
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_STATUS Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+TcgPpiNotify (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
+ )
+{
+ UINT32 FspMeasureMask;
+
+ DEBUG ((DEBUG_INFO, "TcgPpiNotify FSPI\n"));
+
+ FspMeasureMask = PcdGet32 (PcdFspMeasurementConfig);
+
+ if ((FspMeasureMask & FSP_MEASURE_FSPI) != 0) {
+ MeasureFspFirmwareBlob (
+ 0,
+ "FSPI",
+ PcdGet32 (PcdFspiBaseAddress),
+ (UINT32)((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdFspiBaseAddress))->FvLength
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This is the entrypoint of PEIM.
+
+ @param[in] FileHandle Handle of the file being invoked.
+ @param[in] PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS if it completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+FspiWrapperPeimEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "FspiWrapperPeimEntryPoint\n"));
+
+ Status = PeiServicesNotifyPpi (&mTcgPpiNotifyDesc);
+ ASSERT_EFI_ERROR (Status);
+
+ if (PcdGet8 (PcdFspModeSelection) == 1) {
+ Status = FspiWrapperInitApiMode ();
+ } else {
+ Status = FspiWrapperInitDispatchMode ();
+ }
+
+ return Status;
+}
diff --git a/IntelFsp2WrapperPkg/FspiWrapperPeim/FspiWrapperPeim.inf b/IntelFsp2WrapperPkg/FspiWrapperPeim/FspiWrapperPeim.inf
new file mode 100644
index 000000000000..e03434cccacd
--- /dev/null
+++ b/IntelFsp2WrapperPkg/FspiWrapperPeim/FspiWrapperPeim.inf
@@ -0,0 +1,70 @@
+## @file
+# FSP-I wrapper PEI Module
+#
+# This PEIM initialize FSP.
+# This will be invoked only once. It will call FspSmmInit API,
+# to call MmIplPei to load MM Core and dispatch all Standalone
+# MM drivers.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = FspiWrapperPeim
+ FILE_GUID = 64D6CA11-6F4C-4B79-B77F-37A281CF0FCC
+ VERSION_STRING = 1.0
+ MODULE_TYPE = PEIM
+ ENTRY_POINT = FspiWrapperPeimEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ PeimEntryPoint
+ PeiServicesLib
+ PeiServicesTablePointerLib
+ BaseMemoryLib
+ TimerLib
+ DebugLib
+ HobLib
+ MemoryAllocationLib
+ FspWrapperPlatformLib
+ FspWrapperHobProcessLib
+ PerformanceLib
+ FspWrapperApiLib
+ FspWrapperApiTestLib
+ FspMeasurementLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+ SecurityPkg/SecurityPkg.dec
+ IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
+
+[Ppis]
+ gEdkiiTcgPpiGuid ## NOTIFY
+ gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid ## PRODUCES
+
+[Pcd]
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspiBaseAddress ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspiUpdDataAddress ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspMeasurementConfig ## CONSUMES
+
+[Guids]
+ gFspHobGuid ## CONSUMES ## HOB
+ gFspApiPerformanceGuid ## SOMETIMES_CONSUMES ## GUID
+
+[Sources]
+ FspiWrapperPeim.c
+
+[Depex]
+ gEfiPeiMemoryDiscoveredPpiGuid
diff --git a/IntelFsp2WrapperPkg/Include/Library/FspMeasurementLib.h b/IntelFsp2WrapperPkg/Include/Library/FspMeasurementLib.h
index db599cc1f835..7b303dab3ed6 100644
--- a/IntelFsp2WrapperPkg/Include/Library/FspMeasurementLib.h
+++ b/IntelFsp2WrapperPkg/Include/Library/FspMeasurementLib.h
@@ -13,6 +13,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define FSP_MEASURE_FSPT BIT1
#define FSP_MEASURE_FSPM BIT2
#define FSP_MEASURE_FSPS BIT3
+#define FSP_MEASURE_FSPI BIT4
#define FSP_MEASURE_FSPUPD BIT31
/**
diff --git a/IntelFsp2WrapperPkg/Include/Library/FspWrapperApiLib.h b/IntelFsp2WrapperPkg/Include/Library/FspWrapperApiLib.h
index d38582d3e591..59df1d7cd7d7 100644
--- a/IntelFsp2WrapperPkg/Include/Library/FspWrapperApiLib.h
+++ b/IntelFsp2WrapperPkg/Include/Library/FspWrapperApiLib.h
@@ -78,4 +78,17 @@ CallFspSiliconInit (
IN VOID *FspsUpdDataPtr
);
+/**
+ Call FSP API - FspSmmInit.
+
+ @param[in] FspiUpdDataPtr Pointer to the FSPI_UPD data structure.
+
+ @return EFI status returned by FspSmmInit API.
+**/
+EFI_STATUS
+EFIAPI
+CallFspSmmInit (
+ IN VOID *FspiUpdDataPtr
+ );
+
#endif
diff --git a/IntelFsp2WrapperPkg/Include/Library/FspWrapperApiTestLib.h b/IntelFsp2WrapperPkg/Include/Library/FspWrapperApiTestLib.h
index 2ff2d0cbced3..26ad8f0dbd5b 100644
--- a/IntelFsp2WrapperPkg/Include/Library/FspWrapperApiTestLib.h
+++ b/IntelFsp2WrapperPkg/Include/Library/FspWrapperApiTestLib.h
@@ -52,4 +52,17 @@ TestFspSiliconInitApiOutput (
IN VOID *FspsUpdDataPtr
);
+/**
+ Test the output of FSP API - FspSmmInit.
+
+ @param[in] FspiUpdDataPtr Address pointer to the Smm Init parameters structure.
+
+ @return test result on output of FspSmmInit API.
+**/
+EFI_STATUS
+EFIAPI
+TestFspSmmInitApiOutput (
+ IN VOID *FspiUpdDataPtr
+ );
+
#endif
diff --git a/IntelFsp2WrapperPkg/Include/Library/FspWrapperHobProcessLib.h b/IntelFsp2WrapperPkg/Include/Library/FspWrapperHobProcessLib.h
index c91dbb5ea209..9ae9d67960a9 100644
--- a/IntelFsp2WrapperPkg/Include/Library/FspWrapperHobProcessLib.h
+++ b/IntelFsp2WrapperPkg/Include/Library/FspWrapperHobProcessLib.h
@@ -35,4 +35,17 @@ PostFspsHobProcess (
IN VOID *FspHobList
);
+/**
+ Post FSP-I HOB process.
+
+ @param[in] FspHobList Pointer to the HOB data structure produced by FSP.
+
+ @return If platform process the FSP hob list successfully.
+**/
+EFI_STATUS
+EFIAPI
+PostFspiHobProcess (
+ IN VOID *FspHobList
+ );
+
#endif
diff --git a/IntelFsp2WrapperPkg/Include/Library/FspWrapperPlatformLib.h b/IntelFsp2WrapperPkg/Include/Library/FspWrapperPlatformLib.h
index fe9f0d7408cd..8e3cd6430751 100644
--- a/IntelFsp2WrapperPkg/Include/Library/FspWrapperPlatformLib.h
+++ b/IntelFsp2WrapperPkg/Include/Library/FspWrapperPlatformLib.h
@@ -77,4 +77,16 @@ CallFspWrapperResetSystem (
IN EFI_STATUS FspStatusResetType
);
+/**
+ This function overrides the default configurations in the FSP-I UPD data region.
+
+ @param[in,out] FspUpdRgnPtr A pointer to the UPD data region data structure.
+
+**/
+VOID
+EFIAPI
+UpdateFspiUpdData (
+ IN OUT VOID *FspUpdRgnPtr
+ );
+
#endif
diff --git a/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec b/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
index 6865ffaf1373..2a3b270777bf 100644
--- a/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
+++ b/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
@@ -98,10 +98,11 @@
gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection|0x00000001|UINT8|0x4000000A
#
- ## These are the base address of FSP-M/S
+ ## These are the base address of FSP-M/S/I
#
gIntelFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddress|0x00000000|UINT32|0x00001000
gIntelFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddress|0x00000000|UINT32|0x00001001
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspiBaseAddress|0x00000000|UINT32|0x00001002
#
# To provide flexibility for platform to pre-allocate FSP UPD buffer
#
@@ -137,3 +138,12 @@
#1: measure FSP UPD region in one record (PCR1), the FSP code without UPD in another record (PCR0).
#
gIntelFsp2WrapperTokenSpaceGuid.PcdFspMeasurementConfig|0x00000000|UINT32|0x50000004
+ #
+ # To provide flexibility for platform to pre-allocate FSP UPD buffer
+ #
+ # The PCDs define the pre-allocated FSPI UPD Data Buffer Address.
+ # 0x00000000 - Platform will not pre-allocate UPD buffer before FspWrapper module
+ # non-zero - Platform will pre-allocate UPD buffer and patch this value to
+ # buffer address before FspWrapper module executing.
+ #
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspiUpdDataAddress|0x00000000|UINT64|0x50000005
diff --git a/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dsc b/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dsc
index fe621244a61b..f51e1c89f622 100644
--- a/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dsc
+++ b/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dsc
@@ -78,7 +78,7 @@
DevicePathLib|MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
-[Components.Ia32]
+[Components.Ia32, Components.X64]
IntelFsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
IntelFsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.inf
IntelFsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
@@ -87,6 +87,7 @@
IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
+ IntelFsp2WrapperPkg/FspiWrapperPeim/FspiWrapperPeim.inf
[Components.IA32, Components.X64]
IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
diff --git a/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
index 1e348b539fe7..14760df0014a 100644
--- a/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
+++ b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
@@ -63,3 +63,4 @@
[Pcd]
gIntelFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddress ## CONSUMES
gIntelFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddress ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspiBaseAddress ## CONSUMES
diff --git a/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c
index 2e82a0c1b59a..4d4cc8b5be62 100644
--- a/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c
+++ b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c
@@ -230,3 +230,39 @@ CallFspSiliconInit (
return Status;
}
+
+/**
+ Call FSP API - FspSmmInit.
+
+ @param[in] FspiUpdDataPtr Address pointer to the Smm Init parameters structure.
+
+ @return EFI status returned by FspSmmInit API.
+**/
+EFI_STATUS
+EFIAPI
+CallFspSmmInit (
+ IN VOID *FspiUpdDataPtr
+ )
+{
+ FSP_INFO_HEADER *FspHeader;
+ FSP_SMM_INIT FspSmmInitApi;
+ EFI_STATUS Status;
+ BOOLEAN InterruptState;
+
+ FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspiBaseAddress));
+ if (FspHeader == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ FspSmmInitApi = (FSP_SMM_INIT)((UINTN)FspHeader->ImageBase + FspHeader->FspSmmInitEntryOffset);
+ InterruptState = SaveAndDisableInterrupts ();
+ if ((FspHeader->ImageAttribute & IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT) == FSP_IA32) {
+ Status = Execute32BitCode ((UINTN)FspSmmInitApi, (UINTN)FspiUpdDataPtr, (UINTN)NULL);
+ } else {
+ Status = Execute64BitCode ((UINTN)FspSmmInitApi, (UINTN)FspiUpdDataPtr, (UINTN)NULL);
+ }
+
+ SetInterruptState (InterruptState);
+
+ return Status;
+}
diff --git a/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/FspWrapperApiTestNull.c b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/FspWrapperApiTestNull.c
index 4ac5d3d738fa..beaf56bd0902 100644
--- a/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/FspWrapperApiTestNull.c
+++ b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/FspWrapperApiTestNull.c
@@ -57,3 +57,19 @@ TestFspSiliconInitApiOutput (
{
return RETURN_UNSUPPORTED;
}
+
+/**
+ Test the output of FSP API - FspSmmInit.
+
+ @param[in] FspiUpdDataPtr Address pointer to the Smm Init parameters structure.
+
+ @return test result on output of FspSmmInit API.
+**/
+EFI_STATUS
+EFIAPI
+TestFspSmmInitApiOutput (
+ IN VOID *FspiUpdDataPtr
+ )
+{
+ return RETURN_SUCCESS;
+}
diff --git a/IntelFsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c b/IntelFsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c
index 00b4799fb493..6e0e8942ef25 100644
--- a/IntelFsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c
+++ b/IntelFsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c
@@ -95,3 +95,17 @@ CallFspWrapperResetSystem (
CpuDeadLoop ();
}
+
+/**
+ This function overrides the default configurations in the FSP-I UPD data region.
+
+ @param[in,out] FspUpdRgnPtr A pointer to the UPD data region data structure.
+
+**/
+VOID
+EFIAPI
+UpdateFspiUpdData (
+ IN OUT VOID *FspUpdRgnPtr
+ )
+{
+}
diff --git a/IntelFsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/FspWrapperApiTest.c b/IntelFsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/FspWrapperApiTest.c
index 0b48677b77a1..24722ea2875f 100644
--- a/IntelFsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/FspWrapperApiTest.c
+++ b/IntelFsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/FspWrapperApiTest.c
@@ -83,3 +83,19 @@ TestFspSiliconInitApiOutput (
{
return RETURN_SUCCESS;
}
+
+/**
+ Test the output of FSP API - FspSmmInit.
+
+ @param[in] FspiUpdDataPtr Address pointer to the Smm Init parameters structure.
+
+ @return test result on output of FspSmmInit API.
+**/
+EFI_STATUS
+EFIAPI
+TestFspSmmInitApiOutput (
+ IN VOID *FspiUpdDataPtr
+ )
+{
+ return RETURN_SUCCESS;
+}
diff --git a/IntelFsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c b/IntelFsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c
index 84360ac6e3a9..c11df5894c02 100644
--- a/IntelFsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c
+++ b/IntelFsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c
@@ -400,3 +400,19 @@ PostFspsHobProcess (
return EFI_SUCCESS;
}
+
+/**
+ Post FSP-I HOB process.
+
+ @param[in] FspHobList Pointer to the HOB data structure produced by FSP.
+
+ @return If platform process the FSP hob list successfully.
+**/
+EFI_STATUS
+EFIAPI
+PostFspiHobProcess (
+ IN VOID *FspHobList
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/MmFoundationHob.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/MmFoundationHob.c
index b2611f2b4961..27103a456420 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/MmFoundationHob.c
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/MmFoundationHob.c
@@ -803,6 +803,49 @@ GetRemainingHobSize (
}
}
+/**
+ Check if FV HOB was created.
+
+ Check if FV HOB was created on HOB list,
+ if yes, skip building MM Core FV HOB,
+ if No, continue to build MM Core FV HOB
+
+ @param[in] HobList HOB list.
+ @param[in] HobSize HOB size.
+
+ @retval TRUE Skip building MM Core FV HOB.
+ FALSE Continue to build MM Core FV HOB.
+**/
+BOOLEAN
+IsFvHobExist (
+ IN UINT8 *HobList,
+ IN UINTN HobSize
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ UINTN HobLength;
+
+ if ((HobList == NULL) || (HobSize == 0)) {
+ return FALSE;
+ }
+
+ Hob.Raw = (UINT8 *)HobList;
+ HobLength = GET_HOB_LENGTH (Hob);
+ //
+ // Parse the HOB list until end of list or matching type is found.
+ //
+ while (HobLength <= HobSize) {
+ if (Hob.Header->HobType == EFI_HOB_TYPE_FV) {
+ return TRUE;
+ }
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ HobLength += GET_HOB_LENGTH (Hob);
+ }
+
+ return FALSE;
+}
+
/**
Create the MM foundation specific HOB list which StandaloneMm Core needed.
@@ -892,11 +935,16 @@ CreateMmFoundationHobList (
UsedSize += HobLength;
//
- // BFV address for StandaloneMm Core
+ // Skip to report FV that contains MmCore when Platform reports FV
//
- HobLength = GetRemainingHobSize (*FoundationHobSize, UsedSize);
- MmIplBuildFvHob (FoundationHobList + UsedSize, &HobLength, MmFvBase, MmFvSize);
- UsedSize += HobLength;
+ if (!IsFvHobExist (PlatformHobList, PlatformHobSize)) {
+ //
+ // BFV address for StandaloneMm Core
+ //
+ HobLength = GetRemainingHobSize (*FoundationHobSize, UsedSize);
+ MmIplBuildFvHob (FoundationHobList + UsedSize, &HobLength, MmFvBase, MmFvSize);
+ UsedSize += HobLength;
+ }
//
// Build MM ACPI S3 Enable HOB
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
index 1a01d7a465c5..d8112b0fef42 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
@@ -147,12 +147,47 @@ LocateMmCoreFv (
OUT VOID **MmCoreImageAddress
)
{
- EFI_STATUS Status;
- UINTN FvIndex;
- EFI_PEI_FV_HANDLE VolumeHandle;
- EFI_PEI_FILE_HANDLE FileHandle;
- EFI_PE32_SECTION *SectionData;
- EFI_FV_INFO VolumeInfo;
+ EFI_STATUS Status;
+ UINTN FvIndex;
+ EFI_PEI_FV_HANDLE VolumeHandle;
+ EFI_PEI_FILE_HANDLE FileHandle;
+ EFI_PE32_SECTION *SectionData;
+ EFI_FV_INFO VolumeInfo;
+ MM_CORE_FV_LOCATION_PPI *MmCoreFvLocation;
+
+ //
+ // The producer of the MmCoreFvLocation PPI is responsible for ensuring
+ // that it reports the correct Firmware Volume (FV) containing the MmCore.
+ // If the gMmCoreFvLocationPpiGuid is not found, the system will search
+ // all Firmware Volumes (FVs) to locate the FV that contains the MM Core.
+ //
+ Status = PeiServicesLocatePpi (&gMmCoreFvLocationPpiGuid, 0, NULL, (VOID **)&MmCoreFvLocation);
+ if (Status == EFI_SUCCESS) {
+ *MmFvBase = MmCoreFvLocation->Address;
+ *MmFvSize = MmCoreFvLocation->Size;
+ FileHandle = NULL;
+ Status = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_MM_CORE_STANDALONE, (VOID *)(UINTN)MmCoreFvLocation->Address, &FileHandle);
+ ASSERT_EFI_ERROR (Status);
+ if (Status == EFI_SUCCESS) {
+ ASSERT (FileHandle != NULL);
+ if (FileHandle != NULL) {
+ CopyGuid (MmCoreFileName, &((EFI_FFS_FILE_HEADER *)FileHandle)->Name);
+ //
+ // Search Section
+ //
+ Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, MmCoreImageAddress);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get MM Core section data.
+ //
+ SectionData = (EFI_PE32_SECTION *)((UINT8 *)*MmCoreImageAddress - sizeof (EFI_PE32_SECTION));
+ ASSERT (SectionData->Type == EFI_SECTION_PE32);
+ }
+ }
+
+ return EFI_SUCCESS;
+ }
//
// Search all FV
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
index 9301b8f3f5c4..e385c7768dd5 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include
#include
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
index dfc181218ed0..f07f26ee4144 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
@@ -61,6 +61,7 @@
gEfiPeiMmControlPpiGuid
gEfiPeiMmCommunicationPpiGuid
gEfiEndOfPeiSignalPpiGuid
+ gMmCoreFvLocationPpiGuid
[Protocols]
gEfiMmEndOfPeiProtocol
diff --git a/StandaloneMmPkg/Include/Ppi/MmCoreFvLocationPpi.h b/StandaloneMmPkg/Include/Ppi/MmCoreFvLocationPpi.h
new file mode 100644
index 000000000000..5769ac421211
--- /dev/null
+++ b/StandaloneMmPkg/Include/Ppi/MmCoreFvLocationPpi.h
@@ -0,0 +1,34 @@
+/** @file
+ MM Core FV location PPI header file.
+
+ MM Core FV location PPI is used by StandaloneMm IPL to find MM Core.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MM_CORE_FV_LOCATION_PPI_H_
+#define MM_CORE_FV_LOCATION_PPI_H_
+
+#pragma pack(1)
+
+///
+/// Global ID for the MM_CORE_FV_LOCATION_PPI.
+///
+#define MM_CORE_FV_LOCATION_GUID \
+ { \
+ 0x47a00618, 0x237a, 0x4386, { 0x8f, 0xc5, 0x2a, 0x86, 0xd8, 0xac, 0x41, 0x05 } \
+ }
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS Address;
+ UINT64 Size;
+} MM_CORE_FV_LOCATION_PPI;
+
+extern EFI_GUID gMmCoreFvLocationPpiGuid;
+
+#pragma pack()
+
+#endif
diff --git a/StandaloneMmPkg/StandaloneMmPkg.dec b/StandaloneMmPkg/StandaloneMmPkg.dec
index 5ac57c1013c5..dc2313ea1218 100644
--- a/StandaloneMmPkg/StandaloneMmPkg.dec
+++ b/StandaloneMmPkg/StandaloneMmPkg.dec
@@ -51,6 +51,9 @@
gEventMmDispatchGuid = { 0x7e6efffa, 0x69b4, 0x4c1b, { 0xa4, 0xc7, 0xaf, 0xf9, 0xc9, 0x24, 0x4f, 0xee }}
+[Ppis]
+ gMmCoreFvLocationPpiGuid = { 0x47a00618, 0x237a, 0x4386, { 0x8f, 0xc5, 0x2a, 0x86, 0xd8, 0xac, 0x41, 0x05 }}
+
[PcdsFixedAtBuild, PcdsPatchableInModule]
## Maximum permitted encapsulation levels of sections in a firmware volume,
# in the MM phase. Minimum value is 1. Sections nested more deeply are rejected.
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
index 4862cf075fed..f28da7e0fbc0 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
@@ -749,6 +749,7 @@ InitSmmProfileInternal (
UINTN MsrDsAreaSizePerCpu;
UINT64 SmmProfileSize;
+ Status = EFI_SUCCESS;
mPFEntryCount = (UINTN *)AllocateZeroPool (sizeof (UINTN) * mMaxNumberOfCpus);
ASSERT (mPFEntryCount != NULL);
mLastPFEntryValue = (UINT64 (*)[MAX_PF_ENTRY_COUNT])AllocateZeroPool (
@@ -840,12 +841,14 @@ InitSmmProfileInternal (
//
// Start SMM profile when SmmReadyToLock protocol is installed.
//
- Status = gMmst->MmRegisterProtocolNotify (
- &gEfiSmmReadyToLockProtocolGuid,
- InitSmmProfileCallBack,
- &Registration
- );
- ASSERT_EFI_ERROR (Status);
+ if (!mIsStandaloneMm) {
+ Status = gMmst->MmRegisterProtocolNotify (
+ &gEfiSmmReadyToLockProtocolGuid,
+ InitSmmProfileCallBack,
+ &Registration
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
return;
}