2 EFI PEI Core PPI services
4 Copyright (c) 2006 - 2013, 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
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.
19 Initialize PPI services.
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.
27 InitializePpiServices (
28 IN PEI_CORE_INSTANCE
*PrivateData
,
29 IN PEI_CORE_INSTANCE
*OldCoreData
32 if (OldCoreData
== NULL
) {
33 PrivateData
->PpiData
.NotifyListEnd
= FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1;
34 PrivateData
->PpiData
.DispatchListEnd
= FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1;
35 PrivateData
->PpiData
.LastDispatchedNotify
= FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1;
41 Migrate Single PPI Pointer from the temporary memory to PEI installed memory.
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.
51 ConverSinglePpiPointer (
52 IN PEI_PPI_LIST_POINTERS
*PpiPointer
,
56 IN BOOLEAN OffsetPositive
59 if (((UINTN
)PpiPointer
->Raw
< TempTop
) &&
60 ((UINTN
)PpiPointer
->Raw
>= TempBottom
)) {
62 // Convert the pointer to the PPI descriptor from the old TempRam
63 // to the relocated physical memory.
66 PpiPointer
->Raw
= (VOID
*) ((UINTN
)PpiPointer
->Raw
+ Offset
);
68 PpiPointer
->Raw
= (VOID
*) ((UINTN
)PpiPointer
->Raw
- Offset
);
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
76 if (((UINTN
)PpiPointer
->Ppi
->Guid
< TempTop
) &&
77 ((UINTN
)PpiPointer
->Ppi
->Guid
>= TempBottom
)) {
79 // Convert the pointer to the GUID in the PPI or NOTIFY descriptor
80 // from the old TempRam to the relocated physical memory.
83 PpiPointer
->Ppi
->Guid
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Guid
+ Offset
);
85 PpiPointer
->Ppi
->Guid
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Guid
- Offset
);
90 // Convert the pointer to the PPI interface structure in the PPI descriptor
91 // from the old TempRam to the relocated physical memory.
93 if ((UINTN
)PpiPointer
->Ppi
->Ppi
< TempTop
&&
94 (UINTN
)PpiPointer
->Ppi
->Ppi
>= TempBottom
) {
96 PpiPointer
->Ppi
->Ppi
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Ppi
+ Offset
);
98 PpiPointer
->Ppi
->Ppi
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Ppi
- Offset
);
106 Migrate PPI Pointers from the temporary memory stack to PEI installed memory.
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.
115 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
116 IN PEI_CORE_INSTANCE
*PrivateData
122 for (Index
= 0; Index
< FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
); Index
++) {
123 if (Index
< PrivateData
->PpiData
.PpiListEnd
|| Index
> PrivateData
->PpiData
.NotifyListEnd
) {
125 // Convert PPI pointer in old Heap
127 ConverSinglePpiPointer (
128 &PrivateData
->PpiData
.PpiListPtrs
[Index
],
129 (UINTN
)SecCoreData
->PeiTemporaryRamBase
,
130 (UINTN
)SecCoreData
->PeiTemporaryRamBase
+ SecCoreData
->PeiTemporaryRamSize
,
131 PrivateData
->HeapOffset
,
132 PrivateData
->HeapOffsetPositive
136 // Convert PPI pointer in old Stack
138 ConverSinglePpiPointer (
139 &PrivateData
->PpiData
.PpiListPtrs
[Index
],
140 (UINTN
)SecCoreData
->StackBase
,
141 (UINTN
)SecCoreData
->StackBase
+ SecCoreData
->StackSize
,
142 PrivateData
->StackOffset
,
143 PrivateData
->StackOffsetPositive
147 // Convert PPI pointer in old TempRam Hole
149 for (IndexHole
= 0; IndexHole
< HOLE_MAX_NUMBER
; IndexHole
++) {
150 if (PrivateData
->HoleData
[IndexHole
].Size
== 0) {
154 ConverSinglePpiPointer (
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
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.
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.
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
184 IN CONST EFI_PEI_SERVICES
**PeiServices
,
185 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
188 PEI_CORE_INSTANCE
*PrivateData
;
190 INTN LastCallbackInstall
;
193 if (PpiList
== NULL
) {
194 return EFI_INVALID_PARAMETER
;
197 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
199 Index
= PrivateData
->PpiData
.PpiListEnd
;
200 LastCallbackInstall
= Index
;
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.
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.
214 if (Index
== PrivateData
->PpiData
.NotifyListEnd
+ 1) {
215 return EFI_OUT_OF_RESOURCES
;
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.
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
;
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
++;
233 // Continue until the end of the PPI List.
235 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
236 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
244 // Dispatch any callback level notifies for newly installed PPIs.
248 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
250 PrivateData
->PpiData
.PpiListEnd
,
251 PrivateData
->PpiData
.DispatchListEnd
,
252 PrivateData
->PpiData
.NotifyListEnd
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
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.
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
279 IN CONST EFI_PEI_SERVICES
**PeiServices
,
280 IN CONST EFI_PEI_PPI_DESCRIPTOR
*OldPpi
,
281 IN CONST EFI_PEI_PPI_DESCRIPTOR
*NewPpi
284 PEI_CORE_INSTANCE
*PrivateData
;
288 if ((OldPpi
== NULL
) || (NewPpi
== NULL
)) {
289 return EFI_INVALID_PARAMETER
;
292 if ((NewPpi
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
293 return EFI_INVALID_PARAMETER
;
296 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
299 // Find the old PPI instance in the database. If we can not find it,
300 // return the EFI_NOT_FOUND error.
302 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
303 if (OldPpi
== PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
) {
307 if (Index
== PrivateData
->PpiData
.PpiListEnd
) {
308 return EFI_NOT_FOUND
;
312 // Remove the old PPI from the database, add the new one.
314 DEBUG((EFI_D_INFO
, "Reinstall PPI: %g\n", NewPpi
->Guid
));
315 ASSERT (Index
< (INTN
)(FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)));
316 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*) NewPpi
;
319 // Dispatch any callback level notifies for the newly installed PPI.
323 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
326 PrivateData
->PpiData
.DispatchListEnd
,
327 PrivateData
->PpiData
.NotifyListEnd
336 Locate a given named PPI.
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
346 @retval EFI_SUCCESS if the PPI is in the database
347 @retval EFI_NOT_FOUND if the PPI is not in the database
353 IN CONST EFI_PEI_SERVICES
**PeiServices
,
354 IN CONST EFI_GUID
*Guid
,
356 IN OUT EFI_PEI_PPI_DESCRIPTOR
**PpiDescriptor
,
360 PEI_CORE_INSTANCE
*PrivateData
;
363 EFI_PEI_PPI_DESCRIPTOR
*TempPtr
;
366 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
369 // Search the data base for the matching instance of the GUIDed PPI.
371 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
372 TempPtr
= PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
;
373 CheckGuid
= TempPtr
->Guid
;
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.
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])) {
386 if (PpiDescriptor
!= NULL
) {
387 *PpiDescriptor
= TempPtr
;
401 return EFI_NOT_FOUND
;
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.
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.
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
421 IN CONST EFI_PEI_SERVICES
**PeiServices
,
422 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyList
425 PEI_CORE_INSTANCE
*PrivateData
;
428 INTN LastCallbackNotify
;
429 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyPtr
;
430 UINTN NotifyDispatchCount
;
433 NotifyDispatchCount
= 0;
435 if (NotifyList
== NULL
) {
436 return EFI_INVALID_PARAMETER
;
439 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
441 Index
= PrivateData
->PpiData
.NotifyListEnd
;
442 LastCallbackNotify
= Index
;
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.
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.
456 if (Index
== PrivateData
->PpiData
.PpiListEnd
- 1) {
457 return EFI_OUT_OF_RESOURCES
;
461 // If some of the PPI data is invalid restore original Notify PPI database value
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
;
469 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
470 NotifyDispatchCount
++;
473 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= (EFI_PEI_NOTIFY_DESCRIPTOR
*) NotifyList
;
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
) {
482 // Go the next descriptor. Remember the NotifyList moves down.
489 // If there is Dispatch Notify PPI installed put them on the bottom
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
;
496 for (Index
= NotifyIndex
; Index
< PrivateData
->PpiData
.DispatchListEnd
; Index
++){
497 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= PrivateData
->PpiData
.PpiListPtrs
[Index
+ 1].Notify
;
499 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= NotifyPtr
;
500 PrivateData
->PpiData
.DispatchListEnd
--;
504 LastCallbackNotify
-= NotifyDispatchCount
;
508 // Dispatch any callback level notifies for all previously installed PPIs.
512 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
514 PrivateData
->PpiData
.PpiListEnd
,
516 PrivateData
->PpiData
.NotifyListEnd
525 Process the Notify List at dispatch level.
527 @param PrivateData PeiCore's private data structure.
532 IN PEI_CORE_INSTANCE
*PrivateData
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.
545 while (PrivateData
->PpiData
.LastDispatchedNotify
!= PrivateData
->PpiData
.DispatchListEnd
) {
546 TempValue
= PrivateData
->PpiData
.DispatchListEnd
;
549 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
551 PrivateData
->PpiData
.LastDispatchedInstall
,
552 PrivateData
->PpiData
.LastDispatchedNotify
,
553 PrivateData
->PpiData
.DispatchListEnd
555 PrivateData
->PpiData
.LastDispatchedNotify
= TempValue
;
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.
566 while (PrivateData
->PpiData
.LastDispatchedInstall
!= PrivateData
->PpiData
.PpiListEnd
) {
567 TempValue
= PrivateData
->PpiData
.PpiListEnd
;
570 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
571 PrivateData
->PpiData
.LastDispatchedInstall
,
572 PrivateData
->PpiData
.PpiListEnd
,
573 FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1,
574 PrivateData
->PpiData
.DispatchListEnd
576 PrivateData
->PpiData
.LastDispatchedInstall
= TempValue
;
579 if (PrivateData
->PpiData
.LastDispatchedNotify
== PrivateData
->PpiData
.DispatchListEnd
) {
588 Dispatch notifications.
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.
600 IN PEI_CORE_INSTANCE
*PrivateData
,
602 IN INTN InstallStartIndex
,
603 IN INTN InstallStopIndex
,
604 IN INTN NotifyStartIndex
,
605 IN INTN NotifyStopIndex
610 EFI_GUID
*SearchGuid
;
612 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
;
615 // Remember that Installs moves up and Notifies moves down.
617 for (Index1
= NotifyStartIndex
; Index1
> NotifyStopIndex
; Index1
--) {
618 NotifyDescriptor
= PrivateData
->PpiData
.PpiListPtrs
[Index1
].Notify
;
620 CheckGuid
= NotifyDescriptor
->Guid
;
622 for (Index2
= InstallStartIndex
; Index2
< InstallStopIndex
; Index2
++) {
623 SearchGuid
= PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
->Guid
;
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.
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",
635 NotifyDescriptor
->Notify
637 NotifyDescriptor
->Notify (
638 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer (),
640 (PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
)->Ppi