From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by mx.groups.io with SMTP id smtpd.web11.5494.1686219494164094591 for ; Thu, 08 Jun 2023 03:18:14 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=kB1UkQvq; spf=pass (domain: intel.com, ip: 134.134.136.31, mailfrom: hongbin1.zhang@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686219494; x=1717755494; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=ykPdcEAqM5G7PlAIA69K3I1RyTrRnKpoAG+qv4FGk/4=; b=kB1UkQvqlWkQ34hBM3ejg1PVCVa0ez2B2+lAb0ZhCvOsCyy4P6whwhPk /I7uHpid6pMjR4OY7G9X/LMlr67lJPzWKd/imp1K7MPC/serPlq6Md8AC 5GieJ3JKcDIfXA/p3rfAikBeU4yv+BquEn2dTaJ3J+YQ96VlCDV0HQLOA KOufO0cOPUb2waf9OUCN+qitARivpRWLAhDwRl5w8ZdSNY0Ye9Ju/ZLjy yUt94zq7uYcIwoUNOZlv9FKkrKrmrhghn8QBsoZ95pJPpnOr56j+pJOQ4 XZvJdp4OYKn8q1QAsM2cuU68piFIAeV+OPYBG/IzNQKKs2bkpROim5Kri g==; X-IronPort-AV: E=McAfee;i="6600,9927,10734"; a="420833126" X-IronPort-AV: E=Sophos;i="6.00,226,1681196400"; d="scan'208";a="420833126" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2023 03:18:13 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10734"; a="660327706" X-IronPort-AV: E=Sophos;i="6.00,226,1681196400"; d="scan'208";a="660327706" Received: from hongbin1-mobl1.ccr.corp.intel.com ([10.254.210.124]) by orsmga003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2023 03:18:11 -0700 From: "Zhang, Hongbin1" To: devel@edk2.groups.io Cc: "Zhang, Hongbin1" , Jiewen Yao , Ray Ni , Star Zeng , Jiaxin Wu , Sami Mujawar , Ard Biesheuvel , Supreeth Venkatesh Subject: [PATCH v2] StandaloneMmPkg: Add StandaloneMmIplPei driver. Date: Thu, 8 Jun 2023 18:18:04 +0800 Message-Id: <20230608101804.1922-1-hongbin1.zhang@intel.com> X-Mailer: git-send-email 2.37.0.windows.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 Cc: Jiewen Yao Cc: Ray Ni Cc: Star Zeng Cc: Jiaxin Wu Cc: Sami Mujawar Cc: Ard Biesheuvel Cc: Supreeth Venkatesh --- StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c | 264 ++++++++++++++++++++ StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf | 54 ++++ StandaloneMmPkg/StandaloneMmPkg.dsc | 15 +- 3 files changed, 331 insertions(+), 2 deletions(-) diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c new file mode 100644 index 0000000000..f988521c12 --- /dev/null +++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c @@ -0,0 +1,264 @@ +/** @file + SMM IPL that load the SMM Core into SMRAM at PEI stage + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// 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; + +/** + 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; + UINTN SmramRangeCount; + + // + // Get SMRAM information. + // + Size = 0; + Status = mSmmAccess->GetCapabilities ((EFI_PEI_SERVICES **)PeiServices, mSmmAccess, &Size, NULL); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + SmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR); + + // + // Reserve one entry SMM Core in the full SMRAM ranges. + // + AdditionSmramRangeCount = 1; + + *FullSmramRangeCount = SmramRangeCount + 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 + // + Status = mSmmAccess->Open ((EFI_PEI_SERVICES **)PeiServices, mSmmAccess, 0); + 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.
+# +# 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