2 EFI PEI Core PPI services
4 Copyright (c) 2006, Intel Corporation
5 All rights reserved. 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.
22 @param PrivateData Pointer to the PEI Core data.
23 @param OldCoreData Pointer to old PEI Core data.
24 NULL if being run in non-permament memory mode.
28 InitializePpiServices (
29 IN PEI_CORE_INSTANCE
*PrivateData
,
30 IN PEI_CORE_INSTANCE
*OldCoreData
33 if (OldCoreData
== NULL
) {
34 PrivateData
->PpiData
.NotifyListEnd
= FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1;
35 PrivateData
->PpiData
.DispatchListEnd
= FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1;
36 PrivateData
->PpiData
.LastDispatchedNotify
= FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1;
42 Migrate the Hob list from the CAR stack to PEI installed memory.
44 @param PeiServices The PEI core services table.
45 @param OldCheckingBottom The old checking bottom.
46 @param OldCheckingTop The old checking top.
47 @param NewHandOffHob The new handoff HOB list.
52 IN CONST EFI_PEI_SERVICES
**PeiServices
,
53 IN UINTN OldCheckingBottom
,
54 IN UINTN OldCheckingTop
,
55 IN EFI_HOB_HANDOFF_INFO_TABLE
*NewHandOffHob
58 PEI_CORE_INSTANCE
*PrivateData
;
60 PEI_PPI_LIST_POINTERS
*PpiPointer
;
63 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
65 Fixup
= (UINTN
)NewHandOffHob
- OldCheckingBottom
;
67 for (Index
= 0; Index
< FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
); Index
++) {
68 if (Index
< PrivateData
->PpiData
.PpiListEnd
||
69 Index
> PrivateData
->PpiData
.NotifyListEnd
) {
70 PpiPointer
= &PrivateData
->PpiData
.PpiListPtrs
[Index
];
72 if (((UINTN
)PpiPointer
->Raw
< OldCheckingTop
) &&
73 ((UINTN
)PpiPointer
->Raw
>= OldCheckingBottom
)) {
75 // Convert the pointer to the PEIM descriptor from the old HOB heap
76 // to the relocated HOB heap.
78 PpiPointer
->Raw
= (VOID
*) ((UINTN
)PpiPointer
->Raw
+ Fixup
);
81 // Only when the PEIM descriptor is in the old HOB should it be necessary
82 // to try to convert the pointers in the PEIM descriptor
85 if (((UINTN
)PpiPointer
->Ppi
->Guid
< OldCheckingTop
) &&
86 ((UINTN
)PpiPointer
->Ppi
->Guid
>= OldCheckingBottom
)) {
88 // Convert the pointer to the GUID in the PPI or NOTIFY descriptor
89 // from the old HOB heap to the relocated HOB heap.
91 PpiPointer
->Ppi
->Guid
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Guid
+ Fixup
);
95 // Assume that no code is located in the temporary memory, so the pointer to
96 // the notification function in the NOTIFY descriptor needs not be converted.
98 if (Index
< PrivateData
->PpiData
.PpiListEnd
&&
99 (UINTN
)PpiPointer
->Ppi
->Ppi
< OldCheckingTop
&&
100 (UINTN
)PpiPointer
->Ppi
->Ppi
>= OldCheckingBottom
) {
102 // Convert the pointer to the PPI interface structure in the PPI descriptor
103 // from the old HOB heap to the relocated HOB heap.
105 PpiPointer
->Ppi
->Ppi
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Ppi
+ Fixup
);
114 Install PPI services.
116 @param PeiServices - Pointer to the PEI Service Table
117 @param PpiList - Pointer to a list of PEI PPI Descriptors.
119 @retval EFI_SUCCESS - if all PPIs in PpiList are successfully installed.
120 @retval EFI_INVALID_PARAMETER - if PpiList is NULL pointer
121 @retval EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid
122 @retval EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI
128 IN CONST EFI_PEI_SERVICES
**PeiServices
,
129 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
132 PEI_CORE_INSTANCE
*PrivateData
;
134 INTN LastCallbackInstall
;
137 if (PpiList
== NULL
) {
138 return EFI_INVALID_PARAMETER
;
141 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
143 Index
= PrivateData
->PpiData
.PpiListEnd
;
144 LastCallbackInstall
= Index
;
147 // This is loop installs all PPI descriptors in the PpiList. It is terminated
148 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
149 // EFI_PEI_PPI_DESCRIPTOR in the list.
154 // Since PpiData is used for NotifyList and InstallList, max resource
155 // is reached if the Install reaches the NotifyList
157 if (Index
== PrivateData
->PpiData
.NotifyListEnd
+ 1) {
158 return EFI_OUT_OF_RESOURCES
;
161 // Check if it is a valid PPI.
162 // If not, rollback list to exclude all in this list.
163 // Try to indicate which item failed.
165 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
166 PrivateData
->PpiData
.PpiListEnd
= LastCallbackInstall
;
167 DEBUG((EFI_D_ERROR
, "ERROR -> InstallPpi: %g %x\n", PpiList
->Guid
, PpiList
->Ppi
));
168 return EFI_INVALID_PARAMETER
;
171 DEBUG((EFI_D_INFO
, "Install PPI: %g\n", PpiList
->Guid
));
172 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*) PpiList
;
173 PrivateData
->PpiData
.PpiListEnd
++;
176 // Continue until the end of the PPI List.
178 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
179 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
187 // Dispatch any callback level notifies for newly installed PPIs.
191 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
193 PrivateData
->PpiData
.PpiListEnd
,
194 PrivateData
->PpiData
.DispatchListEnd
,
195 PrivateData
->PpiData
.NotifyListEnd
204 Re-Install PPI services.
206 @param PeiServices - Pointer to the PEI Service Table
207 @param OldPpi - Pointer to the old PEI PPI Descriptors.
208 @param NewPpi - Pointer to the new PEI PPI Descriptors.
210 @retval EFI_SUCCESS - if the operation was successful
211 @retval EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL
212 @retval EFI_INVALID_PARAMETER - if NewPpi is not valid
213 @retval EFI_NOT_FOUND - if the PPI was not in the database
219 IN CONST EFI_PEI_SERVICES
**PeiServices
,
220 IN CONST EFI_PEI_PPI_DESCRIPTOR
*OldPpi
,
221 IN CONST EFI_PEI_PPI_DESCRIPTOR
*NewPpi
224 PEI_CORE_INSTANCE
*PrivateData
;
228 if ((OldPpi
== NULL
) || (NewPpi
== NULL
)) {
229 return EFI_INVALID_PARAMETER
;
232 if ((NewPpi
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
233 return EFI_INVALID_PARAMETER
;
236 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
239 // Find the old PPI instance in the database. If we can not find it,
240 // return the EFI_NOT_FOUND error.
242 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
243 if (OldPpi
== PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
) {
247 if (Index
== PrivateData
->PpiData
.PpiListEnd
) {
248 return EFI_NOT_FOUND
;
252 // Remove the old PPI from the database, add the new one.
254 DEBUG((EFI_D_INFO
, "Reinstall PPI: %g\n", NewPpi
->Guid
));
255 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*) NewPpi
;
258 // Dispatch any callback level notifies for the newly installed PPI.
262 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
265 PrivateData
->PpiData
.DispatchListEnd
,
266 PrivateData
->PpiData
.NotifyListEnd
275 Locate a given named PPI.
278 @param PeiServices - Pointer to the PEI Service Table
279 @param Guid - Pointer to GUID of the PPI.
280 @param Instance - Instance Number to discover.
281 @param PpiDescriptor - Pointer to reference the found descriptor. If not NULL,
282 returns a pointer to the descriptor (includes flags, etc)
283 @param Ppi - Pointer to reference the found PPI
285 @retval EFI_SUCCESS if the PPI is in the database
286 @retval EFI_NOT_FOUND if the PPI is not in the database
292 IN CONST EFI_PEI_SERVICES
**PeiServices
,
293 IN CONST EFI_GUID
*Guid
,
295 IN OUT EFI_PEI_PPI_DESCRIPTOR
**PpiDescriptor
,
299 PEI_CORE_INSTANCE
*PrivateData
;
302 EFI_PEI_PPI_DESCRIPTOR
*TempPtr
;
305 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
308 // Search the data base for the matching instance of the GUIDed PPI.
310 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
311 TempPtr
= PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
;
312 CheckGuid
= TempPtr
->Guid
;
315 // Don't use CompareGuid function here for performance reasons.
316 // Instead we compare the GUID as INT32 at a time and branch
317 // on the first failed comparison.
319 if ((((INT32
*)Guid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
320 (((INT32
*)Guid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
321 (((INT32
*)Guid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
322 (((INT32
*)Guid
)[3] == ((INT32
*)CheckGuid
)[3])) {
325 if (PpiDescriptor
!= NULL
) {
326 *PpiDescriptor
= TempPtr
;
340 return EFI_NOT_FOUND
;
345 Install a notification for a given PPI.
348 @param PeiServices - Pointer to the PEI Service Table
349 @param NotifyList - Pointer to list of Descriptors to notify upon.
351 @retval EFI_SUCCESS if successful
352 @retval EFI_OUT_OF_RESOURCES if no space in the database
353 @retval EFI_INVALID_PARAMETER if not a good decriptor
359 IN CONST EFI_PEI_SERVICES
**PeiServices
,
360 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyList
363 PEI_CORE_INSTANCE
*PrivateData
;
366 INTN LastCallbackNotify
;
367 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyPtr
;
368 UINTN NotifyDispatchCount
;
371 NotifyDispatchCount
= 0;
373 if (NotifyList
== NULL
) {
374 return EFI_INVALID_PARAMETER
;
377 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
379 Index
= PrivateData
->PpiData
.NotifyListEnd
;
380 LastCallbackNotify
= Index
;
383 // This is loop installs all Notify descriptors in the NotifyList. It is
384 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
385 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.
390 // Since PpiData is used for NotifyList and InstallList, max resource
391 // is reached if the Install reaches the PpiList
393 if (Index
== PrivateData
->PpiData
.PpiListEnd
- 1) {
394 return EFI_OUT_OF_RESOURCES
;
398 // If some of the PPI data is invalid restore original Notify PPI database value
400 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES
) == 0) {
401 PrivateData
->PpiData
.NotifyListEnd
= LastCallbackNotify
;
402 DEBUG((EFI_D_ERROR
, "ERROR -> InstallNotify: %g %x\n", NotifyList
->Guid
, NotifyList
->Notify
));
403 return EFI_INVALID_PARAMETER
;
406 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
407 NotifyDispatchCount
++;
410 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= (EFI_PEI_NOTIFY_DESCRIPTOR
*) NotifyList
;
412 PrivateData
->PpiData
.NotifyListEnd
--;
413 DEBUG((EFI_D_INFO
, "Register PPI Notify: %g\n", NotifyList
->Guid
));
414 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
415 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
419 // Go the next descriptor. Remember the NotifyList moves down.
426 // If there is Dispatch Notify PPI installed put them on the bottom
428 if (NotifyDispatchCount
> 0) {
429 for (NotifyIndex
= LastCallbackNotify
; NotifyIndex
> PrivateData
->PpiData
.NotifyListEnd
; NotifyIndex
--) {
430 if ((PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
431 NotifyPtr
= PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
;
433 for (Index
= NotifyIndex
; Index
< PrivateData
->PpiData
.DispatchListEnd
; Index
++){
434 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= PrivateData
->PpiData
.PpiListPtrs
[Index
+ 1].Notify
;
436 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= NotifyPtr
;
437 PrivateData
->PpiData
.DispatchListEnd
--;
441 LastCallbackNotify
-= NotifyDispatchCount
;
445 // Dispatch any callback level notifies for all previously installed PPIs.
449 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
451 PrivateData
->PpiData
.PpiListEnd
,
453 PrivateData
->PpiData
.NotifyListEnd
463 Process the Notify List at dispatch level.
465 @param PrivateData PeiCore's private data structure.
470 IN PEI_CORE_INSTANCE
*PrivateData
477 // Check if the PEIM that was just dispatched resulted in any
478 // Notifies getting installed. If so, go process any dispatch
479 // level Notifies that match the previouly installed PPIs.
480 // Use "while" instead of "if" since DispatchNotify can modify
481 // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.
483 while (PrivateData
->PpiData
.LastDispatchedNotify
!= PrivateData
->PpiData
.DispatchListEnd
) {
484 TempValue
= PrivateData
->PpiData
.DispatchListEnd
;
487 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
489 PrivateData
->PpiData
.LastDispatchedInstall
,
490 PrivateData
->PpiData
.LastDispatchedNotify
,
491 PrivateData
->PpiData
.DispatchListEnd
493 PrivateData
->PpiData
.LastDispatchedNotify
= TempValue
;
498 // Check if the PEIM that was just dispatched resulted in any
499 // PPIs getting installed. If so, go process any dispatch
500 // level Notifies that match the installed PPIs.
501 // Use "while" instead of "if" since DispatchNotify can modify
502 // PpiListEnd (with InstallPpi) so we have to iterate until the same.
504 while (PrivateData
->PpiData
.LastDispatchedInstall
!= PrivateData
->PpiData
.PpiListEnd
) {
505 TempValue
= PrivateData
->PpiData
.PpiListEnd
;
508 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
509 PrivateData
->PpiData
.LastDispatchedInstall
,
510 PrivateData
->PpiData
.PpiListEnd
,
511 FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1,
512 PrivateData
->PpiData
.DispatchListEnd
514 PrivateData
->PpiData
.LastDispatchedInstall
= TempValue
;
517 if (PrivateData
->PpiData
.LastDispatchedNotify
== PrivateData
->PpiData
.DispatchListEnd
) {
526 Dispatch notifications.
528 @param PrivateData PeiCore's private data structure
529 @param NotifyType Type of notify to fire.
530 @param InstallStartIndex Install Beginning index.
531 @param InstallStopIndex Install Ending index.
532 @param NotifyStartIndex Notify Beginning index.
533 @param NotifyStopIndex Notify Ending index.
538 IN PEI_CORE_INSTANCE
*PrivateData
,
540 IN INTN InstallStartIndex
,
541 IN INTN InstallStopIndex
,
542 IN INTN NotifyStartIndex
,
543 IN INTN NotifyStopIndex
548 EFI_GUID
*SearchGuid
;
550 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
;
553 // Remember that Installs moves up and Notifies moves down.
555 for (Index1
= NotifyStartIndex
; Index1
> NotifyStopIndex
; Index1
--) {
556 NotifyDescriptor
= PrivateData
->PpiData
.PpiListPtrs
[Index1
].Notify
;
558 CheckGuid
= NotifyDescriptor
->Guid
;
560 for (Index2
= InstallStartIndex
; Index2
< InstallStopIndex
; Index2
++) {
561 SearchGuid
= PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
->Guid
;
563 // Don't use CompareGuid function here for performance reasons.
564 // Instead we compare the GUID as INT32 at a time and branch
565 // on the first failed comparison.
567 if ((((INT32
*)SearchGuid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
568 (((INT32
*)SearchGuid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
569 (((INT32
*)SearchGuid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
570 (((INT32
*)SearchGuid
)[3] == ((INT32
*)CheckGuid
)[3])) {
571 DEBUG ((EFI_D_INFO
, "Notify: PPI Guid: %g, Peim notify entry point: %x\n",
573 NotifyDescriptor
->Notify
575 NotifyDescriptor
->Notify (
576 GetPeiServicesTablePointer (),
578 (PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
)->Ppi