3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 EFI PEI Core PPI services
25 // Include common header file for this module.
27 #include "CommonHeader.h"
32 InitializePpiServices (
33 IN EFI_PEI_SERVICES
**PeiServices
,
34 IN PEI_CORE_INSTANCE
*OldCoreData
40 Initialize PPI services.
44 PeiServices - The PEI core services table.
45 OldCoreData - Pointer to the PEI Core data.
46 NULL if being run in non-permament memory mode.
53 PEI_CORE_INSTANCE
*PrivateData
;
55 if (OldCoreData
== NULL
) {
56 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
58 PrivateData
->PpiData
.NotifyListEnd
= MAX_PPI_DESCRIPTORS
-1;
59 PrivateData
->PpiData
.DispatchListEnd
= MAX_PPI_DESCRIPTORS
-1;
60 PrivateData
->PpiData
.LastDispatchedNotify
= MAX_PPI_DESCRIPTORS
-1;
68 IN EFI_PEI_SERVICES
**PeiServices
,
69 IN EFI_HOB_HANDOFF_INFO_TABLE
*OldHandOffHob
,
70 IN EFI_HOB_HANDOFF_INFO_TABLE
*NewHandOffHob
76 Migrate the Hob list from the CAR stack to PEI installed memory.
80 PeiServices - The PEI core services table.
81 OldHandOffHob - The old handoff HOB list.
82 NewHandOffHob - The new handoff HOB list.
88 PEI_CORE_INSTANCE
*PrivateData
;
90 PEI_PPI_LIST_POINTERS
*PpiPointer
;
93 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
95 Fixup
= (UINTN
)NewHandOffHob
- (UINTN
)OldHandOffHob
;
97 for (Index
= 0; Index
< MAX_PPI_DESCRIPTORS
; Index
++) {
98 if (Index
< PrivateData
->PpiData
.PpiListEnd
||
99 Index
> PrivateData
->PpiData
.NotifyListEnd
) {
100 PpiPointer
= &PrivateData
->PpiData
.PpiListPtrs
[Index
];
102 if (((UINTN
)PpiPointer
->Raw
< (UINTN
)OldHandOffHob
->EfiFreeMemoryBottom
) &&
103 ((UINTN
)PpiPointer
->Raw
>= (UINTN
)OldHandOffHob
)) {
105 // Convert the pointer to the PEIM descriptor from the old HOB heap
106 // to the relocated HOB heap.
108 PpiPointer
->Raw
= (VOID
*) ((UINTN
)PpiPointer
->Raw
+ Fixup
);
111 // Only when the PEIM descriptor is in the old HOB should it be necessary
112 // to try to convert the pointers in the PEIM descriptor
115 if (((UINTN
)PpiPointer
->Ppi
->Guid
< (UINTN
)OldHandOffHob
->EfiFreeMemoryBottom
) &&
116 ((UINTN
)PpiPointer
->Ppi
->Guid
>= (UINTN
)OldHandOffHob
)) {
118 // Convert the pointer to the GUID in the PPI or NOTIFY descriptor
119 // from the old HOB heap to the relocated HOB heap.
121 PpiPointer
->Ppi
->Guid
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Guid
+ Fixup
);
125 // Assume that no code is located in the temporary memory, so the pointer to
126 // the notification function in the NOTIFY descriptor needs not be converted.
128 if (Index
< PrivateData
->PpiData
.PpiListEnd
&&
129 (UINTN
)PpiPointer
->Ppi
->Ppi
< (UINTN
)OldHandOffHob
->EfiFreeMemoryBottom
&&
130 (UINTN
)PpiPointer
->Ppi
->Ppi
>= (UINTN
)OldHandOffHob
) {
132 // Convert the pointer to the PPI interface structure in the PPI descriptor
133 // from the old HOB heap to the relocated HOB heap.
135 PpiPointer
->Ppi
->Ppi
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Ppi
+ Fixup
);
147 IN EFI_PEI_SERVICES
**PeiServices
,
148 IN EFI_PEI_PPI_DESCRIPTOR
*PpiList
154 Install PPI services.
158 PeiServices - Pointer to the PEI Service Table
159 PpiList - Pointer to a list of PEI PPI Descriptors.
163 EFI_SUCCESS - if all PPIs in PpiList are successfully installed.
164 EFI_INVALID_PARAMETER - if PpiList is NULL pointer
165 EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid
166 EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI
170 PEI_CORE_INSTANCE
*PrivateData
;
172 INTN LastCallbackInstall
;
175 if (PpiList
== NULL
) {
176 return EFI_INVALID_PARAMETER
;
179 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
181 Index
= PrivateData
->PpiData
.PpiListEnd
;
182 LastCallbackInstall
= Index
;
185 // This is loop installs all PPI descriptors in the PpiList. It is terminated
186 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
187 // EFI_PEI_PPI_DESCRIPTOR in the list.
192 // Since PpiData is used for NotifyList and InstallList, max resource
193 // is reached if the Install reaches the NotifyList
195 if (Index
== PrivateData
->PpiData
.NotifyListEnd
+ 1) {
196 return EFI_OUT_OF_RESOURCES
;
199 // Check if it is a valid PPI.
200 // If not, rollback list to exclude all in this list.
201 // Try to indicate which item failed.
203 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
204 PrivateData
->PpiData
.PpiListEnd
= LastCallbackInstall
;
205 DEBUG((EFI_D_ERROR
, "ERROR -> InstallPpi: %g %x\n", PpiList
->Guid
, PpiList
->Ppi
));
206 return EFI_INVALID_PARAMETER
;
209 DEBUG((EFI_D_INFO
, "Install PPI: %g\n", PpiList
->Guid
));
210 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= PpiList
;
211 PrivateData
->PpiData
.PpiListEnd
++;
214 // Continue until the end of the PPI List.
216 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
217 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
225 // Dispatch any callback level notifies for newly installed PPIs.
229 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
231 PrivateData
->PpiData
.PpiListEnd
,
232 PrivateData
->PpiData
.DispatchListEnd
,
233 PrivateData
->PpiData
.NotifyListEnd
244 IN EFI_PEI_SERVICES
**PeiServices
,
245 IN EFI_PEI_PPI_DESCRIPTOR
*OldPpi
,
246 IN EFI_PEI_PPI_DESCRIPTOR
*NewPpi
252 Re-Install PPI services.
256 PeiServices - Pointer to the PEI Service Table
257 OldPpi - Pointer to the old PEI PPI Descriptors.
258 NewPpi - Pointer to the new PEI PPI Descriptors.
262 EFI_SUCCESS - if the operation was successful
263 EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL
264 EFI_INVALID_PARAMETER - if NewPpi is not valid
265 EFI_NOT_FOUND - if the PPI was not in the database
269 PEI_CORE_INSTANCE
*PrivateData
;
273 if ((OldPpi
== NULL
) || (NewPpi
== NULL
)) {
274 return EFI_INVALID_PARAMETER
;
277 if ((NewPpi
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
278 return EFI_INVALID_PARAMETER
;
281 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
284 // Find the old PPI instance in the database. If we can not find it,
285 // return the EFI_NOT_FOUND error.
287 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
288 if (OldPpi
== PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
) {
292 if (Index
== PrivateData
->PpiData
.PpiListEnd
) {
293 return EFI_NOT_FOUND
;
297 // Remove the old PPI from the database, add the new one.
299 DEBUG((EFI_D_INFO
, "Reinstall PPI: %g\n", NewPpi
->Guid
));
300 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= NewPpi
;
303 // Dispatch any callback level notifies for the newly installed PPI.
307 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
310 PrivateData
->PpiData
.DispatchListEnd
,
311 PrivateData
->PpiData
.NotifyListEnd
322 IN EFI_PEI_SERVICES
**PeiServices
,
325 IN OUT EFI_PEI_PPI_DESCRIPTOR
**PpiDescriptor
,
332 Locate a given named PPI.
336 PeiServices - Pointer to the PEI Service Table
337 Guid - Pointer to GUID of the PPI.
338 Instance - Instance Number to discover.
339 PpiDescriptor - Pointer to reference the found descriptor. If not NULL,
340 returns a pointer to the descriptor (includes flags, etc)
341 Ppi - Pointer to reference the found PPI
345 Status - EFI_SUCCESS if the PPI is in the database
346 EFI_NOT_FOUND if the PPI is not in the database
349 PEI_CORE_INSTANCE
*PrivateData
;
352 EFI_PEI_PPI_DESCRIPTOR
*TempPtr
;
355 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
358 // Search the data base for the matching instance of the GUIDed PPI.
360 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
361 TempPtr
= PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
;
362 CheckGuid
= TempPtr
->Guid
;
365 // Don't use CompareGuid function here for performance reasons.
366 // Instead we compare the GUID as INT32 at a time and branch
367 // on the first failed comparison.
369 if ((((INT32
*)Guid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
370 (((INT32
*)Guid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
371 (((INT32
*)Guid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
372 (((INT32
*)Guid
)[3] == ((INT32
*)CheckGuid
)[3])) {
375 if (PpiDescriptor
!= NULL
) {
376 *PpiDescriptor
= TempPtr
;
390 return EFI_NOT_FOUND
;
397 IN EFI_PEI_SERVICES
**PeiServices
,
398 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyList
404 Install a notification for a given PPI.
408 PeiServices - Pointer to the PEI Service Table
409 NotifyList - Pointer to list of Descriptors to notify upon.
413 Status - EFI_SUCCESS if successful
414 EFI_OUT_OF_RESOURCES if no space in the database
415 EFI_INVALID_PARAMETER if not a good decriptor
419 PEI_CORE_INSTANCE
*PrivateData
;
422 INTN LastCallbackNotify
;
423 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyPtr
;
424 UINTN NotifyDispatchCount
;
427 NotifyDispatchCount
= 0;
429 if (NotifyList
== NULL
) {
430 return EFI_INVALID_PARAMETER
;
433 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
435 Index
= PrivateData
->PpiData
.NotifyListEnd
;
436 LastCallbackNotify
= Index
;
439 // This is loop installs all Notify descriptors in the NotifyList. It is
440 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
441 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.
446 // Since PpiData is used for NotifyList and InstallList, max resource
447 // is reached if the Install reaches the PpiList
449 if (Index
== PrivateData
->PpiData
.PpiListEnd
- 1) {
450 return EFI_OUT_OF_RESOURCES
;
454 // If some of the PPI data is invalid restore original Notify PPI database value
456 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES
) == 0) {
457 PrivateData
->PpiData
.NotifyListEnd
= LastCallbackNotify
;
458 DEBUG((EFI_D_ERROR
, "ERROR -> InstallNotify: %g %x\n", NotifyList
->Guid
, NotifyList
->Notify
));
459 return EFI_INVALID_PARAMETER
;
462 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
463 NotifyDispatchCount
++;
466 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= NotifyList
;
468 PrivateData
->PpiData
.NotifyListEnd
--;
469 DEBUG((EFI_D_INFO
, "Register PPI Notify: %g\n", NotifyList
->Guid
));
470 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
471 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
475 // Go the next descriptor. Remember the NotifyList moves down.
482 // If there is Dispatch Notify PPI installed put them on the bottom
484 if (NotifyDispatchCount
> 0) {
485 for (NotifyIndex
= LastCallbackNotify
; NotifyIndex
> PrivateData
->PpiData
.NotifyListEnd
; NotifyIndex
--) {
486 if ((PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
487 NotifyPtr
= PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
;
489 for (Index
= NotifyIndex
; Index
< PrivateData
->PpiData
.DispatchListEnd
; Index
++){
490 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= PrivateData
->PpiData
.PpiListPtrs
[Index
+ 1].Notify
;
492 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= NotifyPtr
;
493 PrivateData
->PpiData
.DispatchListEnd
--;
497 LastCallbackNotify
-= NotifyDispatchCount
;
501 // Dispatch any callback level notifies for all previously installed PPIs.
505 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
507 PrivateData
->PpiData
.PpiListEnd
,
509 PrivateData
->PpiData
.NotifyListEnd
519 IN EFI_PEI_SERVICES
**PeiServices
525 Process the Notify List at dispatch level.
529 PeiServices - Pointer to the PEI Service Table
536 PEI_CORE_INSTANCE
*PrivateData
;
539 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
544 // Check if the PEIM that was just dispatched resulted in any
545 // Notifies getting installed. If so, go process any dispatch
546 // level Notifies that match the previouly installed PPIs.
547 // Use "while" instead of "if" since DispatchNotify can modify
548 // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.
550 while (PrivateData
->PpiData
.LastDispatchedNotify
!= PrivateData
->PpiData
.DispatchListEnd
) {
551 TempValue
= PrivateData
->PpiData
.DispatchListEnd
;
554 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
556 PrivateData
->PpiData
.LastDispatchedInstall
,
557 PrivateData
->PpiData
.LastDispatchedNotify
,
558 PrivateData
->PpiData
.DispatchListEnd
560 PrivateData
->PpiData
.LastDispatchedNotify
= TempValue
;
565 // Check if the PEIM that was just dispatched resulted in any
566 // PPIs getting installed. If so, go process any dispatch
567 // level Notifies that match the installed PPIs.
568 // Use "while" instead of "if" since DispatchNotify can modify
569 // PpiListEnd (with InstallPpi) so we have to iterate until the same.
571 while (PrivateData
->PpiData
.LastDispatchedInstall
!= PrivateData
->PpiData
.PpiListEnd
) {
572 TempValue
= PrivateData
->PpiData
.PpiListEnd
;
575 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
576 PrivateData
->PpiData
.LastDispatchedInstall
,
577 PrivateData
->PpiData
.PpiListEnd
,
578 MAX_PPI_DESCRIPTORS
-1,
579 PrivateData
->PpiData
.DispatchListEnd
581 PrivateData
->PpiData
.LastDispatchedInstall
= TempValue
;
584 if (PrivateData
->PpiData
.LastDispatchedNotify
== PrivateData
->PpiData
.DispatchListEnd
) {
593 IN EFI_PEI_SERVICES
**PeiServices
,
595 IN INTN InstallStartIndex
,
596 IN INTN InstallStopIndex
,
597 IN INTN NotifyStartIndex
,
598 IN INTN NotifyStopIndex
604 Dispatch notifications.
608 PeiServices - Pointer to the PEI Service Table
609 NotifyType - Type of notify to fire.
610 InstallStartIndex - Install Beginning index.
611 InstallStopIndex - Install Ending index.
612 NotifyStartIndex - Notify Beginning index.
613 NotifyStopIndex - Notify Ending index.
620 PEI_CORE_INSTANCE
*PrivateData
;
623 EFI_GUID
*SearchGuid
;
625 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
;
627 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
630 // Remember that Installs moves up and Notifies moves down.
632 for (Index1
= NotifyStartIndex
; Index1
> NotifyStopIndex
; Index1
--) {
633 NotifyDescriptor
= PrivateData
->PpiData
.PpiListPtrs
[Index1
].Notify
;
635 CheckGuid
= NotifyDescriptor
->Guid
;
637 for (Index2
= InstallStartIndex
; Index2
< InstallStopIndex
; Index2
++) {
638 SearchGuid
= PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
->Guid
;
640 // Don't use CompareGuid function here for performance reasons.
641 // Instead we compare the GUID as INT32 at a time and branch
642 // on the first failed comparison.
644 if ((((INT32
*)SearchGuid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
645 (((INT32
*)SearchGuid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
646 (((INT32
*)SearchGuid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
647 (((INT32
*)SearchGuid
)[3] == ((INT32
*)CheckGuid
)[3])) {
648 DEBUG ((EFI_D_INFO
, "Notify: PPI Guid: %g, Peim notify entry point: %x\n",
650 NotifyDescriptor
->Notify
652 NotifyDescriptor
->Notify (
655 (PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
)->Ppi