public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v4 1/5] StandaloneMmPkg: Add StandaloneMmIplPei driver.
@ 2023-06-19  7:46 Zhang, Hongbin1
  2023-06-19  7:46 ` [PATCH v4 2/5] " Zhang, Hongbin1
                   ` (3 more replies)
  0 siblings, 4 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.
And this is the 1st patch to implement the entrypoint
to find the correct SMRAM range and dump it

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   | 266 ++++++++++++++++++++
 StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf |  54 ++++
 StandaloneMmPkg/StandaloneMmPkg.dsc                               |  15 +-
 3 files changed, 333 insertions(+), 2 deletions(-)

diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
new file mode 100644
index 0000000000..16e7d59d0e
--- /dev/null
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
@@ -0,0 +1,266 @@
+/** @file
+  SMM IPL that load the SMM Core into SMRAM at PEI stage
+
+  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Ppi/SmmAccess.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/HobLib.h>
+#include <Guid/MmCoreData.h>
+
+//
+// MM Core Private Data structure that contains the data shared between
+// the SMM IPL and the Standalone MM Core.
+//
+MM_CORE_PRIVATE_DATA  mMmCorePrivateData = {
+  MM_CORE_PRIVATE_DATA_SIGNATURE,     // Signature
+  0,                                  // MmramRangeCount
+  0,                                  // MmramRanges
+  0,                                  // MmEntryPoint
+  FALSE,                              // MmEntryPointRegistered
+  FALSE,                              // InMm
+  0,                                  // Mmst
+  0,                                  // CommunicationBuffer
+  0,                                  // BufferSize
+  EFI_SUCCESS,                        // ReturnStatus
+  0,                                  // MmCoreImageBase
+  0,                                  // MmCoreImageSize
+  0,                                  // MmCoreEntryPoint
+  0,                                  // StandaloneBfvAddress
+};
+
+//
+// Global pointer used to access mMmCorePrivateData from outside and inside SMM
+//
+MM_CORE_PRIVATE_DATA  *gMmCorePrivate;
+
+//
+// SMM IPL global variables
+//
+PEI_SMM_ACCESS_PPI    *mSmmAccess;
+EFI_SMRAM_DESCRIPTOR  *mCurrentSmramRange;
+EFI_PHYSICAL_ADDRESS  mSmramCacheBase;
+UINT64                mSmramCacheSize;
+UINTN                 mSmramRangeCount;
+
+/**
+  Find the maximum SMRAM cache range that covers the range specified by SmramRange.
+
+  This function searches and joins all adjacent ranges of SmramRange into a range to be cached.
+
+  @param   SmramRange       The SMRAM range to search from.
+  @param   SmramCacheBase   The returned cache range base.
+  @param   SmramCacheSize   The returned cache range size.
+**/
+VOID
+GetSmramCacheRange (
+  IN  EFI_SMRAM_DESCRIPTOR  *SmramRange,
+  OUT EFI_PHYSICAL_ADDRESS  *SmramCacheBase,
+  OUT UINT64                *SmramCacheSize
+  )
+{
+  UINTN                 Index;
+  EFI_PHYSICAL_ADDRESS  RangeCpuStart;
+  UINT64                RangePhysicalSize;
+  BOOLEAN               FoundAdjacentRange;
+  EFI_SMRAM_DESCRIPTOR  *SmramRanges;
+
+  *SmramCacheBase = SmramRange->CpuStart;
+  *SmramCacheSize = SmramRange->PhysicalSize;
+
+  SmramRanges = (EFI_SMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate->MmramRanges;
+  do {
+    FoundAdjacentRange = FALSE;
+    for (Index = 0; Index < gMmCorePrivate->MmramRangeCount; Index++) {
+      RangeCpuStart     = SmramRanges[Index].CpuStart;
+      RangePhysicalSize = SmramRanges[Index].PhysicalSize;
+      if ((RangeCpuStart < *SmramCacheBase) && (*SmramCacheBase == (RangeCpuStart + RangePhysicalSize))) {
+        *SmramCacheBase    = RangeCpuStart;
+        *SmramCacheSize   += RangePhysicalSize;
+        FoundAdjacentRange = TRUE;
+      } else if (((*SmramCacheBase + *SmramCacheSize) == RangeCpuStart) && (RangePhysicalSize > 0)) {
+        *SmramCacheSize   += RangePhysicalSize;
+        FoundAdjacentRange = TRUE;
+      }
+    }
+  } while (FoundAdjacentRange);
+}
+
+/**
+  Get full SMRAM ranges.
+
+  It will get SMRAM ranges from SmmAccess PPI. It will also reserve one entry
+  for SMM core.
+
+  @param[in]  PeiServices           Describes the list of possible PEI Services.
+  @param[out] FullSmramRangeCount   Output pointer to full SMRAM range count.
+
+  @return Pointer to full SMRAM ranges.
+
+**/
+EFI_SMRAM_DESCRIPTOR *
+GetFullSmramRanges (
+  IN  CONST EFI_PEI_SERVICES  **PeiServices,
+  OUT       UINTN             *FullSmramRangeCount
+  )
+{
+  EFI_STATUS            Status;
+  UINTN                 Size;
+  EFI_SMRAM_DESCRIPTOR  *FullSmramRanges;
+  UINTN                 AdditionSmramRangeCount;
+
+  //
+  // Get SMRAM information.
+  //
+  Size   = 0;
+  Status = mSmmAccess->GetCapabilities ((EFI_PEI_SERVICES **)PeiServices, mSmmAccess, &Size, NULL);
+  ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+
+  mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
+
+  //
+  // Reserve one entry SMM Core in the full SMRAM ranges.
+  //
+  AdditionSmramRangeCount = 1;
+
+  *FullSmramRangeCount = mSmramRangeCount + AdditionSmramRangeCount;
+  Size                 = (*FullSmramRangeCount) * sizeof (EFI_SMRAM_DESCRIPTOR);
+  FullSmramRanges      = (EFI_SMRAM_DESCRIPTOR *)AllocateZeroPool (Size);
+  ASSERT (FullSmramRanges != NULL);
+  if (FullSmramRanges == NULL) {
+    return NULL;
+  }
+
+  Status = mSmmAccess->GetCapabilities ((EFI_PEI_SERVICES **)PeiServices, mSmmAccess, &Size, FullSmramRanges);
+
+  ASSERT_EFI_ERROR (Status);
+
+  return FullSmramRanges;
+}
+
+/**
+  The Entry Point for SMM IPL at PEI stage
+
+  Load SMM Core into SMRAM.
+
+  @param  FileHandle  Handle of the file being invoked.
+  @param  PeiServices Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCESS    The entry point is executed successfully.
+  @retval Other          Some error occurred when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+StandaloneMmIplPeiEntry (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS             Status;
+  UINTN                  Index;
+  UINT64                 MaxSize;
+  MM_CORE_DATA_HOB_DATA  SmmCoreDataHobData;
+  EFI_SMRAM_DESCRIPTOR   *MmramRanges;
+
+  //
+  // Build Hob for SMM and DXE phase
+  //
+  SmmCoreDataHobData.Address = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateRuntimePages (EFI_SIZE_TO_PAGES (sizeof (mMmCorePrivateData)));
+  ASSERT (SmmCoreDataHobData.Address != 0);
+  gMmCorePrivate = (VOID *)(UINTN)SmmCoreDataHobData.Address;
+  CopyMem ((VOID *)(UINTN)SmmCoreDataHobData.Address, &mMmCorePrivateData, sizeof (mMmCorePrivateData));
+  DEBUG ((DEBUG_INFO, "gMmCorePrivate - 0x%x\n", gMmCorePrivate));
+
+  BuildGuidDataHob (
+    &gMmCoreDataHobGuid,
+    (VOID *)&SmmCoreDataHobData,
+    sizeof (SmmCoreDataHobData)
+    );
+
+  //
+  // Get SMM Access PPI
+  //
+  Status = PeiServicesLocatePpi (&gPeiSmmAccessPpiGuid, 0, NULL, (VOID **)&mSmmAccess);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Get SMRAM information
+  //
+  gMmCorePrivate->MmramRanges = (EFI_PHYSICAL_ADDRESS)(UINTN)GetFullSmramRanges (PeiServices, (UINTN *)&gMmCorePrivate->MmramRangeCount);
+  ASSERT (gMmCorePrivate->MmramRanges != 0);
+  if (gMmCorePrivate->MmramRanges == 0) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Open all SMRAM ranges
+  //
+  for (Index = 0; Index < mSmramRangeCount; Index++) {
+    Status = mSmmAccess->Open ((EFI_PEI_SERVICES **)PeiServices, mSmmAccess, Index);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  //
+  // Print debug message that the SMRAM window is now open.
+  //
+  DEBUG ((DEBUG_INFO, "SMM IPL opened SMRAM window\n"));
+
+  //
+  // Find the largest SMRAM range between 1MB and 4GB that is at least 256KB - 4K in size
+  //
+  mCurrentSmramRange = NULL;
+  MmramRanges        = (EFI_MMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate->MmramRanges;
+  if (MmramRanges == NULL) {
+    DEBUG ((DEBUG_ERROR, "Fail to retrieve MmramRanges\n"));
+    return EFI_UNSUPPORTED;
+  }
+
+  for (Index = 0, MaxSize = SIZE_256KB - EFI_PAGE_SIZE; Index < gMmCorePrivate->MmramRangeCount; Index++) {
+    //
+    // Skip any SMRAM region that is already allocated, needs testing, or needs ECC initialization
+    //
+    if ((MmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) {
+      continue;
+    }
+
+    if (MmramRanges[Index].CpuStart >= BASE_1MB) {
+      if ((MmramRanges[Index].CpuStart + MmramRanges[Index].PhysicalSize) <= BASE_4GB) {
+        if (MmramRanges[Index].PhysicalSize >= MaxSize) {
+          MaxSize            = MmramRanges[Index].PhysicalSize;
+          mCurrentSmramRange = &MmramRanges[Index];
+        }
+      }
+    }
+  }
+
+  if (mCurrentSmramRange != NULL) {
+    //
+    // Print debug message showing SMRAM window that will be used by SMM IPL and SMM Core
+    //
+    DEBUG ((
+      DEBUG_INFO,
+      "SMM IPL found SMRAM window %p - %p\n",
+      (VOID *)(UINTN)mCurrentSmramRange->CpuStart,
+      (VOID *)(UINTN)(mCurrentSmramRange->CpuStart + mCurrentSmramRange->PhysicalSize - 1)
+      ));
+
+    GetSmramCacheRange (mCurrentSmramRange, &mSmramCacheBase, &mSmramCacheSize);
+  } else {
+    //
+    // Print error message that there are not enough SMRAM resources to load the SMM Core.
+    //
+    DEBUG ((DEBUG_ERROR, "SMM IPL could not find a large enough SMRAM region to load SMM Core\n"));
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
new file mode 100644
index 0000000000..372c59c1fa
--- /dev/null
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
@@ -0,0 +1,54 @@
+## @file
+#  This module provide a Standalone SMM compliant implementation of SMM IPL PEIM.
+#
+#  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = StandaloneMmIplPei
+  FILE_GUID                      = 578A0D17-2DC0-4C7D-A121-D8D771923BB0
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  PI_SPECIFICATION_VERSION       = 0x0001000A
+  ENTRY_POINT                    = StandaloneMmIplPeiEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  StandaloneMmIplPei.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  StandaloneMmPkg/StandaloneMmPkg.dec
+
+[LibraryClasses]
+  PeimEntryPoint
+  PeiServicesTablePointerLib
+  PeiServicesLib
+  BaseLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  DebugLib
+  HobLib
+  IntrinsicLib
+
+[Guids]
+  gMmCoreDataHobGuid
+
+[Ppis]
+  gPeiSmmAccessPpiGuid                     ## CONSUMES
+
+[Pcd]
+
+[Depex]
+  gPeiSmmAccessPpiGuid
+
diff --git a/StandaloneMmPkg/StandaloneMmPkg.dsc b/StandaloneMmPkg/StandaloneMmPkg.dsc
index 8012f93b7d..d88471fe82 100644
--- a/StandaloneMmPkg/StandaloneMmPkg.dsc
+++ b/StandaloneMmPkg/StandaloneMmPkg.dsc
@@ -20,7 +20,7 @@
   PLATFORM_VERSION               = 1.0
   DSC_SPECIFICATION              = 0x00010011
   OUTPUT_DIRECTORY               = Build/StandaloneMm
-  SUPPORTED_ARCHITECTURES        = AARCH64|X64|ARM
+  SUPPORTED_ARCHITECTURES        = AARCH64|X64|ARM|IA32
   BUILD_TARGETS                  = DEBUG|RELEASE
   SKUID_IDENTIFIER               = DEFAULT
 
@@ -60,6 +60,14 @@
   StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
   VariableMmDependency|StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf
 
+[LibraryClasses.common.PEIM]
+  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+  PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+  PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+  PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
+  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+
 [LibraryClasses.AARCH64, LibraryClasses.ARM]
   ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
   StandaloneMmMmuLib|ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.inf
@@ -104,7 +112,7 @@
 #       generated for it, but the binary will not be put into any firmware volume.
 #
 ###################################################################################################
-[Components.common]
+[Components.AARCH64, Components.ARM, Components.X64]
   #
   # MM Core
   #
@@ -122,6 +130,9 @@
   StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf
   StandaloneMmPkg/Library/StandaloneMmPeCoffExtraActionLib/StandaloneMmPeCoffExtraActionLib.inf
 
+[Components.X64, Components.IA32]
+  StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
+
 ###################################################################################################
 #
 # BuildOptions Section - Define the module specific tool chain flags that should be used as
-- 
2.37.0.windows.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [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

* [PATCH v4 4/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 ` [PATCH v4 3/5] " Zhang, Hongbin1
@ 2023-06-19  7:46 ` 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/StandaloneMmIplPei.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
index 47cc18ecbd..0d0c678f90 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
@@ -400,8 +400,17 @@ ExecuteSmmCoreFromSmram (
       DEBUG ((DEBUG_INFO, "SMM IPL calling Standalone MM Core at SMRAM address - 0x%016lx\n", gMmCorePrivate->MmCoreEntryPoint));
 
       //
-      // 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
+      // If StandaloneMmIpl driver is X64 image, but Standalone MM core is IA32 image
+      // This case is not supported
+      //
+      if ((sizeof (UINTN) == sizeof (UINT64)) && (ImageContext.Machine == EFI_IMAGE_MACHINE_IA32)) {
+        DEBUG ((DEBUG_ERROR, "X64 SMM IPL call IA32 MM core is not supported !\n"));
+        CpuDeadLoop ();
+      }
+
+      //
+      // 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.
       //
       if ((sizeof (UINTN) == sizeof (UINT32)) && (ImageContext.Machine == EFI_IMAGE_MACHINE_X64)) {
         //
-- 
2.37.0.windows.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v4 5/5] StandaloneMmPkg: Add StandaloneMmIplPei driver.
  2023-06-19  7:46 [PATCH v4 1/5] StandaloneMmPkg: Add StandaloneMmIplPei driver Zhang, Hongbin1
                   ` (2 preceding siblings ...)
  2023-06-19  7:46 ` [PATCH v4 4/5] " Zhang, Hongbin1
@ 2023-06-19  7:46 ` 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/StandaloneMmIplPei.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
index 0d0c678f90..78939faeea 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
@@ -626,5 +626,16 @@ StandaloneMmIplPeiEntry (
     DEBUG ((DEBUG_ERROR, "SMM IPL could not find a large enough SMRAM region to load SMM Core\n"));
   }
 
+  //
+  // Close and lock all SMRAM ranges.
+  //
+  for (Index = 0; Index < mSmramRangeCount; Index++) {
+    Status = mSmmAccess->Close ((EFI_PEI_SERVICES **)PeiServices, mSmmAccess, Index);
+    ASSERT_EFI_ERROR (Status);
+
+    Status = mSmmAccess->Lock ((EFI_PEI_SERVICES **)PeiServices, mSmmAccess, Index);
+    ASSERT_EFI_ERROR (Status);
+  }
+
   return EFI_SUCCESS;
 }
-- 
2.37.0.windows.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-06-19  7:47 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH v4 3/5] " Zhang, Hongbin1
2023-06-19  7:46 ` [PATCH v4 4/5] " Zhang, Hongbin1
2023-06-19  7:46 ` [PATCH v4 5/5] " Zhang, Hongbin1

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox