//\r
EFI_SECURITY_ARCH_PROTOCOL *mSecurity = NULL;\r
\r
+//\r
+// The global variable is defined for Loading modules at fixed address feature to track the SMM code\r
+// memory range usage. It is a bit mapped array in which every bit indicates the correspoding \r
+// memory page available or not. \r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mSmmCodeMemoryRangeUsageBitMap=NULL;\r
+\r
+/**\r
+ 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 \r
+ memory range is avaliable, the function will mark the correponding bits to 1 which indicates the memory range is used.\r
+ The function is only invoked when load modules at fixed address feature is enabled. \r
+ \r
+ @param ImageBase The base addres the image will be loaded at.\r
+ @param ImageSize The size of the image\r
+ \r
+ @retval EFI_SUCCESS The memory range the image will be loaded in is available\r
+ @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available\r
+**/\r
+EFI_STATUS\r
+CheckAndMarkFixLoadingMemoryUsageBitMap (\r
+ IN EFI_PHYSICAL_ADDRESS ImageBase,\r
+ IN UINTN ImageSize\r
+ )\r
+{\r
+ UINT32 SmmCodePageNumber;\r
+ UINT64 SmmCodeSize; \r
+ EFI_PHYSICAL_ADDRESS SmmCodeBase;\r
+ UINTN BaseOffsetPageNumber;\r
+ UINTN TopOffsetPageNumber;\r
+ UINTN Index;\r
+ //\r
+ // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber\r
+ //\r
+ SmmCodePageNumber = PcdGet32(PcdLoadFixAddressSmmCodePageNumber);\r
+ SmmCodeSize = EFI_PAGES_TO_SIZE (SmmCodePageNumber);\r
+ SmmCodeBase = gLoadModuleAtFixAddressSmramBase;\r
+ \r
+ //\r
+ // If the memory usage bit map is not initialized, do it. Every bit in the array \r
+ // indicate the status of the corresponding memory page, available or not\r
+ // \r
+ if (mSmmCodeMemoryRangeUsageBitMap == NULL) {\r
+ mSmmCodeMemoryRangeUsageBitMap = AllocateZeroPool(((SmmCodePageNumber / 64) + 1)*sizeof(UINT64));\r
+ }\r
+ //\r
+ // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND\r
+ //\r
+ if (mSmmCodeMemoryRangeUsageBitMap == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // see if the memory range for loading the image is in the SMM code range.\r
+ //\r
+ if (SmmCodeBase + SmmCodeSize < ImageBase + ImageSize || SmmCodeBase > ImageBase) {\r
+ return EFI_NOT_FOUND; \r
+ } \r
+ //\r
+ // Test if the memory is avalaible or not.\r
+ // \r
+ BaseOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase - SmmCodeBase));\r
+ TopOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - SmmCodeBase));\r
+ for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+ if ((mSmmCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {\r
+ //\r
+ // This page is already used.\r
+ //\r
+ return EFI_NOT_FOUND; \r
+ }\r
+ }\r
+ \r
+ //\r
+ // Being here means the memory range is available. So mark the bits for the memory range\r
+ // \r
+ for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+ mSmmCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));\r
+ }\r
+ return EFI_SUCCESS; \r
+}\r
+/**\r
+ Get the fixed loadding address from image header assigned by build tool. This function only be called \r
+ when Loading module at Fixed address feature enabled.\r
+ \r
+ @param ImageContext Pointer to the image context structure that describes the PE/COFF\r
+ image that needs to be examined by this function.\r
+ @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .\r
+ @retval EFI_NOT_FOUND The image has no assigned fixed loadding address.\r
+\r
+**/\r
+EFI_STATUS\r
+GetPeCoffImageFixLoadingAssignedAddress(\r
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
+ )\r
+{\r
+ UINTN SectionHeaderOffset;\r
+ EFI_STATUS Status;\r
+ EFI_IMAGE_SECTION_HEADER SectionHeader;\r
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
+ EFI_PHYSICAL_ADDRESS FixLoaddingAddress;\r
+ UINT16 Index;\r
+ UINTN Size; \r
+ UINT16 NumberOfSections;\r
+ UINT64 ValueInSectionHeader;\r
+ \r
+ FixLoaddingAddress = 0;\r
+ Status = EFI_NOT_FOUND;\r
+ \r
+ //\r
+ // Get PeHeader pointer\r
+ //\r
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset);\r
+ SectionHeaderOffset = (UINTN)(\r
+ ImageContext->PeCoffHeaderOffset +\r
+ sizeof (UINT32) +\r
+ sizeof (EFI_IMAGE_FILE_HEADER) +\r
+ ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
+ );\r
+ NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;\r
+ \r
+ //\r
+ // Get base address from the first section header that doesn't point to code section.\r
+ //\r
+ for (Index = 0; Index < NumberOfSections; Index++) {\r
+ //\r
+ // Read section header from file\r
+ //\r
+ Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+ Status = ImageContext->ImageRead (\r
+ ImageContext->Handle,\r
+ SectionHeaderOffset,\r
+ &Size,\r
+ &SectionHeader\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ Status = EFI_NOT_FOUND;\r
+ \r
+ if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
+ //\r
+ // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header \r
+ // that doesn't point to code section in image header.So there is an assumption that when the feature is enabled,\r
+ // if a module with a loading address assigned by tools, the PointerToRelocations & PointerToLineNumbers fields\r
+ // should not be Zero, or else, these 2 fileds should be set to Zero\r
+ //\r
+ ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);\r
+ if (ValueInSectionHeader != 0) {\r
+ //\r
+ // Found first section header that doesn't point to code section in which uild tool saves the\r
+ // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields\r
+ // \r
+ FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressSmramBase + (INT64)ValueInSectionHeader);\r
+ //\r
+ // Check if the memory range is avaliable.\r
+ //\r
+ Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoaddingAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));\r
+ if (!EFI_ERROR(Status)) {\r
+ //\r
+ // The assigned address is valid. Return the specified loadding address\r
+ //\r
+ ImageContext->ImageAddress = FixLoaddingAddress;\r
+ }\r
+ }\r
+ break; \r
+ }\r
+ SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); \r
+ }\r
+ DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r\n", FixLoaddingAddress, Status));\r
+ return Status;\r
+}\r
/**\r
Loads an EFI image into SMRAM.\r
\r
}\r
return Status;\r
}\r
-\r
- PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);\r
- DstBuffer = (UINTN)(-1);\r
- \r
- Status = SmmAllocatePages (\r
- AllocateMaxAddress,\r
- EfiRuntimeServicesCode,\r
- PageCount,\r
- &DstBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- if (Buffer != NULL) {\r
- Status = gBS->FreePool (Buffer);\r
+ //\r
+ // if Loading module at Fixed Address feature is enabled, then cut out a memory range started from TESG BASE\r
+ // to hold the Smm driver code\r
+ //\r
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+ //\r
+ // Get the fixed loading address assigned by Build tool\r
+ //\r
+ Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Since the memory range to load Smm core alreay been cut out, so no need to allocate and free this range\r
+ // following statements is to bypass SmmFreePages\r
+ //\r
+ PageCount = 0;\r
+ DstBuffer = (UINTN)gLoadModuleAtFixAddressSmramBase; \r
+ } else {\r
+ DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));\r
+ //\r
+ // allocate the memory to load the SMM driver\r
+ //\r
+ PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+ DstBuffer = (UINTN)(-1);\r
+ \r
+ Status = SmmAllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiRuntimeServicesCode,\r
+ PageCount,\r
+ &DstBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ if (Buffer != NULL) {\r
+ Status = gBS->FreePool (Buffer);\r
+ } \r
+ return Status;\r
+ } \r
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;\r
}\r
- return Status;\r
+ } else {\r
+ PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+ DstBuffer = (UINTN)(-1);\r
+ \r
+ Status = SmmAllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiRuntimeServicesCode,\r
+ PageCount,\r
+ &DstBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ if (Buffer != NULL) {\r
+ Status = gBS->FreePool (Buffer);\r
+ }\r
+ return Status;\r
+ }\r
+ \r
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;\r
}\r
-\r
- ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;\r
//\r
// Align buffer on section boundry\r
//\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/DevicePathLib.h> \r
#include <Library/UefiLib.h> \r
-#include <Library/UefiBootServicesTableLib.h> \r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/PcdLib.h>\r
\r
#include "PiSmmCorePrivateData.h"\r
\r
extern SMM_CORE_PRIVATE_DATA *gSmmCorePrivate;\r
extern EFI_SMM_SYSTEM_TABLE2 gSmmCoreSmst;\r
extern LIST_ENTRY gHandleList;\r
+extern EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressSmramBase;\r
\r
/**\r
Called to initialize the memory service.\r
\r
[Packages]\r
MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
\r
[LibraryClasses]\r
UefiDriverEntryPoint\r
UefiLib \r
UefiBootServicesTableLib \r
MemoryAllocationLib\r
+ PcdLib\r
\r
[Protocols]\r
gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODUCED\r
gEfiDevicePathProtocolGuid # PROTOCOL SOMETIMES_CONSUMED\r
\r
+[Pcd]\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber # SIMETIMES_CONSUMED \r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable # ALWAYS_CONSUMED\r
+ \r
[Guids]\r
gAprioriGuid # ALWAYS_CONSUMED\r
gEfiEventDxeDispatchGuid # ALWAYS_CONSUMED\r
\r
#include <Guid/EventGroup.h>\r
#include <Guid/EventLegacyBios.h>\r
+#include <Guid/LoadModuleAtFixedAddress.h>\r
\r
#include <Library/BaseLib.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DxeServicesTableLib.h>\r
#include <Library/UefiLib.h>\r
#include <Library/UefiRuntimeLib.h>\r
+#include <Library/PcdLib.h>\r
\r
#include "PiSmmCorePrivateData.h"\r
\r
\r
return NULL;\r
}\r
+/**\r
+ Get the fixed loadding address from image header assigned by build tool. This function only be called\r
+ when Loading module at Fixed address feature enabled.\r
\r
+ @param ImageContext Pointer to the image context structure that describes the PE/COFF\r
+ image that needs to be examined by this function.\r
+ @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .\r
+ @retval EFI_NOT_FOUND The image has no assigned fixed loadding address.\r
+**/\r
+EFI_STATUS\r
+GetPeCoffImageFixLoadingAssignedAddress(\r
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
+ )\r
+{\r
+ UINTN SectionHeaderOffset;\r
+ EFI_STATUS Status;\r
+ EFI_IMAGE_SECTION_HEADER SectionHeader;\r
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
+ EFI_PHYSICAL_ADDRESS FixLoaddingAddress;\r
+ UINT16 Index;\r
+ UINTN Size;\r
+ UINT16 NumberOfSections;\r
+ EFI_PHYSICAL_ADDRESS SmramBase;\r
+ UINT64 SmmCodeSize;\r
+ UINT64 ValueInSectionHeader;\r
+ //\r
+ // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber\r
+ //\r
+ SmmCodeSize = EFI_PAGES_TO_SIZE (PcdGet32(PcdLoadFixAddressSmmCodePageNumber));\r
+ \r
+ FixLoaddingAddress = 0;\r
+ Status = EFI_NOT_FOUND;\r
+ SmramBase = mCurrentSmramRange->CpuStart;\r
+ //\r
+ // Get PeHeader pointer\r
+ //\r
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset);\r
+ SectionHeaderOffset = (UINTN)(\r
+ ImageContext->PeCoffHeaderOffset +\r
+ sizeof (UINT32) +\r
+ sizeof (EFI_IMAGE_FILE_HEADER) +\r
+ ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
+ );\r
+ NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;\r
+\r
+ //\r
+ // Get base address from the first section header that doesn't point to code section.\r
+ //\r
+ for (Index = 0; Index < NumberOfSections; Index++) {\r
+ //\r
+ // Read section header from file\r
+ //\r
+ Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+ Status = ImageContext->ImageRead (\r
+ ImageContext->Handle,\r
+ SectionHeaderOffset,\r
+ &Size,\r
+ &SectionHeader\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ Status = EFI_NOT_FOUND;\r
+ \r
+ if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
+ //\r
+ // Build tool saves the offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields in the\r
+ // first section header that doesn't point to code section in image header. And there is an assumption that when the\r
+ // feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers\r
+ // fields should NOT be Zero, or else, these 2 fileds should be set to Zero\r
+ //\r
+ ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);\r
+ if (ValueInSectionHeader != 0) {\r
+ //\r
+ // Found first section header that doesn't point to code section in which uild tool saves the\r
+ // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields\r
+ //\r
+ FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(SmramBase + (INT64)ValueInSectionHeader);\r
+\r
+ if (SmramBase + SmmCodeSize > FixLoaddingAddress && SmramBase <= FixLoaddingAddress) {\r
+ //\r
+ // The assigned address is valid. Return the specified loadding address\r
+ //\r
+ ImageContext->ImageAddress = FixLoaddingAddress;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
+ }\r
+ DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r \n", FixLoaddingAddress, Status));\r
+ return Status;\r
+}\r
/**\r
Load the SMM Core image into SMRAM and executes the SMM Core from SMRAM.\r
\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
-\r
//\r
- // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR \r
- // specified by SmramRange\r
+ // if Loading module at Fixed Address feature is enabled, the SMM core driver will be loaded to \r
+ // the address assigned by build tool.\r
//\r
- PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+ //\r
+ // Get the fixed loading address assigned by Build tool\r
+ //\r
+ Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Since the memory range to load SMM CORE will be cut out in SMM core, so no need to allocate and free this range\r
+ //\r
+ PageCount = 0;\r
+ } else {\r
+ DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR: Loading module at fixed address at address failed\n"));\r
+ //\r
+ // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR \r
+ // specified by SmramRange\r
+ //\r
+ PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);\r
\r
- ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) == 0);\r
- ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));\r
+ ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) == 0);\r
+ ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));\r
\r
- SmramRange->PhysicalSize -= EFI_PAGES_TO_SIZE (PageCount);\r
- DestinationBuffer = SmramRange->CpuStart + SmramRange->PhysicalSize;\r
+ SmramRange->PhysicalSize -= EFI_PAGES_TO_SIZE (PageCount);\r
+ DestinationBuffer = SmramRange->CpuStart + SmramRange->PhysicalSize;\r
\r
- //\r
- // Align buffer on section boundry\r
- //\r
- ImageContext.ImageAddress = DestinationBuffer;\r
+ //\r
+ // Align buffer on section boundry\r
+ //\r
+ ImageContext.ImageAddress = DestinationBuffer;\r
+ }\r
+ } else {\r
+ //\r
+ // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR \r
+ // specified by SmramRange\r
+ //\r
+ PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+\r
+ ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) == 0);\r
+ ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));\r
+\r
+ SmramRange->PhysicalSize -= EFI_PAGES_TO_SIZE (PageCount);\r
+ DestinationBuffer = SmramRange->CpuStart + SmramRange->PhysicalSize;\r
+\r
+ //\r
+ // Align buffer on section boundry\r
+ //\r
+ ImageContext.ImageAddress = DestinationBuffer;\r
+ }\r
+ \r
ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);\r
\r
EFI_SMM_RESERVED_SMRAM_REGION *SmramResRegion;\r
UINT64 MaxSize;\r
VOID *Registration;\r
+ UINT64 SmmCodeSize;\r
+ EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE *LMFAConfigurationTable;\r
\r
//\r
// Fill in the image handle of the SMM IPL so the SMM Core can use this as the \r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_WARN, "SMM IPL failed to set SMRAM window to EFI_MEMORY_WB\n"));\r
} \r
-\r
+ //\r
+ // if Loading module at Fixed Address feature is enabled, save the SMRAM base to Load\r
+ // Modules At Fixed Address Configuration Table.\r
+ //\r
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+ //\r
+ // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber\r
+ //\r
+ SmmCodeSize = LShiftU64 (PcdGet32(PcdLoadFixAddressSmmCodePageNumber), EFI_PAGE_SHIFT);\r
+ //\r
+ // The SMRAM available memory is assumed to be larger than SmmCodeSize\r
+ //\r
+ ASSERT (mCurrentSmramRange->PhysicalSize > SmmCodeSize);\r
+ //\r
+ // Retrieve Load modules At fixed address configuration table and save the SMRAM base.\r
+ //\r
+ Status = EfiGetSystemConfigurationTable (\r
+ &gLoadFixedAddressConfigurationTableGuid,\r
+ (VOID **) &LMFAConfigurationTable\r
+ );\r
+ if (!EFI_ERROR (Status) && LMFAConfigurationTable != NULL) {\r
+ LMFAConfigurationTable->SmramBase = mCurrentSmramRange->CpuStart;\r
+ }\r
+ //\r
+ // Print the SMRAM base\r
+ //\r
+ DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: TSEG BASE is %x. \n", LMFAConfigurationTable->SmramBase));\r
+ }\r
//\r
// Load SMM Core into SMRAM and execute it from SMRAM\r
//\r
\r
[Packages]\r
MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
\r
[LibraryClasses]\r
UefiDriverEntryPoint\r
gEfiEventReadyToBootGuid # ALWAYS_CONSUMED\r
gEfiEventLegacyBootGuid # ALWAYS_CONSUMED\r
gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED\r
- \r
+ gLoadFixedAddressConfigurationTableGuid # SIMETIMES_CONSUMED\r
+\r
+[Pcd]\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber # SIMETIMES_CONSUMED \r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable # ALWAYS_CONSUMED\r
+\r
+ \r
[Depex]\r
gEfiSmmAccess2ProtocolGuid AND gEfiSmmControl2ProtocolGuid AND gEfiCpuArchProtocolGuid\r
} FREE_POOL_HEADER;\r
\r
LIST_ENTRY mSmmPoolLists[MAX_POOL_INDEX];\r
+//\r
+// To cache the SMRAM base since when Loading modules At fixed address feature is enabled, \r
+// all module is assigned an offset relative the SMRAM base in build time.\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressSmramBase = 0;\r
\r
/**\r
Called to initialize the memory service.\r
IN EFI_SMRAM_DESCRIPTOR *SmramRanges\r
)\r
{\r
- UINTN Index;\r
+ UINTN Index;\r
+ UINT64 SmmCodeSize;\r
+ UINTN CurrentSmramRangesIndex;\r
+ UINT64 MaxSize;\r
\r
//\r
// Initialize Pool list\r
for (Index = sizeof (mSmmPoolLists) / sizeof (*mSmmPoolLists); Index > 0;) {\r
InitializeListHead (&mSmmPoolLists[--Index]);\r
}\r
-\r
+ CurrentSmramRangesIndex = 0;\r
+ //\r
+ // If Loadding Module At fixed Address feature is enabled, cache the SMRAM base here\r
+ //\r
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+ //\r
+ // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber\r
+ //\r
+ SmmCodeSize = LShiftU64 (PcdGet32(PcdLoadFixAddressSmmCodePageNumber), EFI_PAGE_SHIFT);\r
+ \r
+ //\r
+ // Find the largest SMRAM range between 1MB and 4GB that is at least 256KB - 4K in size\r
+ //\r
+ for (Index = 0, MaxSize = SIZE_256KB - EFI_PAGE_SIZE; Index < SmramRangeCount; Index++) {\r
+ if (SmramRanges[Index].CpuStart >= BASE_1MB) {\r
+ if ((SmramRanges[Index].CpuStart + SmramRanges[Index].PhysicalSize) <= BASE_4GB) {\r
+ if (SmramRanges[Index].PhysicalSize >= MaxSize) {\r
+ MaxSize = SmramRanges[Index].PhysicalSize;\r
+ CurrentSmramRangesIndex = Index;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ gLoadModuleAtFixAddressSmramBase = SmramRanges[CurrentSmramRangesIndex].CpuStart;\r
+ \r
+ //\r
+ // cut out a memory range from this SMRAM range with the size SmmCodeSize to hold SMM driver code\r
+ // A notable thing is that SMM core is already loaded into this range.\r
+ //\r
+ SmramRanges[CurrentSmramRangesIndex].CpuStart = SmramRanges[CurrentSmramRangesIndex].CpuStart + SmmCodeSize; \r
+ SmramRanges[CurrentSmramRangesIndex].PhysicalSize = SmramRanges[CurrentSmramRangesIndex].PhysicalSize - SmmCodeSize;\r
+ }\r
//\r
// Initialize free SMRAM regions\r
//\r
SmramRanges[Index].RegionState\r
);\r
}\r
+\r
}\r
\r
/**\r
\r
typedef struct {\r
EFI_PHYSICAL_ADDRESS DxeCodeTopAddress; ///< The top address below which the Dxe runtime code and below which the Dxe runtime/boot code and PEI code.\r
- EFI_PHYSICAL_ADDRESS TsegBase; ///< Tseg base. build tool will assigned an offset relative to Tseg base to SMM driver\r
+ EFI_PHYSICAL_ADDRESS SmramBase; ///< SMM RAME base. build tool will assigned an offset relative to SMRAM base for SMM driver\r
} EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE;\r
\r
#endif\r