]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
revise the debug message to add 0x in front of the HEX number for consistency
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
index c63bce8fd8afae409e6e8f8f7a9b307f6b1f66fc..0a4eaee482b2c00345263f3a10bb3a82825508a5 100644 (file)
@@ -75,7 +75,7 @@ DiscoverPeimsAndOrderWithApriori (
   //\r
   // Go ahead to scan this Fv, and cache FileHandles within it.\r
   //\r
-  for (PeimCount = 0; PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) {\r
+  for (PeimCount = 0; PeimCount < PcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) {\r
     Status = FvPpi->FindFileByType (FvPpi, PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, CoreFileHandle->FvHandle, &FileHandle);\r
     if (Status != EFI_SUCCESS) {\r
       break;\r
@@ -88,7 +88,7 @@ DiscoverPeimsAndOrderWithApriori (
   // Check whether the count of Peims exceeds the max support PEIMs in a FV image\r
   // If more Peims are required in a FV image, PcdPeiCoreMaxPeimPerFv can be set to a larger value in DSC file.\r
   //\r
-  ASSERT (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv));\r
+  ASSERT (PeimCount < PcdGet32 (PcdPeiCoreMaxPeimPerFv));\r
 \r
   //\r
   // Get Apriori File handle\r
@@ -221,6 +221,7 @@ ShadowPeiCore(
   Status = PeiLoadImage (\r
               PeiServices,\r
               *((EFI_PEI_FILE_HANDLE*)&PeiCoreFileHandle),\r
+              PEIM_STATE_REGISITER_FOR_SHADOW,\r
               &EntryPoint,\r
               &AuthenticationState\r
               );\r
@@ -232,7 +233,326 @@ ShadowPeiCore(
   //\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
+  @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 = MINIMUM_INITIAL_MEMORY_SIZE + EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber));\r
+  TotalReservedMemorySize+= EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)) ;  \r
+  //\r
+  // PEI memory range lies below the top reserved memory\r
+  // \r
+  TotalReservedMemorySize += PeiMemorySize;\r
+  \r
+  DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber)));\r
+  DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)));\r
+  DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressPeiCodePageNumber)));   \r
+  DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = 0x%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)PcdGet64(PcdLoadModuleAtFixAddressEnable) > 0 ) {\r
+    //\r
+    // The LMFA feature is enabled as load module at fixed absolute address.\r
+    //\r
+    TopLoadingAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64(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 0x%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 0x%lx is valid \n",  TopLoadingAddress));\r
+      TopLoadingAddress += MINIMUM_INITIAL_MEMORY_SIZE; \r
+    } else {\r
+      DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%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, "(0x%lx, 0x%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 = 0x%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
@@ -276,6 +596,7 @@ PeiDispatcher (
   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
@@ -292,12 +613,13 @@ PeiDispatcher (
     SaveCurrentFileHandle =  Private->CurrentFileHandle;\r
 \r
     for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {\r
-      for (Index2 = 0; (Index2 < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {\r
+      for (Index2 = 0; (Index2 < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {\r
         if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {\r
           PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];\r
           Status = PeiLoadImage (\r
                     (CONST EFI_PEI_SERVICES **) &Private->PS,\r
                     PeimFileHandle,\r
+                    PEIM_STATE_REGISITER_FOR_SHADOW,\r
                     &EntryPoint,\r
                     &AuthenticationState\r
                     );\r
@@ -314,9 +636,9 @@ PeiDispatcher (
             //\r
             PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
 \r
-            PERF_START (0, "PEIM", NULL, 0);\r
+            PERF_START (PeimFileHandle, "PEIM", NULL, 0);\r
             PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->PS);\r
-            PERF_END (0, "PEIM", NULL, 0);\r
+            PERF_END (PeimFileHandle, "PEIM", NULL, 0);\r
           }\r
 \r
           //\r
@@ -377,7 +699,7 @@ PeiDispatcher (
       // Start to dispatch all modules within the current Fv.\r
       //\r
       for (PeimCount = Private->CurrentPeimCount;\r
-           (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);\r
+           (PeimCount < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);\r
            PeimCount++) {\r
         Private->CurrentPeimCount  = PeimCount;\r
         PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];\r
@@ -401,6 +723,7 @@ PeiDispatcher (
               Status = PeiLoadImage (\r
                          PeiServices,\r
                          PeimFileHandle,\r
+                         PEIM_STATE_NOT_DISPATCHED,\r
                          &EntryPoint,\r
                          &AuthenticationState\r
                          );\r
@@ -411,13 +734,13 @@ PeiDispatcher (
               // The PEIM has its dependencies satisfied, and its entry point\r
               // has been found, so invoke it.\r
               //\r
-              PERF_START (0, "PEIM", NULL, 0);\r
+              PERF_START (PeimFileHandle, "PEIM", NULL, 0);\r
 \r
               ExtendedData.Handle = (EFI_HANDLE)PeimFileHandle;\r
 \r
               REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
                 EFI_PROGRESS_CODE,\r
-                PcdGet32(PcdStatusCodeValuePeimDispatch),\r
+                (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),\r
                 (VOID *)(&ExtendedData),\r
                 sizeof (ExtendedData)\r
                 );\r
@@ -442,11 +765,11 @@ PeiDispatcher (
 \r
               REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
                 EFI_PROGRESS_CODE,\r
-                PcdGet32(PcdStatusCodeValuePeimDispatch),\r
+                (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),\r
                 (VOID *)(&ExtendedData),\r
                 sizeof (ExtendedData)\r
                 );\r
-              PERF_END (0, "PEIM", NULL, 0);\r
+              PERF_END (PeimFileHandle, "PEIM", NULL, 0);\r
 \r
             }\r
 \r
@@ -473,6 +796,13 @@ PeiDispatcher (
                       ));\r
               DEBUG_CODE_END ();\r
               \r
+              if (PcdGet64(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
@@ -610,6 +940,19 @@ PeiDispatcher (
               //\r
               PrivateInMem->PeimDispatcherReenter  = TRUE;\r
               \r
+              if (PcdGet64(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 = 0x%lx, PeiCodeTop= 0xl%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
@@ -820,3 +1163,4 @@ PeiRegisterForShadow (
 }\r
 \r
 \r
+\r