]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/Ppi/Ppi.c
MdeModule PeiCore: Support pre memory page allocation
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Ppi / Ppi.c
1 /** @file
2 EFI PEI Core PPI services
3
4 Copyright (c) 2006 - 2017, 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 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 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 if (PrivateData->MemoryPages.Size != 0) {
125 //
126 // Convert PPI pointer in old memory pages
127 // It needs to be done before Convert PPI pointer in old Heap
128 //
129 ConvertSinglePpiPointer (
130 &PrivateData->PpiData.PpiListPtrs[Index],
131 (UINTN)PrivateData->MemoryPages.Base,
132 (UINTN)PrivateData->MemoryPages.Base + PrivateData->MemoryPages.Size,
133 PrivateData->MemoryPages.Offset,
134 PrivateData->MemoryPages.OffsetPositive
135 );
136 }
137
138 //
139 // Convert PPI pointer in old Heap
140 //
141 ConvertSinglePpiPointer (
142 &PrivateData->PpiData.PpiListPtrs[Index],
143 (UINTN)SecCoreData->PeiTemporaryRamBase,
144 (UINTN)SecCoreData->PeiTemporaryRamBase + SecCoreData->PeiTemporaryRamSize,
145 PrivateData->HeapOffset,
146 PrivateData->HeapOffsetPositive
147 );
148
149 //
150 // Convert PPI pointer in old Stack
151 //
152 ConvertSinglePpiPointer (
153 &PrivateData->PpiData.PpiListPtrs[Index],
154 (UINTN)SecCoreData->StackBase,
155 (UINTN)SecCoreData->StackBase + SecCoreData->StackSize,
156 PrivateData->StackOffset,
157 PrivateData->StackOffsetPositive
158 );
159
160 //
161 // Convert PPI pointer in old TempRam Hole
162 //
163 for (IndexHole = 0; IndexHole < HOLE_MAX_NUMBER; IndexHole ++) {
164 if (PrivateData->HoleData[IndexHole].Size == 0) {
165 continue;
166 }
167
168 ConvertSinglePpiPointer (
169 &PrivateData->PpiData.PpiListPtrs[Index],
170 (UINTN)PrivateData->HoleData[IndexHole].Base,
171 (UINTN)PrivateData->HoleData[IndexHole].Base + PrivateData->HoleData[IndexHole].Size,
172 PrivateData->HoleData[IndexHole].Offset,
173 PrivateData->HoleData[IndexHole].OffsetPositive
174 );
175 }
176 }
177 }
178 }
179
180 /**
181
182 This function installs an interface in the PEI PPI database by GUID.
183 The purpose of the service is to publish an interface that other parties
184 can use to call additional PEIMs.
185
186 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
187 @param PpiList Pointer to a list of PEI PPI Descriptors.
188 @param Single TRUE if only single entry in the PpiList.
189 FALSE if the PpiList is ended with an entry which has the
190 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.
191
192 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.
193 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer
194 if any PPI in PpiList is not valid
195 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI
196
197 **/
198 EFI_STATUS
199 InternalPeiInstallPpi (
200 IN CONST EFI_PEI_SERVICES **PeiServices,
201 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,
202 IN BOOLEAN Single
203 )
204 {
205 PEI_CORE_INSTANCE *PrivateData;
206 INTN Index;
207 INTN LastCallbackInstall;
208
209
210 if (PpiList == NULL) {
211 return EFI_INVALID_PARAMETER;
212 }
213
214 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
215
216 Index = PrivateData->PpiData.PpiListEnd;
217 LastCallbackInstall = Index;
218
219 //
220 // This is loop installs all PPI descriptors in the PpiList. It is terminated
221 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
222 // EFI_PEI_PPI_DESCRIPTOR in the list.
223 //
224
225 for (;;) {
226 //
227 // Since PpiData is used for NotifyList and PpiList, max resource
228 // is reached if the Install reaches the NotifyList
229 // PcdPeiCoreMaxPpiSupported can be set to a larger value in DSC to satisfy more PPI requirement.
230 //
231 if (Index == PrivateData->PpiData.NotifyListEnd + 1) {
232 return EFI_OUT_OF_RESOURCES;
233 }
234 //
235 // Check if it is a valid PPI.
236 // If not, rollback list to exclude all in this list.
237 // Try to indicate which item failed.
238 //
239 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {
240 PrivateData->PpiData.PpiListEnd = LastCallbackInstall;
241 DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi));
242 return EFI_INVALID_PARAMETER;
243 }
244
245 DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid));
246 PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR*) PpiList;
247 PrivateData->PpiData.PpiListEnd++;
248
249 if (Single) {
250 //
251 // Only single entry in the PpiList.
252 //
253 break;
254 } else if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
255 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
256 //
257 // Continue until the end of the PPI List.
258 //
259 break;
260 }
261 PpiList++;
262 Index++;
263 }
264
265 //
266 // Dispatch any callback level notifies for newly installed PPIs.
267 //
268 DispatchNotify (
269 PrivateData,
270 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
271 LastCallbackInstall,
272 PrivateData->PpiData.PpiListEnd,
273 PrivateData->PpiData.DispatchListEnd,
274 PrivateData->PpiData.NotifyListEnd
275 );
276
277
278 return EFI_SUCCESS;
279 }
280
281 /**
282
283 This function installs an interface in the PEI PPI database by GUID.
284 The purpose of the service is to publish an interface that other parties
285 can use to call additional PEIMs.
286
287 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
288 @param PpiList Pointer to a list of PEI PPI Descriptors.
289
290 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.
291 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer
292 if any PPI in PpiList is not valid
293 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI
294
295 **/
296 EFI_STATUS
297 EFIAPI
298 PeiInstallPpi (
299 IN CONST EFI_PEI_SERVICES **PeiServices,
300 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList
301 )
302 {
303 return InternalPeiInstallPpi (PeiServices, PpiList, FALSE);
304 }
305
306 /**
307
308 This function reinstalls an interface in the PEI PPI database by GUID.
309 The purpose of the service is to publish an interface that other parties can
310 use to replace an interface of the same name in the protocol database with a
311 different interface.
312
313 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
314 @param OldPpi Pointer to the old PEI PPI Descriptors.
315 @param NewPpi Pointer to the new PEI PPI Descriptors.
316
317 @retval EFI_SUCCESS if the operation was successful
318 @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL
319 @retval EFI_INVALID_PARAMETER if NewPpi is not valid
320 @retval EFI_NOT_FOUND if the PPI was not in the database
321
322 **/
323 EFI_STATUS
324 EFIAPI
325 PeiReInstallPpi (
326 IN CONST EFI_PEI_SERVICES **PeiServices,
327 IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi,
328 IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi
329 )
330 {
331 PEI_CORE_INSTANCE *PrivateData;
332 INTN Index;
333
334
335 if ((OldPpi == NULL) || (NewPpi == NULL)) {
336 return EFI_INVALID_PARAMETER;
337 }
338
339 if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {
340 return EFI_INVALID_PARAMETER;
341 }
342
343 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
344
345 //
346 // Find the old PPI instance in the database. If we can not find it,
347 // return the EFI_NOT_FOUND error.
348 //
349 for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {
350 if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) {
351 break;
352 }
353 }
354 if (Index == PrivateData->PpiData.PpiListEnd) {
355 return EFI_NOT_FOUND;
356 }
357
358 //
359 // Remove the old PPI from the database, add the new one.
360 //
361 DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));
362 ASSERT (Index < (INTN)(PcdGet32 (PcdPeiCoreMaxPpiSupported)));
363 PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) NewPpi;
364
365 //
366 // Dispatch any callback level notifies for the newly installed PPI.
367 //
368 DispatchNotify (
369 PrivateData,
370 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
371 Index,
372 Index+1,
373 PrivateData->PpiData.DispatchListEnd,
374 PrivateData->PpiData.NotifyListEnd
375 );
376
377
378 return EFI_SUCCESS;
379 }
380
381 /**
382
383 Locate a given named PPI.
384
385
386 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
387 @param Guid Pointer to GUID of the PPI.
388 @param Instance Instance Number to discover.
389 @param PpiDescriptor Pointer to reference the found descriptor. If not NULL,
390 returns a pointer to the descriptor (includes flags, etc)
391 @param Ppi Pointer to reference the found PPI
392
393 @retval EFI_SUCCESS if the PPI is in the database
394 @retval EFI_NOT_FOUND if the PPI is not in the database
395
396 **/
397 EFI_STATUS
398 EFIAPI
399 PeiLocatePpi (
400 IN CONST EFI_PEI_SERVICES **PeiServices,
401 IN CONST EFI_GUID *Guid,
402 IN UINTN Instance,
403 IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,
404 IN OUT VOID **Ppi
405 )
406 {
407 PEI_CORE_INSTANCE *PrivateData;
408 INTN Index;
409 EFI_GUID *CheckGuid;
410 EFI_PEI_PPI_DESCRIPTOR *TempPtr;
411
412
413 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
414
415 //
416 // Search the data base for the matching instance of the GUIDed PPI.
417 //
418 for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {
419 TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi;
420 CheckGuid = TempPtr->Guid;
421
422 //
423 // Don't use CompareGuid function here for performance reasons.
424 // Instead we compare the GUID as INT32 at a time and branch
425 // on the first failed comparison.
426 //
427 if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) &&
428 (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) &&
429 (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) &&
430 (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) {
431 if (Instance == 0) {
432
433 if (PpiDescriptor != NULL) {
434 *PpiDescriptor = TempPtr;
435 }
436
437 if (Ppi != NULL) {
438 *Ppi = TempPtr->Ppi;
439 }
440
441
442 return EFI_SUCCESS;
443 }
444 Instance--;
445 }
446 }
447
448 return EFI_NOT_FOUND;
449 }
450
451 /**
452
453 This function installs a notification service to be called back when a given
454 interface is installed or reinstalled. The purpose of the service is to publish
455 an interface that other parties can use to call additional PPIs that may materialize later.
456
457 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
458 @param NotifyList Pointer to list of Descriptors to notify upon.
459 @param Single TRUE if only single entry in the NotifyList.
460 FALSE if the NotifyList is ended with an entry which has the
461 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.
462
463 @retval EFI_SUCCESS if successful
464 @retval EFI_OUT_OF_RESOURCES if no space in the database
465 @retval EFI_INVALID_PARAMETER if not a good descriptor
466
467 **/
468 EFI_STATUS
469 InternalPeiNotifyPpi (
470 IN CONST EFI_PEI_SERVICES **PeiServices,
471 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList,
472 IN BOOLEAN Single
473 )
474 {
475 PEI_CORE_INSTANCE *PrivateData;
476 INTN Index;
477 INTN NotifyIndex;
478 INTN LastCallbackNotify;
479 EFI_PEI_NOTIFY_DESCRIPTOR *NotifyPtr;
480 UINTN NotifyDispatchCount;
481
482
483 NotifyDispatchCount = 0;
484
485 if (NotifyList == NULL) {
486 return EFI_INVALID_PARAMETER;
487 }
488
489 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
490
491 Index = PrivateData->PpiData.NotifyListEnd;
492 LastCallbackNotify = Index;
493
494 //
495 // This is loop installs all Notify descriptors in the NotifyList. It is
496 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
497 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.
498 //
499
500 for (;;) {
501 //
502 // Since PpiData is used for NotifyList and InstallList, max resource
503 // is reached if the Install reaches the PpiList
504 // PcdPeiCoreMaxPpiSupported can be set to a larger value in DSC to satisfy more Notify PPIs requirement.
505 //
506 if (Index == PrivateData->PpiData.PpiListEnd - 1) {
507 return EFI_OUT_OF_RESOURCES;
508 }
509
510 //
511 // If some of the PPI data is invalid restore original Notify PPI database value
512 //
513 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {
514 PrivateData->PpiData.NotifyListEnd = LastCallbackNotify;
515 DEBUG((EFI_D_ERROR, "ERROR -> InstallNotify: %g %p\n", NotifyList->Guid, NotifyList->Notify));
516 return EFI_INVALID_PARAMETER;
517 }
518
519 if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {
520 NotifyDispatchCount ++;
521 }
522
523 PrivateData->PpiData.PpiListPtrs[Index].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList;
524
525 PrivateData->PpiData.NotifyListEnd--;
526 DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));
527 if (Single) {
528 //
529 // Only single entry in the NotifyList.
530 //
531 break;
532 } else if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
533 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
534 //
535 // Continue until the end of the Notify List.
536 //
537 break;
538 }
539 //
540 // Go the next descriptor. Remember the NotifyList moves down.
541 //
542 NotifyList++;
543 Index--;
544 }
545
546 //
547 // If there is Dispatch Notify PPI installed put them on the bottom
548 //
549 if (NotifyDispatchCount > 0) {
550 for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) {
551 if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {
552 NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify;
553
554 for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){
555 PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify;
556 }
557 PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr;
558 PrivateData->PpiData.DispatchListEnd--;
559 }
560 }
561
562 LastCallbackNotify -= NotifyDispatchCount;
563 }
564
565 //
566 // Dispatch any callback level notifies for all previously installed PPIs.
567 //
568 DispatchNotify (
569 PrivateData,
570 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
571 0,
572 PrivateData->PpiData.PpiListEnd,
573 LastCallbackNotify,
574 PrivateData->PpiData.NotifyListEnd
575 );
576
577 return EFI_SUCCESS;
578 }
579
580 /**
581
582 This function installs a notification service to be called back when a given
583 interface is installed or reinstalled. The purpose of the service is to publish
584 an interface that other parties can use to call additional PPIs that may materialize later.
585
586 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
587 @param NotifyList Pointer to list of Descriptors to notify upon.
588
589 @retval EFI_SUCCESS if successful
590 @retval EFI_OUT_OF_RESOURCES if no space in the database
591 @retval EFI_INVALID_PARAMETER if not a good descriptor
592
593 **/
594 EFI_STATUS
595 EFIAPI
596 PeiNotifyPpi (
597 IN CONST EFI_PEI_SERVICES **PeiServices,
598 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList
599 )
600 {
601 return InternalPeiNotifyPpi (PeiServices, NotifyList, FALSE);
602 }
603
604
605 /**
606
607 Process the Notify List at dispatch level.
608
609 @param PrivateData PeiCore's private data structure.
610
611 **/
612 VOID
613 ProcessNotifyList (
614 IN PEI_CORE_INSTANCE *PrivateData
615 )
616 {
617 INTN TempValue;
618
619 while (TRUE) {
620 //
621 // Check if the PEIM that was just dispatched resulted in any
622 // Notifies getting installed. If so, go process any dispatch
623 // level Notifies that match the previouly installed PPIs.
624 // Use "while" instead of "if" since DispatchNotify can modify
625 // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.
626 //
627 while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) {
628 TempValue = PrivateData->PpiData.DispatchListEnd;
629 DispatchNotify (
630 PrivateData,
631 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,
632 0,
633 PrivateData->PpiData.LastDispatchedInstall,
634 PrivateData->PpiData.LastDispatchedNotify,
635 PrivateData->PpiData.DispatchListEnd
636 );
637 PrivateData->PpiData.LastDispatchedNotify = TempValue;
638 }
639
640
641 //
642 // Check if the PEIM that was just dispatched resulted in any
643 // PPIs getting installed. If so, go process any dispatch
644 // level Notifies that match the installed PPIs.
645 // Use "while" instead of "if" since DispatchNotify can modify
646 // PpiListEnd (with InstallPpi) so we have to iterate until the same.
647 //
648 while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) {
649 TempValue = PrivateData->PpiData.PpiListEnd;
650 DispatchNotify (
651 PrivateData,
652 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,
653 PrivateData->PpiData.LastDispatchedInstall,
654 PrivateData->PpiData.PpiListEnd,
655 PcdGet32 (PcdPeiCoreMaxPpiSupported)-1,
656 PrivateData->PpiData.DispatchListEnd
657 );
658 PrivateData->PpiData.LastDispatchedInstall = TempValue;
659 }
660
661 if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) {
662 break;
663 }
664 }
665 return;
666 }
667
668 /**
669
670 Dispatch notifications.
671
672 @param PrivateData PeiCore's private data structure
673 @param NotifyType Type of notify to fire.
674 @param InstallStartIndex Install Beginning index.
675 @param InstallStopIndex Install Ending index.
676 @param NotifyStartIndex Notify Beginning index.
677 @param NotifyStopIndex Notify Ending index.
678
679 **/
680 VOID
681 DispatchNotify (
682 IN PEI_CORE_INSTANCE *PrivateData,
683 IN UINTN NotifyType,
684 IN INTN InstallStartIndex,
685 IN INTN InstallStopIndex,
686 IN INTN NotifyStartIndex,
687 IN INTN NotifyStopIndex
688 )
689 {
690 INTN Index1;
691 INTN Index2;
692 EFI_GUID *SearchGuid;
693 EFI_GUID *CheckGuid;
694 EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;
695
696 //
697 // Remember that Installs moves up and Notifies moves down.
698 //
699 for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) {
700 NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify;
701
702 CheckGuid = NotifyDescriptor->Guid;
703
704 for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {
705 SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid;
706 //
707 // Don't use CompareGuid function here for performance reasons.
708 // Instead we compare the GUID as INT32 at a time and branch
709 // on the first failed comparison.
710 //
711 if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) &&
712 (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) &&
713 (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) &&
714 (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) {
715 DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %p\n",
716 SearchGuid,
717 NotifyDescriptor->Notify
718 ));
719 NotifyDescriptor->Notify (
720 (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),
721 NotifyDescriptor,
722 (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi
723 );
724 }
725 }
726 }
727 }
728
729 /**
730 Process PpiList from SEC phase.
731
732 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
733 @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
734 These PPI's will be installed and/or immediately signaled if they are notification type.
735
736 **/
737 VOID
738 ProcessPpiListFromSec (
739 IN CONST EFI_PEI_SERVICES **PeiServices,
740 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList
741 )
742 {
743 EFI_STATUS Status;
744 EFI_SEC_HOB_DATA_PPI *SecHobDataPpi;
745 EFI_HOB_GENERIC_HEADER *SecHobList;
746
747 for (;;) {
748 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) != 0) {
749 //
750 // It is a notification PPI.
751 //
752 Status = InternalPeiNotifyPpi (PeiServices, (CONST EFI_PEI_NOTIFY_DESCRIPTOR *) PpiList, TRUE);
753 ASSERT_EFI_ERROR (Status);
754 } else {
755 //
756 // It is a normal PPI.
757 //
758 Status = InternalPeiInstallPpi (PeiServices, PpiList, TRUE);
759 ASSERT_EFI_ERROR (Status);
760 }
761
762 if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
763 //
764 // Continue until the end of the PPI List.
765 //
766 break;
767 }
768
769 PpiList++;
770 }
771
772 //
773 // If the EFI_SEC_HOB_DATA_PPI is in the list of PPIs passed to the PEI entry point,
774 // the PEI Foundation will call the GetHobs() member function and install all HOBs
775 // returned into the HOB list. It does this after installing all PPIs passed from SEC
776 // into the PPI database and before dispatching any PEIMs.
777 //
778 Status = PeiLocatePpi (PeiServices, &gEfiSecHobDataPpiGuid, 0, NULL, (VOID **) &SecHobDataPpi);
779 if (!EFI_ERROR (Status)) {
780 Status = SecHobDataPpi->GetHobs (SecHobDataPpi, &SecHobList);
781 if (!EFI_ERROR (Status)) {
782 Status = PeiInstallSecHobData (PeiServices, SecHobList);
783 ASSERT_EFI_ERROR (Status);
784 }
785 }
786 }
787