* [PATCH v4 2/5] StandaloneMmPkg: Add StandaloneMmIplPei driver.
2023-06-19 7:46 [PATCH v4 1/5] StandaloneMmPkg: Add StandaloneMmIplPei driver Zhang, Hongbin1
@ 2023-06-19 7:46 ` Zhang, Hongbin1
2023-06-19 7:46 ` [PATCH v4 3/5] " Zhang, Hongbin1
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Zhang, Hongbin1 @ 2023-06-19 7:46 UTC (permalink / raw)
To: devel
Cc: Zhang, Hongbin1, Jiewen Yao, Ray Ni, Star Zeng, Jiaxin Wu,
Sami Mujawar, Ard Biesheuvel, Supreeth Venkatesh
Add StandaloneMmIplPei IA32/X64 driver at PEI stage.
FSP will use this driver to load Standalone MM code
to dispatch other Standalone MM drivers.
Signed-off-by: Hongbin1 Zhang <hongbin1.zhang@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Supreeth Venkatesh <supreeth.venkatesh@arm.com>
---
StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c | 343 ++++++++++++++++++++
StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf | 2 +
2 files changed, 345 insertions(+)
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
index 16e7d59d0e..e043fcdb65 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
@@ -7,9 +7,13 @@
**/
#include <PiPei.h>
+#include <PiSmm.h>
+#include <StandaloneMm.h>
#include <Ppi/SmmAccess.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/CacheMaintenanceLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/PeiServicesTablePointerLib.h>
@@ -95,6 +99,329 @@ GetSmramCacheRange (
} while (FoundAdjacentRange);
}
+/**
+ Load SMM core to dispatch other Standalone MM drivers.
+
+ @param Entry Entry of Standalone MM Foundation.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function.
+ @retval EFI_SUCCESS Successfully loaded SMM core.
+ @retval Others Failed to load SMM core.
+**/
+EFI_STATUS
+LoadSmmCore (
+ IN EFI_PHYSICAL_ADDRESS Entry,
+ IN VOID *Context1
+ )
+{
+ STANDALONE_MM_FOUNDATION_ENTRY_POINT EntryPoint;
+
+ EntryPoint = (STANDALONE_MM_FOUNDATION_ENTRY_POINT)(UINTN)Entry;
+ return EntryPoint (Context1);
+}
+
+/**
+ Get the fixed loading address from image header assigned by build tool. This function only be called
+ when Loading module at Fixed address feature enabled.
+
+ @param ImageContext Pointer to the image context structure that describes the PE/COFF
+ image that needs to be examined by this function.
+ @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
+ @retval EFI_NOT_FOUND The image has no assigned fixed loading address.
+**/
+EFI_STATUS
+GetPeCoffImageFixLoadingAssignedAddress (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+{
+ UINTN SectionHeaderOffset;
+ EFI_STATUS Status;
+ EFI_IMAGE_SECTION_HEADER SectionHeader;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
+ EFI_PHYSICAL_ADDRESS FixLoadingAddress;
+ UINT16 Index;
+ UINTN Size;
+ UINT16 NumberOfSections;
+ EFI_PHYSICAL_ADDRESS SmramBase;
+ UINT64 ValueInSectionHeader;
+
+ FixLoadingAddress = 0;
+ Status = EFI_NOT_FOUND;
+ SmramBase = mCurrentSmramRange->CpuStart;
+ //
+ // Get PeHeader pointer
+ //
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8 *)ImageContext->Handle + ImageContext->PeCoffHeaderOffset);
+ SectionHeaderOffset = (UINTN)(
+ ImageContext->PeCoffHeaderOffset +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
+ );
+ NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
+
+ //
+ // Get base address from the first section header that doesn't point to code section.
+ //
+ for (Index = 0; Index < NumberOfSections; Index++) {
+ //
+ // Read section header from file
+ //
+ Size = sizeof (EFI_IMAGE_SECTION_HEADER);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ SectionHeaderOffset,
+ &Size,
+ &SectionHeader
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = EFI_NOT_FOUND;
+
+ if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
+ //
+ // Build tool saves the offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields in the
+ // first section header that doesn't point to code section in image header. And there is an assumption that when the
+ // feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers
+ // fields should NOT be Zero, or else, these 2 fields should be set to Zero
+ //
+ ValueInSectionHeader = ReadUnaligned64 ((UINT64 *)&SectionHeader.PointerToRelocations);
+ if (ValueInSectionHeader != 0) {
+ //
+ // Found first section header that doesn't point to code section in which build tool saves the
+ // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields
+ //
+ FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(SmramBase + (INT64)ValueInSectionHeader);
+
+ if ((SmramBase > FixLoadingAddress) && (SmramBase <= FixLoadingAddress)) {
+ //
+ // The assigned address is valid. Return the specified loading address
+ //
+ ImageContext->ImageAddress = FixLoadingAddress;
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ break;
+ }
+
+ SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
+ }
+
+ DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r \n", FixLoadingAddress, Status));
+ return Status;
+}
+
+/**
+ Search all the available firmware volumes for SMM Core driver
+
+ @param MmFvBaseAddress Base address of FV which included SMM Core driver.
+ @param MmCoreImageAddress Image address of SMM Core driver.
+
+ @retval EFI_SUCCESS The specified FFS section was returned.
+ @retval EFI_NOT_FOUND The specified FFS section could not be found.
+
+**/
+EFI_STATUS
+LocateMmFvForMmCore (
+ OUT EFI_PHYSICAL_ADDRESS *MmFvBaseAddress,
+ 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;
+
+ //
+ // Search all FV
+ //
+ VolumeHandle = NULL;
+ for (FvIndex = 0; ; FvIndex++) {
+ Status = PeiServicesFfsFindNextVolume (FvIndex, &VolumeHandle);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ //
+ // Search PEIM FFS
+ //
+ FileHandle = NULL;
+ Status = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_MM_CORE_STANDALONE, VolumeHandle, &FileHandle);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Search Section
+ //
+ Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, MmCoreImageAddress);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Great!
+ //
+ SectionData = (EFI_PE32_SECTION *)((UINT8 *)*MmCoreImageAddress - sizeof (EFI_PE32_SECTION));
+ ASSERT (SectionData->Type == EFI_SECTION_PE32);
+
+ //
+ // This is SMM BFV
+ //
+ Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
+ if (!EFI_ERROR (Status)) {
+ *MmFvBaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)VolumeInfo.FvStart;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Load the SMM Core image into SMRAM and executes the SMM Core from SMRAM.
+
+ @param[in, out] SmramRange Descriptor for the range of SMRAM to reload the
+ currently executing image, the rang of SMRAM to
+ hold SMM Core will be excluded.
+ @param[in, out] SmramRangeSmmCore Descriptor for the range of SMRAM to hold SMM Core.
+
+ @param[in] Context Context to pass into SMM Core
+
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+ExecuteSmmCoreFromSmram (
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramRange,
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramRangeSmmCore,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *SourceBuffer;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ UINTN PageCount;
+ VOID *HobList;
+ EFI_PHYSICAL_ADDRESS SourceFvBaseAddress;
+
+ Status = PeiServicesGetHobList (&HobList);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Search all Firmware Volumes for a PE/COFF image in a file of type SMM_CORE
+ //
+ Status = LocateMmFvForMmCore (&SourceFvBaseAddress, &SourceBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gMmCorePrivate->StandaloneBfvAddress = SourceFvBaseAddress;
+
+ //
+ // Initialize ImageContext
+ //
+ ImageContext.Handle = SourceBuffer;
+ ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
+
+ //
+ // Get information about the image being loaded
+ //
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR
+ // specified by SmramRange
+ //
+ PageCount = (UINTN)EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);
+
+ ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) == 0);
+ ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));
+
+ SmramRange->PhysicalSize -= EFI_PAGES_TO_SIZE (PageCount);
+ SmramRangeSmmCore->CpuStart = SmramRange->CpuStart + SmramRange->PhysicalSize;
+ SmramRangeSmmCore->PhysicalStart = SmramRange->PhysicalStart + SmramRange->PhysicalSize;
+ SmramRangeSmmCore->RegionState = SmramRange->RegionState | EFI_ALLOCATED;
+ SmramRangeSmmCore->PhysicalSize = EFI_PAGES_TO_SIZE (PageCount);
+
+ //
+ // Align buffer on section boundary
+ //
+ ImageContext.ImageAddress = SmramRangeSmmCore->CpuStart;
+
+ ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
+ ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
+
+ //
+ // Print debug message showing SMM Core load address.
+ //
+ DEBUG ((DEBUG_INFO, "SMM IPL loading SMM Core at SMRAM address %p\n", (VOID *)(UINTN)ImageContext.ImageAddress));
+
+ //
+ // Load the image to our new buffer
+ //
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Relocate the image in our new buffer
+ //
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Flush the instruction cache so the image data are written before we execute it
+ //
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+
+ //
+ // Print debug message showing SMM Core entry point address.
+ //
+ DEBUG ((DEBUG_INFO, "SMM IPL calling SMM Core at SMRAM address %p\n", (VOID *)(UINTN)ImageContext.EntryPoint));
+
+ gMmCorePrivate->MmCoreImageBase = ImageContext.ImageAddress;
+ gMmCorePrivate->MmCoreImageSize = ImageContext.ImageSize;
+ DEBUG ((DEBUG_INFO, "SmmCoreImageBase - 0x%016lx\n", gMmCorePrivate->MmCoreImageBase));
+ DEBUG ((DEBUG_INFO, "SmmCoreImageSize - 0x%016lx\n", gMmCorePrivate->MmCoreImageSize));
+
+ gMmCorePrivate->MmCoreEntryPoint = ImageContext.EntryPoint;
+
+ //
+ // Print debug message showing Standalone MM Core entry point address.
+ //
+ DEBUG ((DEBUG_INFO, "SMM IPL calling Standalone MM Core at SMRAM address - 0x%016lx\n", gMmCorePrivate->MmCoreEntryPoint));
+
+ //
+ // Execute image
+ //
+ LoadSmmCore (ImageContext.EntryPoint, HobList);
+ }
+ }
+
+ //
+ // If the load operation, relocate operation, or the image execution return an
+ // error, then free memory allocated from the EFI_SRAM_DESCRIPTOR specified by
+ // SmramRange
+ //
+ if (EFI_ERROR (Status)) {
+ SmramRange->PhysicalSize += EFI_PAGES_TO_SIZE (PageCount);
+ }
+
+ //
+ // Always free memory allocated by GetFileBufferByFilePath ()
+ //
+ FreePool (SourceBuffer);
+
+ return Status;
+}
+
/**
Get full SMRAM ranges.
@@ -255,6 +582,22 @@ StandaloneMmIplPeiEntry (
));
GetSmramCacheRange (mCurrentSmramRange, &mSmramCacheBase, &mSmramCacheSize);
+
+ //
+ // Load SMM Core into SMRAM and execute it from SMRAM
+ // Note: SmramRanges specific for SMM Core will put in the gMmCorePrivate->MmramRangeCount - 1.
+ //
+ Status = ExecuteSmmCoreFromSmram (
+ mCurrentSmramRange,
+ &(((EFI_MMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate->MmramRanges)[gMmCorePrivate->MmramRangeCount - 1]),
+ gMmCorePrivate
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Print error message that the SMM Core failed to be loaded and executed.
+ //
+ DEBUG ((DEBUG_ERROR, "SMM IPL could not load and execute SMM Core from SMRAM\n"));
+ }
} else {
//
// Print error message that there are not enough SMRAM resources to load the SMM Core.
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
index 372c59c1fa..668d3afbf4 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
@@ -36,6 +36,8 @@
PeiServicesLib
BaseLib
BaseMemoryLib
+ PeCoffLib
+ CacheMaintenanceLib
MemoryAllocationLib
DebugLib
HobLib
--
2.37.0.windows.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 3/5] StandaloneMmPkg: Add StandaloneMmIplPei driver.
2023-06-19 7:46 [PATCH v4 1/5] StandaloneMmPkg: Add StandaloneMmIplPei driver Zhang, Hongbin1
2023-06-19 7:46 ` [PATCH v4 2/5] " Zhang, Hongbin1
@ 2023-06-19 7:46 ` Zhang, Hongbin1
2023-06-19 7:46 ` [PATCH v4 4/5] " Zhang, Hongbin1
2023-06-19 7:46 ` [PATCH v4 5/5] " Zhang, Hongbin1
3 siblings, 0 replies; 5+ messages in thread
From: Zhang, Hongbin1 @ 2023-06-19 7:46 UTC (permalink / raw)
To: devel
Cc: Zhang, Hongbin1, Jiewen Yao, Ray Ni, Star Zeng, Jiaxin Wu,
Sami Mujawar, Ard Biesheuvel, Supreeth Venkatesh
Add StandaloneMmIplPei IA32/X64 driver at PEI stage.
FSP will use this driver to load Standalone MM code
to dispatch other Standalone MM drivers.
Signed-off-by: Hongbin1 Zhang <hongbin1.zhang@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Supreeth Venkatesh <supreeth.venkatesh@arm.com>
---
StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/LoadSmmCore.c | 456 ++++++++++++++++++++
StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c | 18 +-
StandaloneMmPkg/Drivers/StandaloneMmIplPei/X64/LoadSmmCore.c | 29 ++
StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm | 148 +++++++
StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h | 47 ++
StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf | 11 +
StandaloneMmPkg/StandaloneMmPkg.ci.yaml | 4 +-
7 files changed, 709 insertions(+), 4 deletions(-)
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/LoadSmmCore.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/LoadSmmCore.c
new file mode 100644
index 0000000000..2d43807a88
--- /dev/null
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/LoadSmmCore.c
@@ -0,0 +1,456 @@
+/** @file
+ SMM IPL that load the SMM Core into SMRAM
+
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <PiSmm.h>
+#include <StandaloneMm.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <StandaloneMmIplPei.h>
+
+#pragma pack(1)
+
+//
+// Page-Map Level-4 Offset (PML4) and
+// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
+//
+
+typedef union {
+ struct {
+ UINT64 Present : 1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite : 1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor : 1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough : 1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled : 1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed : 1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Reserved : 1; // Reserved
+ UINT64 MustBeZero : 2; // Must Be Zero
+ UINT64 Available : 3; // Available for use by system software
+ UINT64 PageTableBaseAddress : 40; // Page Table Base Address
+ UINT64 AvailableHigh : 11; // Available for use by system software
+ UINT64 Nx : 1; // No Execute bit
+ } Bits;
+ UINT64 Uint64;
+} PAGE_MAP_AND_DIRECTORY_POINTER;
+
+//
+// Page Table Entry 2MB
+//
+typedef union {
+ struct {
+ UINT64 Present : 1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite : 1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor : 1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough : 1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled : 1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed : 1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty : 1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 MustBe1 : 1; // Must be 1
+ UINT64 Global : 1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available : 3; // Available for use by system software
+ UINT64 Pat : 1; //
+ UINT64 MustBeZero : 8; // Must be zero
+ UINT64 PageTableBaseAddress : 31; // Page Table Base Address
+ UINT64 AvailableHigh : 11; // Available for use by system software
+ UINT64 Nx : 1; // 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_ENTRY;
+
+//
+// Page Table Entry 1GB
+//
+typedef union {
+ struct {
+ UINT64 Present : 1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite : 1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor : 1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough : 1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled : 1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed : 1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty : 1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 MustBe1 : 1; // Must be 1
+ UINT64 Global : 1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available : 3; // Available for use by system software
+ UINT64 Pat : 1; //
+ UINT64 MustBeZero : 17; // Must be zero;
+ UINT64 PageTableBaseAddress : 22; // Page Table Base Address
+ UINT64 AvailableHigh : 11; // Available for use by system software
+ UINT64 Nx : 1; // 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_1G_ENTRY;
+
+#pragma pack()
+
+//
+// Global Descriptor Table (GDT)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED IA32_SEGMENT_DESCRIPTOR mGdtEntries[] = {
+ /* selector { Global Segment Descriptor } */
+ /* 0x00 */ {
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+ }, // null descriptor
+ /* 0x08 */ {
+ { 0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }
+ }, // linear data segment descriptor
+ /* 0x10 */ {
+ { 0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }
+ }, // linear code segment descriptor
+ /* 0x18 */ {
+ { 0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }
+ }, // system data segment descriptor
+ /* 0x20 */ {
+ { 0xffff, 0, 0, 0xb, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }
+ }, // system code segment descriptor
+ /* 0x28 */ {
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+ }, // spare segment descriptor
+ /* 0x30 */ {
+ { 0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }
+ }, // system data segment descriptor
+ /* 0x38 */ {
+ { 0xffff, 0, 0, 0xb, 1, 0, 1, 0xf, 0, 1, 0, 1, 0 }
+ }, // system code segment descriptor
+ /* 0x40 */ {
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+ }, // spare segment descriptor
+};
+
+//
+// IA32 Gdt register
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR mGdt = {
+ sizeof (mGdtEntries) - 1,
+ (UINTN)mGdtEntries
+};
+
+/**
+ Calculate the total size of page table.
+
+ @return The size of page table.
+
+**/
+UINTN
+CalculatePageTableSize (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ UINT32 RegEdx;
+ UINTN TotalPagesNum;
+ UINT8 PhysicalAddressBits;
+ VOID *Hob;
+ UINT32 NumberOfPml4EntriesNeeded;
+ UINT32 NumberOfPdpEntriesNeeded;
+ BOOLEAN Page1GSupport;
+
+ Page1GSupport = FALSE;
+ if (PcdGetBool (PcdUse1GPageTable)) {
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000001) {
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT26) != 0) {
+ Page1GSupport = TRUE;
+ }
+ }
+ }
+
+ //
+ // Get physical address bits supported.
+ //
+ Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
+ if (Hob != NULL) {
+ PhysicalAddressBits = ((EFI_HOB_CPU *)Hob)->SizeOfMemorySpace;
+ } else {
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+ PhysicalAddressBits = (UINT8)RegEax;
+ } else {
+ PhysicalAddressBits = 36;
+ }
+ }
+
+ //
+ // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
+ //
+ ASSERT (PhysicalAddressBits <= 52);
+ if (PhysicalAddressBits > 48) {
+ PhysicalAddressBits = 48;
+ }
+
+ //
+ // Calculate the table entries needed.
+ //
+ if (PhysicalAddressBits <= 39 ) {
+ NumberOfPml4EntriesNeeded = 1;
+ NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));
+ } else {
+ NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));
+ NumberOfPdpEntriesNeeded = 512;
+ }
+
+ if (!Page1GSupport) {
+ TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1;
+ } else {
+ TotalPagesNum = NumberOfPml4EntriesNeeded + 1;
+ }
+
+ return EFI_PAGES_TO_SIZE (TotalPagesNum);
+}
+
+/**
+ Allocates and fills in the Page Directory and Page Table Entries to
+ establish a 1:1 Virtual to Physical mapping.
+
+ @param[in] PageTablesAddress The base address of page table.
+
+**/
+VOID
+CreateIdentityMappingPageTables (
+ IN EFI_PHYSICAL_ADDRESS PageTablesAddress
+ )
+{
+ UINT32 RegEax;
+ UINT32 RegEdx;
+ UINT8 PhysicalAddressBits;
+ EFI_PHYSICAL_ADDRESS PageAddress;
+ UINTN IndexOfPml4Entries;
+ UINTN IndexOfPdpEntries;
+ UINTN IndexOfPageDirectoryEntries;
+ UINT32 NumberOfPml4EntriesNeeded;
+ UINT32 NumberOfPdpEntriesNeeded;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
+ PAGE_TABLE_ENTRY *PageDirectoryEntry;
+ UINTN BigPageAddress;
+ VOID *Hob;
+ BOOLEAN Page1GSupport;
+ PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
+
+ Page1GSupport = FALSE;
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000001) {
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT26) != 0) {
+ Page1GSupport = TRUE;
+ }
+ }
+
+ //
+ // Get physical address bits supported.
+ //
+ Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
+ if (Hob != NULL) {
+ PhysicalAddressBits = ((EFI_HOB_CPU *)Hob)->SizeOfMemorySpace;
+ } else {
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+ PhysicalAddressBits = (UINT8)RegEax;
+ } else {
+ PhysicalAddressBits = 36;
+ }
+ }
+
+ //
+ // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
+ //
+ ASSERT (PhysicalAddressBits <= 52);
+ if (PhysicalAddressBits > 48) {
+ PhysicalAddressBits = 48;
+ }
+
+ //
+ // Calculate the table entries needed.
+ //
+ if (PhysicalAddressBits <= 39 ) {
+ NumberOfPml4EntriesNeeded = 1;
+ NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));
+ } else {
+ NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));
+ NumberOfPdpEntriesNeeded = 512;
+ }
+
+ //
+ // Pre-allocate big pages to avoid later allocations.
+ //
+ BigPageAddress = (UINTN)PageTablesAddress;
+
+ //
+ // By architecture only one PageMapLevel4 exists - so lets allocate storage for it.
+ //
+ PageMap = (VOID *)BigPageAddress;
+ BigPageAddress += SIZE_4KB;
+
+ PageMapLevel4Entry = PageMap;
+ PageAddress = 0;
+ for (IndexOfPml4Entries = 0; IndexOfPml4Entries < NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, PageMapLevel4Entry++) {
+ //
+ // Each PML4 entry points to a page of Page Directory Pointer entires.
+ // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.
+ //
+ PageDirectoryPointerEntry = (VOID *)BigPageAddress;
+ BigPageAddress += SIZE_4KB;
+
+ //
+ // Make a PML4 Entry
+ //
+ PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;
+ PageMapLevel4Entry->Bits.ReadWrite = 1;
+ PageMapLevel4Entry->Bits.Present = 1;
+
+ if (Page1GSupport) {
+ PageDirectory1GEntry = (VOID *)PageDirectoryPointerEntry;
+
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
+ //
+ // Fill in the Page Directory entries
+ //
+ PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;
+ PageDirectory1GEntry->Bits.ReadWrite = 1;
+ PageDirectory1GEntry->Bits.Present = 1;
+ PageDirectory1GEntry->Bits.MustBe1 = 1;
+ }
+ } else {
+ for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
+ //
+ // Each Directory Pointer entries points to a page of Page Directory entires.
+ // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.
+ //
+ PageDirectoryEntry = (VOID *)BigPageAddress;
+ BigPageAddress += SIZE_4KB;
+
+ //
+ // Fill in a Page Directory Pointer Entries
+ //
+ PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;
+ PageDirectoryPointerEntry->Bits.ReadWrite = 1;
+ PageDirectoryPointerEntry->Bits.Present = 1;
+
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {
+ //
+ // Fill in the Page Directory entries
+ //
+ PageDirectoryEntry->Uint64 = (UINT64)PageAddress;
+ PageDirectoryEntry->Bits.ReadWrite = 1;
+ PageDirectoryEntry->Bits.Present = 1;
+ PageDirectoryEntry->Bits.MustBe1 = 1;
+ }
+ }
+
+ for ( ; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
+ ZeroMem (
+ PageDirectoryPointerEntry,
+ sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
+ );
+ }
+ }
+ }
+
+ //
+ // For the PML4 entries we are not using fill in a null entry.
+ //
+ for ( ; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) {
+ ZeroMem (
+ PageMapLevel4Entry,
+ sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
+ );
+ }
+}
+
+/**
+ If in 32 bit protection mode, and coalesce image is of X64, switch to long mode.
+
+ @param Entry Entry of Standalone MM Foundation.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function.
+ @param Context2 A pointer to the context to pass into the EntryPoint
+ function.
+ @retval EFI_SUCCESS Successfully switched to long mode and execute coalesce.
+ @retval Others Failed to execute coalesce in long mode.
+
+**/
+EFI_STATUS
+ModeSwitch (
+ IN EFI_PHYSICAL_ADDRESS Entry,
+ IN VOID *Context1,
+ IN VOID *Context2
+ )
+{
+ UINTN PageTableAddress;
+ UINTN PageTableSize;
+ EFI_STATUS Status;
+ IA32_DESCRIPTOR Gdtr;
+
+ DEBUG ((DEBUG_INFO, "ModeSwitch\n"));
+
+ //
+ // Save IA32 GDTR
+ //
+ AsmReadGdtr (&Gdtr);
+
+ //
+ // Set X64 GDTR
+ //
+ AsmWriteGdtr (&mGdt);
+
+ PageTableAddress = AsmReadCr3 () & 0xFFFFF000;
+
+ //
+ // If page table was created, no need to create
+ //
+ if (PageTableAddress == 0) {
+ PageTableSize = CalculatePageTableSize ();
+
+ PageTableAddress = (UINTN)AllocatePages (EFI_SIZE_TO_PAGES (PageTableSize));
+ ASSERT (PageTableAddress != 0);
+
+ CreateIdentityMappingPageTables (PageTableAddress);
+
+ AsmWriteCr3 ((UINTN)PageTableAddress);
+ }
+
+ DEBUG ((DEBUG_INFO, "AsmExecute64BitCode ...\n"));
+
+ Status = AsmExecute64BitCode (Entry, (UINT64)(UINTN)Context1, (UINT64)(UINTN)Context2, NULL);
+ if (Status != 0) {
+ Status = Status | MAX_BIT;
+ }
+
+ DEBUG ((DEBUG_INFO, "AsmExecute64BitCode - %r\n", Status));
+
+ //
+ // Restore IA32 GDTR
+ //
+ AsmWriteGdtr (&Gdtr);
+
+ return Status;
+}
+
+/**
+ Load SMM core to dispatch other Standalone MM drivers after IA32 mode to X64 mode.
+
+ @param Entry Entry of Standalone MM Foundation.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function.
+ @retval EFI_SUCCESS Successfully loaded SMM core.
+ @retval Others Failed to load SMM core.
+**/
+EFI_STATUS
+LoadSmmCoreIA32ToX64 (
+ IN EFI_PHYSICAL_ADDRESS Entry,
+ IN VOID *Context1
+ )
+{
+ return ModeSwitch (Entry, Context1, NULL);
+}
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
index e043fcdb65..47cc18ecbd 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
@@ -20,6 +20,7 @@
#include <Library/PeiServicesLib.h>
#include <Library/HobLib.h>
#include <Guid/MmCoreData.h>
+#include <StandaloneMmIplPei.h>
//
// MM Core Private Data structure that contains the data shared between
@@ -43,7 +44,7 @@ MM_CORE_PRIVATE_DATA mMmCorePrivateData = {
};
//
-// Global pointer used to access mMmCorePrivateData from outside and inside SMM
+// Global pointer used to access mMmCorePrivateData from outside and inside SMM.
//
MM_CORE_PRIVATE_DATA *gMmCorePrivate;
@@ -399,9 +400,20 @@ ExecuteSmmCoreFromSmram (
DEBUG ((DEBUG_INFO, "SMM IPL calling Standalone MM Core at SMRAM address - 0x%016lx\n", gMmCorePrivate->MmCoreEntryPoint));
//
- // Execute image
+ // If StandaloneMmIpl driver is IA32 image, but Standalone MM core is X64 image
+ // Switch 32 bit protect mode to X64 mode and load SMM core
//
- LoadSmmCore (ImageContext.EntryPoint, HobList);
+ if ((sizeof (UINTN) == sizeof (UINT32)) && (ImageContext.Machine == EFI_IMAGE_MACHINE_X64)) {
+ //
+ // Switch to X64 mode and load SMM core
+ //
+ LoadSmmCoreIA32ToX64 (ImageContext.EntryPoint, HobList);
+ } else {
+ //
+ // Execute image
+ //
+ LoadSmmCore (ImageContext.EntryPoint, HobList);
+ }
}
}
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/X64/LoadSmmCore.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/X64/LoadSmmCore.c
new file mode 100644
index 0000000000..9cd0636c4b
--- /dev/null
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/X64/LoadSmmCore.c
@@ -0,0 +1,29 @@
+/** @file
+ SMM IPL that load the SMM Core into SMRAM
+
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <PiSmm.h>
+#include <StandaloneMm.h>
+
+/**
+ Load SMM core to dispatch other Standalone MM drivers after IA32 mode to X64 mode.
+
+ @param Entry Entry of Standalone MM Foundation.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function.
+ @retval EFI_SUCCESS Successfully loaded SMM core.
+ @retval Others Failed to load SMM core.
+**/
+EFI_STATUS
+LoadSmmCoreIA32ToX64 (
+ IN EFI_PHYSICAL_ADDRESS Entry,
+ IN VOID *Context1
+ )
+{
+ return EFI_SUCCESS;
+}
\ No newline at end of file
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm
new file mode 100644
index 0000000000..7f887eb77d
--- /dev/null
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm
@@ -0,0 +1,148 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; Thunk32To64.nasm
+;
+; Abstract:
+;
+; This is the assembly code to transition from long mode to compatibility
+; mode to execute 32-bit code and then transit back to long mode.
+;
+;------------------------------------------------------------------------------
+
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; Procedure: AsmExecute64BitCode
+;
+; Input: None
+;
+; Output: None
+;
+; Prototype: UINT32
+; AsmExecute64BitCode (
+; IN UINT64 Function,
+; IN UINT64 Param1,
+; IN UINT64 Param2,
+; IN IA32_DESCRIPTOR *InternalGdtr
+; );
+;
+;
+; Description: A thunk function to execute 32-bit code in long mode.
+;
+;------------------------------------------------------------------------------
+global ASM_PFX(AsmExecute64BitCode)
+ASM_PFX(AsmExecute64BitCode):
+;
+; +---------+
+; | EIP(64) |
+; +---------+
+; | CS (64) |
+; +---------+
+; | EIP(32) |
+; +---------+
+; | CS (32) |<-ESP (16 bytes aligned)
+; +---------+
+; | ... |
+; +---------+
+; | ebx |<-EBP
+; +---------+
+; | ebp |<-EBP + 4
+; +---------+
+; | esi |<-EBP + 8
+; +---------+
+; | edi |<-EBP + 12
+; +---------+
+; | RFlags |<-EBP + 16
+; +---------+
+; | RetAddr |<-EBP (org)
+; +---------+
+; | Func |<-EBP + 24
+; | Func |
+; +---------+
+; | Param1 |<-EBP + 32
+; | Param1 |
+; +---------+
+; | Param2 |<-EBP + 40
+; | Param2 |
+; +---------+
+; | Gdtr |
+; +---------+
+;
+ ;
+ ; Save general purpose register and RFlags register
+ ;
+ pushfd
+ push edi
+ push esi
+ push ebp
+ push ebx
+ mov ebp, esp
+
+ and esp, 0FFFFFFF0h
+
+ push 010h ; protected mode selector on stack
+ mov eax, Compatible ; offset for LongMode
+ push eax ; offset on stack
+
+ push 038h ; long mode selector on stack
+ mov eax, LongMode ; offset for LongMode
+ push eax ; offset on stack
+
+ mov eax, cr4
+ or al, 020h
+ mov cr4, eax ; enable PAE
+ mov ecx, 0c0000080h
+ rdmsr
+ or ah, 1 ; set LME
+ wrmsr
+ mov eax, cr0
+ bts eax, 31 ; set PG
+ mov cr0, eax ; enable paging
+ retf ; topmost 2 dwords hold the address
+LongMode: ; long mode starts here
+
+ ; Call long mode function
+ DB 67h, 48h ; 32-bit address size, 64-bit operand size
+ mov eax, [ebp + 24] ; mov rbx, [ebp + 24]
+ DB 67h, 48h
+ mov ecx, [ebp + 24 + 8] ; mov rcx, [ebp + 24 + 8]
+ DB 67h, 48h
+ mov edx, [ebp + 24 + 16] ; mov rdx, [ebp + 24 + 16]
+
+ DB 48h
+ add esp, -20h ; add rsp, -20h
+ call eax ; call rax
+ DB 48h
+ add esp, 20h ; add rsp, 20h
+
+ ; after long mode function call
+ mov ebx, eax
+
+ retf
+Compatible:
+ mov ecx, cr0
+ btc ecx, 31 ; clear PG
+ mov cr0, ecx ; disable paging
+ mov ecx, 0C0000080h
+ rdmsr
+ btc eax, 8 ; clear LME
+ wrmsr
+
+ ;
+ ; Restore C register and eax hold the return status from 32-bit function.
+ ; Note: Do not touch rax from now which hold the return value from IA32 function
+ ;
+ mov eax, ebx ; put return status to EAX
+ mov esp, ebp ; restore stack pointer
+ pop ebx
+ pop ebp
+ pop esi
+ pop edi
+ popfd
+
+ ret
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
new file mode 100644
index 0000000000..170a6c9e40
--- /dev/null
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
@@ -0,0 +1,47 @@
+/** @file
+ Private header with declarations and definitions specific to the Standalone
+ MM IPL PEI driver
+
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef STANDALONE_MM_IPL_PEI_H_
+#define STANDALONE_MM_IPL_PEI_H_
+
+/**
+ Assembly function to transition from long mode to compatibility mode to
+ execute 32-bit code and then transit back to long mode.
+
+ @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
+ @param[in] InternalGdtr The GDT and GDT descriptor used by this library
+
+ @retval status.
+**/
+UINT32
+AsmExecute64BitCode (
+ IN UINT64 Function,
+ IN UINT64 Param1,
+ IN UINT64 Param2,
+ IN IA32_DESCRIPTOR *InternalGdtr
+ );
+
+/**
+ Load SMM core to dispatch other Standalone MM drivers after IA32 mode to X64 mode.
+
+ @param Entry Entry of Standalone MM Foundation.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function.
+ @retval EFI_SUCCESS Successfully loaded SMM core.
+ @retval Others Failed to load SMM core.
+**/
+EFI_STATUS
+LoadSmmCoreIA32ToX64 (
+ IN EFI_PHYSICAL_ADDRESS Entry,
+ IN VOID *Context1
+ );
+
+#endif
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
index 668d3afbf4..b9851c072f 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
@@ -23,8 +23,16 @@
#
[Sources]
+ StandaloneMmIplPei.h
StandaloneMmIplPei.c
+[Sources.Ia32]
+ Ia32/LoadSmmCore.c
+ Ia32/Thunk32To64.nasm
+
+[Sources.X64]
+ X64/LoadSmmCore.c
+
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
@@ -49,6 +57,9 @@
[Ppis]
gPeiSmmAccessPpiGuid ## CONSUMES
+[Pcd.IA32]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
+
[Pcd]
[Depex]
diff --git a/StandaloneMmPkg/StandaloneMmPkg.ci.yaml b/StandaloneMmPkg/StandaloneMmPkg.ci.yaml
index 4777532a7e..872f7958be 100644
--- a/StandaloneMmPkg/StandaloneMmPkg.ci.yaml
+++ b/StandaloneMmPkg/StandaloneMmPkg.ci.yaml
@@ -78,7 +78,9 @@
## options defined .pytool/Plugin/SpellCheck
"SpellCheck": {
"AuditOnly": False,
- "IgnoreFiles": [], # use gitignore syntax to ignore errors
+ "IgnoreFiles": [
+ "Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm"
+ ], # use gitignore syntax to ignore errors
# in matching files
"ExtendWords": [
"Bsymbolic",
--
2.37.0.windows.1
^ permalink raw reply related [flat|nested] 5+ messages in thread