summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjchen20 <jchen20@6f19259b-4bc3-4df7-8a09-765794883524>2010-03-03 05:45:50 +0000
committerjchen20 <jchen20@6f19259b-4bc3-4df7-8a09-765794883524>2010-03-03 05:45:50 +0000
commit3c447c2760b3438a6d5ff0a7f2dbd580526452e5 (patch)
treece952c6abbc849934ea7138cd2ec0114d62aed44
parentde558d9dfeca14d561a416d139ff521d87e83e47 (diff)
downloadedk2-platforms-3c447c2760b3438a6d5ff0a7f2dbd580526452e5.tar.xz
Enable "Load Module At fixed Address" feature in SMM Core
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10166 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--MdeModulePkg/Core/PiSmmCore/Dispatcher.c241
-rw-r--r--MdeModulePkg/Core/PiSmmCore/PiSmmCore.h4
-rw-r--r--MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf6
-rw-r--r--MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c186
-rw-r--r--MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf9
-rw-r--r--MdeModulePkg/Core/PiSmmCore/Pool.c44
-rw-r--r--MdeModulePkg/Include/Guid/LoadModuleAtFixedAddress.h2
7 files changed, 458 insertions, 34 deletions
diff --git a/MdeModulePkg/Core/PiSmmCore/Dispatcher.c b/MdeModulePkg/Core/PiSmmCore/Dispatcher.c
index 9e1a778900..9625eabd91 100644
--- a/MdeModulePkg/Core/PiSmmCore/Dispatcher.c
+++ b/MdeModulePkg/Core/PiSmmCore/Dispatcher.c
@@ -122,6 +122,176 @@ FV_FILEPATH_DEVICE_PATH mFvDevicePath;
//
EFI_SECURITY_ARCH_PROTOCOL *mSecurity = NULL;
+//
+// The global variable is defined for Loading modules at fixed address feature to track the SMM code
+// memory range usage. It is a bit mapped array in which every bit indicates the correspoding
+// memory page available or not.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mSmmCodeMemoryRangeUsageBitMap=NULL;
+
+/**
+ To check memory usage bit map array to figure out if the memory range in which the image will be loaded is available or not. If
+ memory range is avaliable, the function will mark the correponding bits to 1 which indicates the memory range is used.
+ The function is only invoked when load modules at fixed address feature is enabled.
+
+ @param ImageBase The base addres the image will be loaded at.
+ @param ImageSize The size of the image
+
+ @retval EFI_SUCCESS The memory range the image will be loaded in is available
+ @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
+**/
+EFI_STATUS
+CheckAndMarkFixLoadingMemoryUsageBitMap (
+ IN EFI_PHYSICAL_ADDRESS ImageBase,
+ IN UINTN ImageSize
+ )
+{
+ UINT32 SmmCodePageNumber;
+ UINT64 SmmCodeSize;
+ EFI_PHYSICAL_ADDRESS SmmCodeBase;
+ UINTN BaseOffsetPageNumber;
+ UINTN TopOffsetPageNumber;
+ UINTN Index;
+ //
+ // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber
+ //
+ SmmCodePageNumber = PcdGet32(PcdLoadFixAddressSmmCodePageNumber);
+ SmmCodeSize = EFI_PAGES_TO_SIZE (SmmCodePageNumber);
+ SmmCodeBase = gLoadModuleAtFixAddressSmramBase;
+
+ //
+ // If the memory usage bit map is not initialized, do it. Every bit in the array
+ // indicate the status of the corresponding memory page, available or not
+ //
+ if (mSmmCodeMemoryRangeUsageBitMap == NULL) {
+ mSmmCodeMemoryRangeUsageBitMap = AllocateZeroPool(((SmmCodePageNumber / 64) + 1)*sizeof(UINT64));
+ }
+ //
+ // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND
+ //
+ if (mSmmCodeMemoryRangeUsageBitMap == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // see if the memory range for loading the image is in the SMM code range.
+ //
+ if (SmmCodeBase + SmmCodeSize < ImageBase + ImageSize || SmmCodeBase > ImageBase) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Test if the memory is avalaible or not.
+ //
+ BaseOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase - SmmCodeBase));
+ TopOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - SmmCodeBase));
+ for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
+ if ((mSmmCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {
+ //
+ // This page is already used.
+ //
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ //
+ // Being here means the memory range is available. So mark the bits for the memory range
+ //
+ for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
+ mSmmCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));
+ }
+ return EFI_SUCCESS;
+}
+/**
+ Get the fixed loadding 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 loadding 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 FixLoaddingAddress;
+ UINT16 Index;
+ UINTN Size;
+ UINT16 NumberOfSections;
+ UINT64 ValueInSectionHeader;
+
+ FixLoaddingAddress = 0;
+ Status = EFI_NOT_FOUND;
+
+ //
+ // 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 will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
+ // that doesn't point to code section in image header.So there is an assumption that when the feature is enabled,
+ // if a module with a loading address assigned by tools, the PointerToRelocations & PointerToLineNumbers fields
+ // should not be Zero, or else, these 2 fileds 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 uild tool saves the
+ // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields
+ //
+ FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressSmramBase + (INT64)ValueInSectionHeader);
+ //
+ // Check if the memory range is avaliable.
+ //
+ Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoaddingAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));
+ if (!EFI_ERROR(Status)) {
+ //
+ // The assigned address is valid. Return the specified loadding address
+ //
+ ImageContext->ImageAddress = FixLoaddingAddress;
+ }
+ }
+ break;
+ }
+ SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
+ }
+ DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r\n", FixLoaddingAddress, Status));
+ return Status;
+}
/**
Loads an EFI image into SMRAM.
@@ -258,24 +428,63 @@ SmmLoadImage (
}
return Status;
}
-
- PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
- DstBuffer = (UINTN)(-1);
-
- Status = SmmAllocatePages (
- AllocateMaxAddress,
- EfiRuntimeServicesCode,
- PageCount,
- &DstBuffer
- );
- if (EFI_ERROR (Status)) {
- if (Buffer != NULL) {
- Status = gBS->FreePool (Buffer);
+ //
+ // if Loading module at Fixed Address feature is enabled, then cut out a memory range started from TESG BASE
+ // to hold the Smm driver code
+ //
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
+ //
+ // Get the fixed loading address assigned by Build tool
+ //
+ Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Since the memory range to load Smm core alreay been cut out, so no need to allocate and free this range
+ // following statements is to bypass SmmFreePages
+ //
+ PageCount = 0;
+ DstBuffer = (UINTN)gLoadModuleAtFixAddressSmramBase;
+ } else {
+ DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));
+ //
+ // allocate the memory to load the SMM driver
+ //
+ PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
+ DstBuffer = (UINTN)(-1);
+
+ Status = SmmAllocatePages (
+ AllocateMaxAddress,
+ EfiRuntimeServicesCode,
+ PageCount,
+ &DstBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ if (Buffer != NULL) {
+ Status = gBS->FreePool (Buffer);
+ }
+ return Status;
+ }
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
}
- return Status;
+ } else {
+ PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
+ DstBuffer = (UINTN)(-1);
+
+ Status = SmmAllocatePages (
+ AllocateMaxAddress,
+ EfiRuntimeServicesCode,
+ PageCount,
+ &DstBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ if (Buffer != NULL) {
+ Status = gBS->FreePool (Buffer);
+ }
+ return Status;
+ }
+
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
}
-
- ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
//
// Align buffer on section boundry
//
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
index 2926f90d35..1cbae1ca5a 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
@@ -41,7 +41,8 @@
#include <Library/MemoryAllocationLib.h>
#include <Library/DevicePathLib.h>
#include <Library/UefiLib.h>
-#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
#include "PiSmmCorePrivateData.h"
@@ -178,6 +179,7 @@ typedef struct {
extern SMM_CORE_PRIVATE_DATA *gSmmCorePrivate;
extern EFI_SMM_SYSTEM_TABLE2 gSmmCoreSmst;
extern LIST_ENTRY gHandleList;
+extern EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressSmramBase;
/**
Called to initialize the memory service.
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
index 5f38065c0c..63296bc99e 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
@@ -39,6 +39,7 @@
[Packages]
MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiDriverEntryPoint
@@ -52,6 +53,7 @@
UefiLib
UefiBootServicesTableLib
MemoryAllocationLib
+ PcdLib
[Protocols]
gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_CONSUMED
@@ -62,6 +64,10 @@
gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
gEfiDevicePathProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber # SIMETIMES_CONSUMED
+ gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable # ALWAYS_CONSUMED
+
[Guids]
gAprioriGuid # ALWAYS_CONSUMED
gEfiEventDxeDispatchGuid # ALWAYS_CONSUMED
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
index 1029a07779..ff7eff73bf 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
@@ -24,6 +24,7 @@
#include <Guid/EventGroup.h>
#include <Guid/EventLegacyBios.h>
+#include <Guid/LoadModuleAtFixedAddress.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
@@ -35,6 +36,7 @@
#include <Library/DxeServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiRuntimeLib.h>
+#include <Library/PcdLib.h>
#include "PiSmmCorePrivateData.h"
@@ -703,7 +705,101 @@ GetSectionInAnyFv (
return NULL;
}
+/**
+ Get the fixed loadding 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 loadding 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 FixLoaddingAddress;
+ UINT16 Index;
+ UINTN Size;
+ UINT16 NumberOfSections;
+ EFI_PHYSICAL_ADDRESS SmramBase;
+ UINT64 SmmCodeSize;
+ UINT64 ValueInSectionHeader;
+ //
+ // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber
+ //
+ SmmCodeSize = EFI_PAGES_TO_SIZE (PcdGet32(PcdLoadFixAddressSmmCodePageNumber));
+
+ FixLoaddingAddress = 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 fileds 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 uild tool saves the
+ // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields
+ //
+ FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(SmramBase + (INT64)ValueInSectionHeader);
+
+ if (SmramBase + SmmCodeSize > FixLoaddingAddress && SmramBase <= FixLoaddingAddress) {
+ //
+ // The assigned address is valid. Return the specified loadding address
+ //
+ ImageContext->ImageAddress = FixLoaddingAddress;
+ Status = EFI_SUCCESS;
+ }
+ }
+ break;
+ }
+ SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
+ }
+ DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r \n", FixLoaddingAddress, Status));
+ return Status;
+}
/**
Load the SMM Core image into SMRAM and executes the SMM Core from SMRAM.
@@ -749,23 +845,58 @@ ExecuteSmmCoreFromSmram (
if (EFI_ERROR (Status)) {
return Status;
}
-
//
- // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR
- // specified by SmramRange
+ // if Loading module at Fixed Address feature is enabled, the SMM core driver will be loaded to
+ // the address assigned by build tool.
//
- PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
+ //
+ // Get the fixed loading address assigned by Build tool
+ //
+ Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Since the memory range to load SMM CORE will be cut out in SMM core, so no need to allocate and free this range
+ //
+ PageCount = 0;
+ } else {
+ DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR: Loading module at fixed address at address failed\n"));
+ //
+ // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR
+ // specified by SmramRange
+ //
+ PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
- ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) == 0);
- ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));
+ ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) == 0);
+ ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));
- SmramRange->PhysicalSize -= EFI_PAGES_TO_SIZE (PageCount);
- DestinationBuffer = SmramRange->CpuStart + SmramRange->PhysicalSize;
+ SmramRange->PhysicalSize -= EFI_PAGES_TO_SIZE (PageCount);
+ DestinationBuffer = SmramRange->CpuStart + SmramRange->PhysicalSize;
- //
- // Align buffer on section boundry
- //
- ImageContext.ImageAddress = DestinationBuffer;
+ //
+ // Align buffer on section boundry
+ //
+ ImageContext.ImageAddress = DestinationBuffer;
+ }
+ } else {
+ //
+ // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR
+ // specified by SmramRange
+ //
+ PageCount = (UINTN)EFI_SIZE_TO_PAGES(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);
+ DestinationBuffer = SmramRange->CpuStart + SmramRange->PhysicalSize;
+
+ //
+ // Align buffer on section boundry
+ //
+ ImageContext.ImageAddress = DestinationBuffer;
+ }
+
ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
@@ -847,6 +978,8 @@ SmmIplEntry (
EFI_SMM_RESERVED_SMRAM_REGION *SmramResRegion;
UINT64 MaxSize;
VOID *Registration;
+ UINT64 SmmCodeSize;
+ EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE *LMFAConfigurationTable;
//
// Fill in the image handle of the SMM IPL so the SMM Core can use this as the
@@ -954,7 +1087,34 @@ SmmIplEntry (
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "SMM IPL failed to set SMRAM window to EFI_MEMORY_WB\n"));
}
-
+ //
+ // if Loading module at Fixed Address feature is enabled, save the SMRAM base to Load
+ // Modules At Fixed Address Configuration Table.
+ //
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
+ //
+ // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber
+ //
+ SmmCodeSize = LShiftU64 (PcdGet32(PcdLoadFixAddressSmmCodePageNumber), EFI_PAGE_SHIFT);
+ //
+ // The SMRAM available memory is assumed to be larger than SmmCodeSize
+ //
+ ASSERT (mCurrentSmramRange->PhysicalSize > SmmCodeSize);
+ //
+ // Retrieve Load modules At fixed address configuration table and save the SMRAM base.
+ //
+ Status = EfiGetSystemConfigurationTable (
+ &gLoadFixedAddressConfigurationTableGuid,
+ (VOID **) &LMFAConfigurationTable
+ );
+ if (!EFI_ERROR (Status) && LMFAConfigurationTable != NULL) {
+ LMFAConfigurationTable->SmramBase = mCurrentSmramRange->CpuStart;
+ }
+ //
+ // Print the SMRAM base
+ //
+ DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: TSEG BASE is %x. \n", LMFAConfigurationTable->SmramBase));
+ }
//
// Load SMM Core into SMRAM and execute it from SMRAM
//
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
index 1c4c2af454..d6c33dab30 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
@@ -33,6 +33,7 @@
[Packages]
MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiDriverEntryPoint
@@ -62,6 +63,12 @@
gEfiEventReadyToBootGuid # ALWAYS_CONSUMED
gEfiEventLegacyBootGuid # ALWAYS_CONSUMED
gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED
-
+ gLoadFixedAddressConfigurationTableGuid # SIMETIMES_CONSUMED
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber # SIMETIMES_CONSUMED
+ gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable # ALWAYS_CONSUMED
+
+
[Depex]
gEfiSmmAccess2ProtocolGuid AND gEfiSmmControl2ProtocolGuid AND gEfiCpuArchProtocolGuid
diff --git a/MdeModulePkg/Core/PiSmmCore/Pool.c b/MdeModulePkg/Core/PiSmmCore/Pool.c
index d7f80f4f8c..10a85c47ab 100644
--- a/MdeModulePkg/Core/PiSmmCore/Pool.c
+++ b/MdeModulePkg/Core/PiSmmCore/Pool.c
@@ -42,6 +42,11 @@ typedef struct {
} FREE_POOL_HEADER;
LIST_ENTRY mSmmPoolLists[MAX_POOL_INDEX];
+//
+// To cache the SMRAM base since when Loading modules At fixed address feature is enabled,
+// all module is assigned an offset relative the SMRAM base in build time.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressSmramBase = 0;
/**
Called to initialize the memory service.
@@ -56,7 +61,10 @@ SmmInitializeMemoryServices (
IN EFI_SMRAM_DESCRIPTOR *SmramRanges
)
{
- UINTN Index;
+ UINTN Index;
+ UINT64 SmmCodeSize;
+ UINTN CurrentSmramRangesIndex;
+ UINT64 MaxSize;
//
// Initialize Pool list
@@ -64,7 +72,38 @@ SmmInitializeMemoryServices (
for (Index = sizeof (mSmmPoolLists) / sizeof (*mSmmPoolLists); Index > 0;) {
InitializeListHead (&mSmmPoolLists[--Index]);
}
-
+ CurrentSmramRangesIndex = 0;
+ //
+ // If Loadding Module At fixed Address feature is enabled, cache the SMRAM base here
+ //
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
+ //
+ // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber
+ //
+ SmmCodeSize = LShiftU64 (PcdGet32(PcdLoadFixAddressSmmCodePageNumber), EFI_PAGE_SHIFT);
+
+ //
+ // Find the largest SMRAM range between 1MB and 4GB that is at least 256KB - 4K in size
+ //
+ for (Index = 0, MaxSize = SIZE_256KB - EFI_PAGE_SIZE; Index < SmramRangeCount; Index++) {
+ if (SmramRanges[Index].CpuStart >= BASE_1MB) {
+ if ((SmramRanges[Index].CpuStart + SmramRanges[Index].PhysicalSize) <= BASE_4GB) {
+ if (SmramRanges[Index].PhysicalSize >= MaxSize) {
+ MaxSize = SmramRanges[Index].PhysicalSize;
+ CurrentSmramRangesIndex = Index;
+ }
+ }
+ }
+ }
+ gLoadModuleAtFixAddressSmramBase = SmramRanges[CurrentSmramRangesIndex].CpuStart;
+
+ //
+ // cut out a memory range from this SMRAM range with the size SmmCodeSize to hold SMM driver code
+ // A notable thing is that SMM core is already loaded into this range.
+ //
+ SmramRanges[CurrentSmramRangesIndex].CpuStart = SmramRanges[CurrentSmramRangesIndex].CpuStart + SmmCodeSize;
+ SmramRanges[CurrentSmramRangesIndex].PhysicalSize = SmramRanges[CurrentSmramRangesIndex].PhysicalSize - SmmCodeSize;
+ }
//
// Initialize free SMRAM regions
//
@@ -76,6 +115,7 @@ SmmInitializeMemoryServices (
SmramRanges[Index].RegionState
);
}
+
}
/**
diff --git a/MdeModulePkg/Include/Guid/LoadModuleAtFixedAddress.h b/MdeModulePkg/Include/Guid/LoadModuleAtFixedAddress.h
index 070430db9c..a04e0b224d 100644
--- a/MdeModulePkg/Include/Guid/LoadModuleAtFixedAddress.h
+++ b/MdeModulePkg/Include/Guid/LoadModuleAtFixedAddress.h
@@ -28,7 +28,7 @@ extern EFI_GUID gLoadFixedAddressConfigurationTableGuid;
typedef struct {
EFI_PHYSICAL_ADDRESS DxeCodeTopAddress; ///< The top address below which the Dxe runtime code and below which the Dxe runtime/boot code and PEI code.
- EFI_PHYSICAL_ADDRESS TsegBase; ///< Tseg base. build tool will assigned an offset relative to Tseg base to SMM driver
+ EFI_PHYSICAL_ADDRESS SmramBase; ///< SMM RAME base. build tool will assigned an offset relative to SMRAM base for SMM driver
} EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE;
#endif