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 PEI_CORE_INSTANCE
*PrivateData
,
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 if (OldCoreData
== NULL
) {
49 PrivateData
->PpiData
.NotifyListEnd
= FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1;
50 PrivateData
->PpiData
.DispatchListEnd
= FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1;
51 PrivateData
->PpiData
.LastDispatchedNotify
= FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1;
59 IN CONST EFI_PEI_SERVICES
**PeiServices
,
60 IN UINTN OldCheckingBottom
,
61 IN UINTN OldCheckingTop
,
62 IN EFI_HOB_HANDOFF_INFO_TABLE
*NewHandOffHob
68 Migrate the Hob list from the CAR stack to PEI installed memory.
72 PeiServices - The PEI core services table.
73 OldCheckingBottom - The old checking bottom.
74 OldCheckingTop - The old checking top.
75 NewHandOffHob - The new handoff HOB list.
81 PEI_CORE_INSTANCE
*PrivateData
;
83 PEI_PPI_LIST_POINTERS
*PpiPointer
;
86 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
88 Fixup
= (UINTN
)NewHandOffHob
- OldCheckingBottom
;
90 for (Index
= 0; Index
< FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
); Index
++) {
91 if (Index
< PrivateData
->PpiData
.PpiListEnd
||
92 Index
> PrivateData
->PpiData
.NotifyListEnd
) {
93 PpiPointer
= &PrivateData
->PpiData
.PpiListPtrs
[Index
];
95 if (((UINTN
)PpiPointer
->Raw
< OldCheckingTop
) &&
96 ((UINTN
)PpiPointer
->Raw
>= OldCheckingBottom
)) {
98 // Convert the pointer to the PEIM descriptor from the old HOB heap
99 // to the relocated HOB heap.
101 PpiPointer
->Raw
= (VOID
*) ((UINTN
)PpiPointer
->Raw
+ Fixup
);
104 // Only when the PEIM descriptor is in the old HOB should it be necessary
105 // to try to convert the pointers in the PEIM descriptor
108 if (((UINTN
)PpiPointer
->Ppi
->Guid
< OldCheckingTop
) &&
109 ((UINTN
)PpiPointer
->Ppi
->Guid
>= OldCheckingBottom
)) {
111 // Convert the pointer to the GUID in the PPI or NOTIFY descriptor
112 // from the old HOB heap to the relocated HOB heap.
114 PpiPointer
->Ppi
->Guid
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Guid
+ Fixup
);
118 // Assume that no code is located in the temporary memory, so the pointer to
119 // the notification function in the NOTIFY descriptor needs not be converted.
121 if (Index
< PrivateData
->PpiData
.PpiListEnd
&&
122 (UINTN
)PpiPointer
->Ppi
->Ppi
< OldCheckingTop
&&
123 (UINTN
)PpiPointer
->Ppi
->Ppi
>= OldCheckingBottom
) {
125 // Convert the pointer to the PPI interface structure in the PPI descriptor
126 // from the old HOB heap to the relocated HOB heap.
128 PpiPointer
->Ppi
->Ppi
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Ppi
+ Fixup
);
140 IN CONST EFI_PEI_SERVICES
**PeiServices
,
141 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
147 Install PPI services.
151 PeiServices - Pointer to the PEI Service Table
152 PpiList - Pointer to a list of PEI PPI Descriptors.
156 EFI_SUCCESS - if all PPIs in PpiList are successfully installed.
157 EFI_INVALID_PARAMETER - if PpiList is NULL pointer
158 EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid
159 EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI
163 PEI_CORE_INSTANCE
*PrivateData
;
165 INTN LastCallbackInstall
;
168 if (PpiList
== NULL
) {
169 return EFI_INVALID_PARAMETER
;
172 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
174 Index
= PrivateData
->PpiData
.PpiListEnd
;
175 LastCallbackInstall
= Index
;
178 // This is loop installs all PPI descriptors in the PpiList. It is terminated
179 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
180 // EFI_PEI_PPI_DESCRIPTOR in the list.
185 // Since PpiData is used for NotifyList and InstallList, max resource
186 // is reached if the Install reaches the NotifyList
188 if (Index
== PrivateData
->PpiData
.NotifyListEnd
+ 1) {
189 return EFI_OUT_OF_RESOURCES
;
192 // Check if it is a valid PPI.
193 // If not, rollback list to exclude all in this list.
194 // Try to indicate which item failed.
196 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
197 PrivateData
->PpiData
.PpiListEnd
= LastCallbackInstall
;
198 DEBUG((EFI_D_ERROR
, "ERROR -> InstallPpi: %g %x\n", PpiList
->Guid
, PpiList
->Ppi
));
199 return EFI_INVALID_PARAMETER
;
202 DEBUG((EFI_D_INFO
, "Install PPI: %g\n", PpiList
->Guid
));
203 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*) PpiList
;
204 PrivateData
->PpiData
.PpiListEnd
++;
207 // Continue until the end of the PPI List.
209 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
210 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
218 // Dispatch any callback level notifies for newly installed PPIs.
222 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
224 PrivateData
->PpiData
.PpiListEnd
,
225 PrivateData
->PpiData
.DispatchListEnd
,
226 PrivateData
->PpiData
.NotifyListEnd
237 IN CONST EFI_PEI_SERVICES
**PeiServices
,
238 IN CONST EFI_PEI_PPI_DESCRIPTOR
*OldPpi
,
239 IN CONST EFI_PEI_PPI_DESCRIPTOR
*NewPpi
245 Re-Install PPI services.
249 PeiServices - Pointer to the PEI Service Table
250 OldPpi - Pointer to the old PEI PPI Descriptors.
251 NewPpi - Pointer to the new PEI PPI Descriptors.
255 EFI_SUCCESS - if the operation was successful
256 EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL
257 EFI_INVALID_PARAMETER - if NewPpi is not valid
258 EFI_NOT_FOUND - if the PPI was not in the database
262 PEI_CORE_INSTANCE
*PrivateData
;
266 if ((OldPpi
== NULL
) || (NewPpi
== NULL
)) {
267 return EFI_INVALID_PARAMETER
;
270 if ((NewPpi
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
271 return EFI_INVALID_PARAMETER
;
274 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
277 // Find the old PPI instance in the database. If we can not find it,
278 // return the EFI_NOT_FOUND error.
280 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
281 if (OldPpi
== PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
) {
285 if (Index
== PrivateData
->PpiData
.PpiListEnd
) {
286 return EFI_NOT_FOUND
;
290 // Remove the old PPI from the database, add the new one.
292 DEBUG((EFI_D_INFO
, "Reinstall PPI: %g\n", NewPpi
->Guid
));
293 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*) NewPpi
;
296 // Dispatch any callback level notifies for the newly installed PPI.
300 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
303 PrivateData
->PpiData
.DispatchListEnd
,
304 PrivateData
->PpiData
.NotifyListEnd
315 IN CONST EFI_PEI_SERVICES
**PeiServices
,
316 IN CONST EFI_GUID
*Guid
,
318 IN OUT EFI_PEI_PPI_DESCRIPTOR
**PpiDescriptor
,
325 Locate a given named PPI.
329 PeiServices - Pointer to the PEI Service Table
330 Guid - Pointer to GUID of the PPI.
331 Instance - Instance Number to discover.
332 PpiDescriptor - Pointer to reference the found descriptor. If not NULL,
333 returns a pointer to the descriptor (includes flags, etc)
334 Ppi - Pointer to reference the found PPI
338 Status - EFI_SUCCESS if the PPI is in the database
339 EFI_NOT_FOUND if the PPI is not in the database
342 PEI_CORE_INSTANCE
*PrivateData
;
345 EFI_PEI_PPI_DESCRIPTOR
*TempPtr
;
348 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
351 // Search the data base for the matching instance of the GUIDed PPI.
353 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
354 TempPtr
= PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
;
355 CheckGuid
= TempPtr
->Guid
;
358 // Don't use CompareGuid function here for performance reasons.
359 // Instead we compare the GUID as INT32 at a time and branch
360 // on the first failed comparison.
362 if ((((INT32
*)Guid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
363 (((INT32
*)Guid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
364 (((INT32
*)Guid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
365 (((INT32
*)Guid
)[3] == ((INT32
*)CheckGuid
)[3])) {
368 if (PpiDescriptor
!= NULL
) {
369 *PpiDescriptor
= TempPtr
;
383 return EFI_NOT_FOUND
;
390 IN CONST EFI_PEI_SERVICES
**PeiServices
,
391 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyList
397 Install a notification for a given PPI.
401 PeiServices - Pointer to the PEI Service Table
402 NotifyList - Pointer to list of Descriptors to notify upon.
406 Status - EFI_SUCCESS if successful
407 EFI_OUT_OF_RESOURCES if no space in the database
408 EFI_INVALID_PARAMETER if not a good decriptor
412 PEI_CORE_INSTANCE
*PrivateData
;
415 INTN LastCallbackNotify
;
416 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyPtr
;
417 UINTN NotifyDispatchCount
;
420 NotifyDispatchCount
= 0;
422 if (NotifyList
== NULL
) {
423 return EFI_INVALID_PARAMETER
;
426 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
428 Index
= PrivateData
->PpiData
.NotifyListEnd
;
429 LastCallbackNotify
= Index
;
432 // This is loop installs all Notify descriptors in the NotifyList. It is
433 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
434 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.
439 // Since PpiData is used for NotifyList and InstallList, max resource
440 // is reached if the Install reaches the PpiList
442 if (Index
== PrivateData
->PpiData
.PpiListEnd
- 1) {
443 return EFI_OUT_OF_RESOURCES
;
447 // If some of the PPI data is invalid restore original Notify PPI database value
449 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES
) == 0) {
450 PrivateData
->PpiData
.NotifyListEnd
= LastCallbackNotify
;
451 DEBUG((EFI_D_ERROR
, "ERROR -> InstallNotify: %g %x\n", NotifyList
->Guid
, NotifyList
->Notify
));
452 return EFI_INVALID_PARAMETER
;
455 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
456 NotifyDispatchCount
++;
459 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= (EFI_PEI_NOTIFY_DESCRIPTOR
*) NotifyList
;
461 PrivateData
->PpiData
.NotifyListEnd
--;
462 DEBUG((EFI_D_INFO
, "Register PPI Notify: %g\n", NotifyList
->Guid
));
463 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
464 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
468 // Go the next descriptor. Remember the NotifyList moves down.
475 // If there is Dispatch Notify PPI installed put them on the bottom
477 if (NotifyDispatchCount
> 0) {
478 for (NotifyIndex
= LastCallbackNotify
; NotifyIndex
> PrivateData
->PpiData
.NotifyListEnd
; NotifyIndex
--) {
479 if ((PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
480 NotifyPtr
= PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
;
482 for (Index
= NotifyIndex
; Index
< PrivateData
->PpiData
.DispatchListEnd
; Index
++){
483 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= PrivateData
->PpiData
.PpiListPtrs
[Index
+ 1].Notify
;
485 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= NotifyPtr
;
486 PrivateData
->PpiData
.DispatchListEnd
--;
490 LastCallbackNotify
-= NotifyDispatchCount
;
494 // Dispatch any callback level notifies for all previously installed PPIs.
498 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
500 PrivateData
->PpiData
.PpiListEnd
,
502 PrivateData
->PpiData
.NotifyListEnd
512 IN PEI_CORE_INSTANCE
*PrivateData
518 Process the Notify List at dispatch level.
522 PeiServices - Pointer to the PEI Service Table
533 // Check if the PEIM that was just dispatched resulted in any
534 // Notifies getting installed. If so, go process any dispatch
535 // level Notifies that match the previouly installed PPIs.
536 // Use "while" instead of "if" since DispatchNotify can modify
537 // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.
539 while (PrivateData
->PpiData
.LastDispatchedNotify
!= PrivateData
->PpiData
.DispatchListEnd
) {
540 TempValue
= PrivateData
->PpiData
.DispatchListEnd
;
543 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
545 PrivateData
->PpiData
.LastDispatchedInstall
,
546 PrivateData
->PpiData
.LastDispatchedNotify
,
547 PrivateData
->PpiData
.DispatchListEnd
549 PrivateData
->PpiData
.LastDispatchedNotify
= TempValue
;
554 // Check if the PEIM that was just dispatched resulted in any
555 // PPIs getting installed. If so, go process any dispatch
556 // level Notifies that match the installed PPIs.
557 // Use "while" instead of "if" since DispatchNotify can modify
558 // PpiListEnd (with InstallPpi) so we have to iterate until the same.
560 while (PrivateData
->PpiData
.LastDispatchedInstall
!= PrivateData
->PpiData
.PpiListEnd
) {
561 TempValue
= PrivateData
->PpiData
.PpiListEnd
;
564 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
565 PrivateData
->PpiData
.LastDispatchedInstall
,
566 PrivateData
->PpiData
.PpiListEnd
,
567 FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1,
568 PrivateData
->PpiData
.DispatchListEnd
570 PrivateData
->PpiData
.LastDispatchedInstall
= TempValue
;
573 if (PrivateData
->PpiData
.LastDispatchedNotify
== PrivateData
->PpiData
.DispatchListEnd
) {
582 IN PEI_CORE_INSTANCE
*PrivateData
,
584 IN INTN InstallStartIndex
,
585 IN INTN InstallStopIndex
,
586 IN INTN NotifyStartIndex
,
587 IN INTN NotifyStopIndex
593 Dispatch notifications.
597 PeiServices - Pointer to the PEI Service Table
598 NotifyType - Type of notify to fire.
599 InstallStartIndex - Install Beginning index.
600 InstallStopIndex - Install Ending index.
601 NotifyStartIndex - Notify Beginning index.
602 NotifyStopIndex - Notify Ending index.
611 EFI_GUID
*SearchGuid
;
613 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
;
616 // Remember that Installs moves up and Notifies moves down.
618 for (Index1
= NotifyStartIndex
; Index1
> NotifyStopIndex
; Index1
--) {
619 NotifyDescriptor
= PrivateData
->PpiData
.PpiListPtrs
[Index1
].Notify
;
621 CheckGuid
= NotifyDescriptor
->Guid
;
623 for (Index2
= InstallStartIndex
; Index2
< InstallStopIndex
; Index2
++) {
624 SearchGuid
= PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
->Guid
;
626 // Don't use CompareGuid function here for performance reasons.
627 // Instead we compare the GUID as INT32 at a time and branch
628 // on the first failed comparison.
630 if ((((INT32
*)SearchGuid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
631 (((INT32
*)SearchGuid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
632 (((INT32
*)SearchGuid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
633 (((INT32
*)SearchGuid
)[3] == ((INT32
*)CheckGuid
)[3])) {
634 DEBUG ((EFI_D_INFO
, "Notify: PPI Guid: %g, Peim notify entry point: %x\n",
636 NotifyDescriptor
->Notify
638 NotifyDescriptor
->Notify (
639 GetPeiServicesTablePointer (),
641 (PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
)->Ppi