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
)) {
34 *Pointer
= (VOID
*) ((UINTN
) *Pointer
+ Offset
);
36 *Pointer
= (VOID
*) ((UINTN
) *Pointer
- Offset
);
43 Migrate Pointer in ranges of the temporary memory to PEI installed memory.
45 @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
46 and location of temporary RAM, the stack location and the BFV location.
47 @param PrivateData Pointer to PeiCore's private data structure.
48 @param Pointer Pointer to the Pointer needs to be converted.
52 ConvertPointerInRanges (
53 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
54 IN PEI_CORE_INSTANCE
*PrivateData
,
60 if (PrivateData
->MemoryPages
.Size
!= 0) {
62 // Convert PPI pointer in old memory pages
63 // It needs to be done before Convert PPI pointer in old Heap
67 (UINTN
)PrivateData
->MemoryPages
.Base
,
68 (UINTN
)PrivateData
->MemoryPages
.Base
+ PrivateData
->MemoryPages
.Size
,
69 PrivateData
->MemoryPages
.Offset
,
70 PrivateData
->MemoryPages
.OffsetPositive
75 // Convert PPI pointer in old Heap
79 (UINTN
)SecCoreData
->PeiTemporaryRamBase
,
80 (UINTN
)SecCoreData
->PeiTemporaryRamBase
+ SecCoreData
->PeiTemporaryRamSize
,
81 PrivateData
->HeapOffset
,
82 PrivateData
->HeapOffsetPositive
86 // Convert PPI pointer in old Stack
90 (UINTN
)SecCoreData
->StackBase
,
91 (UINTN
)SecCoreData
->StackBase
+ SecCoreData
->StackSize
,
92 PrivateData
->StackOffset
,
93 PrivateData
->StackOffsetPositive
97 // Convert PPI pointer in old TempRam Hole
99 for (IndexHole
= 0; IndexHole
< HOLE_MAX_NUMBER
; IndexHole
++) {
100 if (PrivateData
->HoleData
[IndexHole
].Size
== 0) {
106 (UINTN
)PrivateData
->HoleData
[IndexHole
].Base
,
107 (UINTN
)PrivateData
->HoleData
[IndexHole
].Base
+ PrivateData
->HoleData
[IndexHole
].Size
,
108 PrivateData
->HoleData
[IndexHole
].Offset
,
109 PrivateData
->HoleData
[IndexHole
].OffsetPositive
116 Migrate Single PPI Pointer from the temporary memory to PEI installed memory.
118 @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
119 and location of temporary RAM, the stack location and the BFV location.
120 @param PrivateData Pointer to PeiCore's private data structure.
121 @param PpiPointer Pointer to Ppi
125 ConvertSinglePpiPointer (
126 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
127 IN PEI_CORE_INSTANCE
*PrivateData
,
128 IN PEI_PPI_LIST_POINTERS
*PpiPointer
132 // 1. Convert the pointer to the PPI descriptor from the old TempRam
133 // to the relocated physical memory.
134 // It (for the pointer to the PPI descriptor) needs to be done before 2 (for
135 // the pointer to the GUID) and 3 (for the pointer to the PPI interface structure).
137 ConvertPointerInRanges (SecCoreData
, PrivateData
, &PpiPointer
->Raw
);
139 // 2. Convert the pointer to the GUID in the PPI or NOTIFY descriptor
140 // from the old TempRam to the relocated physical memory.
142 ConvertPointerInRanges (SecCoreData
, PrivateData
, (VOID
**) &PpiPointer
->Ppi
->Guid
);
144 // 3. Convert the pointer to the PPI interface structure in the PPI descriptor
145 // from the old TempRam to the relocated physical memory.
147 ConvertPointerInRanges (SecCoreData
, PrivateData
, (VOID
**) &PpiPointer
->Ppi
->Ppi
);
152 Migrate PPI Pointers from the temporary memory to PEI installed memory.
154 @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
155 and location of temporary RAM, the stack location and the BFV location.
156 @param PrivateData Pointer to PeiCore's private data structure.
161 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
162 IN PEI_CORE_INSTANCE
*PrivateData
168 // Convert normal PPIs.
170 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiList
.CurrentCount
; Index
++) {
171 ConvertSinglePpiPointer (
174 &PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
]
179 // Convert Callback Notification PPIs.
181 for (Index
= 0; Index
< PrivateData
->PpiData
.CallbackNotifyList
.CurrentCount
; Index
++) {
182 ConvertSinglePpiPointer (
185 &PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
]
190 // Convert Dispatch Notification PPIs.
192 for (Index
= 0; Index
< PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
; Index
++) {
193 ConvertSinglePpiPointer (
196 &PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
]
203 Migrate Notify Pointers inside an FV from temporary memory to permanent memory.
205 @param PrivateData Pointer to PeiCore's private data structure.
206 @param OrgFvHandle Address of FV Handle in temporary memory.
207 @param FvHandle Address of FV Handle in permanent memory.
208 @param FvSize Size of the FV.
212 ConvertPpiPointersFv (
213 IN PEI_CORE_INSTANCE
*PrivateData
,
214 IN UINTN OrgFvHandle
,
221 BOOLEAN OffsetPositive
;
222 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*FvInfoPpi
;
225 EFI_GUID
*GuidCheckList
[2];
227 GuidCheckList
[0] = &gEfiPeiFirmwareVolumeInfoPpiGuid
;
228 GuidCheckList
[1] = &gEfiPeiFirmwareVolumeInfo2PpiGuid
;
230 if (FvHandle
> OrgFvHandle
) {
231 OffsetPositive
= TRUE
;
232 Offset
= FvHandle
- OrgFvHandle
;
234 OffsetPositive
= FALSE
;
235 Offset
= OrgFvHandle
- FvHandle
;
238 DEBUG ((DEBUG_VERBOSE
, "Converting PPI pointers in FV.\n"));
241 " OrgFvHandle at 0x%08x. FvHandle at 0x%08x. FvSize = 0x%x\n",
248 " OrgFvHandle range: 0x%08x - 0x%08x\n",
253 for (Index
= 0; Index
< PrivateData
->PpiData
.CallbackNotifyList
.CurrentCount
; Index
++) {
255 (VOID
**) &PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Raw
,
257 OrgFvHandle
+ FvSize
,
262 (VOID
**) &PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Notify
->Guid
,
264 OrgFvHandle
+ FvSize
,
269 (VOID
**) &PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Notify
->Notify
,
271 OrgFvHandle
+ FvSize
,
277 for (Index
= 0; Index
< PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
; Index
++) {
279 (VOID
**) &PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Raw
,
281 OrgFvHandle
+ FvSize
,
286 (VOID
**) &PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Notify
->Guid
,
288 OrgFvHandle
+ FvSize
,
293 (VOID
**) &PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Notify
->Notify
,
295 OrgFvHandle
+ FvSize
,
301 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiList
.CurrentCount
; Index
++) {
303 (VOID
**) &PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Raw
,
305 OrgFvHandle
+ FvSize
,
310 (VOID
**) &PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
->Guid
,
312 OrgFvHandle
+ FvSize
,
317 (VOID
**) &PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
->Ppi
,
319 OrgFvHandle
+ FvSize
,
324 Guid
= PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
->Guid
;
325 for (GuidIndex
= 0; GuidIndex
< ARRAY_SIZE (GuidCheckList
); ++GuidIndex
) {
327 // Don't use CompareGuid function here for performance reasons.
328 // Instead we compare the GUID as INT32 at a time and branch
329 // on the first failed comparison.
331 if ((((INT32
*)Guid
)[0] == ((INT32
*)GuidCheckList
[GuidIndex
])[0]) &&
332 (((INT32
*)Guid
)[1] == ((INT32
*)GuidCheckList
[GuidIndex
])[1]) &&
333 (((INT32
*)Guid
)[2] == ((INT32
*)GuidCheckList
[GuidIndex
])[2]) &&
334 (((INT32
*)Guid
)[3] == ((INT32
*)GuidCheckList
[GuidIndex
])[3])) {
335 FvInfoPpi
= PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
->Ppi
;
336 DEBUG ((DEBUG_VERBOSE
, " FvInfo: %p -> ", FvInfoPpi
->FvInfo
));
337 if ((UINTN
)FvInfoPpi
->FvInfo
== OrgFvHandle
) {
339 (VOID
**)&FvInfoPpi
->FvInfo
,
341 OrgFvHandle
+ FvSize
,
345 DEBUG ((DEBUG_VERBOSE
, "%p", FvInfoPpi
->FvInfo
));
347 DEBUG ((DEBUG_VERBOSE
, "\n"));
356 Dumps the PPI lists to debug output.
358 @param PrivateData Points to PeiCore's private instance data.
363 IN PEI_CORE_INSTANCE
*PrivateData
369 if (PrivateData
== NULL
) {
373 for (Index
= 0; Index
< PrivateData
->PpiData
.CallbackNotifyList
.CurrentCount
; Index
++) {
376 "CallbackNotify[%2d] {%g} at 0x%x (%a)\n",
378 PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Notify
->Guid
,
379 (UINTN
) PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Raw
,
382 ((EFI_PHYSICAL_ADDRESS
) (UINTN
) PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Raw
>= PrivateData
->PhysicalMemoryBegin
) &&
383 (((EFI_PHYSICAL_ADDRESS
) ((UINTN
) PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index
].Raw
) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR
)) < PrivateData
->FreePhysicalMemoryTop
)
385 ? "CAR" : "Post-Memory"
389 for (Index
= 0; Index
< PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
; Index
++) {
390 DEBUG ((DEBUG_VERBOSE
,
391 "DispatchNotify[%2d] {%g} at 0x%x (%a)\n",
393 PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Notify
->Guid
,
394 (UINTN
) PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Raw
,
397 ((EFI_PHYSICAL_ADDRESS
) (UINTN
) PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Raw
>=PrivateData
->PhysicalMemoryBegin
) &&
398 (((EFI_PHYSICAL_ADDRESS
) ((UINTN
) PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index
].Raw
) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR
)) < PrivateData
->FreePhysicalMemoryTop
)
400 ? "CAR" : "Post-Memory"
404 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiList
.CurrentCount
; Index
++) {
405 DEBUG ((DEBUG_VERBOSE
,
406 "PPI[%2d] {%g} at 0x%x (%a)\n",
408 PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
->Guid
,
409 (UINTN
) PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Raw
,
412 ((EFI_PHYSICAL_ADDRESS
) (UINTN
) PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Raw
>= PrivateData
->PhysicalMemoryBegin
) &&
413 (((EFI_PHYSICAL_ADDRESS
) ((UINTN
) PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Raw
) + sizeof (EFI_PEI_PPI_DESCRIPTOR
)) < PrivateData
->FreePhysicalMemoryTop
)
415 ? "CAR" : "Post-Memory"
424 This function installs an interface in the PEI PPI database by GUID.
425 The purpose of the service is to publish an interface that other parties
426 can use to call additional PEIMs.
428 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
429 @param PpiList Pointer to a list of PEI PPI Descriptors.
430 @param Single TRUE if only single entry in the PpiList.
431 FALSE if the PpiList is ended with an entry which has the
432 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.
434 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.
435 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer
436 if any PPI in PpiList is not valid
437 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI
441 InternalPeiInstallPpi (
442 IN CONST EFI_PEI_SERVICES
**PeiServices
,
443 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
,
447 PEI_CORE_INSTANCE
*PrivateData
;
448 PEI_PPI_LIST
*PpiListPointer
;
453 if (PpiList
== NULL
) {
454 return EFI_INVALID_PARAMETER
;
457 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
459 PpiListPointer
= &PrivateData
->PpiData
.PpiList
;
460 Index
= PpiListPointer
->CurrentCount
;
464 // This is loop installs all PPI descriptors in the PpiList. It is terminated
465 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
466 // EFI_PEI_PPI_DESCRIPTOR in the list.
471 // Check if it is a valid PPI.
472 // If not, rollback list to exclude all in this list.
473 // Try to indicate which item failed.
475 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
476 PpiListPointer
->CurrentCount
= LastCount
;
477 DEBUG((DEBUG_ERROR
, "ERROR -> InstallPpi: %g %p\n", PpiList
->Guid
, PpiList
->Ppi
));
478 return EFI_INVALID_PARAMETER
;
481 if (Index
>= PpiListPointer
->MaxCount
) {
483 // Run out of room, grow the buffer.
485 TempPtr
= AllocateZeroPool (
486 sizeof (PEI_PPI_LIST_POINTERS
) * (PpiListPointer
->MaxCount
+ PPI_GROWTH_STEP
)
488 ASSERT (TempPtr
!= NULL
);
491 PpiListPointer
->PpiPtrs
,
492 sizeof (PEI_PPI_LIST_POINTERS
) * PpiListPointer
->MaxCount
494 PpiListPointer
->PpiPtrs
= TempPtr
;
495 PpiListPointer
->MaxCount
= PpiListPointer
->MaxCount
+ PPI_GROWTH_STEP
;
498 DEBUG((DEBUG_INFO
, "Install PPI: %g\n", PpiList
->Guid
));
499 PpiListPointer
->PpiPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*) PpiList
;
501 PpiListPointer
->CurrentCount
++;
505 // Only single entry in the PpiList.
508 } else if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
509 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
511 // Continue until the end of the PPI List.
516 // Go to the next descriptor.
522 // Process any callback level notifies for newly installed PPIs.
526 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
528 PpiListPointer
->CurrentCount
,
530 PrivateData
->PpiData
.CallbackNotifyList
.CurrentCount
538 This function installs an interface in the PEI PPI database by GUID.
539 The purpose of the service is to publish an interface that other parties
540 can use to call additional PEIMs.
542 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
543 @param PpiList Pointer to a list of PEI PPI Descriptors.
545 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.
546 @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer
547 if any PPI in PpiList is not valid
548 @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI
554 IN CONST EFI_PEI_SERVICES
**PeiServices
,
555 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
558 return InternalPeiInstallPpi (PeiServices
, PpiList
, FALSE
);
563 This function reinstalls an interface in the PEI PPI database by GUID.
564 The purpose of the service is to publish an interface that other parties can
565 use to replace an interface of the same name in the protocol database with a
568 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
569 @param OldPpi Pointer to the old PEI PPI Descriptors.
570 @param NewPpi Pointer to the new PEI PPI Descriptors.
572 @retval EFI_SUCCESS if the operation was successful
573 @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL
574 @retval EFI_INVALID_PARAMETER if NewPpi is not valid
575 @retval EFI_NOT_FOUND if the PPI was not in the database
581 IN CONST EFI_PEI_SERVICES
**PeiServices
,
582 IN CONST EFI_PEI_PPI_DESCRIPTOR
*OldPpi
,
583 IN CONST EFI_PEI_PPI_DESCRIPTOR
*NewPpi
586 PEI_CORE_INSTANCE
*PrivateData
;
590 if ((OldPpi
== NULL
) || (NewPpi
== NULL
)) {
591 return EFI_INVALID_PARAMETER
;
594 if ((NewPpi
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
595 return EFI_INVALID_PARAMETER
;
598 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
601 // Find the old PPI instance in the database. If we can not find it,
602 // return the EFI_NOT_FOUND error.
604 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiList
.CurrentCount
; Index
++) {
605 if (OldPpi
== PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
) {
609 if (Index
== PrivateData
->PpiData
.PpiList
.CurrentCount
) {
610 return EFI_NOT_FOUND
;
614 // Replace the old PPI with the new one.
616 DEBUG((DEBUG_INFO
, "Reinstall PPI: %g\n", NewPpi
->Guid
));
617 PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*) NewPpi
;
620 // Process any callback level notifies for the newly installed PPI.
624 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
628 PrivateData
->PpiData
.CallbackNotifyList
.CurrentCount
636 Locate a given named PPI.
639 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
640 @param Guid Pointer to GUID of the PPI.
641 @param Instance Instance Number to discover.
642 @param PpiDescriptor Pointer to reference the found descriptor. If not NULL,
643 returns a pointer to the descriptor (includes flags, etc)
644 @param Ppi Pointer to reference the found PPI
646 @retval EFI_SUCCESS if the PPI is in the database
647 @retval EFI_NOT_FOUND if the PPI is not in the database
653 IN CONST EFI_PEI_SERVICES
**PeiServices
,
654 IN CONST EFI_GUID
*Guid
,
656 IN OUT EFI_PEI_PPI_DESCRIPTOR
**PpiDescriptor
,
660 PEI_CORE_INSTANCE
*PrivateData
;
663 EFI_PEI_PPI_DESCRIPTOR
*TempPtr
;
666 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
669 // Search the data base for the matching instance of the GUIDed PPI.
671 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiList
.CurrentCount
; Index
++) {
672 TempPtr
= PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index
].Ppi
;
673 CheckGuid
= TempPtr
->Guid
;
676 // Don't use CompareGuid function here for performance reasons.
677 // Instead we compare the GUID as INT32 at a time and branch
678 // on the first failed comparison.
680 if ((((INT32
*)Guid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
681 (((INT32
*)Guid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
682 (((INT32
*)Guid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
683 (((INT32
*)Guid
)[3] == ((INT32
*)CheckGuid
)[3])) {
686 if (PpiDescriptor
!= NULL
) {
687 *PpiDescriptor
= TempPtr
;
701 return EFI_NOT_FOUND
;
706 This function installs a notification service to be called back when a given
707 interface is installed or reinstalled. The purpose of the service is to publish
708 an interface that other parties can use to call additional PPIs that may materialize later.
710 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
711 @param NotifyList Pointer to list of Descriptors to notify upon.
712 @param Single TRUE if only single entry in the NotifyList.
713 FALSE if the NotifyList is ended with an entry which has the
714 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.
716 @retval EFI_SUCCESS if successful
717 @retval EFI_OUT_OF_RESOURCES if no space in the database
718 @retval EFI_INVALID_PARAMETER if not a good descriptor
722 InternalPeiNotifyPpi (
723 IN CONST EFI_PEI_SERVICES
**PeiServices
,
724 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyList
,
728 PEI_CORE_INSTANCE
*PrivateData
;
729 PEI_CALLBACK_NOTIFY_LIST
*CallbackNotifyListPointer
;
730 UINTN CallbackNotifyIndex
;
731 UINTN LastCallbackNotifyCount
;
732 PEI_DISPATCH_NOTIFY_LIST
*DispatchNotifyListPointer
;
733 UINTN DispatchNotifyIndex
;
734 UINTN LastDispatchNotifyCount
;
737 if (NotifyList
== NULL
) {
738 return EFI_INVALID_PARAMETER
;
741 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
743 CallbackNotifyListPointer
= &PrivateData
->PpiData
.CallbackNotifyList
;
744 CallbackNotifyIndex
= CallbackNotifyListPointer
->CurrentCount
;
745 LastCallbackNotifyCount
= CallbackNotifyIndex
;
747 DispatchNotifyListPointer
= &PrivateData
->PpiData
.DispatchNotifyList
;
748 DispatchNotifyIndex
= DispatchNotifyListPointer
->CurrentCount
;
749 LastDispatchNotifyCount
= DispatchNotifyIndex
;
752 // This is loop installs all Notify descriptors in the NotifyList. It is
753 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
754 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.
759 // If some of the PPI data is invalid restore original Notify PPI database value
761 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES
) == 0) {
762 CallbackNotifyListPointer
->CurrentCount
= LastCallbackNotifyCount
;
763 DispatchNotifyListPointer
->CurrentCount
= LastDispatchNotifyCount
;
764 DEBUG((DEBUG_ERROR
, "ERROR -> NotifyPpi: %g %p\n", NotifyList
->Guid
, NotifyList
->Notify
));
765 return EFI_INVALID_PARAMETER
;
768 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
) != 0) {
769 if (CallbackNotifyIndex
>= CallbackNotifyListPointer
->MaxCount
) {
771 // Run out of room, grow the buffer.
773 TempPtr
= AllocateZeroPool (
774 sizeof (PEI_PPI_LIST_POINTERS
) * (CallbackNotifyListPointer
->MaxCount
+ CALLBACK_NOTIFY_GROWTH_STEP
)
776 ASSERT (TempPtr
!= NULL
);
779 CallbackNotifyListPointer
->NotifyPtrs
,
780 sizeof (PEI_PPI_LIST_POINTERS
) * CallbackNotifyListPointer
->MaxCount
782 CallbackNotifyListPointer
->NotifyPtrs
= TempPtr
;
783 CallbackNotifyListPointer
->MaxCount
= CallbackNotifyListPointer
->MaxCount
+ CALLBACK_NOTIFY_GROWTH_STEP
;
785 CallbackNotifyListPointer
->NotifyPtrs
[CallbackNotifyIndex
].Notify
= (EFI_PEI_NOTIFY_DESCRIPTOR
*) NotifyList
;
786 CallbackNotifyIndex
++;
787 CallbackNotifyListPointer
->CurrentCount
++;
789 if (DispatchNotifyIndex
>= DispatchNotifyListPointer
->MaxCount
) {
791 // Run out of room, grow the buffer.
793 TempPtr
= AllocateZeroPool (
794 sizeof (PEI_PPI_LIST_POINTERS
) * (DispatchNotifyListPointer
->MaxCount
+ DISPATCH_NOTIFY_GROWTH_STEP
)
796 ASSERT (TempPtr
!= NULL
);
799 DispatchNotifyListPointer
->NotifyPtrs
,
800 sizeof (PEI_PPI_LIST_POINTERS
) * DispatchNotifyListPointer
->MaxCount
802 DispatchNotifyListPointer
->NotifyPtrs
= TempPtr
;
803 DispatchNotifyListPointer
->MaxCount
= DispatchNotifyListPointer
->MaxCount
+ DISPATCH_NOTIFY_GROWTH_STEP
;
805 DispatchNotifyListPointer
->NotifyPtrs
[DispatchNotifyIndex
].Notify
= (EFI_PEI_NOTIFY_DESCRIPTOR
*) NotifyList
;
806 DispatchNotifyIndex
++;
807 DispatchNotifyListPointer
->CurrentCount
++;
810 DEBUG((DEBUG_INFO
, "Register PPI Notify: %g\n", NotifyList
->Guid
));
814 // Only single entry in the NotifyList.
817 } else if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
818 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
820 // Continue until the end of the Notify List.
825 // Go to the next descriptor.
831 // Process any callback level notifies for all previously installed PPIs.
835 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
837 PrivateData
->PpiData
.PpiList
.CurrentCount
,
838 LastCallbackNotifyCount
,
839 CallbackNotifyListPointer
->CurrentCount
847 This function installs a notification service to be called back when a given
848 interface is installed or reinstalled. The purpose of the service is to publish
849 an interface that other parties can use to call additional PPIs that may materialize later.
851 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
852 @param NotifyList Pointer to list of Descriptors to notify upon.
854 @retval EFI_SUCCESS if successful
855 @retval EFI_OUT_OF_RESOURCES if no space in the database
856 @retval EFI_INVALID_PARAMETER if not a good descriptor
862 IN CONST EFI_PEI_SERVICES
**PeiServices
,
863 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyList
866 return InternalPeiNotifyPpi (PeiServices
, NotifyList
, FALSE
);
871 Process the Notify List at dispatch level.
873 @param PrivateData PeiCore's private data structure.
877 ProcessDispatchNotifyList (
878 IN PEI_CORE_INSTANCE
*PrivateData
885 // Check if the PEIM that was just dispatched resulted in any
886 // Notifies getting installed. If so, go process any dispatch
887 // level Notifies that match the previously installed PPIs.
888 // Use "while" instead of "if" since ProcessNotify can modify
889 // DispatchNotifyList.CurrentCount (with NotifyPpi) so we have
890 // to iterate until the same.
892 while (PrivateData
->PpiData
.DispatchNotifyList
.LastDispatchedCount
!= PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
) {
893 TempValue
= PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
;
896 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
898 PrivateData
->PpiData
.PpiList
.LastDispatchedCount
,
899 PrivateData
->PpiData
.DispatchNotifyList
.LastDispatchedCount
,
900 PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
902 PrivateData
->PpiData
.DispatchNotifyList
.LastDispatchedCount
= TempValue
;
906 // Check if the PEIM that was just dispatched resulted in any
907 // PPIs getting installed. If so, go process any dispatch
908 // level Notifies that match the installed PPIs.
909 // Use "while" instead of "if" since ProcessNotify can modify
910 // PpiList.CurrentCount (with InstallPpi) so we have to iterate
913 while (PrivateData
->PpiData
.PpiList
.LastDispatchedCount
!= PrivateData
->PpiData
.PpiList
.CurrentCount
) {
914 TempValue
= PrivateData
->PpiData
.PpiList
.CurrentCount
;
917 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
918 PrivateData
->PpiData
.PpiList
.LastDispatchedCount
,
919 PrivateData
->PpiData
.PpiList
.CurrentCount
,
921 PrivateData
->PpiData
.DispatchNotifyList
.LastDispatchedCount
923 PrivateData
->PpiData
.PpiList
.LastDispatchedCount
= TempValue
;
926 if (PrivateData
->PpiData
.DispatchNotifyList
.LastDispatchedCount
== PrivateData
->PpiData
.DispatchNotifyList
.CurrentCount
) {
935 Process notifications.
937 @param PrivateData PeiCore's private data structure
938 @param NotifyType Type of notify to fire.
939 @param InstallStartIndex Install Beginning index.
940 @param InstallStopIndex Install Ending index.
941 @param NotifyStartIndex Notify Beginning index.
942 @param NotifyStopIndex Notify Ending index.
947 IN PEI_CORE_INSTANCE
*PrivateData
,
949 IN INTN InstallStartIndex
,
950 IN INTN InstallStopIndex
,
951 IN INTN NotifyStartIndex
,
952 IN INTN NotifyStopIndex
957 EFI_GUID
*SearchGuid
;
959 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
;
961 for (Index1
= NotifyStartIndex
; Index1
< NotifyStopIndex
; Index1
++) {
962 if (NotifyType
== EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
) {
963 NotifyDescriptor
= PrivateData
->PpiData
.CallbackNotifyList
.NotifyPtrs
[Index1
].Notify
;
965 NotifyDescriptor
= PrivateData
->PpiData
.DispatchNotifyList
.NotifyPtrs
[Index1
].Notify
;
968 CheckGuid
= NotifyDescriptor
->Guid
;
970 for (Index2
= InstallStartIndex
; Index2
< InstallStopIndex
; Index2
++) {
971 SearchGuid
= PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index2
].Ppi
->Guid
;
973 // Don't use CompareGuid function here for performance reasons.
974 // Instead we compare the GUID as INT32 at a time and branch
975 // on the first failed comparison.
977 if ((((INT32
*)SearchGuid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
978 (((INT32
*)SearchGuid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
979 (((INT32
*)SearchGuid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
980 (((INT32
*)SearchGuid
)[3] == ((INT32
*)CheckGuid
)[3])) {
981 DEBUG ((DEBUG_INFO
, "Notify: PPI Guid: %g, Peim notify entry point: %p\n",
983 NotifyDescriptor
->Notify
985 NotifyDescriptor
->Notify (
986 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer (),
988 (PrivateData
->PpiData
.PpiList
.PpiPtrs
[Index2
].Ppi
)->Ppi
996 Process PpiList from SEC phase.
998 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
999 @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
1000 These PPI's will be installed and/or immediately signaled if they are notification type.
1004 ProcessPpiListFromSec (
1005 IN CONST EFI_PEI_SERVICES
**PeiServices
,
1006 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
1010 EFI_SEC_HOB_DATA_PPI
*SecHobDataPpi
;
1011 EFI_HOB_GENERIC_HEADER
*SecHobList
;
1014 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES
) != 0) {
1016 // It is a notification PPI.
1018 Status
= InternalPeiNotifyPpi (PeiServices
, (CONST EFI_PEI_NOTIFY_DESCRIPTOR
*) PpiList
, TRUE
);
1019 ASSERT_EFI_ERROR (Status
);
1022 // It is a normal PPI.
1024 Status
= InternalPeiInstallPpi (PeiServices
, PpiList
, TRUE
);
1025 ASSERT_EFI_ERROR (Status
);
1028 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
1030 // Continue until the end of the PPI List.
1039 // If the EFI_SEC_HOB_DATA_PPI is in the list of PPIs passed to the PEI entry point,
1040 // the PEI Foundation will call the GetHobs() member function and install all HOBs
1041 // returned into the HOB list. It does this after installing all PPIs passed from SEC
1042 // into the PPI database and before dispatching any PEIMs.
1044 Status
= PeiLocatePpi (PeiServices
, &gEfiSecHobDataPpiGuid
, 0, NULL
, (VOID
**) &SecHobDataPpi
);
1045 if (!EFI_ERROR (Status
)) {
1046 Status
= SecHobDataPpi
->GetHobs (SecHobDataPpi
, &SecHobList
);
1047 if (!EFI_ERROR (Status
)) {
1048 Status
= PeiInstallSecHobData (PeiServices
, SecHobList
);
1049 ASSERT_EFI_ERROR (Status
);
1056 Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.
1058 @param PrivateData Pointer to PeiCore's private data structure.
1059 @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory.
1063 ConvertPeiCorePpiPointers (
1064 IN PEI_CORE_INSTANCE
*PrivateData
,
1065 IN PEI_CORE_FV_HANDLE
*CoreFvHandle
1068 EFI_FV_FILE_INFO FileInfo
;
1069 EFI_PHYSICAL_ADDRESS OrgImageBase
;
1070 EFI_PHYSICAL_ADDRESS MigratedImageBase
;
1071 UINTN PeiCoreModuleSize
;
1072 EFI_PEI_FILE_HANDLE PeiCoreFileHandle
;
1073 VOID
*PeiCoreImageBase
;
1074 VOID
*PeiCoreEntryPoint
;
1077 PeiCoreFileHandle
= NULL
;
1080 // Find the PEI Core in the BFV in temporary memory.
1082 Status
= CoreFvHandle
->FvPpi
->FindFileByType (
1083 CoreFvHandle
->FvPpi
,
1084 EFI_FV_FILETYPE_PEI_CORE
,
1085 CoreFvHandle
->FvHandle
,
1088 ASSERT_EFI_ERROR (Status
);
1090 if (!EFI_ERROR (Status
)) {
1091 Status
= CoreFvHandle
->FvPpi
->GetFileInfo (CoreFvHandle
->FvPpi
, PeiCoreFileHandle
, &FileInfo
);
1092 ASSERT_EFI_ERROR (Status
);
1094 Status
= PeiGetPe32Data (PeiCoreFileHandle
, &PeiCoreImageBase
);
1095 ASSERT_EFI_ERROR (Status
);
1098 // Find PEI Core EntryPoint in the BFV in temporary memory.
1100 Status
= PeCoffLoaderGetEntryPoint ((VOID
*) (UINTN
) PeiCoreImageBase
, &PeiCoreEntryPoint
);
1101 ASSERT_EFI_ERROR (Status
);
1103 OrgImageBase
= (UINTN
) PeiCoreImageBase
;
1104 MigratedImageBase
= (UINTN
) _ModuleEntryPoint
- ((UINTN
) PeiCoreEntryPoint
- (UINTN
) PeiCoreImageBase
);
1107 // Size of loaded PEI_CORE in permanent memory.
1109 PeiCoreModuleSize
= (UINTN
)FileInfo
.BufferSize
- ((UINTN
) OrgImageBase
- (UINTN
) FileInfo
.Buffer
);
1112 // Migrate PEI_CORE PPI pointers from temporary memory to newly
1113 // installed PEI_CORE in permanent memory.
1115 ConvertPpiPointersFv (PrivateData
, (UINTN
) OrgImageBase
, (UINTN
) MigratedImageBase
, PeiCoreModuleSize
);