diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/MmFoundationHob.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/MmFoundationHob.c
new file mode 100644
index 0000000000..df3355f3fc
--- /dev/null
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/MmFoundationHob.c
@@ -0,0 +1,292 @@
+/** @file
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include
+
+/**
+ Add a new HOB to the HOB List.
+
+ @param[in] Hob The pointer of new HOB buffer.
+ @param[in] HobType Type of the new HOB.
+ @param[in] HobLength Length of the new HOB to allocate.
+
+ @return NULL if there is no space to create a hob.
+ @return The address point to the new created hob.
+
+**/
+VOID *
+MmIplCreateHob (
+ IN VOID *Hob,
+ IN UINT16 HobType,
+ IN UINT16 HobLength
+ )
+{
+ //
+ // Check Length to avoid data overflow.
+ //
+ ASSERT (HobLength < MAX_UINT16 - 0x7);
+
+ HobLength = (UINT16)ALIGN_VALUE (HobLength, 8);
+
+ ((EFI_HOB_GENERIC_HEADER *)Hob)->HobType = HobType;
+ ((EFI_HOB_GENERIC_HEADER *)Hob)->HobLength = HobLength;
+ ((EFI_HOB_GENERIC_HEADER *)Hob)->Reserved = 0;
+
+ return Hob;
+}
+
+/**
+ Builds a Firmware Volume HOB.
+
+ This function builds a Firmware Volume HOB.
+ It can only be invoked during PEI phase;
+ If new HOB buffer is NULL, then ASSERT().
+
+ @param[in] Hob The pointer of new HOB buffer.
+ @param[in, out] HobBufferSize The available size of the HOB buffer when as input.
+ The used size of when as output.
+ @param[in] BaseAddress The base address of the Firmware Volume.
+ @param[in] Length The size of the Firmware Volume in bytes.
+
+**/
+VOID
+MmIplBuildFvHob (
+ IN UINT8 *Hob,
+ IN OUT UINTN *HobBufferSize,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+{
+ EFI_HOB_FIRMWARE_VOLUME *FvHob;
+ UINT16 HobLength;
+
+ ASSERT (Hob != NULL);
+
+ HobLength = ALIGN_VALUE (sizeof (EFI_HOB_FIRMWARE_VOLUME), 8);
+ if (*HobBufferSize >= HobLength) {
+ MmIplCreateHob (Hob, EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME));
+
+ FvHob = (EFI_HOB_FIRMWARE_VOLUME *)Hob;
+ FvHob->BaseAddress = BaseAddress;
+ FvHob->Length = Length;
+ }
+
+ *HobBufferSize = HobLength;
+}
+
+/**
+ Copies a data buffer to a newly-built HOB for GUID HOB
+
+ This function builds a customized HOB tagged with a GUID for identification, copies the
+ input data to the HOB data field and returns the start address of the GUID HOB data.
+ If new HOB buffer is NULL or the GUID HOB could not found, then ASSERT().
+
+ @param[in] HobBuffer The pointer of HOB buffer.
+ @param[in, out] HobBufferSize The available size of the HOB buffer when as input.
+ The used size of when as output.
+ @param[in] Guid The GUID of the GUID type HOB.
+ @param[in] MultiInstances TRUE indicating copying multiple HOBs with the same Guid.
+**/
+VOID
+MmIplCopyGuidHob (
+ IN UINT8 *HobBuffer,
+ IN OUT UINTN *HobBufferSize,
+ IN EFI_GUID *Guid,
+ IN BOOLEAN MultiInstances
+ )
+{
+ EFI_HOB_GENERIC_HEADER *GuidHob;
+ UINTN UsedSize;
+
+ UsedSize = 0;
+ GuidHob = GetFirstGuidHob (Guid);
+ ASSERT (GuidHob != NULL);
+
+ while (GuidHob != NULL) {
+ if (*HobBufferSize >= UsedSize + GuidHob->HobLength) {
+ CopyMem (HobBuffer + UsedSize, GuidHob, GuidHob->HobLength);
+ }
+
+ UsedSize += GuidHob->HobLength;
+
+ if (!MultiInstances) {
+ break;
+ }
+
+ GuidHob = GetNextGuidHob (Guid, GET_NEXT_HOB (GuidHob));
+ }
+
+ *HobBufferSize = UsedSize;
+}
+
+/**
+ Builds a HOB for a loaded PE32 module.
+
+ This function builds a HOB for a loaded PE32 module.
+ It can only be invoked during PEI phase;
+ If physical address of the Module is not 4K aligned, then ASSERT().
+ If new HOB buffer is NULL, then ASSERT().
+
+ @param[in] Hob The pointer of new HOB buffer.
+ @param[in, out] HobBufferSize The available size of the HOB buffer when as input.
+ The used size of when as output.
+ @param[in] ModuleName The GUID File Name of the module.
+ @param[in] Base The 64 bit physical address of the module.
+ @param[in] Length The length of the module in bytes.
+ @param[in] EntryPoint The 64 bit physical address of the module entry point.
+
+**/
+VOID
+MmIplBuildMmCoreModuleHob (
+ IN UINT8 *Hob,
+ IN OUT UINTN *HobBufferSize,
+ IN CONST EFI_GUID *ModuleName,
+ IN EFI_PHYSICAL_ADDRESS Base,
+ IN UINT64 Length,
+ IN EFI_PHYSICAL_ADDRESS EntryPoint
+ )
+{
+ UINT16 HobLength;
+ EFI_HOB_MEMORY_ALLOCATION_MODULE *MmCoreModuleHob;
+
+ ASSERT (Hob != NULL);
+ ASSERT (ADDRESS_IS_ALIGNED (Base, EFI_PAGE_SIZE));
+ ASSERT (IS_ALIGNED (Length, EFI_PAGE_SIZE));
+ ASSERT (EntryPoint >= Base && EntryPoint < Base + Length);
+
+ HobLength = ALIGN_VALUE (sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE), 8);
+ if (*HobBufferSize >= HobLength) {
+ MmIplCreateHob (Hob, EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE));
+
+ MmCoreModuleHob = (EFI_HOB_MEMORY_ALLOCATION_MODULE *)Hob;
+ CopyGuid (&MmCoreModuleHob->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid);
+ MmCoreModuleHob->MemoryAllocationHeader.MemoryBaseAddress = Base;
+ MmCoreModuleHob->MemoryAllocationHeader.MemoryLength = Length;
+ MmCoreModuleHob->MemoryAllocationHeader.MemoryType = EfiReservedMemoryType;
+ ZeroMem (MmCoreModuleHob->MemoryAllocationHeader.Reserved, sizeof (MmCoreModuleHob->MemoryAllocationHeader.Reserved));
+
+ CopyGuid (&MmCoreModuleHob->ModuleName, ModuleName);
+ MmCoreModuleHob->EntryPoint = EntryPoint;
+ }
+
+ *HobBufferSize = HobLength;
+}
+
+/**
+ Get remaining size for building HOBs.
+
+ @param[in] TotalHobSize Total size of foundation HOBs.
+ @param[in] UsedSize Required HOBs' size.
+
+ @retval MAX remaining size for building HOBs
+**/
+UINTN
+GetRemainingHobSize (
+ IN UINTN TotalHobSize,
+ IN UINTN UsedSize
+ )
+{
+ if (TotalHobSize > UsedSize) {
+ return TotalHobSize - UsedSize;
+ } else {
+ return 0;
+ }
+}
+
+/**
+ Create the MM foundation specific HOB list which StandaloneMm Core needed.
+
+ This function build the MM foundation specific HOB list needed by StandaloneMm Core
+ based on the PEI HOB list.
+
+ @param[in] FoundationHobList The foundation HOB list to be used for HOB creation.
+ @param[in, out] FoundationHobSize The foundation HOB size.
+ On return, the expected/used size.
+ @param[in] PlatformHobList Platform HOB list.
+ @param[in] PlatformHobSize Platform HOB size.
+ @param[in] MmFvBase Base of firmare volume which included MM core dirver.
+ @param[in] MmFvSize Size of firmare volume which included MM core dirver.
+ @param[in] MmCoreFileName File name of MM core dirver.
+ @param[in] MmCoreImageAddress Image address of MM core dirver.
+ @param[in] MmCoreImageSize Image size of MM core dirver.
+ @param[in] MmCoreEntryPoint Entry pinter of MM core dirver.
+ @param[in] Block Pointer of MMRAM descriptor block.
+
+ @retval RETURN_BUFFER_TOO_SMALL The buffer is too small for HOB creation.
+ BufferSize is updated to indicate the expected buffer size.
+ When the input BufferSize is bigger than the expected buffer size,
+ the BufferSize value will be changed the used buffer size.
+ @retval RETURN_SUCCESS HOB List is created/updated successfully or the input Length is 0.
+
+**/
+RETURN_STATUS
+CreateMmFoundationHobList (
+ IN UINT8 *FoundationHobList,
+ IN OUT UINTN *FoundationHobSize,
+ IN UINT8 *PlatformHobList,
+ IN UINTN PlatformHobSize,
+ IN EFI_PHYSICAL_ADDRESS MmFvBase,
+ IN UINT64 MmFvSize,
+ IN EFI_GUID *MmCoreFileName,
+ IN EFI_PHYSICAL_ADDRESS MmCoreImageAddress,
+ IN UINT64 MmCoreImageSize,
+ IN EFI_PHYSICAL_ADDRESS MmCoreEntryPoint,
+ IN EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *Block
+ )
+{
+ UINTN UsedSize;
+ RETURN_STATUS Status;
+ UINTN HobLength;
+
+ ASSERT (FoundationHobSize != NULL);
+
+ ASSERT (
+ ((*FoundationHobSize != 0) && (FoundationHobList != NULL)) ||
+ ((*FoundationHobSize == 0) && (FoundationHobList == NULL))
+ );
+
+ UsedSize = 0;
+
+ //
+ // Build communication buffer HOB in MM HOB list
+ //
+ HobLength = *FoundationHobSize;
+ MmIplCopyGuidHob (FoundationHobList + UsedSize, &HobLength, &gMmCommBufferHobGuid, FALSE);
+ UsedSize += HobLength;
+
+ //
+ // Build MmCore module HOB in MM HOB list
+ //
+ HobLength = GetRemainingHobSize (*FoundationHobSize, UsedSize);
+ MmIplBuildMmCoreModuleHob (
+ FoundationHobList + UsedSize,
+ &HobLength,
+ MmCoreFileName,
+ MmCoreImageAddress,
+ MmCoreImageSize,
+ MmCoreEntryPoint
+ );
+
+ UsedSize += HobLength;
+
+ //
+ // BFV address for StandaloneMm Core
+ //
+ HobLength = GetRemainingHobSize (*FoundationHobSize, UsedSize);
+ MmIplBuildFvHob (FoundationHobList + UsedSize, &HobLength, MmFvBase, MmFvSize);
+ UsedSize += HobLength;
+
+ if (*FoundationHobSize < UsedSize) {
+ Status = RETURN_BUFFER_TOO_SMALL;
+ } else {
+ Status = RETURN_SUCCESS;
+ }
+
+ *FoundationHobSize = UsedSize;
+ return Status;
+}
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
index d6406784b7..89dd05c1b7 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
@@ -208,6 +208,132 @@ LocateMmCoreFv (
return EFI_NOT_FOUND;
}
+/**
+ Create HOB list for Standalone MM core.
+
+ @param[out] HobSize HOB size of fundation and platform HOB list.
+ @param[in] MmCommBuffer Pointer of MM communication buffer.
+ @param[in] MmFvBase Base of MM FV which included MM core driver.
+ @param[in] MmFvSize Size of MM FV which included MM core driver.
+ @param[in] MmCoreFileName File GUID of MM core driver.
+ @param[in] MmCoreImageAddress Address of MM core image.
+ @param[in] MmCoreImageSize Size of MM core image.
+ @param[in] MmCoreEntryPoint Entry point of MM core driver.
+ @param[in] Block Pointer of MMRAM descriptor block.
+
+ @retval HobList If fundation and platform HOBs not existed,
+ it is pointed to PEI HOB List. If existed,
+ it is pointed to fundation and platform HOB list.
+**/
+VOID *
+CreatMmHobList (
+ OUT UINTN *HobSize,
+ IN MM_COMM_BUFFER *MmCommBuffer,
+ IN EFI_PHYSICAL_ADDRESS MmFvBase,
+ IN UINT64 MmFvSize,
+ IN EFI_GUID *MmCoreFileName,
+ IN PHYSICAL_ADDRESS MmCoreImageAddress,
+ IN UINT64 MmCoreImageSize,
+ IN PHYSICAL_ADDRESS MmCoreEntryPoint,
+ IN EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *Block
+ )
+{
+ EFI_STATUS Status;
+ VOID *HobList;
+ VOID *PlatformHobList;
+ UINTN PlatformHobSize;
+ UINTN BufferSize;
+ UINTN FoundationHobSize;
+
+ //
+ // Get platform HOBs
+ //
+ PlatformHobSize = 0;
+ Status = CreateMmPlatformHob (NULL, &PlatformHobSize);
+ if (Status == RETURN_BUFFER_TOO_SMALL) {
+ ASSERT (PlatformHobSize != 0);
+ //
+ // Create platform HOBs for MM foundation to get MMIO HOB data.
+ //
+ PlatformHobList = AllocatePages (EFI_SIZE_TO_PAGES (PlatformHobSize));
+ ASSERT (PlatformHobList != NULL);
+ if (PlatformHobList == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Out of resource to create platform MM HOBs\n", __func__));
+ CpuDeadLoop ();
+ }
+
+ BufferSize = PlatformHobSize;
+ Status = CreateMmPlatformHob (PlatformHobList, &PlatformHobSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (BufferSize == PlatformHobSize);
+ }
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get size of foundation HOBs
+ //
+ FoundationHobSize = 0;
+ Status = CreateMmFoundationHobList (
+ NULL,
+ &FoundationHobSize,
+ PlatformHobList,
+ PlatformHobSize,
+ MmFvBase,
+ MmFvSize,
+ MmCoreFileName,
+ MmCoreImageAddress,
+ MmCoreImageSize,
+ MmCoreEntryPoint,
+ Block
+ );
+ FreePages (PlatformHobList, EFI_SIZE_TO_PAGES (PlatformHobSize));
+ ASSERT (Status == RETURN_BUFFER_TOO_SMALL);
+ ASSERT (FoundationHobSize != 0);
+
+ //
+ // Final result includes platform HOBs, foundation HOBs and a END node.
+ //
+ *HobSize = PlatformHobSize + FoundationHobSize + sizeof (EFI_HOB_GENERIC_HEADER);
+ HobList = AllocatePages (EFI_SIZE_TO_PAGES (*HobSize));
+ ASSERT (HobList != NULL);
+ if (HobList == NULL) {
+ DEBUG ((DEBUG_ERROR, "Out of resource to create MM HOBs\n"));
+ CpuDeadLoop ();
+ }
+
+ //
+ // Get platform HOBs
+ //
+ Status = CreateMmPlatformHob (HobList, &PlatformHobSize);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get foundation HOBs
+ //
+ Status = CreateMmFoundationHobList (
+ (UINT8 *)HobList + PlatformHobSize,
+ &FoundationHobSize,
+ HobList,
+ PlatformHobSize,
+ MmFvBase,
+ MmFvSize,
+ MmCoreFileName,
+ MmCoreImageAddress,
+ MmCoreImageSize,
+ MmCoreEntryPoint,
+ Block
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create MM HOB list end.
+ //
+ MmIplCreateHob ((UINT8 *)HobList + PlatformHobSize + FoundationHobSize, EFI_HOB_TYPE_END_OF_HOB_LIST, sizeof (EFI_HOB_GENERIC_HEADER));
+
+ return HobList;
+}
+
/**
Find largest unallocated MMRAM in current MMRAM descriptor block
@@ -360,6 +486,7 @@ ExecuteMmCoreFromMmram (
EFI_STATUS Status;
UINTN PageCount;
VOID *MmHobList;
+ UINTN MmHobSize;
EFI_GUID MmCoreFileName;
UINTN MmFvSize;
EFI_PHYSICAL_ADDRESS MmFvBase;
@@ -438,7 +565,18 @@ ExecuteMmCoreFromMmram (
//
// Get HOB list for Standalone MM Core.
//
- MmHobList = GetHobList ();
+ MmHobSize = 0;
+ MmHobList = CreatMmHobList (
+ &MmHobSize,
+ MmCommBuffer,
+ MmFvBase,
+ MmFvSize,
+ &MmCoreFileName,
+ ImageContext.ImageAddress,
+ ImageContext.ImageSize,
+ ImageContext.EntryPoint,
+ Block
+ );
//
// Print debug message showing Standalone MM Core entry point address.
@@ -451,6 +589,7 @@ ExecuteMmCoreFromMmram (
Entry = (STANDALONE_MM_FOUNDATION_ENTRY_POINT)(UINTN)ImageContext.EntryPoint;
Status = Entry (MmHobList);
ASSERT_EFI_ERROR (Status);
+ FreePages (MmHobList, EFI_SIZE_TO_PAGES (MmHobSize));
}
}
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
index e9be3f5568..d99a64ec08 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
/**
Communicates with a registered handler.
@@ -66,4 +67,63 @@ EndOfPeiCallback (
IN VOID *Ppi
);
+/**
+ Add a new HOB to the HOB List.
+
+ @param[in] Hob The pointer of new HOB buffer.
+ @param[in] HobType Type of the new HOB.
+ @param[in] HobLength Length of the new HOB to allocate.
+
+ @return NULL if there is no space to create a hob.
+ @return The address point to the new created hob.
+
+**/
+VOID *
+MmIplCreateHob (
+ IN VOID *Hob,
+ IN UINT16 HobType,
+ IN UINT16 HobLength
+ );
+
+/**
+ Create the MM foundation specific HOB list which StandaloneMm Core needed.
+
+ This function build the MM foundation specific HOB list needed by StandaloneMm Core
+ based on the PEI HOB list.
+
+ @param[in] FoundationHobList The foundation HOB list to be used for HOB creation.
+ @param[in, out] FoundationHobSize The foundation HOB size.
+ On return, the expected/used size.
+ @param[in] PlatformHobList Platform HOB list.
+ @param[in] PlatformHobSize Platform HOB size.
+ @param[in] MmFvBase Base of firmare volume which included MM core dirver.
+ @param[in] MmFvSize Size of firmare volume which included MM core dirver.
+ @param[in] MmCoreFileName File name of MM core dirver.
+ @param[in] MmCoreImageAddress Image address of MM core dirver.
+ @param[in] MmCoreImageSize Image size of MM core dirver.
+ @param[in] MmCoreEntryPoint Entry pinter of MM core dirver.
+ @param[in] Block Pointer of MMRAM descriptor block.
+
+ @retval RETURN_BUFFER_TOO_SMALL The buffer is too small for HOB creation.
+ BufferSize is updated to indicate the expected buffer size.
+ When the input BufferSize is bigger than the expected buffer size,
+ the BufferSize value will be changed the used buffer size.
+ @retval RETURN_SUCCESS HOB List is created/updated successfully or the input Length is 0.
+
+**/
+RETURN_STATUS
+CreateMmFoundationHobList (
+ IN UINT8 *FoundationHobList,
+ IN OUT UINTN *FoundationHobSize,
+ IN UINT8 *PlatformHobList,
+ IN UINTN PlatformHobSize,
+ IN EFI_PHYSICAL_ADDRESS MmFvBase,
+ IN UINT64 MmFvSize,
+ IN EFI_GUID *MmCoreFileName,
+ IN EFI_PHYSICAL_ADDRESS MmCoreImageAddress,
+ IN UINT64 MmCoreImageSize,
+ IN EFI_PHYSICAL_ADDRESS MmCoreEntryPoint,
+ IN EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *Block
+ );
+
#endif
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
index a873efb0df..94abe6eee7 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
@@ -25,6 +25,7 @@
[Sources]
StandaloneMmIplPei.c
StandaloneMmIplPei.h
+ MmFoundationHob.c
[Packages]
MdePkg/MdePkg.dec
@@ -41,6 +42,7 @@
BaseMemoryLib
PeCoffLib
CacheMaintenanceLib
+ MmPlatformHobProducerLib
[Guids]
gMmCommBufferHobGuid