Home | History | Annotate | Download | only in Ppi
      1 /** @file
      2   EFI PEI Core PPI services
      3 
      4 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "PeiMain.h"
     16 
     17 /**
     18 
     19   Initialize PPI services.
     20 
     21   @param PrivateData     Pointer to the PEI Core data.
     22   @param OldCoreData     Pointer to old PEI Core data.
     23                          NULL if being run in non-permament memory mode.
     24 
     25 **/
     26 VOID
     27 InitializePpiServices (
     28   IN PEI_CORE_INSTANCE *PrivateData,
     29   IN PEI_CORE_INSTANCE *OldCoreData
     30   )
     31 {
     32   if (OldCoreData == NULL) {
     33     PrivateData->PpiData.NotifyListEnd = PcdGet32 (PcdPeiCoreMaxPpiSupported)-1;
     34     PrivateData->PpiData.DispatchListEnd = PcdGet32 (PcdPeiCoreMaxPpiSupported)-1;
     35     PrivateData->PpiData.LastDispatchedNotify = PcdGet32 (PcdPeiCoreMaxPpiSupported)-1;
     36   }
     37 }
     38 
     39 /**
     40 
     41   Migrate Single PPI Pointer from the temporary memory to PEI installed memory.
     42 
     43   @param PpiPointer      Pointer to Ppi
     44   @param TempBottom      Base of old temporary memory
     45   @param TempTop         Top of old temporary memory
     46   @param Offset          Offset of new memory to old temporary memory.
     47   @param OffsetPositive  Positive flag of Offset value.
     48 
     49 **/
     50 VOID
     51 ConverSinglePpiPointer (
     52   IN PEI_PPI_LIST_POINTERS *PpiPointer,
     53   IN UINTN                 TempBottom,
     54   IN UINTN                 TempTop,
     55   IN UINTN                 Offset,
     56   IN BOOLEAN               OffsetPositive
     57   )
     58 {
     59   if (((UINTN)PpiPointer->Raw < TempTop) &&
     60       ((UINTN)PpiPointer->Raw >= TempBottom)) {
     61     //
     62     // Convert the pointer to the PPI descriptor from the old TempRam
     63     // to the relocated physical memory.
     64     //
     65     if (OffsetPositive) {
     66       PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw + Offset);
     67     } else {
     68       PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw - Offset);
     69     }
     70 
     71     //
     72     // Only when the PEIM descriptor is in the old TempRam should it be necessary
     73     // to try to convert the pointers in the PEIM descriptor
     74     //
     75 
     76     if (((UINTN)PpiPointer->Ppi->Guid < TempTop) &&
     77         ((UINTN)PpiPointer->Ppi->Guid >= TempBottom)) {
     78       //
     79       // Convert the pointer to the GUID in the PPI or NOTIFY descriptor
     80       // from the old TempRam to the relocated physical memory.
     81       //
     82       if (OffsetPositive) {
     83         PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid + Offset);
     84       } else {
     85         PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid - Offset);
     86       }
     87     }
     88 
     89     //
     90     // Convert the pointer to the PPI interface structure in the PPI descriptor
     91     // from the old TempRam to the relocated physical memory.
     92     //
     93     if ((UINTN)PpiPointer->Ppi->Ppi < TempTop &&
     94         (UINTN)PpiPointer->Ppi->Ppi >= TempBottom) {
     95       if (OffsetPositive) {
     96         PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi + Offset);
     97       } else {
     98         PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi - Offset);
     99       }
    100     }
    101   }
    102 }
    103 
    104 /**
    105 
    106   Migrate PPI Pointers from the temporary memory stack to PEI installed memory.
    107 
    108   @param SecCoreData     Points to a data structure containing SEC to PEI handoff data, such as the size
    109                          and location of temporary RAM, the stack location and the BFV location.
    110   @param PrivateData     Pointer to PeiCore's private data structure.
    111 
    112 **/
    113 VOID
    114 ConvertPpiPointers (
    115   IN CONST EFI_SEC_PEI_HAND_OFF  *SecCoreData,
    116   IN PEI_CORE_INSTANCE           *PrivateData
    117   )
    118 {
    119   UINT8                 Index;
    120   UINT8                 IndexHole;
    121 
    122   for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxPpiSupported); Index++) {
    123     if (Index < PrivateData->PpiData.PpiListEnd || Index > PrivateData->PpiData.NotifyListEnd) {
    124       //
    125       // Convert PPI pointer in old Heap
    126       //
    127       ConverSinglePpiPointer (
    128         &PrivateData->PpiData.PpiListPtrs[Index],
    129         (UINTN)SecCoreData->PeiTemporaryRamBase,
    130         (UINTN)SecCoreData->PeiTemporaryRamBase + SecCoreData->PeiTemporaryRamSize,
    131         PrivateData->HeapOffset,
    132         PrivateData->HeapOffsetPositive
    133         );
    134 
    135       //
    136       // Convert PPI pointer in old Stack
    137       //
    138       ConverSinglePpiPointer (
    139         &PrivateData->PpiData.PpiListPtrs[Index],
    140         (UINTN)SecCoreData->StackBase,
    141         (UINTN)SecCoreData->StackBase + SecCoreData->StackSize,
    142         PrivateData->StackOffset,
    143         PrivateData->StackOffsetPositive
    144         );
    145 
    146       //
    147       // Convert PPI pointer in old TempRam Hole
    148       //
    149       for (IndexHole = 0; IndexHole < HOLE_MAX_NUMBER; IndexHole ++) {
    150         if (PrivateData->HoleData[IndexHole].Size == 0) {
    151           continue;
    152         }
    153 
    154         ConverSinglePpiPointer (
    155           &PrivateData->PpiData.PpiListPtrs[Index],
    156           (UINTN)PrivateData->HoleData[IndexHole].Base,
    157           (UINTN)PrivateData->HoleData[IndexHole].Base + PrivateData->HoleData[IndexHole].Size,
    158           PrivateData->HoleData[IndexHole].Offset,
    159           PrivateData->HoleData[IndexHole].OffsetPositive
    160           );
    161       }
    162     }
    163   }
    164 }
    165 
    166 /**
    167 
    168   This function installs an interface in the PEI PPI database by GUID.
    169   The purpose of the service is to publish an interface that other parties
    170   can use to call additional PEIMs.
    171 
    172   @param PeiServices                An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
    173   @param PpiList                    Pointer to a list of PEI PPI Descriptors.
    174 
    175   @retval EFI_SUCCESS              if all PPIs in PpiList are successfully installed.
    176   @retval EFI_INVALID_PARAMETER    if PpiList is NULL pointer
    177                                    if any PPI in PpiList is not valid
    178   @retval EFI_OUT_OF_RESOURCES     if there is no more memory resource to install PPI
    179 
    180 **/
    181 EFI_STATUS
    182 EFIAPI
    183 PeiInstallPpi (
    184   IN CONST EFI_PEI_SERVICES        **PeiServices,
    185   IN CONST EFI_PEI_PPI_DESCRIPTOR  *PpiList
    186   )
    187 {
    188   PEI_CORE_INSTANCE *PrivateData;
    189   INTN              Index;
    190   INTN              LastCallbackInstall;
    191 
    192 
    193   if (PpiList == NULL) {
    194     return EFI_INVALID_PARAMETER;
    195   }
    196 
    197   PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
    198 
    199   Index = PrivateData->PpiData.PpiListEnd;
    200   LastCallbackInstall = Index;
    201 
    202   //
    203   // This is loop installs all PPI descriptors in the PpiList.  It is terminated
    204   // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
    205   // EFI_PEI_PPI_DESCRIPTOR in the list.
    206   //
    207 
    208   for (;;) {
    209     //
    210     // Since PpiData is used for NotifyList and PpiList, max resource
    211     // is reached if the Install reaches the NotifyList
    212     // PcdPeiCoreMaxPpiSupported can be set to a larger value in DSC to satisfy more PPI requirement.
    213     //
    214     if (Index == PrivateData->PpiData.NotifyListEnd + 1) {
    215       return  EFI_OUT_OF_RESOURCES;
    216     }
    217     //
    218     // Check if it is a valid PPI.
    219     // If not, rollback list to exclude all in this list.
    220     // Try to indicate which item failed.
    221     //
    222     if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {
    223       PrivateData->PpiData.PpiListEnd = LastCallbackInstall;
    224       DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi));
    225       return  EFI_INVALID_PARAMETER;
    226     }
    227 
    228     DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid));
    229     PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR*) PpiList;
    230     PrivateData->PpiData.PpiListEnd++;
    231 
    232     //
    233     // Continue until the end of the PPI List.
    234     //
    235     if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
    236         EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
    237       break;
    238     }
    239     PpiList++;
    240     Index++;
    241   }
    242 
    243   //
    244   // Dispatch any callback level notifies for newly installed PPIs.
    245   //
    246   DispatchNotify (
    247     PrivateData,
    248     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
    249     LastCallbackInstall,
    250     PrivateData->PpiData.PpiListEnd,
    251     PrivateData->PpiData.DispatchListEnd,
    252     PrivateData->PpiData.NotifyListEnd
    253     );
    254 
    255 
    256   return EFI_SUCCESS;
    257 }
    258 
    259 /**
    260 
    261   This function reinstalls an interface in the PEI PPI database by GUID.
    262   The purpose of the service is to publish an interface that other parties can
    263   use to replace an interface of the same name in the protocol database with a
    264   different interface.
    265 
    266   @param PeiServices            An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
    267   @param OldPpi                 Pointer to the old PEI PPI Descriptors.
    268   @param NewPpi                 Pointer to the new PEI PPI Descriptors.
    269 
    270   @retval EFI_SUCCESS           if the operation was successful
    271   @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL
    272   @retval EFI_INVALID_PARAMETER if NewPpi is not valid
    273   @retval EFI_NOT_FOUND         if the PPI was not in the database
    274 
    275 **/
    276 EFI_STATUS
    277 EFIAPI
    278 PeiReInstallPpi (
    279   IN CONST EFI_PEI_SERVICES        **PeiServices,
    280   IN CONST EFI_PEI_PPI_DESCRIPTOR  *OldPpi,
    281   IN CONST EFI_PEI_PPI_DESCRIPTOR  *NewPpi
    282   )
    283 {
    284   PEI_CORE_INSTANCE   *PrivateData;
    285   INTN                Index;
    286 
    287 
    288   if ((OldPpi == NULL) || (NewPpi == NULL)) {
    289     return EFI_INVALID_PARAMETER;
    290   }
    291 
    292   if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {
    293     return  EFI_INVALID_PARAMETER;
    294   }
    295 
    296   PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
    297 
    298   //
    299   // Find the old PPI instance in the database.  If we can not find it,
    300   // return the EFI_NOT_FOUND error.
    301   //
    302   for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {
    303     if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) {
    304       break;
    305     }
    306   }
    307   if (Index == PrivateData->PpiData.PpiListEnd) {
    308     return EFI_NOT_FOUND;
    309   }
    310 
    311   //
    312   // Remove the old PPI from the database, add the new one.
    313   //
    314   DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));
    315   ASSERT (Index < (INTN)(PcdGet32 (PcdPeiCoreMaxPpiSupported)));
    316   PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) NewPpi;
    317 
    318   //
    319   // Dispatch any callback level notifies for the newly installed PPI.
    320   //
    321   DispatchNotify (
    322     PrivateData,
    323     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
    324     Index,
    325     Index+1,
    326     PrivateData->PpiData.DispatchListEnd,
    327     PrivateData->PpiData.NotifyListEnd
    328     );
    329 
    330 
    331   return EFI_SUCCESS;
    332 }
    333 
    334 /**
    335 
    336   Locate a given named PPI.
    337 
    338 
    339   @param PeiServices        An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
    340   @param Guid               Pointer to GUID of the PPI.
    341   @param Instance           Instance Number to discover.
    342   @param PpiDescriptor      Pointer to reference the found descriptor. If not NULL,
    343                             returns a pointer to the descriptor (includes flags, etc)
    344   @param Ppi                Pointer to reference the found PPI
    345 
    346   @retval EFI_SUCCESS   if the PPI is in the database
    347   @retval EFI_NOT_FOUND if the PPI is not in the database
    348 
    349 **/
    350 EFI_STATUS
    351 EFIAPI
    352 PeiLocatePpi (
    353   IN CONST EFI_PEI_SERVICES        **PeiServices,
    354   IN CONST EFI_GUID                *Guid,
    355   IN UINTN                         Instance,
    356   IN OUT EFI_PEI_PPI_DESCRIPTOR    **PpiDescriptor,
    357   IN OUT VOID                      **Ppi
    358   )
    359 {
    360   PEI_CORE_INSTANCE   *PrivateData;
    361   INTN                Index;
    362   EFI_GUID            *CheckGuid;
    363   EFI_PEI_PPI_DESCRIPTOR  *TempPtr;
    364 
    365 
    366   PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
    367 
    368   //
    369   // Search the data base for the matching instance of the GUIDed PPI.
    370   //
    371   for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {
    372     TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi;
    373     CheckGuid = TempPtr->Guid;
    374 
    375     //
    376     // Don't use CompareGuid function here for performance reasons.
    377     // Instead we compare the GUID as INT32 at a time and branch
    378     // on the first failed comparison.
    379     //
    380     if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) &&
    381         (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) &&
    382         (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) &&
    383         (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) {
    384       if (Instance == 0) {
    385 
    386         if (PpiDescriptor != NULL) {
    387           *PpiDescriptor = TempPtr;
    388         }
    389 
    390         if (Ppi != NULL) {
    391           *Ppi = TempPtr->Ppi;
    392         }
    393 
    394 
    395         return EFI_SUCCESS;
    396       }
    397       Instance--;
    398     }
    399   }
    400 
    401   return EFI_NOT_FOUND;
    402 }
    403 
    404 /**
    405 
    406   This function installs a notification service to be called back when a given
    407   interface is installed or reinstalled. The purpose of the service is to publish
    408   an interface that other parties can use to call additional PPIs that may materialize later.
    409 
    410   @param PeiServices        An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
    411   @param NotifyList         Pointer to list of Descriptors to notify upon.
    412 
    413   @retval EFI_SUCCESS           if successful
    414   @retval EFI_OUT_OF_RESOURCES  if no space in the database
    415   @retval EFI_INVALID_PARAMETER if not a good decriptor
    416 
    417 **/
    418 EFI_STATUS
    419 EFIAPI
    420 PeiNotifyPpi (
    421   IN CONST EFI_PEI_SERVICES           **PeiServices,
    422   IN CONST EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyList
    423   )
    424 {
    425   PEI_CORE_INSTANCE                *PrivateData;
    426   INTN                             Index;
    427   INTN                             NotifyIndex;
    428   INTN                             LastCallbackNotify;
    429   EFI_PEI_NOTIFY_DESCRIPTOR        *NotifyPtr;
    430   UINTN                            NotifyDispatchCount;
    431 
    432 
    433   NotifyDispatchCount = 0;
    434 
    435   if (NotifyList == NULL) {
    436     return EFI_INVALID_PARAMETER;
    437   }
    438 
    439   PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
    440 
    441   Index = PrivateData->PpiData.NotifyListEnd;
    442   LastCallbackNotify = Index;
    443 
    444   //
    445   // This is loop installs all Notify descriptors in the NotifyList.  It is
    446   // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
    447   // EFI_PEI_NOTIFY_DESCRIPTOR in the list.
    448   //
    449 
    450   for (;;) {
    451     //
    452     // Since PpiData is used for NotifyList and InstallList, max resource
    453     // is reached if the Install reaches the PpiList
    454     // PcdPeiCoreMaxPpiSupported can be set to a larger value in DSC to satisfy more Notify PPIs requirement.
    455     //
    456     if (Index == PrivateData->PpiData.PpiListEnd - 1) {
    457       return  EFI_OUT_OF_RESOURCES;
    458     }
    459 
    460     //
    461     // If some of the PPI data is invalid restore original Notify PPI database value
    462     //
    463     if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {
    464         PrivateData->PpiData.NotifyListEnd = LastCallbackNotify;
    465         DEBUG((EFI_D_ERROR, "ERROR -> InstallNotify: %g %p\n", NotifyList->Guid, NotifyList->Notify));
    466       return  EFI_INVALID_PARAMETER;
    467     }
    468 
    469     if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {
    470       NotifyDispatchCount ++;
    471     }
    472 
    473     PrivateData->PpiData.PpiListPtrs[Index].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList;
    474 
    475     PrivateData->PpiData.NotifyListEnd--;
    476     DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));
    477     if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
    478         EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
    479       break;
    480     }
    481     //
    482     // Go the next descriptor. Remember the NotifyList moves down.
    483     //
    484     NotifyList++;
    485     Index--;
    486   }
    487 
    488   //
    489   // If there is Dispatch Notify PPI installed put them on the bottom
    490   //
    491   if (NotifyDispatchCount > 0) {
    492     for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) {
    493       if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {
    494         NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify;
    495 
    496         for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){
    497           PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify;
    498         }
    499         PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr;
    500         PrivateData->PpiData.DispatchListEnd--;
    501       }
    502     }
    503 
    504     LastCallbackNotify -= NotifyDispatchCount;
    505   }
    506 
    507   //
    508   // Dispatch any callback level notifies for all previously installed PPIs.
    509   //
    510   DispatchNotify (
    511     PrivateData,
    512     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
    513     0,
    514     PrivateData->PpiData.PpiListEnd,
    515     LastCallbackNotify,
    516     PrivateData->PpiData.NotifyListEnd
    517     );
    518 
    519   return  EFI_SUCCESS;
    520 }
    521 
    522 
    523 /**
    524 
    525   Process the Notify List at dispatch level.
    526 
    527   @param PrivateData  PeiCore's private data structure.
    528 
    529 **/
    530 VOID
    531 ProcessNotifyList (
    532   IN PEI_CORE_INSTANCE  *PrivateData
    533   )
    534 {
    535   INTN                    TempValue;
    536 
    537   while (TRUE) {
    538     //
    539     // Check if the PEIM that was just dispatched resulted in any
    540     // Notifies getting installed.  If so, go process any dispatch
    541     // level Notifies that match the previouly installed PPIs.
    542     // Use "while" instead of "if" since DispatchNotify can modify
    543     // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.
    544     //
    545     while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) {
    546       TempValue = PrivateData->PpiData.DispatchListEnd;
    547       DispatchNotify (
    548         PrivateData,
    549         EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,
    550         0,
    551         PrivateData->PpiData.LastDispatchedInstall,
    552         PrivateData->PpiData.LastDispatchedNotify,
    553         PrivateData->PpiData.DispatchListEnd
    554         );
    555       PrivateData->PpiData.LastDispatchedNotify = TempValue;
    556     }
    557 
    558 
    559     //
    560     // Check if the PEIM that was just dispatched resulted in any
    561     // PPIs getting installed.  If so, go process any dispatch
    562     // level Notifies that match the installed PPIs.
    563     // Use "while" instead of "if" since DispatchNotify can modify
    564     // PpiListEnd (with InstallPpi) so we have to iterate until the same.
    565     //
    566     while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) {
    567       TempValue = PrivateData->PpiData.PpiListEnd;
    568       DispatchNotify (
    569         PrivateData,
    570         EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,
    571         PrivateData->PpiData.LastDispatchedInstall,
    572         PrivateData->PpiData.PpiListEnd,
    573         PcdGet32 (PcdPeiCoreMaxPpiSupported)-1,
    574         PrivateData->PpiData.DispatchListEnd
    575         );
    576       PrivateData->PpiData.LastDispatchedInstall = TempValue;
    577     }
    578 
    579     if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) {
    580       break;
    581     }
    582   }
    583   return;
    584 }
    585 
    586 /**
    587 
    588   Dispatch notifications.
    589 
    590   @param PrivateData        PeiCore's private data structure
    591   @param NotifyType         Type of notify to fire.
    592   @param InstallStartIndex  Install Beginning index.
    593   @param InstallStopIndex   Install Ending index.
    594   @param NotifyStartIndex   Notify Beginning index.
    595   @param NotifyStopIndex    Notify Ending index.
    596 
    597 **/
    598 VOID
    599 DispatchNotify (
    600   IN PEI_CORE_INSTANCE  *PrivateData,
    601   IN UINTN               NotifyType,
    602   IN INTN                InstallStartIndex,
    603   IN INTN                InstallStopIndex,
    604   IN INTN                NotifyStartIndex,
    605   IN INTN                NotifyStopIndex
    606   )
    607 {
    608   INTN                   Index1;
    609   INTN                   Index2;
    610   EFI_GUID                *SearchGuid;
    611   EFI_GUID                *CheckGuid;
    612   EFI_PEI_NOTIFY_DESCRIPTOR   *NotifyDescriptor;
    613 
    614   //
    615   // Remember that Installs moves up and Notifies moves down.
    616   //
    617   for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) {
    618     NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify;
    619 
    620     CheckGuid = NotifyDescriptor->Guid;
    621 
    622     for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {
    623       SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid;
    624       //
    625       // Don't use CompareGuid function here for performance reasons.
    626       // Instead we compare the GUID as INT32 at a time and branch
    627       // on the first failed comparison.
    628       //
    629       if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) &&
    630           (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) &&
    631           (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) &&
    632           (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) {
    633         DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %p\n",
    634           SearchGuid,
    635           NotifyDescriptor->Notify
    636           ));
    637         NotifyDescriptor->Notify (
    638                             (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),
    639                             NotifyDescriptor,
    640                             (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi
    641                             );
    642       }
    643     }
    644   }
    645 }
    646 
    647