2 EFI PEI Core PPI services
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
13 Migrate Pointer from the temporary memory to PEI installed memory.
15 @param Pointer Pointer to the Pointer needs to be converted.
16 @param TempBottom Base of old temporary memory
17 @param TempTop Top of old temporary memory
18 @param Offset Offset of new memory to old temporary memory.
19 @param OffsetPositive Positive flag of Offset value.
24 IN OUT VOID
**Pointer
,
28 IN BOOLEAN OffsetPositive
31 if (((UINTN
)*Pointer
< TempTop
) &&
32 ((UINTN
)*Pointer
>= TempBottom
))
35 *Pointer
= (VOID
*)((UINTN
)*Pointer
+ Offset
);
37 *Pointer
= (VOID
*)((UINTN
)*Pointer
- Offset
);
44 Migrate Pointer in ranges of the temporary memory to PEI installed memory.
46 @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
47 and location of temporary RAM, the stack location and the BFV location.
48 @param PrivateData Pointer to PeiCore's private data structure.
49 @param Pointer Pointer to the Pointer needs to be converted.
53 ConvertPointerInRanges (
54 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
55 IN PEI_CORE_INSTANCE
*PrivateData
,
61 if (PrivateData
->MemoryPages
.Size
!= 0) {
63 // Convert PPI pointer in old memory pages
64 // It needs to be done before Convert PPI pointer in old Heap
68 (UINTN
)PrivateData
->MemoryPages
.Base
,
69 (UINTN
)PrivateData
->MemoryPages
.Base
+ PrivateData
->MemoryPages
.Size
,
70 PrivateData
->MemoryPages
.Offset
,
71 PrivateData
->MemoryPages
.OffsetPositive
76 // Convert PPI pointer in old Heap
80 (UINTN
)SecCoreData
->PeiTemporaryRamBase
,
81 (UINTN
)SecCoreData
->PeiTemporaryRamBase
+ SecCoreData
->PeiTemporaryRamSize
,
82 PrivateData
->HeapOffset
,
83 PrivateData
->HeapOffsetPositive
87 // Convert PPI pointer in old Stack
91 (UINTN
)SecCoreData
->StackBase
,
92 (UINTN
)SecCoreData
->StackBase
+ SecCoreData
->StackSize
,
93 PrivateData
->StackOffset
,
94 PrivateData
->StackOffsetPositive
98 // Convert PPI pointer in old TempRam Hole
100 for (IndexHole
= 0; IndexHole
< HOLE_MAX_NUMBER
; IndexHole
++) {
101 if (PrivateData
->HoleData
[IndexHole
].Size
== 0) {
107 (UINTN
)PrivateData
->HoleData
[IndexHole
].Base
,
108 (UINTN
)PrivateData
->HoleData
[IndexHole
].Base
+ PrivateData
->HoleData
[IndexHole
].Size
,
109 PrivateData
->HoleData
[IndexHole
].Offset
,
110 PrivateData
->HoleData
[IndexHole
].OffsetPositive
117 Migrate Single PPI Pointer from the temporary memory to PEI installed memory.
119 @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
120 and location of temporary RAM, the stack location and the BFV location.
121 @param PrivateData Pointer to PeiCore's private data structure.
122 @param PpiPointer Pointer to Ppi
126 ConvertSinglePpiPointer (
127 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
128 IN PEI_CORE_INSTANCE
*PrivateData
,
129 IN PEI_PPI_LIST_POINTERS
*PpiPointer
133 // 1. Convert the pointer to the PPI descriptor from the old TempRam
134 // to the relocated physical memory.
135 // It (for the pointer to the PPI descriptor) needs to be done before 2 (for
136 // the pointer to the GUID) and 3 (for the pointer to the PPI interface structure).
138 ConvertPointerInRanges (SecCoreData
, PrivateData
, &PpiPointer
->Raw
);
140 // 2. Convert the pointer to the GUID in the PPI or NOTIFY descriptor
141 // from the old TempRam to the relocated physical memory.
143 ConvertPointerInRanges (SecCoreData
, PrivateData
, (VOID
**)&PpiPointer
->Ppi
->Guid
);
145 // 3. Convert the pointer to the PPI interface structure in the PPI descriptor
146 // from the old TempRam to the relocated physical memory.
148 ConvertPointerInRanges (SecCoreData
, PrivateData
, (VOID
**)&PpiPointer
->Ppi
->Ppi
);
153 Migrate PPI Pointers from the temporary memory to PEI installed memory.
155 @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
156 and location of temporary RAM, the stack location and the BFV location.
157 @param PrivateData Pointer to PeiCore's private data structure.
162 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
163 IN PEI_CORE_INSTANCE
*PrivateData
169 // Convert normal PPIs.
171 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiList
.CurrentCount
; Index
++) {
172 ConvertSinglePpiPointer (
175 &PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
]
180 // Convert Callback Notification PPIs.
182 for (Index
= 0; Index
< PrivateData
->PpiData
.CallbackNotifyList
.CurrentCount
; Index
++) {
183 ConvertSinglePpiPointer (
186 &PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
]
191 // Convert Dispatch Notification PPIs.
193 for (Index
= 0; Index
< PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
; Index
++) {
194 ConvertSinglePpiPointer (
197 &PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
]
204 Migrate Notify Pointers inside an FV from temporary memory to permanent memory.
206 @param PrivateData Pointer to PeiCore's private data structure.
207 @param OrgFvHandle Address of FV Handle in temporary memory.
208 @param FvHandle Address of FV Handle in permanent memory.
209 @param FvSize Size of the FV.
213 ConvertPpiPointersFv (
214 IN PEI_CORE_INSTANCE
*PrivateData
,
215 IN UINTN OrgFvHandle
,
222 BOOLEAN OffsetPositive
;
223 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*FvInfoPpi
;
226 EFI_GUID
*GuidCheckList
[2];
228 GuidCheckList
[0] = &gEfiPeiFirmwareVolumeInfoPpiGuid
;
229 GuidCheckList
[1] = &gEfiPeiFirmwareVolumeInfo2PpiGuid
;
231 if (FvHandle
> OrgFvHandle
) {
232 OffsetPositive
= TRUE
;
233 Offset
= FvHandle
- OrgFvHandle
;
235 OffsetPositive
= FALSE
;
236 Offset
= OrgFvHandle
- FvHandle
;
239 DEBUG ((DEBUG_VERBOSE
, "Converting PPI pointers in FV.\n"));
242 " OrgFvHandle at 0x%08x. FvHandle at 0x%08x. FvSize = 0x%x\n",
249 " OrgFvHandle range: 0x%08x - 0x%08x\n",
254 for (Index
= 0; Index
< PrivateData
->PpiData
.CallbackNotifyList
.CurrentCount
; Index
++) {
256 (VOID
**)&PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Raw
,
258 OrgFvHandle
+ FvSize
,
263 (VOID
**)&PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Notify
->Guid
,
265 OrgFvHandle
+ FvSize
,
270 (VOID
**)&PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Notify
->Notify
,
272 OrgFvHandle
+ FvSize
,
278 for (Index
= 0; Index
< PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
; Index
++) {
280 (VOID
**)&PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Raw
,
282 OrgFvHandle
+ FvSize
,
287 (VOID
**)&PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Notify
->Guid
,
289 OrgFvHandle
+ FvSize
,
294 (VOID
**)&PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Notify
->Notify
,
296 OrgFvHandle
+ FvSize
,
302 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiList
.CurrentCount
; Index
++) {
304 (VOID
**)&PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Raw
,
306 OrgFvHandle
+ FvSize
,
311 (VOID
**)&PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
->Guid
,
313 OrgFvHandle
+ FvSize
,
318 (VOID
**)&PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
->Ppi
,
320 OrgFvHandle
+ FvSize
,
325 Guid
= PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
->Guid
;
326 for (GuidIndex
= 0; GuidIndex
< ARRAY_SIZE (GuidCheckList
); ++GuidIndex
) {
328 // Don't use CompareGuid function here for performance reasons.
329 // Instead we compare the GUID as INT32 at a time and branch
330 // on the first failed comparison.
332 if ((((INT32
*)Guid
)[0] == ((INT32
*)GuidCheckList
[GuidIndex
])[0]) &&
333 (((INT32
*)Guid
)[1] == ((INT32
*)GuidCheckList
[GuidIndex
])[1]) &&
334 (((INT32
*)Guid
)[2] == ((INT32
*)GuidCheckList
[GuidIndex
])[2]) &&
335 (((INT32
*)Guid
)[3] == ((INT32
*)GuidCheckList
[GuidIndex
])[3]))
337 FvInfoPpi
= PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
->Ppi
;
338 DEBUG ((DEBUG_VERBOSE
, " FvInfo: %p -> ", FvInfoPpi
->FvInfo
));
339 if ((UINTN
)FvInfoPpi
->FvInfo
== OrgFvHandle
) {
341 (VOID
**)&FvInfoPpi
->FvInfo
,
343 OrgFvHandle
+ FvSize
,
347 DEBUG ((DEBUG_VERBOSE
, "%p", FvInfoPpi
->FvInfo
));
350 DEBUG ((DEBUG_VERBOSE
, "\n"));
359 Dumps the PPI lists to debug output.
361 @param PrivateData Points to PeiCore's private instance data.
366 IN PEI_CORE_INSTANCE
*PrivateData
372 if (PrivateData
== NULL
) {
376 for (Index
= 0; Index
< PrivateData
->PpiData
.CallbackNotifyList
.CurrentCount
; Index
++) {
379 "CallbackNotify[%2d] {%g} at 0x%x (%a)\n",
381 PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Notify
->Guid
,
382 (UINTN
)PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Raw
,
385 ((EFI_PHYSICAL_ADDRESS
)(UINTN
)PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Raw
>= PrivateData
->PhysicalMemoryBegin
) &&
386 (((EFI_PHYSICAL_ADDRESS
)((UINTN
)PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Raw
) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR
)) < PrivateData
->FreePhysicalMemoryTop
)
388 ? "CAR" : "Post-Memory"
393 for (Index
= 0; Index
< PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
; Index
++) {
396 "DispatchNotify[%2d] {%g} at 0x%x (%a)\n",
398 PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Notify
->Guid
,
399 (UINTN
)PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Raw
,
402 ((EFI_PHYSICAL_ADDRESS
)(UINTN
)PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Raw
>= PrivateData
->PhysicalMemoryBegin
) &&
403 (((EFI_PHYSICAL_ADDRESS
)((UINTN
)PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Raw
) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR
)) < PrivateData
->FreePhysicalMemoryTop
)
405 ? "CAR" : "Post-Memory"
410 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiList
.CurrentCount
; Index
++) {
413 "PPI[%2d] {%g} at 0x%x (%a)\n",
415 PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
->Guid
,
416 (UINTN
)PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Raw
,
419 ((EFI_PHYSICAL_ADDRESS
)(UINTN
)PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Raw
>= PrivateData
->PhysicalMemoryBegin
) &&
420 (((EFI_PHYSICAL_ADDRESS
)((UINTN
)PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Raw
) + sizeof (EFI_PEI_PPI_DESCRIPTOR
)) < PrivateData
->FreePhysicalMemoryTop
)
422 ? "CAR" : "Post-Memory"
432 This function installs an interface in the PEI PPI database by GUID.
433 The purpose of the service is to publish an interface that other parties
434 can use to call additional PEIMs.
436 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
437 @param PpiList Pointer to a list of PEI PPI Descriptors.
438 @param Single TRUE if only single entry in the PpiList.
439 FALSE if the PpiList is ended with an entry which has the
440 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.
442 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.
443 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer
444 if any PPI in PpiList is not valid
445 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI
449 InternalPeiInstallPpi (
450 IN CONST EFI_PEI_SERVICES
**PeiServices
,
451 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
,
455 PEI_CORE_INSTANCE
*PrivateData
;
456 PEI_PPI_LIST
*PpiListPointer
;
461 if (PpiList
== NULL
) {
462 return EFI_INVALID_PARAMETER
;
465 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
467 PpiListPointer
= &PrivateData
->PpiData
.PpiList
;
468 Index
= PpiListPointer
->CurrentCount
;
472 // This is loop installs all PPI descriptors in the PpiList. It is terminated
473 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
474 // EFI_PEI_PPI_DESCRIPTOR in the list.
479 // Check if it is a valid PPI.
480 // If not, rollback list to exclude all in this list.
481 // Try to indicate which item failed.
483 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
484 PpiListPointer
->CurrentCount
= LastCount
;
485 DEBUG ((DEBUG_ERROR
, "ERROR -> InstallPpi: %g %p\n", PpiList
->Guid
, PpiList
->Ppi
));
486 return EFI_INVALID_PARAMETER
;
489 if (Index
>= PpiListPointer
->MaxCount
) {
491 // Run out of room, grow the buffer.
493 TempPtr
= AllocateZeroPool (
494 sizeof (PEI_PPI_LIST_POINTERS
) * (PpiListPointer
->MaxCount
+ PPI_GROWTH_STEP
)
496 ASSERT (TempPtr
!= NULL
);
499 PpiListPointer
->PpiPtrs
,
500 sizeof (PEI_PPI_LIST_POINTERS
) * PpiListPointer
->MaxCount
502 PpiListPointer
->PpiPtrs
= TempPtr
;
503 PpiListPointer
->MaxCount
= PpiListPointer
->MaxCount
+ PPI_GROWTH_STEP
;
506 DEBUG ((DEBUG_INFO
, "Install PPI: %g\n", PpiList
->Guid
));
507 PpiListPointer
->PpiPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*)PpiList
;
509 PpiListPointer
->CurrentCount
++;
513 // Only single entry in the PpiList.
516 } else if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
517 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
)
520 // Continue until the end of the PPI List.
526 // Go to the next descriptor.
532 // Process any callback level notifies for newly installed PPIs.
536 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
538 PpiListPointer
->CurrentCount
,
540 PrivateData
->PpiData
.CallbackNotifyList
.CurrentCount
548 This function installs an interface in the PEI PPI database by GUID.
549 The purpose of the service is to publish an interface that other parties
550 can use to call additional PEIMs.
552 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
553 @param PpiList Pointer to a list of PEI PPI Descriptors.
555 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.
556 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer
557 if any PPI in PpiList is not valid
558 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI
564 IN CONST EFI_PEI_SERVICES
**PeiServices
,
565 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
568 return InternalPeiInstallPpi (PeiServices
, PpiList
, FALSE
);
573 This function reinstalls an interface in the PEI PPI database by GUID.
574 The purpose of the service is to publish an interface that other parties can
575 use to replace an interface of the same name in the protocol database with a
578 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
579 @param OldPpi Pointer to the old PEI PPI Descriptors.
580 @param NewPpi Pointer to the new PEI PPI Descriptors.
582 @retval EFI_SUCCESS if the operation was successful
583 @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL
584 @retval EFI_INVALID_PARAMETER if NewPpi is not valid
585 @retval EFI_NOT_FOUND if the PPI was not in the database
591 IN CONST EFI_PEI_SERVICES
**PeiServices
,
592 IN CONST EFI_PEI_PPI_DESCRIPTOR
*OldPpi
,
593 IN CONST EFI_PEI_PPI_DESCRIPTOR
*NewPpi
596 PEI_CORE_INSTANCE
*PrivateData
;
599 if ((OldPpi
== NULL
) || (NewPpi
== NULL
)) {
600 return EFI_INVALID_PARAMETER
;
603 if ((NewPpi
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
604 return EFI_INVALID_PARAMETER
;
607 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
610 // Find the old PPI instance in the database. If we can not find it,
611 // return the EFI_NOT_FOUND error.
613 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiList
.CurrentCount
; Index
++) {
614 if (OldPpi
== PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
) {
619 if (Index
== PrivateData
->PpiData
.PpiList
.CurrentCount
) {
620 return EFI_NOT_FOUND
;
624 // Replace the old PPI with the new one.
626 DEBUG ((DEBUG_INFO
, "Reinstall PPI: %g\n", NewPpi
->Guid
));
627 PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*)NewPpi
;
630 // Process any callback level notifies for the newly installed PPI.
634 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
638 PrivateData
->PpiData
.CallbackNotifyList
.CurrentCount
646 Locate a given named PPI.
649 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
650 @param Guid Pointer to GUID of the PPI.
651 @param Instance Instance Number to discover.
652 @param PpiDescriptor Pointer to reference the found descriptor. If not NULL,
653 returns a pointer to the descriptor (includes flags, etc)
654 @param Ppi Pointer to reference the found PPI
656 @retval EFI_SUCCESS if the PPI is in the database
657 @retval EFI_NOT_FOUND if the PPI is not in the database
663 IN CONST EFI_PEI_SERVICES
**PeiServices
,
664 IN CONST EFI_GUID
*Guid
,
666 IN OUT EFI_PEI_PPI_DESCRIPTOR
**PpiDescriptor
,
670 PEI_CORE_INSTANCE
*PrivateData
;
673 EFI_PEI_PPI_DESCRIPTOR
*TempPtr
;
675 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
678 // Search the data base for the matching instance of the GUIDed PPI.
680 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiList
.CurrentCount
; Index
++) {
681 TempPtr
= PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
;
682 CheckGuid
= TempPtr
->Guid
;
685 // Don't use CompareGuid function here for performance reasons.
686 // Instead we compare the GUID as INT32 at a time and branch
687 // on the first failed comparison.
689 if ((((INT32
*)Guid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
690 (((INT32
*)Guid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
691 (((INT32
*)Guid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
692 (((INT32
*)Guid
)[3] == ((INT32
*)CheckGuid
)[3]))
695 if (PpiDescriptor
!= NULL
) {
696 *PpiDescriptor
= TempPtr
;
710 return EFI_NOT_FOUND
;
715 This function installs a notification service to be called back when a given
716 interface is installed or reinstalled. The purpose of the service is to publish
717 an interface that other parties can use to call additional PPIs that may materialize later.
719 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
720 @param NotifyList Pointer to list of Descriptors to notify upon.
721 @param Single TRUE if only single entry in the NotifyList.
722 FALSE if the NotifyList is ended with an entry which has the
723 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.
725 @retval EFI_SUCCESS if successful
726 @retval EFI_OUT_OF_RESOURCES if no space in the database
727 @retval EFI_INVALID_PARAMETER if not a good descriptor
731 InternalPeiNotifyPpi (
732 IN CONST EFI_PEI_SERVICES
**PeiServices
,
733 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyList
,
737 PEI_CORE_INSTANCE
*PrivateData
;
738 PEI_CALLBACK_NOTIFY_LIST
*CallbackNotifyListPointer
;
739 UINTN CallbackNotifyIndex
;
740 UINTN LastCallbackNotifyCount
;
741 PEI_DISPATCH_NOTIFY_LIST
*DispatchNotifyListPointer
;
742 UINTN DispatchNotifyIndex
;
743 UINTN LastDispatchNotifyCount
;
746 if (NotifyList
== NULL
) {
747 return EFI_INVALID_PARAMETER
;
750 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
752 CallbackNotifyListPointer
= &PrivateData
->PpiData
.CallbackNotifyList
;
753 CallbackNotifyIndex
= CallbackNotifyListPointer
->CurrentCount
;
754 LastCallbackNotifyCount
= CallbackNotifyIndex
;
756 DispatchNotifyListPointer
= &PrivateData
->PpiData
.DispatchNotifyList
;
757 DispatchNotifyIndex
= DispatchNotifyListPointer
->CurrentCount
;
758 LastDispatchNotifyCount
= DispatchNotifyIndex
;
761 // This is loop installs all Notify descriptors in the NotifyList. It is
762 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
763 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.
768 // If some of the PPI data is invalid restore original Notify PPI database value
770 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES
) == 0) {
771 CallbackNotifyListPointer
->CurrentCount
= LastCallbackNotifyCount
;
772 DispatchNotifyListPointer
->CurrentCount
= LastDispatchNotifyCount
;
773 DEBUG ((DEBUG_ERROR
, "ERROR -> NotifyPpi: %g %p\n", NotifyList
->Guid
, NotifyList
->Notify
));
774 return EFI_INVALID_PARAMETER
;
777 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
) != 0) {
778 if (CallbackNotifyIndex
>= CallbackNotifyListPointer
->MaxCount
) {
780 // Run out of room, grow the buffer.
782 TempPtr
= AllocateZeroPool (
783 sizeof (PEI_PPI_LIST_POINTERS
) * (CallbackNotifyListPointer
->MaxCount
+ CALLBACK_NOTIFY_GROWTH_STEP
)
785 ASSERT (TempPtr
!= NULL
);
788 CallbackNotifyListPointer
->NotifyPtrs
,
789 sizeof (PEI_PPI_LIST_POINTERS
) * CallbackNotifyListPointer
->MaxCount
791 CallbackNotifyListPointer
->NotifyPtrs
= TempPtr
;
792 CallbackNotifyListPointer
->MaxCount
= CallbackNotifyListPointer
->MaxCount
+ CALLBACK_NOTIFY_GROWTH_STEP
;
795 CallbackNotifyListPointer
->NotifyPtrs
[CallbackNotifyIndex
].Notify
= (EFI_PEI_NOTIFY_DESCRIPTOR
*)NotifyList
;
796 CallbackNotifyIndex
++;
797 CallbackNotifyListPointer
->CurrentCount
++;
799 if (DispatchNotifyIndex
>= DispatchNotifyListPointer
->MaxCount
) {
801 // Run out of room, grow the buffer.
803 TempPtr
= AllocateZeroPool (
804 sizeof (PEI_PPI_LIST_POINTERS
) * (DispatchNotifyListPointer
->MaxCount
+ DISPATCH_NOTIFY_GROWTH_STEP
)
806 ASSERT (TempPtr
!= NULL
);
809 DispatchNotifyListPointer
->NotifyPtrs
,
810 sizeof (PEI_PPI_LIST_POINTERS
) * DispatchNotifyListPointer
->MaxCount
812 DispatchNotifyListPointer
->NotifyPtrs
= TempPtr
;
813 DispatchNotifyListPointer
->MaxCount
= DispatchNotifyListPointer
->MaxCount
+ DISPATCH_NOTIFY_GROWTH_STEP
;
816 DispatchNotifyListPointer
->NotifyPtrs
[DispatchNotifyIndex
].Notify
= (EFI_PEI_NOTIFY_DESCRIPTOR
*)NotifyList
;
817 DispatchNotifyIndex
++;
818 DispatchNotifyListPointer
->CurrentCount
++;
821 DEBUG ((DEBUG_INFO
, "Register PPI Notify: %g\n", NotifyList
->Guid
));
825 // Only single entry in the NotifyList.
828 } else if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
829 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
)
832 // Continue until the end of the Notify List.
838 // Go to the next descriptor.
844 // Process any callback level notifies for all previously installed PPIs.
848 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
850 PrivateData
->PpiData
.PpiList
.CurrentCount
,
851 LastCallbackNotifyCount
,
852 CallbackNotifyListPointer
->CurrentCount
860 This function installs a notification service to be called back when a given
861 interface is installed or reinstalled. The purpose of the service is to publish
862 an interface that other parties can use to call additional PPIs that may materialize later.
864 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
865 @param NotifyList Pointer to list of Descriptors to notify upon.
867 @retval EFI_SUCCESS if successful
868 @retval EFI_OUT_OF_RESOURCES if no space in the database
869 @retval EFI_INVALID_PARAMETER if not a good descriptor
875 IN CONST EFI_PEI_SERVICES
**PeiServices
,
876 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyList
879 return InternalPeiNotifyPpi (PeiServices
, NotifyList
, FALSE
);
884 Process the Notify List at dispatch level.
886 @param PrivateData PeiCore's private data structure.
890 ProcessDispatchNotifyList (
891 IN PEI_CORE_INSTANCE
*PrivateData
898 // Check if the PEIM that was just dispatched resulted in any
899 // Notifies getting installed. If so, go process any dispatch
900 // level Notifies that match the previously installed PPIs.
901 // Use "while" instead of "if" since ProcessNotify can modify
902 // DispatchNotifyList.CurrentCount (with NotifyPpi) so we have
903 // to iterate until the same.
905 while (PrivateData
->PpiData
.DispatchNotifyList
.LastDispatchedCount
!= PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
) {
906 TempValue
= PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
;
909 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
911 PrivateData
->PpiData
.PpiList
.LastDispatchedCount
,
912 PrivateData
->PpiData
.DispatchNotifyList
.LastDispatchedCount
,
913 PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
915 PrivateData
->PpiData
.DispatchNotifyList
.LastDispatchedCount
= TempValue
;
919 // Check if the PEIM that was just dispatched resulted in any
920 // PPIs getting installed. If so, go process any dispatch
921 // level Notifies that match the installed PPIs.
922 // Use "while" instead of "if" since ProcessNotify can modify
923 // PpiList.CurrentCount (with InstallPpi) so we have to iterate
926 while (PrivateData
->PpiData
.PpiList
.LastDispatchedCount
!= PrivateData
->PpiData
.PpiList
.CurrentCount
) {
927 TempValue
= PrivateData
->PpiData
.PpiList
.CurrentCount
;
930 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
931 PrivateData
->PpiData
.PpiList
.LastDispatchedCount
,
932 PrivateData
->PpiData
.PpiList
.CurrentCount
,
934 PrivateData
->PpiData
.DispatchNotifyList
.LastDispatchedCount
936 PrivateData
->PpiData
.PpiList
.LastDispatchedCount
= TempValue
;
939 if (PrivateData
->PpiData
.DispatchNotifyList
.LastDispatchedCount
== PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
) {
949 Process notifications.
951 @param PrivateData PeiCore's private data structure
952 @param NotifyType Type of notify to fire.
953 @param InstallStartIndex Install Beginning index.
954 @param InstallStopIndex Install Ending index.
955 @param NotifyStartIndex Notify Beginning index.
956 @param NotifyStopIndex Notify Ending index.
961 IN PEI_CORE_INSTANCE
*PrivateData
,
963 IN INTN InstallStartIndex
,
964 IN INTN InstallStopIndex
,
965 IN INTN NotifyStartIndex
,
966 IN INTN NotifyStopIndex
971 EFI_GUID
*SearchGuid
;
973 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
;
975 for (Index1
= NotifyStartIndex
; Index1
< NotifyStopIndex
; Index1
++) {
976 if (NotifyType
== EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
) {
977 NotifyDescriptor
= PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index1
].Notify
;
979 NotifyDescriptor
= PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index1
].Notify
;
982 CheckGuid
= NotifyDescriptor
->Guid
;
984 for (Index2
= InstallStartIndex
; Index2
< InstallStopIndex
; Index2
++) {
985 SearchGuid
= PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index2
].Ppi
->Guid
;
987 // Don't use CompareGuid function here for performance reasons.
988 // Instead we compare the GUID as INT32 at a time and branch
989 // on the first failed comparison.
991 if ((((INT32
*)SearchGuid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
992 (((INT32
*)SearchGuid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
993 (((INT32
*)SearchGuid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
994 (((INT32
*)SearchGuid
)[3] == ((INT32
*)CheckGuid
)[3]))
998 "Notify: PPI Guid: %g, Peim notify entry point: %p\n",
1000 NotifyDescriptor
->Notify
1002 NotifyDescriptor
->Notify (
1003 (EFI_PEI_SERVICES
**)GetPeiServicesTablePointer (),
1005 (PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index2
].Ppi
)->Ppi
1013 Process PpiList from SEC phase.
1015 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
1016 @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
1017 These PPI's will be installed and/or immediately signaled if they are notification type.
1021 ProcessPpiListFromSec (
1022 IN CONST EFI_PEI_SERVICES
**PeiServices
,
1023 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
1027 EFI_SEC_HOB_DATA_PPI
*SecHobDataPpi
;
1028 EFI_HOB_GENERIC_HEADER
*SecHobList
;
1031 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES
) != 0) {
1033 // It is a notification PPI.
1035 Status
= InternalPeiNotifyPpi (PeiServices
, (CONST EFI_PEI_NOTIFY_DESCRIPTOR
*)PpiList
, TRUE
);
1036 ASSERT_EFI_ERROR (Status
);
1039 // It is a normal PPI.
1041 Status
= InternalPeiInstallPpi (PeiServices
, PpiList
, TRUE
);
1042 ASSERT_EFI_ERROR (Status
);
1045 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
1047 // Continue until the end of the PPI List.
1056 // If the EFI_SEC_HOB_DATA_PPI is in the list of PPIs passed to the PEI entry point,
1057 // the PEI Foundation will call the GetHobs() member function and install all HOBs
1058 // returned into the HOB list. It does this after installing all PPIs passed from SEC
1059 // into the PPI database and before dispatching any PEIMs.
1061 Status
= PeiLocatePpi (PeiServices
, &gEfiSecHobDataPpiGuid
, 0, NULL
, (VOID
**)&SecHobDataPpi
);
1062 if (!EFI_ERROR (Status
)) {
1063 Status
= SecHobDataPpi
->GetHobs (SecHobDataPpi
, &SecHobList
);
1064 if (!EFI_ERROR (Status
)) {
1065 Status
= PeiInstallSecHobData (PeiServices
, SecHobList
);
1066 ASSERT_EFI_ERROR (Status
);
1073 Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.
1075 @param PrivateData Pointer to PeiCore's private data structure.
1076 @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory.
1080 ConvertPeiCorePpiPointers (
1081 IN PEI_CORE_INSTANCE
*PrivateData
,
1082 IN PEI_CORE_FV_HANDLE
*CoreFvHandle
1085 EFI_FV_FILE_INFO FileInfo
;
1086 EFI_PHYSICAL_ADDRESS OrgImageBase
;
1087 EFI_PHYSICAL_ADDRESS MigratedImageBase
;
1088 UINTN PeiCoreModuleSize
;
1089 EFI_PEI_FILE_HANDLE PeiCoreFileHandle
;
1090 VOID
*PeiCoreImageBase
;
1091 VOID
*PeiCoreEntryPoint
;
1094 PeiCoreFileHandle
= NULL
;
1097 // Find the PEI Core in the BFV in temporary memory.
1099 Status
= CoreFvHandle
->FvPpi
->FindFileByType (
1100 CoreFvHandle
->FvPpi
,
1101 EFI_FV_FILETYPE_PEI_CORE
,
1102 CoreFvHandle
->FvHandle
,
1105 ASSERT_EFI_ERROR (Status
);
1107 if (!EFI_ERROR (Status
)) {
1108 Status
= CoreFvHandle
->FvPpi
->GetFileInfo (CoreFvHandle
->FvPpi
, PeiCoreFileHandle
, &FileInfo
);
1109 ASSERT_EFI_ERROR (Status
);
1111 Status
= PeiGetPe32Data (PeiCoreFileHandle
, &PeiCoreImageBase
);
1112 ASSERT_EFI_ERROR (Status
);
1115 // Find PEI Core EntryPoint in the BFV in temporary memory.
1117 Status
= PeCoffLoaderGetEntryPoint ((VOID
*)(UINTN
)PeiCoreImageBase
, &PeiCoreEntryPoint
);
1118 ASSERT_EFI_ERROR (Status
);
1120 OrgImageBase
= (UINTN
)PeiCoreImageBase
;
1121 MigratedImageBase
= (UINTN
)_ModuleEntryPoint
- ((UINTN
)PeiCoreEntryPoint
- (UINTN
)PeiCoreImageBase
);
1124 // Size of loaded PEI_CORE in permanent memory.
1126 PeiCoreModuleSize
= (UINTN
)FileInfo
.BufferSize
- ((UINTN
)OrgImageBase
- (UINTN
)FileInfo
.Buffer
);
1129 // Migrate PEI_CORE PPI pointers from temporary memory to newly
1130 // installed PEI_CORE in permanent memory.
1132 ConvertPpiPointersFv (PrivateData
, (UINTN
)OrgImageBase
, (UINTN
)MigratedImageBase
, PeiCoreModuleSize
);