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
27 InitializePpiServices (
28 IN EFI_PEI_SERVICES
**PeiServices
,
29 IN PEI_CORE_INSTANCE
*OldCoreData
35 Initialize PPI services.
39 PeiServices - The PEI core services table.
40 OldCoreData - Pointer to the PEI Core data.
41 NULL if being run in non-permament memory mode.
48 PEI_CORE_INSTANCE
*PrivateData
;
50 if (OldCoreData
== NULL
) {
51 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
53 PrivateData
->PpiData
.NotifyListEnd
= MAX_PPI_DESCRIPTORS
-1;
54 PrivateData
->PpiData
.DispatchListEnd
= MAX_PPI_DESCRIPTORS
-1;
55 PrivateData
->PpiData
.LastDispatchedNotify
= MAX_PPI_DESCRIPTORS
-1;
63 IN EFI_PEI_SERVICES
**PeiServices
,
64 IN EFI_HOB_HANDOFF_INFO_TABLE
*OldHandOffHob
,
65 IN EFI_HOB_HANDOFF_INFO_TABLE
*NewHandOffHob
71 Migrate the Hob list from the CAR stack to PEI installed memory.
75 PeiServices - The PEI core services table.
76 OldHandOffHob - The old handoff HOB list.
77 NewHandOffHob - The new handoff HOB list.
83 PEI_CORE_INSTANCE
*PrivateData
;
85 PEI_PPI_LIST_POINTERS
*PpiPointer
;
88 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
90 Fixup
= (UINTN
)NewHandOffHob
- (UINTN
)OldHandOffHob
;
92 for (Index
= 0; Index
< MAX_PPI_DESCRIPTORS
; Index
++) {
93 if (Index
< PrivateData
->PpiData
.PpiListEnd
||
94 Index
> PrivateData
->PpiData
.NotifyListEnd
) {
95 PpiPointer
= &PrivateData
->PpiData
.PpiListPtrs
[Index
];
97 if (((UINTN
)PpiPointer
->Raw
< (UINTN
)OldHandOffHob
->EfiFreeMemoryBottom
) &&
98 ((UINTN
)PpiPointer
->Raw
>= (UINTN
)OldHandOffHob
)) {
100 // Convert the pointer to the PEIM descriptor from the old HOB heap
101 // to the relocated HOB heap.
103 PpiPointer
->Raw
= (VOID
*) ((UINTN
)PpiPointer
->Raw
+ Fixup
);
106 // Only when the PEIM descriptor is in the old HOB should it be necessary
107 // to try to convert the pointers in the PEIM descriptor
110 if (((UINTN
)PpiPointer
->Ppi
->Guid
< (UINTN
)OldHandOffHob
->EfiFreeMemoryBottom
) &&
111 ((UINTN
)PpiPointer
->Ppi
->Guid
>= (UINTN
)OldHandOffHob
)) {
113 // Convert the pointer to the GUID in the PPI or NOTIFY descriptor
114 // from the old HOB heap to the relocated HOB heap.
116 PpiPointer
->Ppi
->Guid
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Guid
+ Fixup
);
120 // Assume that no code is located in the temporary memory, so the pointer to
121 // the notification function in the NOTIFY descriptor needs not be converted.
123 if (Index
< PrivateData
->PpiData
.PpiListEnd
&&
124 (UINTN
)PpiPointer
->Ppi
->Ppi
< (UINTN
)OldHandOffHob
->EfiFreeMemoryBottom
&&
125 (UINTN
)PpiPointer
->Ppi
->Ppi
>= (UINTN
)OldHandOffHob
) {
127 // Convert the pointer to the PPI interface structure in the PPI descriptor
128 // from the old HOB heap to the relocated HOB heap.
130 PpiPointer
->Ppi
->Ppi
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Ppi
+ Fixup
);
142 IN EFI_PEI_SERVICES
**PeiServices
,
143 IN EFI_PEI_PPI_DESCRIPTOR
*PpiList
149 Install PPI services.
153 PeiServices - Pointer to the PEI Service Table
154 PpiList - Pointer to a list of PEI PPI Descriptors.
158 EFI_SUCCESS - if all PPIs in PpiList are successfully installed.
159 EFI_INVALID_PARAMETER - if PpiList is NULL pointer
160 EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid
161 EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI
165 PEI_CORE_INSTANCE
*PrivateData
;
167 INTN LastCallbackInstall
;
170 if (PpiList
== NULL
) {
171 return EFI_INVALID_PARAMETER
;
174 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
176 Index
= PrivateData
->PpiData
.PpiListEnd
;
177 LastCallbackInstall
= Index
;
180 // This is loop installs all PPI descriptors in the PpiList. It is terminated
181 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
182 // EFI_PEI_PPI_DESCRIPTOR in the list.
187 // Since PpiData is used for NotifyList and InstallList, max resource
188 // is reached if the Install reaches the NotifyList
190 if (Index
== PrivateData
->PpiData
.NotifyListEnd
+ 1) {
191 return EFI_OUT_OF_RESOURCES
;
194 // Check if it is a valid PPI.
195 // If not, rollback list to exclude all in this list.
196 // Try to indicate which item failed.
198 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
199 PrivateData
->PpiData
.PpiListEnd
= LastCallbackInstall
;
200 DEBUG((EFI_D_ERROR
, "ERROR -> InstallPpi: %g %x\n", PpiList
->Guid
, PpiList
->Ppi
));
201 return EFI_INVALID_PARAMETER
;
204 DEBUG((EFI_D_INFO
, "Install PPI: %g\n", PpiList
->Guid
));
205 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= PpiList
;
206 PrivateData
->PpiData
.PpiListEnd
++;
209 // Continue until the end of the PPI List.
211 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
212 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
220 // Dispatch any callback level notifies for newly installed PPIs.
224 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
226 PrivateData
->PpiData
.PpiListEnd
,
227 PrivateData
->PpiData
.DispatchListEnd
,
228 PrivateData
->PpiData
.NotifyListEnd
239 IN EFI_PEI_SERVICES
**PeiServices
,
240 IN EFI_PEI_PPI_DESCRIPTOR
*OldPpi
,
241 IN EFI_PEI_PPI_DESCRIPTOR
*NewPpi
247 Re-Install PPI services.
251 PeiServices - Pointer to the PEI Service Table
252 OldPpi - Pointer to the old PEI PPI Descriptors.
253 NewPpi - Pointer to the new PEI PPI Descriptors.
257 EFI_SUCCESS - if the operation was successful
258 EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL
259 EFI_INVALID_PARAMETER - if NewPpi is not valid
260 EFI_NOT_FOUND - if the PPI was not in the database
264 PEI_CORE_INSTANCE
*PrivateData
;
268 if ((OldPpi
== NULL
) || (NewPpi
== NULL
)) {
269 return EFI_INVALID_PARAMETER
;
272 if ((NewPpi
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
273 return EFI_INVALID_PARAMETER
;
276 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
279 // Find the old PPI instance in the database. If we can not find it,
280 // return the EFI_NOT_FOUND error.
282 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
283 if (OldPpi
== PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
) {
287 if (Index
== PrivateData
->PpiData
.PpiListEnd
) {
288 return EFI_NOT_FOUND
;
292 // Remove the old PPI from the database, add the new one.
294 DEBUG((EFI_D_INFO
, "Reinstall PPI: %g\n", NewPpi
->Guid
));
295 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= NewPpi
;
298 // Dispatch any callback level notifies for the newly installed PPI.
302 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
305 PrivateData
->PpiData
.DispatchListEnd
,
306 PrivateData
->PpiData
.NotifyListEnd
317 IN EFI_PEI_SERVICES
**PeiServices
,
320 IN OUT EFI_PEI_PPI_DESCRIPTOR
**PpiDescriptor
,
327 Locate a given named PPI.
331 PeiServices - Pointer to the PEI Service Table
332 Guid - Pointer to GUID of the PPI.
333 Instance - Instance Number to discover.
334 PpiDescriptor - Pointer to reference the found descriptor. If not NULL,
335 returns a pointer to the descriptor (includes flags, etc)
336 Ppi - Pointer to reference the found PPI
340 Status - EFI_SUCCESS if the PPI is in the database
341 EFI_NOT_FOUND if the PPI is not in the database
344 PEI_CORE_INSTANCE
*PrivateData
;
347 EFI_PEI_PPI_DESCRIPTOR
*TempPtr
;
350 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
353 // Search the data base for the matching instance of the GUIDed PPI.
355 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
356 TempPtr
= PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
;
357 CheckGuid
= TempPtr
->Guid
;
360 // Don't use CompareGuid function here for performance reasons.
361 // Instead we compare the GUID as INT32 at a time and branch
362 // on the first failed comparison.
364 if ((((INT32
*)Guid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
365 (((INT32
*)Guid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
366 (((INT32
*)Guid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
367 (((INT32
*)Guid
)[3] == ((INT32
*)CheckGuid
)[3])) {
370 if (PpiDescriptor
!= NULL
) {
371 *PpiDescriptor
= TempPtr
;
385 return EFI_NOT_FOUND
;
392 IN EFI_PEI_SERVICES
**PeiServices
,
393 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyList
399 Install a notification for a given PPI.
403 PeiServices - Pointer to the PEI Service Table
404 NotifyList - Pointer to list of Descriptors to notify upon.
408 Status - EFI_SUCCESS if successful
409 EFI_OUT_OF_RESOURCES if no space in the database
410 EFI_INVALID_PARAMETER if not a good decriptor
414 PEI_CORE_INSTANCE
*PrivateData
;
417 INTN LastCallbackNotify
;
418 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyPtr
;
419 UINTN NotifyDispatchCount
;
422 NotifyDispatchCount
= 0;
424 if (NotifyList
== NULL
) {
425 return EFI_INVALID_PARAMETER
;
428 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
430 Index
= PrivateData
->PpiData
.NotifyListEnd
;
431 LastCallbackNotify
= Index
;
434 // This is loop installs all Notify descriptors in the NotifyList. It is
435 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
436 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.
441 // Since PpiData is used for NotifyList and InstallList, max resource
442 // is reached if the Install reaches the PpiList
444 if (Index
== PrivateData
->PpiData
.PpiListEnd
- 1) {
445 return EFI_OUT_OF_RESOURCES
;
449 // If some of the PPI data is invalid restore original Notify PPI database value
451 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES
) == 0) {
452 PrivateData
->PpiData
.NotifyListEnd
= LastCallbackNotify
;
453 DEBUG((EFI_D_ERROR
, "ERROR -> InstallNotify: %g %x\n", NotifyList
->Guid
, NotifyList
->Notify
));
454 return EFI_INVALID_PARAMETER
;
457 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
458 NotifyDispatchCount
++;
461 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= NotifyList
;
463 PrivateData
->PpiData
.NotifyListEnd
--;
464 DEBUG((EFI_D_INFO
, "Register PPI Notify: %g\n", NotifyList
->Guid
));
465 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
466 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
470 // Go the next descriptor. Remember the NotifyList moves down.
477 // If there is Dispatch Notify PPI installed put them on the bottom
479 if (NotifyDispatchCount
> 0) {
480 for (NotifyIndex
= LastCallbackNotify
; NotifyIndex
> PrivateData
->PpiData
.NotifyListEnd
; NotifyIndex
--) {
481 if ((PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
482 NotifyPtr
= PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
;
484 for (Index
= NotifyIndex
; Index
< PrivateData
->PpiData
.DispatchListEnd
; Index
++){
485 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= PrivateData
->PpiData
.PpiListPtrs
[Index
+ 1].Notify
;
487 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= NotifyPtr
;
488 PrivateData
->PpiData
.DispatchListEnd
--;
492 LastCallbackNotify
-= NotifyDispatchCount
;
496 // Dispatch any callback level notifies for all previously installed PPIs.
500 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
502 PrivateData
->PpiData
.PpiListEnd
,
504 PrivateData
->PpiData
.NotifyListEnd
514 IN EFI_PEI_SERVICES
**PeiServices
520 Process the Notify List at dispatch level.
524 PeiServices - Pointer to the PEI Service Table
531 PEI_CORE_INSTANCE
*PrivateData
;
534 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
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 MAX_PPI_DESCRIPTORS
-1,
574 PrivateData
->PpiData
.DispatchListEnd
576 PrivateData
->PpiData
.LastDispatchedInstall
= TempValue
;
579 if (PrivateData
->PpiData
.LastDispatchedNotify
== PrivateData
->PpiData
.DispatchListEnd
) {
588 IN EFI_PEI_SERVICES
**PeiServices
,
590 IN INTN InstallStartIndex
,
591 IN INTN InstallStopIndex
,
592 IN INTN NotifyStartIndex
,
593 IN INTN NotifyStopIndex
599 Dispatch notifications.
603 PeiServices - Pointer to the PEI Service Table
604 NotifyType - Type of notify to fire.
605 InstallStartIndex - Install Beginning index.
606 InstallStopIndex - Install Ending index.
607 NotifyStartIndex - Notify Beginning index.
608 NotifyStopIndex - Notify Ending index.
615 PEI_CORE_INSTANCE
*PrivateData
;
618 EFI_GUID
*SearchGuid
;
620 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
;
622 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
625 // Remember that Installs moves up and Notifies moves down.
627 for (Index1
= NotifyStartIndex
; Index1
> NotifyStopIndex
; Index1
--) {
628 NotifyDescriptor
= PrivateData
->PpiData
.PpiListPtrs
[Index1
].Notify
;
630 CheckGuid
= NotifyDescriptor
->Guid
;
632 for (Index2
= InstallStartIndex
; Index2
< InstallStopIndex
; Index2
++) {
633 SearchGuid
= PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
->Guid
;
635 // Don't use CompareGuid function here for performance reasons.
636 // Instead we compare the GUID as INT32 at a time and branch
637 // on the first failed comparison.
639 if ((((INT32
*)SearchGuid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
640 (((INT32
*)SearchGuid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
641 (((INT32
*)SearchGuid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
642 (((INT32
*)SearchGuid
)[3] == ((INT32
*)CheckGuid
)[3])) {
643 DEBUG ((EFI_D_INFO
, "Notify: PPI Guid: %g, Peim notify entry point: %x\n",
645 NotifyDescriptor
->Notify
647 NotifyDescriptor
->Notify (
650 (PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
)->Ppi