]> 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 4661d779d97199219bcfb2424ae4a4ff7e4eadf1..0a4eaee482b2c00345263f3a10bb3a82825508a5 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   EFI PEI Core dispatch services\r
   \r
-Copyright (c) 2006 - 2009, Intel Corporation\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
@@ -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
-                FixedPcdGet32(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
-                FixedPcdGet32(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,15 +796,22 @@ 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
               OldPeiStackSize = (UINT64) SecCoreData->StackSize;\r
               NewPeiStackSize = (RShiftU64 (Private->PhysicalMemoryLength, 1) + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;\r
-              if (FixedPcdGet32(PcdPeiCoreMaxPeiStackSize) > (UINT32) NewPeiStackSize) {\r
+              if (PcdGet32(PcdPeiCoreMaxPeiStackSize) > (UINT32) NewPeiStackSize) {\r
                 Private->StackSize = NewPeiStackSize;\r
               } else {\r
-                Private->StackSize = FixedPcdGet32(PcdPeiCoreMaxPeiStackSize);\r
+                Private->StackSize = PcdGet32(PcdPeiCoreMaxPeiStackSize);\r
               }\r
 \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
@@ -721,6 +1064,8 @@ InitializeDispatcherData (
   if (OldCoreData == NULL) {\r
     PrivateData->PeimDispatcherReenter = FALSE;\r
     PeiInitializeFv (PrivateData, SecCoreData);\r
+  } else {\r
+    PeiReinitializeFv (PrivateData);\r
   }\r
 \r
   return;\r
@@ -818,3 +1163,4 @@ PeiRegisterForShadow (
 }\r
 \r
 \r
+\r