public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Zhang, Hongbin1" <hongbin1.zhang@intel.com>
To: devel@edk2.groups.io
Cc: "Zhang, Hongbin1" <hongbin1.zhang@intel.com>,
	Jiewen Yao <jiewen.yao@intel.com>, Ray Ni <ray.ni@intel.com>,
	Star Zeng <star.zeng@intel.com>, Jiaxin Wu <jiaxin.wu@intel.com>,
	Sami Mujawar <sami.mujawar@arm.com>,
	Ard Biesheuvel <ardb+tianocore@kernel.org>,
	Supreeth Venkatesh <supreeth.venkatesh@arm.com>
Subject: [PATCH v4 1/5] StandaloneMmPkg: Add StandaloneMmIplPei driver.
Date: Mon, 19 Jun 2023 15:46:35 +0800	[thread overview]
Message-ID: <20230619074639.1569-1-hongbin1.zhang@intel.com> (raw)

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


             reply	other threads:[~2023-06-19  7:46 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-19  7:46 Zhang, Hongbin1 [this message]
2023-06-19  7:46 ` [PATCH v4 2/5] StandaloneMmPkg: Add StandaloneMmIplPei driver 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230619074639.1569-1-hongbin1.zhang@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox