]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Pei/Ppi/Ppi.c
MdeModulePkg PeiCore: Remove the using of PcdPeiCoreMaxPpiSupported
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Ppi / Ppi.c
index c8bea851a5df7d1ed017421c72b425888eb37e3c..c33dfdf8aa5f3201fc9f16afb30d7eda64095ec4 100644 (file)
-/*++\r
-\r
-Copyright (c) 2006, 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
+/** @file\r
+  EFI PEI Core PPI services\r
 \r
-Module Name:\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+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
-  Ppi.c\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
-Abstract:\r
+**/\r
 \r
-  EFI PEI Core PPI services\r
+#include "PeiMain.h"\r
 \r
-Revision History\r
+/**\r
 \r
---*/\r
+  Migrate Pointer from the temporary memory to PEI installed memory.\r
 \r
-#include <PeiMain.h>\r
+  @param Pointer         Pointer to the Pointer needs to be converted.\r
+  @param TempBottom      Base of old temporary memory\r
+  @param TempTop         Top of old temporary memory\r
+  @param Offset          Offset of new memory to old temporary memory.\r
+  @param OffsetPositive  Positive flag of Offset value.\r
 \r
+**/\r
 VOID\r
-InitializePpiServices (\r
-  IN EFI_PEI_SERVICES  **PeiServices,\r
-  IN PEI_CORE_INSTANCE *OldCoreData\r
+ConvertPointer (\r
+  IN OUT VOID              **Pointer,\r
+  IN UINTN                 TempBottom,\r
+  IN UINTN                 TempTop,\r
+  IN UINTN                 Offset,\r
+  IN BOOLEAN               OffsetPositive\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Initialize PPI services.\r
-\r
-Arguments:\r
-\r
-  PeiServices - The PEI core services table.\r
-  OldCoreData - Pointer to the PEI Core data.\r
-                NULL if being run in non-permament memory mode.\r
-\r
-Returns:\r
-  Nothing\r
-\r
---*/\r
 {\r
-  PEI_CORE_INSTANCE                    *PrivateData;\r
-  \r
-  if (OldCoreData == NULL) {\r
-    PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
-\r
-    PrivateData->PpiData.NotifyListEnd = MAX_PPI_DESCRIPTORS-1;\r
-    PrivateData->PpiData.DispatchListEnd = MAX_PPI_DESCRIPTORS-1;\r
-    PrivateData->PpiData.LastDispatchedNotify = MAX_PPI_DESCRIPTORS-1;\r
+  if (((UINTN) *Pointer < TempTop) &&\r
+    ((UINTN) *Pointer >= TempBottom)) {\r
+    if (OffsetPositive) {\r
+      *Pointer = (VOID *) ((UINTN) *Pointer + Offset);\r
+    } else {\r
+      *Pointer = (VOID *) ((UINTN) *Pointer - Offset);\r
+    }\r
   }\r
\r
-  return;   \r
 }\r
 \r
+/**\r
+\r
+  Migrate Pointer in ranges of the temporary memory to PEI installed memory.\r
+\r
+  @param SecCoreData     Points to a data structure containing SEC to PEI handoff data, such as the size\r
+                         and location of temporary RAM, the stack location and the BFV location.\r
+  @param PrivateData     Pointer to PeiCore's private data structure.\r
+  @param Pointer         Pointer to the Pointer needs to be converted.\r
+\r
+**/\r
 VOID\r
-ConvertPpiPointers (\r
-  IN EFI_PEI_SERVICES                     **PeiServices,\r
-  IN EFI_HOB_HANDOFF_INFO_TABLE    *OldHandOffHob,\r
-  IN EFI_HOB_HANDOFF_INFO_TABLE    *NewHandOffHob\r
+ConvertPointerInRanges (\r
+  IN CONST EFI_SEC_PEI_HAND_OFF  *SecCoreData,\r
+  IN PEI_CORE_INSTANCE           *PrivateData,\r
+  IN OUT VOID                    **Pointer\r
   )\r
-/*++\r
+{\r
+  UINT8                 IndexHole;\r
 \r
-Routine Description:\r
+  if (PrivateData->MemoryPages.Size != 0) {\r
+    //\r
+    // Convert PPI pointer in old memory pages\r
+    // It needs to be done before Convert PPI pointer in old Heap\r
+    //\r
+    ConvertPointer (\r
+      Pointer,\r
+      (UINTN)PrivateData->MemoryPages.Base,\r
+      (UINTN)PrivateData->MemoryPages.Base + PrivateData->MemoryPages.Size,\r
+      PrivateData->MemoryPages.Offset,\r
+      PrivateData->MemoryPages.OffsetPositive\r
+      );\r
+  }\r
 \r
-  Migrate the Hob list from the CAR stack to PEI installed memory.\r
+  //\r
+  // Convert PPI pointer in old Heap\r
+  //\r
+  ConvertPointer (\r
+    Pointer,\r
+    (UINTN)SecCoreData->PeiTemporaryRamBase,\r
+    (UINTN)SecCoreData->PeiTemporaryRamBase + SecCoreData->PeiTemporaryRamSize,\r
+    PrivateData->HeapOffset,\r
+    PrivateData->HeapOffsetPositive\r
+    );\r
 \r
-Arguments:\r
+  //\r
+  // Convert PPI pointer in old Stack\r
+  //\r
+  ConvertPointer (\r
+    Pointer,\r
+    (UINTN)SecCoreData->StackBase,\r
+    (UINTN)SecCoreData->StackBase + SecCoreData->StackSize,\r
+    PrivateData->StackOffset,\r
+    PrivateData->StackOffsetPositive\r
+    );\r
 \r
-  PeiServices   - The PEI core services table.\r
-  OldHandOffHob - The old handoff HOB list.\r
-  NewHandOffHob - The new handoff HOB list.\r
+  //\r
+  // Convert PPI pointer in old TempRam Hole\r
+  //\r
+  for (IndexHole = 0; IndexHole < HOLE_MAX_NUMBER; IndexHole ++) {\r
+    if (PrivateData->HoleData[IndexHole].Size == 0) {\r
+      continue;\r
+    }\r
 \r
-Returns:\r
-            \r
---*/\r
-{\r
-  PEI_CORE_INSTANCE     *PrivateData;\r
-  UINT8                 Index;\r
-  PEI_PPI_LIST_POINTERS *PpiPointer;\r
-  UINTN                 Fixup;\r
+    ConvertPointer (\r
+      Pointer,\r
+      (UINTN)PrivateData->HoleData[IndexHole].Base,\r
+      (UINTN)PrivateData->HoleData[IndexHole].Base + PrivateData->HoleData[IndexHole].Size,\r
+      PrivateData->HoleData[IndexHole].Offset,\r
+      PrivateData->HoleData[IndexHole].OffsetPositive\r
+      );\r
+  }\r
+}\r
 \r
-  PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
+/**\r
 \r
-  Fixup = (UINTN)NewHandOffHob - (UINTN)OldHandOffHob;\r
-  \r
-  for (Index = 0; Index < MAX_PPI_DESCRIPTORS; Index++) {\r
-    if (Index < PrivateData->PpiData.PpiListEnd ||\r
-        Index > PrivateData->PpiData.NotifyListEnd) {\r
-      PpiPointer = &PrivateData->PpiData.PpiListPtrs[Index];\r
-      \r
-      if (((UINTN)PpiPointer->Raw < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) && \r
-          ((UINTN)PpiPointer->Raw >= (UINTN)OldHandOffHob)) {\r
-        //\r
-        // Convert the pointer to the PEIM descriptor from the old HOB heap\r
-        // to the relocated HOB heap.\r
-        //\r
-        PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw + Fixup);\r
+  Migrate Single PPI Pointer from the temporary memory to PEI installed memory.\r
 \r
-        //\r
-        // Only when the PEIM descriptor is in the old HOB should it be necessary\r
-        // to try to convert the pointers in the PEIM descriptor\r
-        //\r
-        \r
-        if (((UINTN)PpiPointer->Ppi->Guid < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) && \r
-            ((UINTN)PpiPointer->Ppi->Guid >= (UINTN)OldHandOffHob)) {\r
-          //\r
-          // Convert the pointer to the GUID in the PPI or NOTIFY descriptor\r
-          // from the old HOB heap to the relocated HOB heap.\r
-          //\r
-          PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid + Fixup);\r
-        }\r
+  @param SecCoreData     Points to a data structure containing SEC to PEI handoff data, such as the size\r
+                         and location of temporary RAM, the stack location and the BFV location.\r
+  @param PrivateData     Pointer to PeiCore's private data structure.\r
+  @param PpiPointer      Pointer to Ppi\r
 \r
-        //\r
-        // Assume that no code is located in the temporary memory, so the pointer to\r
-        // the notification function in the NOTIFY descriptor needs not be converted.\r
-        //\r
-        if (Index < PrivateData->PpiData.PpiListEnd &&\r
-            (UINTN)PpiPointer->Ppi->Ppi < (UINTN)OldHandOffHob->EfiFreeMemoryBottom &&\r
-            (UINTN)PpiPointer->Ppi->Ppi >= (UINTN)OldHandOffHob) {\r
-            //\r
-            // Convert the pointer to the PPI interface structure in the PPI descriptor\r
-            // from the old HOB heap to the relocated HOB heap.\r
-            //\r
-            PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi+ Fixup);   \r
-        }\r
-      }\r
-    }\r
-  }\r
+**/\r
+VOID\r
+ConvertSinglePpiPointer (\r
+  IN CONST EFI_SEC_PEI_HAND_OFF  *SecCoreData,\r
+  IN PEI_CORE_INSTANCE           *PrivateData,\r
+  IN PEI_PPI_LIST_POINTERS       *PpiPointer\r
+  )\r
+{\r
+  //\r
+  // 1. Convert the pointer to the PPI descriptor from the old TempRam\r
+  //    to the relocated physical memory.\r
+  // It (for the pointer to the PPI descriptor) needs to be done before 2 (for\r
+  // the pointer to the GUID) and 3 (for the pointer to the PPI interface structure).\r
+  //\r
+  ConvertPointerInRanges (SecCoreData, PrivateData, &PpiPointer->Raw);\r
+  //\r
+  // 2. Convert the pointer to the GUID in the PPI or NOTIFY descriptor\r
+  //    from the old TempRam to the relocated physical memory.\r
+  //\r
+  ConvertPointerInRanges (SecCoreData, PrivateData, (VOID **) &PpiPointer->Ppi->Guid);\r
+  //\r
+  // 3. Convert the pointer to the PPI interface structure in the PPI descriptor\r
+  //    from the old TempRam to the relocated physical memory.\r
+  //\r
+  ConvertPointerInRanges (SecCoreData, PrivateData, (VOID **) &PpiPointer->Ppi->Ppi);\r
 }\r
 \r
+/**\r
 \r
+  Migrate PPI Pointers from the temporary memory to PEI installed memory.\r
 \r
-EFI_STATUS\r
-EFIAPI\r
-PeiInstallPpi (\r
-  IN EFI_PEI_SERVICES        **PeiServices,\r
-  IN EFI_PEI_PPI_DESCRIPTOR  *PpiList\r
+  @param SecCoreData     Points to a data structure containing SEC to PEI handoff data, such as the size\r
+                         and location of temporary RAM, the stack location and the BFV location.\r
+  @param PrivateData     Pointer to PeiCore's private data structure.\r
+\r
+**/\r
+VOID\r
+ConvertPpiPointers (\r
+  IN CONST EFI_SEC_PEI_HAND_OFF  *SecCoreData,\r
+  IN PEI_CORE_INSTANCE           *PrivateData\r
   )\r
-/*++\r
+{\r
+  UINT8                 Index;\r
 \r
-Routine Description:\r
+  //\r
+  // Convert normal PPIs.\r
+  //\r
+  for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
+    ConvertSinglePpiPointer (\r
+      SecCoreData,\r
+      PrivateData,\r
+      &PrivateData->PpiData.PpiList.PpiPtrs[Index]\r
+      );\r
+  }\r
 \r
-  Install PPI services.\r
+  //\r
+  // Convert Callback Notification PPIs.\r
+  //\r
+  for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {\r
+    ConvertSinglePpiPointer (\r
+      SecCoreData,\r
+      PrivateData,\r
+      &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index]\r
+      );\r
+  }\r
 \r
-Arguments:\r
+  //\r
+  // Convert Dispatch Notification PPIs.\r
+  //\r
+  for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {\r
+    ConvertSinglePpiPointer (\r
+      SecCoreData,\r
+      PrivateData,\r
+      &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index]\r
+      );\r
+  }\r
+}\r
 \r
-  PeiServices - Pointer to the PEI Service Table\r
-  PpiList     - Pointer to a list of PEI PPI Descriptors.\r
+/**\r
 \r
-Returns:\r
+  This function installs an interface in the PEI PPI database by GUID.\r
+  The purpose of the service is to publish an interface that other parties\r
+  can use to call additional PEIMs.\r
 \r
-    EFI_SUCCESS             - if all PPIs in PpiList are successfully installed.\r
-    EFI_INVALID_PARAMETER   - if PpiList is NULL pointer\r
-    EFI_INVALID_PARAMETER   - if any PPI in PpiList is not valid\r
-    EFI_OUT_OF_RESOURCES    - if there is no more memory resource to install PPI\r
+  @param PeiServices                An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+  @param PpiList                    Pointer to a list of PEI PPI Descriptors.\r
+  @param Single                     TRUE if only single entry in the PpiList.\r
+                                    FALSE if the PpiList is ended with an entry which has the\r
+                                    EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.\r
 \r
---*/\r
-{\r
-  PEI_CORE_INSTANCE *PrivateData;\r
-  INTN              Index;\r
-  INTN              LastCallbackInstall;\r
+  @retval EFI_SUCCESS              if all PPIs in PpiList are successfully installed.\r
+  @retval EFI_INVALID_PARAMETER    if PpiList is NULL pointer\r
+                                   if any PPI in PpiList is not valid\r
+  @retval EFI_OUT_OF_RESOURCES     if there is no more memory resource to install PPI\r
 \r
+**/\r
+EFI_STATUS\r
+InternalPeiInstallPpi (\r
+  IN CONST EFI_PEI_SERVICES        **PeiServices,\r
+  IN CONST EFI_PEI_PPI_DESCRIPTOR  *PpiList,\r
+  IN BOOLEAN                       Single\r
+  )\r
+{\r
+  PEI_CORE_INSTANCE     *PrivateData;\r
+  PEI_PPI_LIST          *PpiListPointer;\r
+  UINTN                 Index;\r
+  UINTN                 LastCount;\r
+  VOID                  *TempPtr;\r
 \r
   if (PpiList == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -173,96 +241,135 @@ Returns:
 \r
   PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
 \r
-  Index = PrivateData->PpiData.PpiListEnd;\r
-  LastCallbackInstall = Index;\r
+  PpiListPointer = &PrivateData->PpiData.PpiList;\r
+  Index = PpiListPointer->CurrentCount;\r
+  LastCount = Index;\r
 \r
   //\r
   // This is loop installs all PPI descriptors in the PpiList.  It is terminated\r
   // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last\r
   // EFI_PEI_PPI_DESCRIPTOR in the list.\r
   //\r
-    \r
+\r
   for (;;) {\r
     //\r
-    // Since PpiData is used for NotifyList and InstallList, max resource\r
-    // is reached if the Install reaches the NotifyList\r
-    //\r
-    if (Index == PrivateData->PpiData.NotifyListEnd + 1) {\r
-      return  EFI_OUT_OF_RESOURCES;\r
-    }\r
-    //\r
-    // Check if it is a valid PPI. \r
+    // Check if it is a valid PPI.\r
     // If not, rollback list to exclude all in this list.\r
     // Try to indicate which item failed.\r
     //\r
     if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {\r
-      PrivateData->PpiData.PpiListEnd = LastCallbackInstall;\r
-      DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %x\n", PpiList->Guid, PpiList->Ppi));\r
+      PpiListPointer->CurrentCount = LastCount;\r
+      DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi));\r
       return  EFI_INVALID_PARAMETER;\r
     }\r
 \r
-    DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid)); \r
-    PrivateData->PpiData.PpiListPtrs[Index].Ppi = PpiList;    \r
-    PrivateData->PpiData.PpiListEnd++;\r
-    \r
-    //\r
-    // Continue until the end of the PPI List.\r
-    //\r
-    if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==  \r
-        EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
+    if (Index >= PpiListPointer->MaxCount) {\r
+      //\r
+      // Run out of room, grow the buffer.\r
+      //\r
+      TempPtr = AllocateZeroPool (\r
+                  sizeof (PEI_PPI_LIST_POINTERS) * (PpiListPointer->MaxCount + PPI_GROWTH_STEP)\r
+                  );\r
+      ASSERT (TempPtr != NULL);\r
+      CopyMem (\r
+        TempPtr,\r
+        PpiListPointer->PpiPtrs,\r
+        sizeof (PEI_PPI_LIST_POINTERS) * PpiListPointer->MaxCount\r
+        );\r
+      PpiListPointer->PpiPtrs = TempPtr;\r
+      PpiListPointer->MaxCount = PpiListPointer->MaxCount + PPI_GROWTH_STEP;\r
+    }\r
+\r
+    DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid));\r
+    PpiListPointer->PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) PpiList;\r
+    Index++;\r
+    PpiListPointer->CurrentCount++;\r
+\r
+    if (Single) {\r
+      //\r
+      // Only single entry in the PpiList.\r
+      //\r
+      break;\r
+    } else if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
+               EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
+      //\r
+      // Continue until the end of the PPI List.\r
+      //\r
       break;\r
     }\r
+    //\r
+    // Go to the next descriptor.\r
+    //\r
     PpiList++;\r
-    Index++;\r
   }\r
 \r
   //\r
-  // Dispatch any callback level notifies for newly installed PPIs.\r
+  // Process any callback level notifies for newly installed PPIs.\r
   //\r
-  DispatchNotify (\r
-    PeiServices,\r
+  ProcessNotify (\r
+    PrivateData,\r
     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
-    LastCallbackInstall,\r
-    PrivateData->PpiData.PpiListEnd,\r
-    PrivateData->PpiData.DispatchListEnd,                 \r
-    PrivateData->PpiData.NotifyListEnd\r
+    LastCount,\r
+    PpiListPointer->CurrentCount,\r
+    0,\r
+    PrivateData->PpiData.CallbackNotifyList.CurrentCount\r
     );\r
 \r
-\r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+\r
+  This function installs an interface in the PEI PPI database by GUID.\r
+  The purpose of the service is to publish an interface that other parties\r
+  can use to call additional PEIMs.\r
 \r
+  @param PeiServices                An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+  @param PpiList                    Pointer to a list of PEI PPI Descriptors.\r
+\r
+  @retval EFI_SUCCESS              if all PPIs in PpiList are successfully installed.\r
+  @retval EFI_INVALID_PARAMETER    if PpiList is NULL pointer\r
+                                   if any PPI in PpiList is not valid\r
+  @retval EFI_OUT_OF_RESOURCES     if there is no more memory resource to install PPI\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
-PeiReInstallPpi (\r
-  IN EFI_PEI_SERVICES        **PeiServices,\r
-  IN EFI_PEI_PPI_DESCRIPTOR  *OldPpi,\r
-  IN EFI_PEI_PPI_DESCRIPTOR  *NewPpi\r
+PeiInstallPpi (\r
+  IN CONST EFI_PEI_SERVICES        **PeiServices,\r
+  IN CONST EFI_PEI_PPI_DESCRIPTOR  *PpiList\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Re-Install PPI services.\r
+{\r
+  return InternalPeiInstallPpi (PeiServices, PpiList, FALSE);\r
+}\r
 \r
-Arguments:\r
+/**\r
 \r
-  PeiServices - Pointer to the PEI Service Table\r
-  OldPpi      - Pointer to the old PEI PPI Descriptors.\r
-  NewPpi      - Pointer to the new PEI PPI Descriptors.\r
+  This function reinstalls an interface in the PEI PPI database by GUID.\r
+  The purpose of the service is to publish an interface that other parties can\r
+  use to replace an interface of the same name in the protocol database with a\r
+  different interface.\r
 \r
-Returns:\r
+  @param PeiServices            An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+  @param OldPpi                 Pointer to the old PEI PPI Descriptors.\r
+  @param NewPpi                 Pointer to the new PEI PPI Descriptors.\r
 \r
-  EFI_SUCCESS           - if the operation was successful\r
-  EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL\r
-  EFI_INVALID_PARAMETER - if NewPpi is not valid\r
-  EFI_NOT_FOUND         - if the PPI was not in the database\r
+  @retval EFI_SUCCESS           if the operation was successful\r
+  @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL\r
+  @retval EFI_INVALID_PARAMETER if NewPpi is not valid\r
+  @retval EFI_NOT_FOUND         if the PPI was not in the database\r
 \r
---*/\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiReInstallPpi (\r
+  IN CONST EFI_PEI_SERVICES        **PeiServices,\r
+  IN CONST EFI_PEI_PPI_DESCRIPTOR  *OldPpi,\r
+  IN CONST EFI_PEI_PPI_DESCRIPTOR  *NewPpi\r
+  )\r
 {\r
   PEI_CORE_INSTANCE   *PrivateData;\r
-  INTN                Index;\r
+  UINTN               Index;\r
 \r
 \r
   if ((OldPpi == NULL) || (NewPpi == NULL)) {\r
@@ -279,81 +386,75 @@ Returns:
   // Find the old PPI instance in the database.  If we can not find it,\r
   // return the EFI_NOT_FOUND error.\r
   //\r
-  for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {\r
-    if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) {\r
+  for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
+    if (OldPpi == PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi) {\r
       break;\r
     }\r
   }\r
-  if (Index == PrivateData->PpiData.PpiListEnd) {\r
+  if (Index == PrivateData->PpiData.PpiList.CurrentCount) {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
   //\r
-  // Remove the old PPI from the database, add the new one.\r
-  // \r
+  // Replace the old PPI with the new one.\r
+  //\r
   DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));\r
-  PrivateData->PpiData.PpiListPtrs[Index].Ppi = NewPpi;\r
+  PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) NewPpi;\r
 \r
   //\r
-  // Dispatch any callback level notifies for the newly installed PPI.\r
+  // Process any callback level notifies for the newly installed PPI.\r
   //\r
-  DispatchNotify (\r
-    PeiServices,\r
+  ProcessNotify (\r
+    PrivateData,\r
     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
     Index,\r
     Index+1,\r
-    PrivateData->PpiData.DispatchListEnd,                 \r
-    PrivateData->PpiData.NotifyListEnd\r
+    0,\r
+    PrivateData->PpiData.CallbackNotifyList.CurrentCount\r
     );\r
 \r
-\r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
-EFI_STATUS\r
-EFIAPI\r
-PeiLocatePpi (\r
-  IN EFI_PEI_SERVICES        **PeiServices,\r
-  IN EFI_GUID                *Guid,\r
-  IN UINTN                   Instance,\r
-  IN OUT EFI_PEI_PPI_DESCRIPTOR  **PpiDescriptor,\r
-  IN OUT VOID                **Ppi\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
+/**\r
 \r
   Locate a given named PPI.\r
 \r
-Arguments:\r
 \r
-  PeiServices   - Pointer to the PEI Service Table\r
-  Guid          - Pointer to GUID of the PPI.\r
-  Instance      - Instance Number to discover.\r
-  PpiDescriptor - Pointer to reference the found descriptor. If not NULL,\r
-                returns a pointer to the descriptor (includes flags, etc)\r
-  Ppi           - Pointer to reference the found PPI\r
+  @param PeiServices        An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+  @param Guid               Pointer to GUID of the PPI.\r
+  @param Instance           Instance Number to discover.\r
+  @param PpiDescriptor      Pointer to reference the found descriptor. If not NULL,\r
+                            returns a pointer to the descriptor (includes flags, etc)\r
+  @param Ppi                Pointer to reference the found PPI\r
 \r
-Returns:\r
+  @retval EFI_SUCCESS   if the PPI is in the database\r
+  @retval EFI_NOT_FOUND if the PPI is not in the database\r
 \r
-  Status -  EFI_SUCCESS   if the PPI is in the database           \r
-            EFI_NOT_FOUND if the PPI is not in the database\r
---*/\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiLocatePpi (\r
+  IN CONST EFI_PEI_SERVICES        **PeiServices,\r
+  IN CONST EFI_GUID                *Guid,\r
+  IN UINTN                         Instance,\r
+  IN OUT EFI_PEI_PPI_DESCRIPTOR    **PpiDescriptor,\r
+  IN OUT VOID                      **Ppi\r
+  )\r
 {\r
-  PEI_CORE_INSTANCE   *PrivateData;\r
-  INTN                Index;\r
-  EFI_GUID            *CheckGuid;\r
-  EFI_PEI_PPI_DESCRIPTOR  *TempPtr;\r
+  PEI_CORE_INSTANCE         *PrivateData;\r
+  UINTN                     Index;\r
+  EFI_GUID                  *CheckGuid;\r
+  EFI_PEI_PPI_DESCRIPTOR    *TempPtr;\r
+\r
 \r
-  \r
   PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
 \r
   //\r
   // Search the data base for the matching instance of the GUIDed PPI.\r
   //\r
-  for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {\r
-    TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi;\r
+  for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
+    TempPtr = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi;\r
     CheckGuid = TempPtr->Guid;\r
 \r
     //\r
@@ -385,41 +486,38 @@ Returns:
   return EFI_NOT_FOUND;\r
 }\r
 \r
+/**\r
 \r
-EFI_STATUS\r
-EFIAPI\r
-PeiNotifyPpi (\r
-  IN EFI_PEI_SERVICES           **PeiServices,\r
-  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyList\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Install a notification for a given PPI.\r
+  This function installs a notification service to be called back when a given\r
+  interface is installed or reinstalled. The purpose of the service is to publish\r
+  an interface that other parties can use to call additional PPIs that may materialize later.\r
 \r
-Arguments:\r
+  @param PeiServices        An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+  @param NotifyList         Pointer to list of Descriptors to notify upon.\r
+  @param Single             TRUE if only single entry in the NotifyList.\r
+                            FALSE if the NotifyList is ended with an entry which has the\r
+                            EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.\r
 \r
-  PeiServices - Pointer to the PEI Service Table\r
-  NotifyList  - Pointer to list of Descriptors to notify upon.\r
+  @retval EFI_SUCCESS           if successful\r
+  @retval EFI_OUT_OF_RESOURCES  if no space in the database\r
+  @retval EFI_INVALID_PARAMETER if not a good descriptor\r
 \r
-Returns:\r
-\r
-  Status - EFI_SUCCESS           if successful\r
-           EFI_OUT_OF_RESOURCES  if no space in the database\r
-           EFI_INVALID_PARAMETER if not a good decriptor\r
-\r
---*/\r
+**/\r
+EFI_STATUS\r
+InternalPeiNotifyPpi (\r
+  IN CONST EFI_PEI_SERVICES           **PeiServices,\r
+  IN CONST EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyList,\r
+  IN BOOLEAN                          Single\r
+  )\r
 {\r
-  PEI_CORE_INSTANCE                *PrivateData;\r
-  INTN                             Index;\r
-  INTN                             NotifyIndex;\r
-  INTN                             LastCallbackNotify;\r
-  EFI_PEI_NOTIFY_DESCRIPTOR        *NotifyPtr;\r
-  UINTN                            NotifyDispatchCount;\r
-\r
-\r
-  NotifyDispatchCount = 0;\r
+  PEI_CORE_INSTANCE         *PrivateData;\r
+  PEI_CALLBACK_NOTIFY_LIST  *CallbackNotifyListPointer;\r
+  UINTN                     CallbackNotifyIndex;\r
+  UINTN                     LastCallbackNotifyCount;\r
+  PEI_DISPATCH_NOTIFY_LIST  *DispatchNotifyListPointer;\r
+  UINTN                     DispatchNotifyIndex;\r
+  UINTN                     LastDispatchNotifyCount;\r
+  VOID                      *TempPtr;\r
 \r
   if (NotifyList == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -427,8 +525,13 @@ Returns:
 \r
   PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
 \r
-  Index = PrivateData->PpiData.NotifyListEnd;\r
-  LastCallbackNotify = Index;\r
+  CallbackNotifyListPointer = &PrivateData->PpiData.CallbackNotifyList;\r
+  CallbackNotifyIndex = CallbackNotifyListPointer->CurrentCount;\r
+  LastCallbackNotifyCount = CallbackNotifyIndex;\r
+\r
+  DispatchNotifyListPointer = &PrivateData->PpiData.DispatchNotifyList;\r
+  DispatchNotifyIndex = DispatchNotifyListPointer->CurrentCount;\r
+  LastDispatchNotifyCount = DispatchNotifyIndex;\r
 \r
   //\r
   // This is loop installs all Notify descriptors in the NotifyList.  It is\r
@@ -437,200 +540,220 @@ Returns:
   //\r
 \r
   for (;;) {\r
-    //\r
-    // Since PpiData is used for NotifyList and InstallList, max resource\r
-    // is reached if the Install reaches the PpiList\r
-    //\r
-    if (Index == PrivateData->PpiData.PpiListEnd - 1) {\r
-      return  EFI_OUT_OF_RESOURCES;\r
-    }\r
-    \r
     //\r
     // If some of the PPI data is invalid restore original Notify PPI database value\r
     //\r
     if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {\r
-        PrivateData->PpiData.NotifyListEnd = LastCallbackNotify;\r
-        DEBUG((EFI_D_ERROR, "ERROR -> InstallNotify: %g %x\n", NotifyList->Guid, NotifyList->Notify));\r
+        CallbackNotifyListPointer->CurrentCount = LastCallbackNotifyCount;\r
+        DispatchNotifyListPointer->CurrentCount = LastDispatchNotifyCount;\r
+        DEBUG((DEBUG_ERROR, "ERROR -> NotifyPpi: %g %p\n", NotifyList->Guid, NotifyList->Notify));\r
       return  EFI_INVALID_PARAMETER;\r
     }\r
-     \r
-    if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {\r
-      NotifyDispatchCount ++; \r
-    }        \r
-    \r
-    PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyList;      \r
-   \r
-    PrivateData->PpiData.NotifyListEnd--;\r
+\r
+    if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) != 0) {\r
+      if (CallbackNotifyIndex >= CallbackNotifyListPointer->MaxCount) {\r
+        //\r
+        // Run out of room, grow the buffer.\r
+        //\r
+        TempPtr = AllocateZeroPool (\r
+                    sizeof (PEI_PPI_LIST_POINTERS) * (CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP)\r
+                    );\r
+        ASSERT (TempPtr != NULL);\r
+        CopyMem (\r
+          TempPtr,\r
+          CallbackNotifyListPointer->NotifyPtrs,\r
+          sizeof (PEI_PPI_LIST_POINTERS) * CallbackNotifyListPointer->MaxCount\r
+          );\r
+        CallbackNotifyListPointer->NotifyPtrs = TempPtr;\r
+        CallbackNotifyListPointer->MaxCount = CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP;\r
+      }\r
+      CallbackNotifyListPointer->NotifyPtrs[CallbackNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList;\r
+      CallbackNotifyIndex++;\r
+      CallbackNotifyListPointer->CurrentCount++;\r
+    } else {\r
+      if (DispatchNotifyIndex >= DispatchNotifyListPointer->MaxCount) {\r
+        //\r
+        // Run out of room, grow the buffer.\r
+        //\r
+        TempPtr = AllocateZeroPool (\r
+                    sizeof (PEI_PPI_LIST_POINTERS) * (DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP)\r
+                    );\r
+        ASSERT (TempPtr != NULL);\r
+        CopyMem (\r
+          TempPtr,\r
+          DispatchNotifyListPointer->NotifyPtrs,\r
+          sizeof (PEI_PPI_LIST_POINTERS) * DispatchNotifyListPointer->MaxCount\r
+          );\r
+        DispatchNotifyListPointer->NotifyPtrs = TempPtr;\r
+        DispatchNotifyListPointer->MaxCount = DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP;\r
+      }\r
+      DispatchNotifyListPointer->NotifyPtrs[DispatchNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList;\r
+      DispatchNotifyIndex++;\r
+      DispatchNotifyListPointer->CurrentCount++;\r
+    }\r
+\r
     DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));\r
-    if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
-        EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
+\r
+    if (Single) {\r
+      //\r
+      // Only single entry in the NotifyList.\r
+      //\r
+      break;\r
+    } else if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==\r
+               EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
+      //\r
+      // Continue until the end of the Notify List.\r
+      //\r
       break;\r
     }\r
     //\r
-    // Go the next descriptor. Remember the NotifyList moves down.\r
+    // Go to the next descriptor.\r
     //\r
     NotifyList++;\r
-    Index--;\r
-  }\r
\r
-  //\r
-  // If there is Dispatch Notify PPI installed put them on the bottom \r
-  //\r
-  if (NotifyDispatchCount > 0) {\r
-    for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) {             \r
-      if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {\r
-        NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify;\r
-        \r
-        for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){\r
-          PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify;\r
-        }\r
-        PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr;\r
-        PrivateData->PpiData.DispatchListEnd--;                \r
-      }\r
-    }\r
-    \r
-    LastCallbackNotify -= NotifyDispatchCount;        \r
   }\r
-  \r
+\r
   //\r
-  // Dispatch any callback level notifies for all previously installed PPIs.\r
+  // Process any callback level notifies for all previously installed PPIs.\r
   //\r
-  DispatchNotify (\r
-    PeiServices,\r
+  ProcessNotify (\r
+    PrivateData,\r
     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
     0,\r
-    PrivateData->PpiData.PpiListEnd,\r
-    LastCallbackNotify,\r
-    PrivateData->PpiData.NotifyListEnd\r
+    PrivateData->PpiData.PpiList.CurrentCount,\r
+    LastCallbackNotifyCount,\r
+    CallbackNotifyListPointer->CurrentCount\r
     );\r
-  \r
-  \r
+\r
   return  EFI_SUCCESS;\r
 }\r
 \r
+/**\r
 \r
-VOID\r
-ProcessNotifyList (\r
-  IN EFI_PEI_SERVICES    **PeiServices\r
-  )\r
-/*++\r
+  This function installs a notification service to be called back when a given\r
+  interface is installed or reinstalled. The purpose of the service is to publish\r
+  an interface that other parties can use to call additional PPIs that may materialize later.\r
 \r
-Routine Description:\r
+  @param PeiServices        An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+  @param NotifyList         Pointer to list of Descriptors to notify upon.\r
 \r
-  Process the Notify List at dispatch level.\r
+  @retval EFI_SUCCESS           if successful\r
+  @retval EFI_OUT_OF_RESOURCES  if no space in the database\r
+  @retval EFI_INVALID_PARAMETER if not a good descriptor\r
 \r
-Arguments:\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiNotifyPpi (\r
+  IN CONST EFI_PEI_SERVICES           **PeiServices,\r
+  IN CONST EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyList\r
+  )\r
+{\r
+  return InternalPeiNotifyPpi (PeiServices, NotifyList, FALSE);\r
+}\r
 \r
-  PeiServices - Pointer to the PEI Service Table\r
+/**\r
 \r
-Returns:\r
+  Process the Notify List at dispatch level.\r
 \r
---*/\r
+  @param PrivateData  PeiCore's private data structure.\r
 \r
+**/\r
+VOID\r
+ProcessDispatchNotifyList (\r
+  IN PEI_CORE_INSTANCE  *PrivateData\r
+  )\r
 {\r
-  PEI_CORE_INSTANCE       *PrivateData;\r
-  INTN                    TempValue;\r
+  UINTN                 TempValue;\r
 \r
-  PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
-\r
\r
   while (TRUE) {\r
     //\r
     // Check if the PEIM that was just dispatched resulted in any\r
     // Notifies getting installed.  If so, go process any dispatch\r
     // level Notifies that match the previouly installed PPIs.\r
-    // Use "while" instead of "if" since DispatchNotify can modify \r
-    // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.\r
+    // Use "while" instead of "if" since ProcessNotify can modify\r
+    // DispatchNotifyList.CurrentCount (with NotifyPpi) so we have\r
+    // to iterate until the same.\r
     //\r
-    while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) {\r
-      TempValue = PrivateData->PpiData.DispatchListEnd;\r
-      DispatchNotify (\r
-        PeiServices,\r
+    while (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount != PrivateData->PpiData.DispatchNotifyList.CurrentCount) {\r
+      TempValue = PrivateData->PpiData.DispatchNotifyList.CurrentCount;\r
+      ProcessNotify (\r
+        PrivateData,\r
         EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
         0,\r
-        PrivateData->PpiData.LastDispatchedInstall,\r
-        PrivateData->PpiData.LastDispatchedNotify,\r
-        PrivateData->PpiData.DispatchListEnd\r
+        PrivateData->PpiData.PpiList.LastDispatchedCount,\r
+        PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount,\r
+        PrivateData->PpiData.DispatchNotifyList.CurrentCount\r
         );\r
-      PrivateData->PpiData.LastDispatchedNotify = TempValue;\r
+      PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount = TempValue;\r
     }\r
-    \r
-    \r
+\r
     //\r
     // Check if the PEIM that was just dispatched resulted in any\r
     // PPIs getting installed.  If so, go process any dispatch\r
     // level Notifies that match the installed PPIs.\r
-    // Use "while" instead of "if" since DispatchNotify can modify \r
-    // PpiListEnd (with InstallPpi) so we have to iterate until the same.\r
+    // Use "while" instead of "if" since ProcessNotify can modify\r
+    // PpiList.CurrentCount (with InstallPpi) so we have to iterate\r
+    // until the same.\r
     //\r
-    while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) {\r
-      TempValue = PrivateData->PpiData.PpiListEnd;\r
-      DispatchNotify (\r
-        PeiServices,\r
+    while (PrivateData->PpiData.PpiList.LastDispatchedCount != PrivateData->PpiData.PpiList.CurrentCount) {\r
+      TempValue = PrivateData->PpiData.PpiList.CurrentCount;\r
+      ProcessNotify (\r
+        PrivateData,\r
         EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,\r
-        PrivateData->PpiData.LastDispatchedInstall,\r
-        PrivateData->PpiData.PpiListEnd,\r
-        MAX_PPI_DESCRIPTORS-1,\r
-        PrivateData->PpiData.DispatchListEnd\r
+        PrivateData->PpiData.PpiList.LastDispatchedCount,\r
+        PrivateData->PpiData.PpiList.CurrentCount,\r
+        0,\r
+        PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount\r
         );\r
-      PrivateData->PpiData.LastDispatchedInstall = TempValue;\r
+      PrivateData->PpiData.PpiList.LastDispatchedCount = TempValue;\r
     }\r
-    \r
-    if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) {\r
+\r
+    if (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount == PrivateData->PpiData.DispatchNotifyList.CurrentCount) {\r
       break;\r
     }\r
-  } \r
+  }\r
   return;\r
 }\r
 \r
+/**\r
+\r
+  Process notifications.\r
+\r
+  @param PrivateData        PeiCore's private data structure\r
+  @param NotifyType         Type of notify to fire.\r
+  @param InstallStartIndex  Install Beginning index.\r
+  @param InstallStopIndex   Install Ending index.\r
+  @param NotifyStartIndex   Notify Beginning index.\r
+  @param NotifyStopIndex    Notify Ending index.\r
+\r
+**/\r
 VOID\r
-DispatchNotify (\r
-  IN EFI_PEI_SERVICES    **PeiServices,\r
+ProcessNotify (\r
+  IN PEI_CORE_INSTANCE  *PrivateData,\r
   IN UINTN               NotifyType,\r
   IN INTN                InstallStartIndex,\r
   IN INTN                InstallStopIndex,\r
   IN INTN                NotifyStartIndex,\r
   IN INTN                NotifyStopIndex\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Dispatch notifications.\r
-\r
-Arguments:\r
-\r
-  PeiServices         - Pointer to the PEI Service Table\r
-  NotifyType          - Type of notify to fire.\r
-  InstallStartIndex   - Install Beginning index.\r
-  InstallStopIndex    - Install Ending index.\r
-  NotifyStartIndex    - Notify Beginning index.\r
-  NotifyStopIndex    - Notify Ending index.\r
-\r
-Returns:  None\r
-\r
---*/\r
-\r
 {\r
-  PEI_CORE_INSTANCE       *PrivateData;\r
-  INTN                   Index1;\r
-  INTN                   Index2;\r
-  EFI_GUID                *SearchGuid;\r
-  EFI_GUID                *CheckGuid;\r
-  EFI_PEI_NOTIFY_DESCRIPTOR   *NotifyDescriptor;\r
-\r
-  PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
-\r
-  //\r
-  // Remember that Installs moves up and Notifies moves down.\r
-  //\r
-  for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) {\r
-    NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify;\r
+  INTN                          Index1;\r
+  INTN                          Index2;\r
+  EFI_GUID                      *SearchGuid;\r
+  EFI_GUID                      *CheckGuid;\r
+  EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor;\r
+\r
+  for (Index1 = NotifyStartIndex; Index1 < NotifyStopIndex; Index1++) {\r
+    if (NotifyType == EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) {\r
+      NotifyDescriptor = PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index1].Notify;\r
+    } else {\r
+      NotifyDescriptor = PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index1].Notify;\r
+    }\r
 \r
     CheckGuid = NotifyDescriptor->Guid;\r
 \r
     for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {\r
-      SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid;\r
+      SearchGuid = PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi->Guid;\r
       //\r
       // Don't use CompareGuid function here for performance reasons.\r
       // Instead we compare the GUID as INT32 at a time and branch\r
@@ -640,19 +763,76 @@ Returns:  None
           (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) &&\r
           (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) &&\r
           (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) {\r
-        DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %x\n", \r
-          SearchGuid, \r
+        DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %p\n",\r
+          SearchGuid,\r
           NotifyDescriptor->Notify\r
           ));\r
         NotifyDescriptor->Notify (\r
-                            PeiServices,\r
+                            (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),\r
                             NotifyDescriptor,\r
-                            (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi\r
+                            (PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi)->Ppi\r
                             );\r
       }\r
     }\r
   }\r
+}\r
 \r
-  return;\r
+/**\r
+  Process PpiList from SEC phase.\r
+\r
+  @param PeiServices    An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+  @param PpiList        Points to a list of one or more PPI descriptors to be installed initially by the PEI core.\r
+                        These PPI's will be installed and/or immediately signaled if they are notification type.\r
+\r
+**/\r
+VOID\r
+ProcessPpiListFromSec (\r
+  IN CONST EFI_PEI_SERVICES         **PeiServices,\r
+  IN CONST EFI_PEI_PPI_DESCRIPTOR   *PpiList\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_SEC_HOB_DATA_PPI      *SecHobDataPpi;\r
+  EFI_HOB_GENERIC_HEADER    *SecHobList;\r
+\r
+  for (;;) {\r
+    if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) != 0) {\r
+      //\r
+      // It is a notification PPI.\r
+      //\r
+      Status = InternalPeiNotifyPpi (PeiServices, (CONST EFI_PEI_NOTIFY_DESCRIPTOR *) PpiList, TRUE);\r
+      ASSERT_EFI_ERROR (Status);\r
+    } else {\r
+      //\r
+      // It is a normal PPI.\r
+      //\r
+      Status = InternalPeiInstallPpi (PeiServices, PpiList, TRUE);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+\r
+    if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {\r
+      //\r
+      // Continue until the end of the PPI List.\r
+      //\r
+      break;\r
+    }\r
+\r
+    PpiList++;\r
+  }\r
+\r
+  //\r
+  // If the EFI_SEC_HOB_DATA_PPI is in the list of PPIs passed to the PEI entry point,\r
+  // the PEI Foundation will call the GetHobs() member function and install all HOBs\r
+  // returned into the HOB list. It does this after installing all PPIs passed from SEC\r
+  // into the PPI database and before dispatching any PEIMs.\r
+  //\r
+  Status = PeiLocatePpi (PeiServices, &gEfiSecHobDataPpiGuid, 0, NULL, (VOID **) &SecHobDataPpi);\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = SecHobDataPpi->GetHobs (SecHobDataPpi, &SecHobList);\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = PeiInstallSecHobData (PeiServices, SecHobList);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
 }\r
 \r