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