]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Enable "Load Module At fixed Address" feature in SMM Core
authorjchen20 <jchen20@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 3 Mar 2010 05:45:50 +0000 (05:45 +0000)
committerjchen20 <jchen20@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 3 Mar 2010 05:45:50 +0000 (05:45 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10166 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Core/PiSmmCore/Dispatcher.c
MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
MdeModulePkg/Core/PiSmmCore/Pool.c
MdeModulePkg/Include/Guid/LoadModuleAtFixedAddress.h

index 9e1a77890079e9f4907d17d4bee60080f17c2fe7..9625eabd9147f29d714ca17f9c69b8e745f9a558 100644 (file)
@@ -122,6 +122,176 @@ FV_FILEPATH_DEVICE_PATH  mFvDevicePath;
 //\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
@@ -258,24 +428,63 @@ SmmLoadImage (
     }\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
index 2926f90d35ee6717222a7b52eae7d470d9b763a5..1cbae1ca5a855f028ae8e6eb1735df50ace8a055 100644 (file)
@@ -41,7 +41,8 @@
 #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
@@ -178,6 +179,7 @@ typedef struct {
 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
index 5f38065c0c0bb27ce0e5efe9c5b9b2036c904a89..63296bc99e3bbb931759994f2fa0e3a78b102c0e 100644 (file)
@@ -39,6 +39,7 @@
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
   \r
 [LibraryClasses]\r
   UefiDriverEntryPoint\r
@@ -52,6 +53,7 @@
   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
index 1029a077794cb23fe8daf7bd5eaa1e713ab97af9..ff7eff73bfb08976b3f72fa4f139bbd0c804533b 100644 (file)
@@ -24,6 +24,7 @@
 \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
@@ -35,6 +36,7 @@
 #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
@@ -703,7 +705,101 @@ GetSectionInAnyFv (
   \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
@@ -749,23 +845,58 @@ ExecuteSmmCoreFromSmram (
   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
@@ -847,6 +978,8 @@ SmmIplEntry (
   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
@@ -954,7 +1087,34 @@ SmmIplEntry (
     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
index 1c4c2af4543b8a56e3809d18ccd462bda55b7fa2..d6c33dab3044e54ac1d937dd92bcf996d5767aff 100644 (file)
@@ -33,6 +33,7 @@
 \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
index d7f80f4f8c2448b776a5c2f84066607d23c55d6b..10a85c47abafb4d122092a84fbe49db8df6823ea 100644 (file)
@@ -42,6 +42,11 @@ typedef struct {
 } 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
@@ -56,7 +61,10 @@ SmmInitializeMemoryServices (
   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
@@ -64,7 +72,38 @@ SmmInitializeMemoryServices (
   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
@@ -76,6 +115,7 @@ SmmInitializeMemoryServices (
       SmramRanges[Index].RegionState\r
       );\r
   }\r
+\r
 }\r
 \r
 /**\r
index 070430db9c4d78f43fb9d652b725e320d6e7c72b..a04e0b224dd4291c73412033cd7ed5ccdf9982c6 100644 (file)
@@ -28,7 +28,7 @@ extern EFI_GUID gLoadFixedAddressConfigurationTableGuid;
 \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