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
This commit is contained in:
jchen20 2010-03-03 05:45:50 +00:00
parent de558d9dfe
commit 3c447c2760
7 changed files with 458 additions and 34 deletions

View File

@ -122,6 +122,176 @@ FV_FILEPATH_DEVICE_PATH mFvDevicePath;
// //
EFI_SECURITY_ARCH_PROTOCOL *mSecurity = NULL; 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. Loads an EFI image into SMRAM.
@ -258,7 +428,45 @@ SmmLoadImage (
} }
return Status; return Status;
} }
//
// 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;
}
} else {
PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment); PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
DstBuffer = (UINTN)(-1); DstBuffer = (UINTN)(-1);
@ -276,6 +484,7 @@ SmmLoadImage (
} }
ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer; ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
}
// //
// Align buffer on section boundry // Align buffer on section boundry
// //

View File

@ -42,6 +42,7 @@
#include <Library/DevicePathLib.h> #include <Library/DevicePathLib.h>
#include <Library/UefiLib.h> #include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h> #include <Library/UefiBootServicesTableLib.h>
#include <Library/PcdLib.h>
#include "PiSmmCorePrivateData.h" #include "PiSmmCorePrivateData.h"
@ -178,6 +179,7 @@ typedef struct {
extern SMM_CORE_PRIVATE_DATA *gSmmCorePrivate; extern SMM_CORE_PRIVATE_DATA *gSmmCorePrivate;
extern EFI_SMM_SYSTEM_TABLE2 gSmmCoreSmst; extern EFI_SMM_SYSTEM_TABLE2 gSmmCoreSmst;
extern LIST_ENTRY gHandleList; extern LIST_ENTRY gHandleList;
extern EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressSmramBase;
/** /**
Called to initialize the memory service. Called to initialize the memory service.

View File

@ -39,6 +39,7 @@
[Packages] [Packages]
MdePkg/MdePkg.dec MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses] [LibraryClasses]
UefiDriverEntryPoint UefiDriverEntryPoint
@ -52,6 +53,7 @@
UefiLib UefiLib
UefiBootServicesTableLib UefiBootServicesTableLib
MemoryAllocationLib MemoryAllocationLib
PcdLib
[Protocols] [Protocols]
gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_CONSUMED
@ -62,6 +64,10 @@
gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODUCED gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
gEfiDevicePathProtocolGuid # PROTOCOL SOMETIMES_CONSUMED gEfiDevicePathProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber # SIMETIMES_CONSUMED
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable # ALWAYS_CONSUMED
[Guids] [Guids]
gAprioriGuid # ALWAYS_CONSUMED gAprioriGuid # ALWAYS_CONSUMED
gEfiEventDxeDispatchGuid # ALWAYS_CONSUMED gEfiEventDxeDispatchGuid # ALWAYS_CONSUMED

View File

@ -24,6 +24,7 @@
#include <Guid/EventGroup.h> #include <Guid/EventGroup.h>
#include <Guid/EventLegacyBios.h> #include <Guid/EventLegacyBios.h>
#include <Guid/LoadModuleAtFixedAddress.h>
#include <Library/BaseLib.h> #include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h> #include <Library/BaseMemoryLib.h>
@ -35,6 +36,7 @@
#include <Library/DxeServicesTableLib.h> #include <Library/DxeServicesTableLib.h>
#include <Library/UefiLib.h> #include <Library/UefiLib.h>
#include <Library/UefiRuntimeLib.h> #include <Library/UefiRuntimeLib.h>
#include <Library/PcdLib.h>
#include "PiSmmCorePrivateData.h" #include "PiSmmCorePrivateData.h"
@ -703,7 +705,101 @@ GetSectionInAnyFv (
return NULL; 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. Load the SMM Core image into SMRAM and executes the SMM Core from SMRAM.
@ -749,7 +845,22 @@ ExecuteSmmCoreFromSmram (
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
} }
//
// if Loading module at Fixed Address feature is enabled, the SMM core driver will be loaded to
// the address assigned by build tool.
//
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 // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR
// specified by SmramRange // specified by SmramRange
@ -766,6 +877,26 @@ ExecuteSmmCoreFromSmram (
// Align buffer on section boundry // Align buffer on section boundry
// //
ImageContext.ImageAddress = DestinationBuffer; 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;
ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1); ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
@ -847,6 +978,8 @@ SmmIplEntry (
EFI_SMM_RESERVED_SMRAM_REGION *SmramResRegion; EFI_SMM_RESERVED_SMRAM_REGION *SmramResRegion;
UINT64 MaxSize; UINT64 MaxSize;
VOID *Registration; 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 // 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)) { if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "SMM IPL failed to set SMRAM window to EFI_MEMORY_WB\n")); 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 // Load SMM Core into SMRAM and execute it from SMRAM
// //

View File

@ -33,6 +33,7 @@
[Packages] [Packages]
MdePkg/MdePkg.dec MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses] [LibraryClasses]
UefiDriverEntryPoint UefiDriverEntryPoint
@ -62,6 +63,12 @@
gEfiEventReadyToBootGuid # ALWAYS_CONSUMED gEfiEventReadyToBootGuid # ALWAYS_CONSUMED
gEfiEventLegacyBootGuid # ALWAYS_CONSUMED gEfiEventLegacyBootGuid # ALWAYS_CONSUMED
gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED
gLoadFixedAddressConfigurationTableGuid # SIMETIMES_CONSUMED
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber # SIMETIMES_CONSUMED
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable # ALWAYS_CONSUMED
[Depex] [Depex]
gEfiSmmAccess2ProtocolGuid AND gEfiSmmControl2ProtocolGuid AND gEfiCpuArchProtocolGuid gEfiSmmAccess2ProtocolGuid AND gEfiSmmControl2ProtocolGuid AND gEfiCpuArchProtocolGuid

View File

@ -42,6 +42,11 @@ typedef struct {
} FREE_POOL_HEADER; } FREE_POOL_HEADER;
LIST_ENTRY mSmmPoolLists[MAX_POOL_INDEX]; 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. Called to initialize the memory service.
@ -57,6 +62,9 @@ SmmInitializeMemoryServices (
) )
{ {
UINTN Index; UINTN Index;
UINT64 SmmCodeSize;
UINTN CurrentSmramRangesIndex;
UINT64 MaxSize;
// //
// Initialize Pool list // Initialize Pool list
@ -64,7 +72,38 @@ SmmInitializeMemoryServices (
for (Index = sizeof (mSmmPoolLists) / sizeof (*mSmmPoolLists); Index > 0;) { for (Index = sizeof (mSmmPoolLists) / sizeof (*mSmmPoolLists); Index > 0;) {
InitializeListHead (&mSmmPoolLists[--Index]); 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 // Initialize free SMRAM regions
// //
@ -76,6 +115,7 @@ SmmInitializeMemoryServices (
SmramRanges[Index].RegionState SmramRanges[Index].RegionState
); );
} }
} }
/** /**

View File

@ -28,7 +28,7 @@ extern EFI_GUID gLoadFixedAddressConfigurationTableGuid;
typedef struct { 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 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; } EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE;
#endif #endif