]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Enable the Load Module At fixed Address feature
authorjchen20 <jchen20@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 5 Feb 2010 07:54:16 +0000 (07:54 +0000)
committerjchen20 <jchen20@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 5 Feb 2010 07:54:16 +0000 (07:54 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9937 6f19259b-4bc3-4df7-8a09-765794883524

12 files changed:
MdeModulePkg/Core/Dxe/DxeMain.h
MdeModulePkg/Core/Dxe/DxeMain.inf
MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
MdeModulePkg/Core/Dxe/Gcd/Gcd.c
MdeModulePkg/Core/Dxe/Image/Image.c
MdeModulePkg/Core/Dxe/Mem/Page.c
MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
MdeModulePkg/Core/Pei/Image/Image.c
MdeModulePkg/Core/Pei/PeiMain.h
MdeModulePkg/Core/Pei/PeiMain.inf
MdeModulePkg/Include/Guid/LoadModuleAtFixedAddress.h [new file with mode: 0644]
MdeModulePkg/MdeModulePkg.dec

index 1c496bd8bdbb61cf8f907fd10d26244eb94f04b6..2f7f8b5ea0a6395caf0585f1045049d1d631ce2c 100644 (file)
@@ -60,7 +60,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Guid/MemoryAllocationHob.h>\r
 #include <Guid/EventLegacyBios.h>\r
 #include <Guid/EventGroup.h>\r
 #include <Guid/MemoryAllocationHob.h>\r
 #include <Guid/EventLegacyBios.h>\r
 #include <Guid/EventGroup.h>\r
-\r
+#include <Guid/LoadModuleAtFixedAddress.h>\r
 \r
 #include <Library/DxeCoreEntryPoint.h>\r
 #include <Library/DebugLib.h>\r
 \r
 #include <Library/DxeCoreEntryPoint.h>\r
 #include <Library/DebugLib.h>\r
@@ -81,6 +81,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/TimerLib.h>\r
 #include <Library/DxeServicesLib.h>\r
 \r
 #include <Library/TimerLib.h>\r
 #include <Library/DxeServicesLib.h>\r
 \r
+\r
 //\r
 // attributes for reserved memory before it is promoted to system memory\r
 //\r
 //\r
 // attributes for reserved memory before it is promoted to system memory\r
 //\r
@@ -204,6 +205,8 @@ extern EFI_MEMORY_TYPE_INFORMATION              gMemoryTypeInformation[EfiMaxMem
 extern BOOLEAN                                  gDispatcherRunning;\r
 extern EFI_RUNTIME_ARCH_PROTOCOL                gRuntimeTemplate;\r
 \r
 extern BOOLEAN                                  gDispatcherRunning;\r
 extern EFI_RUNTIME_ARCH_PROTOCOL                gRuntimeTemplate;\r
 \r
+extern EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE    gLoadModuleAtFixAddressConfigurationTable;\r
+extern BOOLEAN                                       gLoadFixedAddressCodeMemoryReady;\r
 //\r
 // Service Initialization Functions\r
 //\r
 //\r
 // Service Initialization Functions\r
 //\r
index a5b90cf1dd732e2d3bd1d36837feee10f6f74985..3a32e1ff3104bb915a4129a71079e1dededb0dd1 100644 (file)
   gEfiDxeServicesTableGuid                      ## CONSUMES ## GUID\r
   gEfiMemoryTypeInformationGuid                 ## CONSUMES ## GUID\r
   gEfiEventDxeDispatchGuid                      ## CONSUMES ## GUID\r
   gEfiDxeServicesTableGuid                      ## CONSUMES ## GUID\r
   gEfiMemoryTypeInformationGuid                 ## CONSUMES ## GUID\r
   gEfiEventDxeDispatchGuid                      ## CONSUMES ## GUID\r
+  gLoadFixedAddressConfigurationTableGuid       ## SOMETIMES_CONSUMES\r
   \r
 \r
 [Protocols]\r
   \r
 \r
 [Protocols]\r
 \r
 [FeaturePcd.common]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport         ## CONSUMES\r
 \r
 [FeaturePcd.common]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport         ## CONSUMES\r
+\r
+[FixedPcd.common]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable           ## CONSUMES\r
+\r
+[Pcd]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber    ## SOMETIMES_CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressRuntimeCodePageNumber     ## SOMETIMES_CONSUMES
\ No newline at end of file
index 52f9437b9e47194eb44b3e286a004864deb82d1e..5d1d6df20293a63c31f05bed08905c2364717669 100644 (file)
@@ -210,6 +210,11 @@ EFI_DECOMPRESS_PROTOCOL  gEfiDecompress = {
 };\r
 \r
 //\r
 };\r
 \r
 //\r
+// For Loading modules at fixed address feature, the configuration table is to cache the top address below which to load \r
+// Runtime code&boot time code \r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE    gLoadModuleAtFixAddressConfigurationTable;\r
+\r
 // Main entry point to the DXE Core\r
 //\r
 \r
 // Main entry point to the DXE Core\r
 //\r
 \r
@@ -284,7 +289,16 @@ DxeMain (
   //\r
   Status = CoreInstallConfigurationTable (&gEfiMemoryTypeInformationGuid, &gMemoryTypeInformation);\r
   ASSERT_EFI_ERROR (Status);\r
   //\r
   Status = CoreInstallConfigurationTable (&gEfiMemoryTypeInformationGuid, &gMemoryTypeInformation);\r
   ASSERT_EFI_ERROR (Status);\r
-\r
+  \r
+  //\r
+  // If Loading modules At fixed address feature is enabled, install Load moduels at fixed address \r
+  // Configuration Table so that user could easily to retrieve the top address to load Dxe and PEI\r
+  // Code and Tseg base to load SMM driver. \r
+  //\r
+  if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+    Status = CoreInstallConfigurationTable (&gLoadFixedAddressConfigurationTableGuid, &gLoadModuleAtFixAddressConfigurationTable);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
   //\r
   // Report Status Code here for DXE_ENTRY_POINT once it is available\r
   //\r
   //\r
   // Report Status Code here for DXE_ENTRY_POINT once it is available\r
   //\r
index 8081fef1b083cddc827ff4cc18fdb97bb0a6072a..2a026c0724402fb87e62a527246984b970050b23 100644 (file)
@@ -1765,6 +1765,7 @@ CoreInitializeMemoryServices (
   EFI_PHYSICAL_ADDRESS               HighAddress;\r
   EFI_HOB_RESOURCE_DESCRIPTOR        *MaxResourceHob;\r
   EFI_HOB_GUID_TYPE                  *GuidHob;\r
   EFI_PHYSICAL_ADDRESS               HighAddress;\r
   EFI_HOB_RESOURCE_DESCRIPTOR        *MaxResourceHob;\r
   EFI_HOB_GUID_TYPE                  *GuidHob;\r
+  UINT32                              ReservedCodePageNumber;\r
 \r
   //\r
   // Point at the first HOB.  This must be the PHIT HOB.\r
 \r
   //\r
   // Point at the first HOB.  This must be the PHIT HOB.\r
@@ -1795,7 +1796,17 @@ CoreInitializeMemoryServices (
   // Cache the PHIT HOB for later use\r
   //\r
   PhitHob = Hob.HandoffInformationTable;\r
   // Cache the PHIT HOB for later use\r
   //\r
   PhitHob = Hob.HandoffInformationTable;\r
-\r
+  \r
+  if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+       ReservedCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
+       ReservedCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
+   \r
+       //\r
+       // cache the Top address for loading modules at Fixed Address \r
+       //\r
+    gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress = PhitHob->EfiMemoryTop \r
+                                                                   + EFI_PAGES_TO_SIZE(ReservedCodePageNumber);\r
+  }\r
   //\r
   // See if a Memory Type Information HOB is available\r
   //\r
   //\r
   // See if a Memory Type Information HOB is available\r
   //\r
index 7e5cea7b76ad2d27a861e59f52d51c8f72febb4f..f516f26f489415a58b20441e911828b18eef2aac 100644 (file)
@@ -70,8 +70,12 @@ LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage  = {
   NULL,                       // RuntimeData\r
   NULL                        // LoadedImageDevicePath\r
 };\r
   NULL,                       // RuntimeData\r
   NULL                        // LoadedImageDevicePath\r
 };\r
-\r
-\r
+//\r
+// The field is define for Loading modules at fixed address feature to tracker the PEI code\r
+// memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page\r
+// available or not. \r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED    UINT64                *mDxeCodeMemoryRangeUsageBitMap=NULL;\r
 \r
 /**\r
   Add the Image Services to EFI Boot Services Table and install the protocol\r
 \r
 /**\r
   Add the Image Services to EFI Boot Services Table and install the protocol\r
@@ -202,7 +206,170 @@ CoreReadImageFile (
   CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);\r
   return EFI_SUCCESS;\r
 }\r
   CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);\r
   return EFI_SUCCESS;\r
 }\r
+/**\r
+  To check memory usage bit map arry to figure out if the memory range the image will be loaded in 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                             DxeCodePageNumber;\r
+   UINT64                             DxeCodeSize; \r
+   EFI_PHYSICAL_ADDRESS               DxeCodeBase;\r
+   UINTN                              BaseOffsetPageNumber;\r
+   UINTN                              TopOffsetPageNumber;\r
+   UINTN                              Index;\r
+   //\r
+   // The DXE code range includes RuntimeCodePage range and Boot time code range.\r
+   //  \r
+   DxeCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
+   DxeCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
+   DxeCodeSize       = EFI_PAGES_TO_SIZE(DxeCodePageNumber);\r
+   DxeCodeBase       =  gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - DxeCodeSize;\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 (mDxeCodeMemoryRangeUsageBitMap == NULL) {\r
+     mDxeCodeMemoryRangeUsageBitMap = AllocateZeroPool(((DxeCodePageNumber/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 (!gLoadFixedAddressCodeMemoryReady || mDxeCodeMemoryRangeUsageBitMap == NULL) {\r
+     return EFI_NOT_FOUND;\r
+   }\r
+   //\r
+   // Test the memory range for loading the image in the DXE code range.\r
+   //\r
+   if (gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress <  ImageBase + ImageSize ||\r
+       DxeCodeBase >  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 - DxeCodeBase));\r
+   TopOffsetPageNumber  = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - DxeCodeBase));\r
+   for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+     if ((mDxeCodeMemoryRangeUsageBitMap[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
+     mDxeCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));\r
+   }\r
+   return  EFI_SUCCESS;   \r
+}\r
+/**\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
+   UINT16                             Index;\r
+   UINTN                              Size;\r
+   UINT16                             NumberOfSections;\r
+   IMAGE_FILE_HANDLE                  *Handle;\r
+   UINT64                             ValueInSectionHeader;\r
+                             \r
+\r
+   Status = EFI_NOT_FOUND;\r
\r
+   //\r
+   // Get PeHeader pointer\r
+   //\r
+   Handle = (IMAGE_FILE_HANDLE*)ImageContext->Handle;\r
+   ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )Handle->Source + 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, as well as ImageBase field of image header. And there is an \r
+       // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations  \r
+       // & PointerToLineNumbers 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
+         // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext \r
+         // hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset\r
+         // relative to top address\r
+         //\r
+         if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) < 0) {\r
+                ImageContext->ImageAddress = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress + (INT64)ImageContext->ImageAddress;\r
+         }\r
+         //\r
+         // Check if the memory range is avaliable.\r
+         //\r
+         Status = CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext->ImageAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));\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", ImageContext->ImageAddress, Status));\r
+   return Status;\r
+}\r
 /**\r
   Loads, relocates, and invokes a PE/COFF image\r
 \r
 /**\r
   Loads, relocates, and invokes a PE/COFF image\r
 \r
@@ -308,21 +475,43 @@ CoreLoadPeImage (
     // no modules whose preferred load addresses are below 1MB.\r
     //\r
     Status = EFI_OUT_OF_RESOURCES;\r
     // no modules whose preferred load addresses are below 1MB.\r
     //\r
     Status = EFI_OUT_OF_RESOURCES;\r
-    if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {\r
-      Status = CoreAllocatePages (\r
-                 AllocateAddress,\r
-                 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
-                 Image->NumberOfPages,\r
-                 &Image->ImageContext.ImageAddress\r
-                 );\r
-    }\r
-    if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {\r
-      Status = CoreAllocatePages (\r
-                 AllocateAnyPages,\r
-                 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
-                 Image->NumberOfPages,\r
-                 &Image->ImageContext.ImageAddress\r
-                 );\r
+    //\r
+    // If Loading Module At Fixed Address feature is enabled, the module should be loaded to\r
+    // a specified address.\r
+    //\r
+    if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 ) {\r
+      Status = GetPeCoffImageFixLoadingAssignedAddress (&(Image->ImageContext));\r
+\r
+      if (EFI_ERROR (Status))  {\r
+          //\r
+         // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.\r
+         //\r
+          DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));\r
+        \r
+          Status = CoreAllocatePages (\r
+                     AllocateAnyPages,\r
+                     (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
+                     Image->NumberOfPages,\r
+                     &Image->ImageContext.ImageAddress\r
+                     );         \r
+      } \r
+    } else {\r
+      if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {\r
+        Status = CoreAllocatePages (\r
+                   AllocateAddress,\r
+                   (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
+                   Image->NumberOfPages,\r
+                   &Image->ImageContext.ImageAddress\r
+                   );\r
+      }\r
+      if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {\r
+        Status = CoreAllocatePages (\r
+                   AllocateAnyPages,\r
+                   (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
+                   Image->NumberOfPages,\r
+                   &Image->ImageContext.ImageAddress\r
+                   );\r
+      }\r
     }\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
@@ -355,9 +544,9 @@ CoreLoadPeImage (
 \r
   Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
   if (!Image->ImageContext.IsTeImage) {\r
 \r
   Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
   if (!Image->ImageContext.IsTeImage) {\r
-         Image->ImageContext.ImageAddress =\r
-             (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &\r
-             ~((UINTN)Image->ImageContext.SectionAlignment - 1);\r
+    Image->ImageContext.ImageAddress =\r
+        (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &\r
+        ~((UINTN)Image->ImageContext.SectionAlignment - 1);\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
index 4f31b5f57f5e5fd04f1f30637e430e7973f799c3..2a99507c585bcb9786d7df641397ebd6a3f47465 100644 (file)
@@ -89,7 +89,12 @@ EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = {
   { EfiPalCode,                 0 },\r
   { EfiMaxMemoryType,           0 }\r
 };\r
   { EfiPalCode,                 0 },\r
   { EfiMaxMemoryType,           0 }\r
 };\r
-\r
+//\r
+// Only used when load module at fixed address feature is enabled. True means the memory is alreay successfully allocated\r
+// and ready to load the module in to specified address.or else, the memory is not ready and module will be loaded at a \r
+//  address assigned by DXE core.\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED   BOOLEAN       gLoadFixedAddressCodeMemoryReady = FALSE;\r
 \r
 /**\r
   Enter critical section by gaining lock on gMemoryLock.\r
 \r
 /**\r
   Enter critical section by gaining lock on gMemoryLock.\r
@@ -419,7 +424,70 @@ PromoteMemoryResource (
 \r
   return;\r
 }\r
 \r
   return;\r
 }\r
+/**\r
+  This function try to allocate Runtime code & Boot time code memory range. If LMFA enabled, 2 patchable PCD \r
+  PcdLoadFixAddressRuntimeCodePageNumber & PcdLoadFixAddressBootTimeCodePageNumber which are set by tools will record the \r
+  size of boot time and runtime code.\r
 \r
 \r
+**/\r
+VOID\r
+CoreLoadingFixedAddressHook (\r
+  VOID\r
+  )\r
+{\r
+   UINT32                     RuntimeCodePageNumber;\r
+   UINT32                     BootTimeCodePageNumber;\r
+   EFI_PHYSICAL_ADDRESS       RuntimeCodeBase;\r
+   EFI_PHYSICAL_ADDRESS       BootTimeCodeBase;\r
+   EFI_STATUS                 Status;\r
+\r
+   //\r
+   // Make sure these 2 areas are not initialzied.\r
+   //\r
+   if (!gLoadFixedAddressCodeMemoryReady) {   \r
+     RuntimeCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
+     BootTimeCodePageNumber= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
+     RuntimeCodeBase       = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - EFI_PAGES_TO_SIZE (RuntimeCodePageNumber));\r
+     BootTimeCodeBase      = (EFI_PHYSICAL_ADDRESS)(RuntimeCodeBase - EFI_PAGES_TO_SIZE (BootTimeCodePageNumber));\r
+     //\r
+     // Try to allocate runtime memory.\r
+     //\r
+     Status = CoreAllocatePages (\r
+                       AllocateAddress,\r
+                       EfiRuntimeServicesCode,\r
+                       RuntimeCodePageNumber,\r
+                       &RuntimeCodeBase\r
+                       );\r
+     if (EFI_ERROR(Status)) {\r
+       //\r
+       // Runtime memory allocation failed \r
+       //\r
+       return;\r
+     }\r
+     //\r
+     // Try to allocate boot memory.\r
+     //\r
+     Status = CoreAllocatePages (\r
+                       AllocateAddress,\r
+                       EfiBootServicesCode,\r
+                       BootTimeCodePageNumber,\r
+                       &BootTimeCodeBase\r
+                       );\r
+     if (EFI_ERROR(Status)) {\r
+       //\r
+        // boot memory allocation failed. Free Runtime code range and will try the allocation again when \r
+        // new memory range is installed.\r
+        //\r
+        CoreFreePages (\r
+              RuntimeCodeBase,\r
+              RuntimeCodePageNumber\r
+              );\r
+       return;\r
+     }\r
+     gLoadFixedAddressCodeMemoryReady = TRUE;\r
+   } \r
+   return;\r
+}  \r
 \r
 /**\r
   Called to initialize the memory map and add descriptors to\r
 \r
 /**\r
   Called to initialize the memory map and add descriptors to\r
@@ -448,7 +516,7 @@ CoreAddMemoryDescriptor (
   EFI_STATUS                  Status;\r
   UINTN                       Index;\r
   UINTN                       FreeIndex;\r
   EFI_STATUS                  Status;\r
   UINTN                       Index;\r
   UINTN                       FreeIndex;\r
-\r
+  \r
   if ((Start & EFI_PAGE_MASK) != 0) {\r
     return;\r
   }\r
   if ((Start & EFI_PAGE_MASK) != 0) {\r
     return;\r
   }\r
@@ -456,13 +524,19 @@ CoreAddMemoryDescriptor (
   if (Type >= EfiMaxMemoryType && Type <= 0x7fffffff) {\r
     return;\r
   }\r
   if (Type >= EfiMaxMemoryType && Type <= 0x7fffffff) {\r
     return;\r
   }\r
-\r
   CoreAcquireMemoryLock ();\r
   End = Start + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT) - 1;\r
   CoreAddRange (Type, Start, End, Attribute);\r
   CoreFreeMemoryMapStack ();\r
   CoreReleaseMemoryLock ();\r
 \r
   CoreAcquireMemoryLock ();\r
   End = Start + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT) - 1;\r
   CoreAddRange (Type, Start, End, Attribute);\r
   CoreFreeMemoryMapStack ();\r
   CoreReleaseMemoryLock ();\r
 \r
+  //\r
+  // If Loading Module At Fixed Address feature is enabled. try to allocate memory with Runtime code & Boot time code type\r
+  //\r
+  if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+    CoreLoadingFixedAddressHook();\r
+  }\r
+  \r
   //\r
   // Check to see if the statistics for the different memory types have already been established\r
   //\r
   //\r
   // Check to see if the statistics for the different memory types have already been established\r
   //\r
@@ -470,6 +544,7 @@ CoreAddMemoryDescriptor (
     return;\r
   }\r
 \r
     return;\r
   }\r
 \r
+  \r
   //\r
   // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array\r
   //\r
   //\r
   // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array\r
   //\r
@@ -481,7 +556,6 @@ CoreAddMemoryDescriptor (
     if (Type < 0 || Type > EfiMaxMemoryType) {\r
       continue;\r
     }\r
     if (Type < 0 || Type > EfiMaxMemoryType) {\r
       continue;\r
     }\r
-\r
     if (gMemoryTypeInformation[Index].NumberOfPages != 0) {\r
       //\r
       // Allocate pages for the current memory type from the top of available memory\r
     if (gMemoryTypeInformation[Index].NumberOfPages != 0) {\r
       //\r
       // Allocate pages for the current memory type from the top of available memory\r
@@ -549,7 +623,6 @@ CoreAddMemoryDescriptor (
     if (Type < 0 || Type > EfiMaxMemoryType) {\r
       continue;\r
     }\r
     if (Type < 0 || Type > EfiMaxMemoryType) {\r
       continue;\r
     }\r
-\r
     if (gMemoryTypeInformation[Index].NumberOfPages != 0) {\r
       CoreFreePages (\r
         mMemoryTypeStatistics[Type].BaseAddress,\r
     if (gMemoryTypeInformation[Index].NumberOfPages != 0) {\r
       CoreFreePages (\r
         mMemoryTypeStatistics[Type].BaseAddress,\r
index bdbb00b205f86dcec674c108743fe5a830811168..bceae0c62d7e7b131a09723eb8649766a3481cb0 100644 (file)
@@ -233,7 +233,326 @@ ShadowPeiCore(
   //\r
   return (VOID*) ((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);\r
 }\r
   //\r
   return (VOID*) ((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);\r
 }\r
+//\r
+// This is the minimum memory required by DxeCore initialization. When LMFA feature enabled,\r
+// This part of memory still need reserved on the very top of memory so that the DXE Core could  \r
+// use these memory for data initialization. This macro should be sync with the same marco\r
+// defined in DXE Core.\r
+//\r
+#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000\r
+/**\r
+  Hook function for Loading Module at Fixed Address feature\r
+  \r
+  This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. When feature is\r
+  configured as Load Modules at Fix Absolute Address, this function is to validate the top address assigned by user. When \r
+  feature is configured as Load Modules at Fixed Offset, the functino is to find the top address which is TOLM-TSEG in general.  \r
+  And also the function will re-install PEI memory. \r
 \r
 \r
+  @param PrivateData         Pointer to the private data passed in from caller\r
+\r
+**/\r
+VOID\r
+PeiLoadFixAddressHook(\r
+  IN PEI_CORE_INSTANCE           *PrivateData\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS               TopLoadingAddress;\r
+  UINT64                             PeiMemorySize;\r
+  UINT64                             TotalReservedMemorySize;\r
+  UINT64                             MemoryRangeEnd;\r
+  EFI_PHYSICAL_ADDRESS               HighAddress; \r
+  EFI_HOB_RESOURCE_DESCRIPTOR        *ResourceHob;\r
+  EFI_HOB_RESOURCE_DESCRIPTOR        *NextResourceHob;\r
+  EFI_HOB_RESOURCE_DESCRIPTOR        *CurrentResourceHob;\r
+  EFI_PEI_HOB_POINTERS               CurrentHob;\r
+  EFI_PEI_HOB_POINTERS               Hob;\r
+  EFI_PEI_HOB_POINTERS               NextHob;\r
+  EFI_PHYSICAL_ADDRESS               MaxMemoryBaseAddress;\r
+  UINT64                             MaxMemoryLength;\r
+  //\r
+  // Initialize Local Variables\r
+  //\r
+  CurrentResourceHob    = NULL;\r
+  ResourceHob           = NULL;\r
+  NextResourceHob       = NULL;\r
+  MaxMemoryBaseAddress  = 0;\r
+  MaxMemoryLength       = 0;\r
+  HighAddress           = 0;\r
+  TopLoadingAddress     = 0;\r
+  MemoryRangeEnd      = 0;\r
+  CurrentHob.Raw      = PrivateData->HobList.Raw;\r
+  PeiMemorySize = PrivateData->PhysicalMemoryLength;\r
+  //\r
+  // The top reserved memory include 3 parts: the topest range is for DXE core initialization with the size  MINIMUM_INITIAL_MEMORY_SIZE\r
+  // then RuntimeCodePage range and Boot time code range.\r
+  //  \r
+  TotalReservedMemorySize = EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber)+ PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber))\r
+                               + MINIMUM_INITIAL_MEMORY_SIZE;  \r
\r
+  DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= %x.\n", PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber)));\r
+  DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= %x.\n", PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)));\r
+  DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= %x.\n", PcdGet32(PcdLoadFixAddressPeiCodePageNumber)));   \r
+  //\r
+  // PEI memory range lies below the top reserved memory\r
+  // \r
+  TotalReservedMemorySize += PeiMemorySize;\r
+  DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = %lx.\n", TotalReservedMemorySize));\r
+  //\r
+  // Loop through the system memory typed hob to merge the adjacent memory range \r
+  //\r
+  for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
+    //                                                              \r
+    // See if this is a resource descriptor HOB                     \r
+    //\r
+    if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+      \r
+      ResourceHob = Hob.ResourceDescriptor;  \r
+      //\r
+      // If range described in this hob is not system memory or heigher than MAX_ADDRESS, ignored.\r
+      //\r
+      if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY &&\r
+          ResourceHob->PhysicalStart + ResourceHob->ResourceLength > MAX_ADDRESS)   {\r
+        continue;\r
+      }   \r
+      \r
+      for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(NextHob); NextHob.Raw = GET_NEXT_HOB(NextHob)) {       \r
+        if (NextHob.Raw == Hob.Raw){\r
+          continue;\r
+        }  \r
+        //\r
+        // See if this is a resource descriptor HOB\r
+        //\r
+        if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+      \r
+          NextResourceHob = NextHob.ResourceDescriptor;\r
+          //\r
+          // test if range described in this NextResourceHob is system memory and have the same attribute.\r
+          // Note: Here is a assumption that system memory should always be healthy even without test.\r
+          //    \r
+          if (NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
+             (((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute)&(~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0)){\r
+              \r
+              //\r
+              // See if the memory range described in ResourceHob and NextResourceHob is adjacent\r
+              //\r
+              if ((ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart && \r
+                    ResourceHob->PhysicalStart + ResourceHob->ResourceLength >= NextResourceHob->PhysicalStart)|| \r
+                  (ResourceHob->PhysicalStart >= NextResourceHob->PhysicalStart&&\r
+                     ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) {\r
+             \r
+                MemoryRangeEnd = ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength)>(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) ?\r
+                                     (ResourceHob->PhysicalStart + ResourceHob->ResourceLength):(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength);\r
+          \r
+                ResourceHob->PhysicalStart = (ResourceHob->PhysicalStart < NextResourceHob->PhysicalStart) ? \r
+                                                    ResourceHob->PhysicalStart : NextResourceHob->PhysicalStart;\r
+                \r
+               \r
+                ResourceHob->ResourceLength = (MemoryRangeEnd - ResourceHob->PhysicalStart);\r
+                \r
+                ResourceHob->ResourceAttribute = ResourceHob->ResourceAttribute & (~EFI_RESOURCE_ATTRIBUTE_TESTED);\r
+                //\r
+                // Delete the NextResourceHob by marking it as unused.\r
+                //\r
+                GET_HOB_TYPE (NextHob) = EFI_HOB_TYPE_UNUSED;\r
+                \r
+              }\r
+           }\r
+        } \r
+      }\r
+    } \r
+  }\r
+  //\r
+  // Try to find and validate the TOP address.\r
+  //  \r
+  if ((INT64)FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) > 0 ) {\r
+    //\r
+    // The LMFA feature is enabled as load module at fixed absolute address.\r
+    //\r
+    TopLoadingAddress = (EFI_PHYSICAL_ADDRESS)FixedPcdGet64(PcdLoadModuleAtFixAddressEnable);\r
+    DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Loading module at fixed absolute address.\n"));\r
+    //\r
+    // validate the Address. Loop the resource descriptor HOB to make sure the address is in valid memory range\r
+    //\r
+    if ((TopLoadingAddress & EFI_PAGE_MASK) != 0) {\r
+      DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address %lx is invalid since top address should be page align. \n", TopLoadingAddress)); \r
+      ASSERT (FALSE);    \r
+    }\r
+    //\r
+    // Search for a memory region that is below MAX_ADDRESS and in which TopLoadingAddress lies \r
+    //\r
+    for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
+      //\r
+      // See if this is a resource descriptor HOB\r
+      //\r
+      if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+\r
+        ResourceHob = Hob.ResourceDescriptor;\r
+        //\r
+        // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS\r
+        //    \r
+        if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
+            ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {\r
+            //\r
+            // See if Top address specified by user is valid.\r
+            //\r
+            if (ResourceHob->PhysicalStart + TotalReservedMemorySize < TopLoadingAddress && \r
+                (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MINIMUM_INITIAL_MEMORY_SIZE) >= TopLoadingAddress) {\r
+              CurrentResourceHob = ResourceHob; \r
+              CurrentHob = Hob;\r
+              break;\r
+            }\r
+        }\r
+      }  \r
+    }  \r
+    if (CurrentResourceHob != NULL) {\r
+      DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO:Top Address %lx is valid \n",  TopLoadingAddress));\r
+      TopLoadingAddress += MINIMUM_INITIAL_MEMORY_SIZE; \r
+    } else {\r
+      DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address %lx is invalid \n",  TopLoadingAddress)); \r
+      DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The recommended Top Address for the platform is: \n")); \r
+      //\r
+      // Print the recomended Top address range.\r
+      // \r
+      for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
+        //\r
+        // See if this is a resource descriptor HOB\r
+        //\r
+        if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+        \r
+          ResourceHob = Hob.ResourceDescriptor;\r
+          //\r
+          // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS\r
+          //    \r
+          if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
+              ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {\r
+              //\r
+              // See if Top address specified by user is valid.\r
+              //\r
+              if (ResourceHob->ResourceLength > TotalReservedMemorySize) {\r
+                 DEBUG ((EFI_D_INFO, "(%lx, %lx)\n",  \r
+                          (ResourceHob->PhysicalStart + TotalReservedMemorySize -MINIMUM_INITIAL_MEMORY_SIZE), \r
+                          (ResourceHob->PhysicalStart + ResourceHob->ResourceLength -MINIMUM_INITIAL_MEMORY_SIZE) \r
+                        )); \r
+              }\r
+          }\r
+        }\r
+      }  \r
+      //\r
+      // Assert here \r
+      //\r
+      ASSERT (FALSE);      \r
+    }     \r
+  } else {\r
+    //\r
+    // The LMFA feature is enabled as load module at fixed offset relative to TOLM\r
+    // Parse the Hob list to find the topest available memory. Generally it is (TOLM - TSEG)\r
+    //\r
+    //\r
+    // Search for a tested memory region that is below MAX_ADDRESS\r
+    //\r
+    for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
+      //\r
+      // See if this is a resource descriptor HOB \r
+      //\r
+      if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+        \r
+        ResourceHob = Hob.ResourceDescriptor;                                                                                                                                                                                                                               \r
+        //\r
+        // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS\r
+        //\r
+        if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && \r
+            ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS &&\r
+            ResourceHob->ResourceLength > TotalReservedMemorySize) {\r
+          //\r
+          // See if this is the highest largest system memory region below MaxAddress\r
+          //\r
+          if (ResourceHob->PhysicalStart > HighAddress) {\r
+             CurrentResourceHob = ResourceHob;\r
+             CurrentHob = Hob;\r
+             HighAddress = CurrentResourceHob->PhysicalStart;\r
+          }\r
+        }\r
+      }  \r
+    }\r
+    if (CurrentResourceHob == NULL) {\r
+      DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The System Memory is too small\n")); \r
+      //\r
+      // Assert here \r
+      //\r
+      ASSERT (FALSE);      \r
+    } else {\r
+      TopLoadingAddress = CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength ; \r
+    }         \r
+  }\r
+  \r
+  if (CurrentResourceHob != NULL) {\r
+    //\r
+    // rebuild hob for PEI memmory and reserved memory\r
+    //\r
+    BuildResourceDescriptorHob (\r
+      EFI_RESOURCE_SYSTEM_MEMORY,                       // MemoryType,\r
+      (\r
+      EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
+      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
+      EFI_RESOURCE_ATTRIBUTE_TESTED |\r
+      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
+      EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
+      EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
+      EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
+      ),\r
+      (TopLoadingAddress - TotalReservedMemorySize),                             // MemoryBegin\r
+      TotalReservedMemorySize      // MemoryLength\r
+    );\r
+    //\r
+    // rebuild hob for the remain memory if necessary\r
+    //\r
+    if (CurrentResourceHob->PhysicalStart < TopLoadingAddress - TotalReservedMemorySize) {\r
+      BuildResourceDescriptorHob (\r
+        EFI_RESOURCE_SYSTEM_MEMORY,                       // MemoryType,\r
+        (\r
+         EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
+         EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
+         EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
+         EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
+         EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
+         EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
+         ),\r
+         CurrentResourceHob->PhysicalStart,                             // MemoryBegin\r
+         (TopLoadingAddress - TotalReservedMemorySize - CurrentResourceHob->PhysicalStart)      // MemoryLength\r
+       );\r
+    }\r
+    if (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength  > TopLoadingAddress ) {\r
+      BuildResourceDescriptorHob (\r
+        EFI_RESOURCE_SYSTEM_MEMORY,                     \r
+        (\r
+         EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
+         EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
+         EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
+         EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
+         EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
+         EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
+         ),\r
+         TopLoadingAddress,                            \r
+         (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength  - TopLoadingAddress)     \r
+       );\r
+    }\r
+    //\r
+    // Delete CurrentHob by marking it as unused since the the memory range described by is rebuilt.\r
+    //\r
+    GET_HOB_TYPE (CurrentHob) = EFI_HOB_TYPE_UNUSED;         \r
+  }\r
+\r
+  //\r
+  // Cache the top address for Loading Module at Fixed Address feature\r
+  //\r
+  PrivateData->LoadModuleAtFixAddressTopAddress = TopLoadingAddress - MINIMUM_INITIAL_MEMORY_SIZE;\r
+  DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Top address = %lx\n",  PrivateData->LoadModuleAtFixAddressTopAddress)); \r
+  //\r
+  // reinstall the PEI memory relative to TopLoadingAddress\r
+  //\r
+  PrivateData->PhysicalMemoryBegin   = TopLoadingAddress - TotalReservedMemorySize;\r
+  PrivateData->FreePhysicalMemoryTop = PrivateData->PhysicalMemoryBegin + PeiMemorySize;\r
+}\r
 /**\r
   Conduct PEIM dispatch.\r
 \r
 /**\r
   Conduct PEIM dispatch.\r
 \r
@@ -277,6 +596,7 @@ PeiDispatcher (
   UINTN                               OldCheckingTop;\r
   UINTN                               OldCheckingBottom;\r
   PEI_CORE_FV_HANDLE                  *CoreFvHandle;\r
   UINTN                               OldCheckingTop;\r
   UINTN                               OldCheckingBottom;\r
   PEI_CORE_FV_HANDLE                  *CoreFvHandle;\r
+  VOID                                *LoadFixPeiCodeBegin;\r
 \r
   PeiServices = (CONST EFI_PEI_SERVICES **) &Private->PS;\r
   PeimEntryPoint = NULL;\r
 \r
   PeiServices = (CONST EFI_PEI_SERVICES **) &Private->PS;\r
   PeimEntryPoint = NULL;\r
@@ -476,6 +796,13 @@ PeiDispatcher (
                       ));\r
               DEBUG_CODE_END ();\r
               \r
                       ));\r
               DEBUG_CODE_END ();\r
               \r
+              if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+                //\r
+                // Loading Module at Fixed Address is enabled\r
+                //\r
+                PeiLoadFixAddressHook(Private);\r
+              }\r
+              \r
               //\r
               // Reserve the size of new stack at bottom of physical memory\r
               //\r
               //\r
               // Reserve the size of new stack at bottom of physical memory\r
               //\r
@@ -613,6 +940,19 @@ PeiDispatcher (
               //\r
               PrivateInMem->PeimDispatcherReenter  = TRUE;\r
               \r
               //\r
               PrivateInMem->PeimDispatcherReenter  = TRUE;\r
               \r
+              if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+                //\r
+                // if Loading Module at Fixed Address is enabled, This is the first invoke to page \r
+                // allocation for Pei Core segment. This memory segment should be reserved for loading PEIM\r
+                //\r
+                LoadFixPeiCodeBegin = AllocatePages((UINTN)PcdGet32(PcdLoadFixAddressPeiCodePageNumber));\r
+                DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PeiCodeBegin = %x, PeiCodeTop= %x\n", (UINTN)LoadFixPeiCodeBegin, ((UINTN)LoadFixPeiCodeBegin) + PcdGet32(PcdLoadFixAddressPeiCodePageNumber) * EFI_PAGE_SIZE));                 \r
+                //\r
+                // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array.\r
+                // Every bit in the array indicate the status of the corresponding memory page, available or not\r
+                //\r
+                PrivateInMem->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32(PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof(UINT64));\r
+              }\r
               //\r
               // Shadow PEI Core. When permanent memory is avaiable, shadow\r
               // PEI Core and PEIMs to get high performance.\r
               //\r
               // Shadow PEI Core. When permanent memory is avaiable, shadow\r
               // PEI Core and PEIMs to get high performance.\r
index 63c8868894a163e92a4fcfc25649376c9f34eb1e..c2683762b73e4f62abe5e6e0eed3245e2c568cc0 100644 (file)
@@ -1,14 +1,14 @@
 /** @file\r
   Pei Core Load Image Support\r
 /** @file\r
   Pei Core Load Image Support\r
-  \r
-Copyright (c) 2006 - 2010, Intel Corporation                                                         \r
-All rights reserved. This program and the accompanying materials                          \r
-are licensed and made available under the terms and conditions of the BSD License         \r
-which accompanies this distribution.  The full text of the license may be found at        \r
-http://opensource.org/licenses/bsd-license.php                                            \r
-                                                                                          \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Copyright (c) 2006 - 2010, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
 **/\r
 \r
 \r
 **/\r
 \r
@@ -96,7 +96,192 @@ GetImageReadFunction (
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
+/**\r
+  To check memory usage bit map arry to figure out if the memory range the image will be loaded in 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  Private                  Pointer to the private data passed in from caller\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  PEI_CORE_INSTANCE             *Private,\r
+  IN  EFI_PHYSICAL_ADDRESS          ImageBase,\r
+  IN  UINT32                        ImageSize\r
+  )\r
+{\r
+   UINT32                             DxeCodePageNumber;\r
+   UINT64                             ReservedCodeSize;\r
+   EFI_PHYSICAL_ADDRESS               PeiCodeBase;\r
+   UINT32                             BaseOffsetPageNumber;\r
+   UINT32                             TopOffsetPageNumber;\r
+   UINT32                             Index;\r
+   UINT64                             *MemoryUsageBitMap;\r
+   \r
+\r
+   //\r
+   // The reserved code range includes RuntimeCodePage range, Boot time code range and PEI code range.\r
+   //\r
+   DxeCodePageNumber = PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
+   DxeCodePageNumber += PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
+   ReservedCodeSize  = EFI_PAGES_TO_SIZE(DxeCodePageNumber + PcdGet32(PcdLoadFixAddressPeiCodePageNumber));\r
+   PeiCodeBase       = Private->LoadModuleAtFixAddressTopAddress - ReservedCodeSize;\r
+   \r
+   //\r
+   // Test the memory range for loading the image in the PEI code range.\r
+   //\r
+   if ((Private->LoadModuleAtFixAddressTopAddress - EFI_PAGES_TO_SIZE(DxeCodePageNumber)) < (ImageBase + ImageSize) ||\r
+       (PeiCodeBase > ImageBase)) {         \r
+     return EFI_NOT_FOUND; \r
+   }\r
+   \r
+   //\r
+   // Test if the memory is avalaible or not.\r
+   //\r
+   MemoryUsageBitMap    = Private->PeiCodeMemoryRangeUsageBitMap;  \r
+   BaseOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase - PeiCodeBase));\r
+   TopOffsetPageNumber  = EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - PeiCodeBase));\r
+   for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+     if ((MemoryUsageBitMap[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
+     MemoryUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));\r
+   }\r
+   return  EFI_SUCCESS;   \r
+}\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
+  @param Private                    Pointer to the private data passed in from caller\r
+\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
+**/\r
+EFI_STATUS\r
+GetPeCoffImageFixLoadingAssignedAddress(\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,\r
+  IN     PEI_CORE_INSTANCE             *Private\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
+\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
+   if (ImageContext->IsTeImage) {\r
+     //\r
+     // for TE image, the fix loadding address is saved in first section header that doesn't point\r
+     // to code section.\r
+     //\r
+     SectionHeaderOffset = sizeof (EFI_TE_IMAGE_HEADER);\r
+     NumberOfSections = ImgHdr->Te.NumberOfSections;\r
+   } else {\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, as well as ImageBase field of image header. A notable thing is\r
+       // that for PEIM, the value in ImageBase field may not be equal to the value in PointerToRelocations & PointerToLineNumbers because\r
+       // for XIP PEIM, ImageBase field holds the image base address running on the Flash. And PointerToRelocations & PointerToLineNumbers\r
+       // hold the image base address when it is shadow to the memory. And there is an assumption that when the feature is enabled, if a\r
+       // module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers fields should NOT be Zero, or\r
+       // 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.\r
+         //\r
+         if ((INT64)FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) > 0) {\r
+           //\r
+           // When LMFA feature is configured as Load Module at Fixed Absolute Address mode, PointerToRelocations & PointerToLineNumbers field\r
+           // hold the absolute address of image base runing in memory\r
+           //\r
+           FixLoaddingAddress = ValueInSectionHeader;\r
+         } else {\r
+           //\r
+           // When LMFA feature is configured as Load Module at Fixed offset mode, PointerToRelocations & PointerToLineNumbers field\r
+           // hold the offset relative to a platform-specific top address.\r
+           //\r
+           FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(Private->LoadModuleAtFixAddressTopAddress + (INT64)ValueInSectionHeader);\r
+         }\r
+         //\r
+         // Check if the memory range is avaliable.\r
+         //\r
+         Status = CheckAndMarkFixLoadingMemoryUsageBitMap (Private, FixLoaddingAddress, (UINT32) ImageContext->ImageSize);\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 %lx. Status= %r \n", FixLoaddingAddress, Status));\r
+   return Status;\r
+}\r
 /**\r
 \r
   Loads and relocates a PE/COFF image into memory.\r
 /**\r
 \r
   Loads and relocates a PE/COFF image into memory.\r
@@ -139,29 +324,40 @@ LoadAndRelocatePeCoffImage (
   // When Image has no reloc section, it can't be relocated into memory.\r
   //\r
   if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
   // When Image has no reloc section, it can't be relocated into memory.\r
   //\r
   if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
-    DEBUG ((EFI_D_INFO, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data));\r
+    DEBUG ((EFI_D_INFO|EFI_D_LOAD, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data));\r
   }\r
 \r
   //\r
   // Set default base address to current image address.\r
   //\r
   ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data;\r
   }\r
 \r
   //\r
   // Set default base address to current image address.\r
   //\r
   ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data;\r
-  \r
+\r
   //\r
   // Allocate Memory for the image when memory is ready, boot mode is not S3, and image is relocatable.\r
   //\r
   if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
   //\r
   // Allocate Memory for the image when memory is ready, boot mode is not S3, and image is relocatable.\r
   //\r
   if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
-    ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
+    if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+      Status = GetPeCoffImageFixLoadingAssignedAddress(&ImageContext, Private);\r
+      if (EFI_ERROR (Status)){\r
+        DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));\r
+        //\r
+        // The PEIM is not assiged valid address, try to allocate page to load it.\r
+        //\r
+        ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
+      }\r
+    } else {\r
+      ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
+    }\r
     ASSERT (ImageContext.ImageAddress != 0);\r
     if (ImageContext.ImageAddress == 0) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
     ASSERT (ImageContext.ImageAddress != 0);\r
     if (ImageContext.ImageAddress == 0) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
-    \r
+\r
     //\r
     // Skip the reserved space for the stripped PeHeader when load TeImage into memory.\r
     //\r
     if (ImageContext.IsTeImage) {\r
     //\r
     // Skip the reserved space for the stripped PeHeader when load TeImage into memory.\r
     //\r
     if (ImageContext.IsTeImage) {\r
-      ImageContext.ImageAddress = ImageContext.ImageAddress + \r
+      ImageContext.ImageAddress = ImageContext.ImageAddress +\r
                                   ((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize -\r
                                   sizeof (EFI_TE_IMAGE_HEADER);\r
     }\r
                                   ((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize -\r
                                   sizeof (EFI_TE_IMAGE_HEADER);\r
     }\r
@@ -197,8 +393,8 @@ LoadAndRelocatePeCoffImage (
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
-  Loads a PEIM into memory for subsequent execution. If there are compressed \r
-  images or images that need to be relocated into memory for performance reasons, \r
+  Loads a PEIM into memory for subsequent execution. If there are compressed\r
+  images or images that need to be relocated into memory for performance reasons,\r
   this service performs that transformation.\r
 \r
   @param PeiServices      An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
   this service performs that transformation.\r
 \r
   @param PeiServices      An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
@@ -245,7 +441,7 @@ PeiLoadImageLoadImage (
   }\r
 \r
   //\r
   }\r
 \r
   //\r
-  // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst \r
+  // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst\r
   // is true, TE will be searched first).\r
   //\r
   Status = PeiServicesFfsFindSectionData (\r
   // is true, TE will be searched first).\r
   //\r
   Status = PeiServicesFfsFindSectionData (\r
@@ -270,7 +466,7 @@ PeiLoadImageLoadImage (
       return Status;\r
     }\r
   }\r
       return Status;\r
     }\r
   }\r
-  \r
+\r
   //\r
   // If memory is installed, perform the shadow operations\r
   //\r
   //\r
   // If memory is installed, perform the shadow operations\r
   //\r
@@ -293,9 +489,9 @@ PeiLoadImageLoadImage (
   //\r
   Pe32Data    = (VOID *) ((UINTN) ImageAddress);\r
   *EntryPoint = ImageEntryPoint;\r
   //\r
   Pe32Data    = (VOID *) ((UINTN) ImageAddress);\r
   *EntryPoint = ImageEntryPoint;\r
-  \r
+\r
   Machine = PeCoffLoaderGetMachineType (Pe32Data);\r
   Machine = PeCoffLoaderGetMachineType (Pe32Data);\r
-  \r
+\r
   if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {\r
     if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) {\r
       return EFI_UNSUPPORTED;\r
   if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {\r
     if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) {\r
       return EFI_UNSUPPORTED;\r
@@ -309,7 +505,7 @@ PeiLoadImageLoadImage (
   if (ImageSizeArg != NULL) {\r
     *ImageSizeArg = ImageSize;\r
   }\r
   if (ImageSizeArg != NULL) {\r
     *ImageSizeArg = ImageSize;\r
   }\r
-  \r
+\r
   DEBUG_CODE_BEGIN ();\r
     CHAR8                              *AsciiString;\r
     CHAR8                              AsciiBuffer[512];\r
   DEBUG_CODE_BEGIN ();\r
     CHAR8                              *AsciiString;\r
     CHAR8                              AsciiBuffer[512];\r
@@ -327,12 +523,12 @@ PeiLoadImageLoadImage (
       //\r
       DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));\r
     }\r
       //\r
       DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));\r
     }\r
-    \r
+\r
     //\r
     // Print Module Name by PeImage PDB file name.\r
     //\r
     AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data);\r
     //\r
     // Print Module Name by PeImage PDB file name.\r
     //\r
     AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data);\r
-    \r
+\r
     if (AsciiString != NULL) {\r
       for (Index = (INT32) AsciiStrLen (AsciiString) - 1; Index >= 0; Index --) {\r
         if (AsciiString[Index] == '\\') {\r
     if (AsciiString != NULL) {\r
       for (Index = (INT32) AsciiStrLen (AsciiString) - 1; Index >= 0; Index --) {\r
         if (AsciiString[Index] == '\\') {\r
@@ -454,7 +650,7 @@ RelocationIsStrip (
 \r
 /**\r
   Routine to load image file for subsequent execution by LoadFile Ppi.\r
 \r
 /**\r
   Routine to load image file for subsequent execution by LoadFile Ppi.\r
-  If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE \r
+  If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE\r
   XIP image format is used.\r
 \r
   @param PeiServices     - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
   XIP image format is used.\r
 \r
   @param PeiServices     - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
@@ -500,9 +696,9 @@ PeiLoadImage (
                   );\r
     if (!EFI_ERROR (PpiStatus)) {\r
       Status = LoadFile->LoadFile (\r
                   );\r
     if (!EFI_ERROR (PpiStatus)) {\r
       Status = LoadFile->LoadFile (\r
-                          LoadFile, \r
-                          FileHandle, \r
-                          &ImageAddress, \r
+                          LoadFile,\r
+                          FileHandle,\r
+                          &ImageAddress,\r
                           &ImageSize,\r
                           EntryPoint,\r
                           AuthenticationState\r
                           &ImageSize,\r
                           EntryPoint,\r
                           AuthenticationState\r
@@ -560,10 +756,10 @@ InitializeImageServices (
     PeiServicesInstallPpi (PrivateData->XipLoadFile);\r
   } else {\r
     //\r
     PeiServicesInstallPpi (PrivateData->XipLoadFile);\r
   } else {\r
     //\r
-    // 2nd time we are running from memory so replace the XIP version with the \r
-    // new memory version. \r
+    // 2nd time we are running from memory so replace the XIP version with the\r
+    // new memory version.\r
     //\r
     //\r
-    PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList); \r
+    PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList);\r
   }\r
 }\r
 \r
   }\r
 }\r
 \r
index aa23cc57edae9caf6096233f78cde112c7f4682f..268aedf454ac0ab7f1f1f688ea77bb86f6968f06 100644 (file)
@@ -177,6 +177,18 @@ typedef struct{
   EFI_PHYSICAL_ADDRESS               FreePhysicalMemoryTop;\r
   VOID*                              ShadowedPeiCore;\r
   CACHE_SECTION_DATA                 CacheSection;\r
   EFI_PHYSICAL_ADDRESS               FreePhysicalMemoryTop;\r
   VOID*                              ShadowedPeiCore;\r
   CACHE_SECTION_DATA                 CacheSection;\r
+  //\r
+  // For Loading modules at fixed address feature to cache the top address below which the \r
+  // Runtime code, boot time code and PEI memory will be placed. Please note that the offset between this field \r
+  // and  PS should not be changed since maybe user could get this top address by using the offet to PS. \r
+  //\r
+  EFI_PHYSICAL_ADDRESS               LoadModuleAtFixAddressTopAddress;\r
+  //\r
+  // The field is define for Loading modules at fixed address feature to tracker the PEI code\r
+  // memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page\r
+  // available or not. \r
+  //\r
+  UINT64                            *PeiCodeMemoryRangeUsageBitMap;\r
 } PEI_CORE_INSTANCE;\r
 \r
 ///\r
 } PEI_CORE_INSTANCE;\r
 \r
 ///\r
index b2747bbd7ca93028eb7f6e14d3d8330646f605ce..2b8c4ad8b9784d70286056b4588df1300870010e 100644 (file)
   gEfiTemporaryRamSupportPpiGuid                ## CONSUMES\r
 \r
 [FixedPcd]\r
   gEfiTemporaryRamSupportPpiGuid                ## CONSUMES\r
 \r
 [FixedPcd]\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxFvSupported       ## CONSUMES\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeimPerFv         ## CONSUMES\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPpiSupported      ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxFvSupported             ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeimPerFv               ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPpiSupported            ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable      ## CONSUMES  \r
 \r
 [Pcd]  \r
   gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize                   ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst   ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport            ## CONSUMES\r
 \r
 [Pcd]  \r
   gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize                   ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst   ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport            ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressPeiCodePageNumber          ## SOMETIMES_CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber     ## SOMETIMES_CONSUMES \r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressRuntimeCodePageNumber      ## SOMETIMES_CONSUMES \r
   \r
   \r
diff --git a/MdeModulePkg/Include/Guid/LoadModuleAtFixedAddress.h b/MdeModulePkg/Include/Guid/LoadModuleAtFixedAddress.h
new file mode 100644 (file)
index 0000000..90bb246
--- /dev/null
@@ -0,0 +1,34 @@
+/** @file\r
+  This file defines:\r
+  A configuration Table Guid for Load module at fixed address. \r
+  This configuration table is to hold  the top address below which the Dxe runtime code and \r
+  boot time code will be loaded and Tseg base. When this feature is enabled, Build tools will assigned \r
+  module loading address relative to these 2 address.\r
+  \r
+\r
+Copyright (c) 2010, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __LOAD_MODULE_AT_FIX_ADDRESS_GUID_H__\r
+#define __LOAD_MODULE_AT_FIX_ADDRESS_GUID_H__\r
+\r
+#define EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE_GUID \\r
+  { 0x2CA88B53,0xD296,0x4080, { 0xA4,0xA5,0xCA,0xD9,0xBA,0xE2,0x4B,0x9} }\r
+\r
+\r
+extern EFI_GUID gLoadFixedAddressConfigurationTableGuid;\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_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE;\r
+\r
+#endif\r
index 68805d2f9536c7c58d384d894b55e19bf03a617c..d14cf8b56bfd96419175fa25bee7a0b88d07e442 100644 (file)
   #  Include/Guid/StatusCodeDataTypeDebug.h\r
   gEfiStatusCodeDataTypeDebugGuid  = { 0x9A4E9246, 0xD553, 0x11D5, { 0x87, 0xE2, 0x00, 0x06, 0x29, 0x45, 0xC3, 0xB9 }}\r
 \r
   #  Include/Guid/StatusCodeDataTypeDebug.h\r
   gEfiStatusCodeDataTypeDebugGuid  = { 0x9A4E9246, 0xD553, 0x11D5, { 0x87, 0xE2, 0x00, 0x06, 0x29, 0x45, 0xC3, 0xB9 }}\r
 \r
+  ##  A configuration Table Guid for Load module at fixed address \r
+  #  Include/Guid/LoadModuleAtFixedAddress.h\r
+  gLoadFixedAddressConfigurationTableGuid  = { 0x2CA88B53,0xD296,0x4080, { 0xA4,0xA5,0xCA,0xD9,0xBA,0xE2,0x4B,0x9 } }\r
+\r
 [Protocols.common]\r
   ## Load File protocol provides capability to load and unload EFI image into memory and execute it.\r
   #  Include/Protocol/LoadPe32Image.h\r
 [Protocols.common]\r
   ## Load File protocol provides capability to load and unload EFI image into memory and execute it.\r
   #  Include/Protocol/LoadPe32Image.h\r
   #  BIT1 set indicates 8KB alignment\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize|0x1|UINT32|0x10000047\r
   \r
   #  BIT1 set indicates 8KB alignment\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize|0x1|UINT32|0x10000047\r
   \r
+  ## Flag of enabling/disabling the feature of Loading Module at Fixed Address \r
+  #  -1: Enable the feature as fixed offset to TOLM\r
+  #   0: Disable the feature.\r
+  #  Positive Value:  Enable the feature as fixed absolute address, and the value is the top memory address \r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable|0|UINT64|0x30001015\r
+  \r
   ## Smbios version\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion|0x0206|UINT16|0x00010055\r
 \r
   ## Smbios version\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion|0x0206|UINT16|0x00010055\r
 \r
   #  The default value in DxePhase is 128 KBytes.\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1|UINT16|0x00010054\r
 \r
   #  The default value in DxePhase is 128 KBytes.\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1|UINT16|0x00010054\r
 \r
+[PcdsPatchableInModule]\r
+  ## Specify  memory size with page number for PEI code when \r
+  #  the feature of Loading Module at Fixed Address is enabled\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressPeiCodePageNumber|0|UINT32|0x00000029\r
+  \r
+  ## Specify  memory size with page number for DXE boot time code when \r
+  #  the feature of Loading Module at Fixed Address is enabled\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber|0|UINT32|0x0000002a\r
+  \r
+  ## Specify  memory size with page number for DXE runtime code when \r
+  #  the feature of Loading Module at Fixed Address is enabled\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressRuntimeCodePageNumber|0|UINT32|0x0000002b\r
\r
+  ## Specify  memory size with page number for SMM code when \r
+  #  the feature of Loading Module at Fixed Address is enabled\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber|0|UINT32|0x0000002c\r
+\r