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
InitializePpiServices(IN PEI_CORE_INSTANCE * PrivateData,IN PEI_CORE_INSTANCE * OldCoreData)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
ConvertSinglePpiPointer(IN PEI_PPI_LIST_POINTERS * PpiPointer,IN UINTN TempBottom,IN UINTN TempTop,IN UINTN Offset,IN BOOLEAN OffsetPositive)51 ConvertSinglePpiPointer (
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
ConvertPpiPointers(IN CONST EFI_SEC_PEI_HAND_OFF * SecCoreData,IN PEI_CORE_INSTANCE * PrivateData)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       ConvertSinglePpiPointer (
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       ConvertSinglePpiPointer (
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         ConvertSinglePpiPointer (
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
PeiInstallPpi(IN CONST EFI_PEI_SERVICES ** PeiServices,IN CONST EFI_PEI_PPI_DESCRIPTOR * PpiList)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
PeiReInstallPpi(IN CONST EFI_PEI_SERVICES ** PeiServices,IN CONST EFI_PEI_PPI_DESCRIPTOR * OldPpi,IN CONST EFI_PEI_PPI_DESCRIPTOR * NewPpi)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
PeiLocatePpi(IN CONST EFI_PEI_SERVICES ** PeiServices,IN CONST EFI_GUID * Guid,IN UINTN Instance,IN OUT EFI_PEI_PPI_DESCRIPTOR ** PpiDescriptor,IN OUT VOID ** Ppi)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
PeiNotifyPpi(IN CONST EFI_PEI_SERVICES ** PeiServices,IN CONST EFI_PEI_NOTIFY_DESCRIPTOR * NotifyList)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
ProcessNotifyList(IN PEI_CORE_INSTANCE * PrivateData)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
DispatchNotify(IN PEI_CORE_INSTANCE * PrivateData,IN UINTN NotifyType,IN INTN InstallStartIndex,IN INTN InstallStopIndex,IN INTN NotifyStartIndex,IN INTN NotifyStopIndex)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