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 Fixup The address difference between
48 the new Hob list and old Hob list.
53 IN CONST EFI_PEI_SERVICES
**PeiServices
,
54 IN UINTN OldCheckingBottom
,
55 IN UINTN OldCheckingTop
,
59 PEI_CORE_INSTANCE
*PrivateData
;
61 PEI_PPI_LIST_POINTERS
*PpiPointer
;
63 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
65 for (Index
= 0; Index
< FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
); Index
++) {
66 if (Index
< PrivateData
->PpiData
.PpiListEnd
||
67 Index
> PrivateData
->PpiData
.NotifyListEnd
) {
68 PpiPointer
= &PrivateData
->PpiData
.PpiListPtrs
[Index
];
70 if (((UINTN
)PpiPointer
->Raw
< OldCheckingTop
) &&
71 ((UINTN
)PpiPointer
->Raw
>= OldCheckingBottom
)) {
73 // Convert the pointer to the PEIM descriptor from the old HOB heap
74 // to the relocated HOB heap.
76 PpiPointer
->Raw
= (VOID
*) ((UINTN
)PpiPointer
->Raw
+ Fixup
);
79 // Only when the PEIM descriptor is in the old HOB should it be necessary
80 // to try to convert the pointers in the PEIM descriptor
83 if (((UINTN
)PpiPointer
->Ppi
->Guid
< OldCheckingTop
) &&
84 ((UINTN
)PpiPointer
->Ppi
->Guid
>= OldCheckingBottom
)) {
86 // Convert the pointer to the GUID in the PPI or NOTIFY descriptor
87 // from the old HOB heap to the relocated HOB heap.
89 PpiPointer
->Ppi
->Guid
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Guid
+ Fixup
);
93 // Assume that no code is located in the temporary memory, so the pointer to
94 // the notification function in the NOTIFY descriptor needs not be converted.
96 if (Index
< PrivateData
->PpiData
.PpiListEnd
&&
97 (UINTN
)PpiPointer
->Ppi
->Ppi
< OldCheckingTop
&&
98 (UINTN
)PpiPointer
->Ppi
->Ppi
>= OldCheckingBottom
) {
100 // Convert the pointer to the PPI interface structure in the PPI descriptor
101 // from the old HOB heap to the relocated HOB heap.
103 PpiPointer
->Ppi
->Ppi
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Ppi
+ Fixup
);
112 Install PPI services.
114 @param PeiServices - Pointer to the PEI Service Table
115 @param PpiList - Pointer to a list of PEI PPI Descriptors.
117 @retval EFI_SUCCESS - if all PPIs in PpiList are successfully installed.
118 @retval EFI_INVALID_PARAMETER - if PpiList is NULL pointer
119 @retval EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid
120 @retval EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI
126 IN CONST EFI_PEI_SERVICES
**PeiServices
,
127 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
130 PEI_CORE_INSTANCE
*PrivateData
;
132 INTN LastCallbackInstall
;
135 if (PpiList
== NULL
) {
136 return EFI_INVALID_PARAMETER
;
139 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
141 Index
= PrivateData
->PpiData
.PpiListEnd
;
142 LastCallbackInstall
= Index
;
145 // This is loop installs all PPI descriptors in the PpiList. It is terminated
146 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
147 // EFI_PEI_PPI_DESCRIPTOR in the list.
152 // Since PpiData is used for NotifyList and InstallList, max resource
153 // is reached if the Install reaches the NotifyList
155 if (Index
== PrivateData
->PpiData
.NotifyListEnd
+ 1) {
156 return EFI_OUT_OF_RESOURCES
;
159 // Check if it is a valid PPI.
160 // If not, rollback list to exclude all in this list.
161 // Try to indicate which item failed.
163 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
164 PrivateData
->PpiData
.PpiListEnd
= LastCallbackInstall
;
165 DEBUG((EFI_D_ERROR
, "ERROR -> InstallPpi: %g %x\n", PpiList
->Guid
, PpiList
->Ppi
));
166 return EFI_INVALID_PARAMETER
;
169 DEBUG((EFI_D_INFO
, "Install PPI: %g\n", PpiList
->Guid
));
170 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*) PpiList
;
171 PrivateData
->PpiData
.PpiListEnd
++;
174 // Continue until the end of the PPI List.
176 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
177 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
185 // Dispatch any callback level notifies for newly installed PPIs.
189 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
191 PrivateData
->PpiData
.PpiListEnd
,
192 PrivateData
->PpiData
.DispatchListEnd
,
193 PrivateData
->PpiData
.NotifyListEnd
202 Re-Install PPI services.
204 @param PeiServices - Pointer to the PEI Service Table
205 @param OldPpi - Pointer to the old PEI PPI Descriptors.
206 @param NewPpi - Pointer to the new PEI PPI Descriptors.
208 @retval EFI_SUCCESS - if the operation was successful
209 @retval EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL
210 @retval EFI_INVALID_PARAMETER - if NewPpi is not valid
211 @retval EFI_NOT_FOUND - if the PPI was not in the database
217 IN CONST EFI_PEI_SERVICES
**PeiServices
,
218 IN CONST EFI_PEI_PPI_DESCRIPTOR
*OldPpi
,
219 IN CONST EFI_PEI_PPI_DESCRIPTOR
*NewPpi
222 PEI_CORE_INSTANCE
*PrivateData
;
226 if ((OldPpi
== NULL
) || (NewPpi
== NULL
)) {
227 return EFI_INVALID_PARAMETER
;
230 if ((NewPpi
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
231 return EFI_INVALID_PARAMETER
;
234 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
237 // Find the old PPI instance in the database. If we can not find it,
238 // return the EFI_NOT_FOUND error.
240 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
241 if (OldPpi
== PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
) {
245 if (Index
== PrivateData
->PpiData
.PpiListEnd
) {
246 return EFI_NOT_FOUND
;
250 // Remove the old PPI from the database, add the new one.
252 DEBUG((EFI_D_INFO
, "Reinstall PPI: %g\n", NewPpi
->Guid
));
253 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*) NewPpi
;
256 // Dispatch any callback level notifies for the newly installed PPI.
260 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
263 PrivateData
->PpiData
.DispatchListEnd
,
264 PrivateData
->PpiData
.NotifyListEnd
273 Locate a given named PPI.
276 @param PeiServices - Pointer to the PEI Service Table
277 @param Guid - Pointer to GUID of the PPI.
278 @param Instance - Instance Number to discover.
279 @param PpiDescriptor - Pointer to reference the found descriptor. If not NULL,
280 returns a pointer to the descriptor (includes flags, etc)
281 @param Ppi - Pointer to reference the found PPI
283 @retval EFI_SUCCESS if the PPI is in the database
284 @retval EFI_NOT_FOUND if the PPI is not in the database
290 IN CONST EFI_PEI_SERVICES
**PeiServices
,
291 IN CONST EFI_GUID
*Guid
,
293 IN OUT EFI_PEI_PPI_DESCRIPTOR
**PpiDescriptor
,
297 PEI_CORE_INSTANCE
*PrivateData
;
300 EFI_PEI_PPI_DESCRIPTOR
*TempPtr
;
303 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
306 // Search the data base for the matching instance of the GUIDed PPI.
308 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
309 TempPtr
= PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
;
310 CheckGuid
= TempPtr
->Guid
;
313 // Don't use CompareGuid function here for performance reasons.
314 // Instead we compare the GUID as INT32 at a time and branch
315 // on the first failed comparison.
317 if ((((INT32
*)Guid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
318 (((INT32
*)Guid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
319 (((INT32
*)Guid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
320 (((INT32
*)Guid
)[3] == ((INT32
*)CheckGuid
)[3])) {
323 if (PpiDescriptor
!= NULL
) {
324 *PpiDescriptor
= TempPtr
;
338 return EFI_NOT_FOUND
;
343 Install a notification for a given PPI.
346 @param PeiServices - Pointer to the PEI Service Table
347 @param NotifyList - Pointer to list of Descriptors to notify upon.
349 @retval EFI_SUCCESS if successful
350 @retval EFI_OUT_OF_RESOURCES if no space in the database
351 @retval EFI_INVALID_PARAMETER if not a good decriptor
357 IN CONST EFI_PEI_SERVICES
**PeiServices
,
358 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyList
361 PEI_CORE_INSTANCE
*PrivateData
;
364 INTN LastCallbackNotify
;
365 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyPtr
;
366 UINTN NotifyDispatchCount
;
369 NotifyDispatchCount
= 0;
371 if (NotifyList
== NULL
) {
372 return EFI_INVALID_PARAMETER
;
375 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
377 Index
= PrivateData
->PpiData
.NotifyListEnd
;
378 LastCallbackNotify
= Index
;
381 // This is loop installs all Notify descriptors in the NotifyList. It is
382 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
383 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.
388 // Since PpiData is used for NotifyList and InstallList, max resource
389 // is reached if the Install reaches the PpiList
391 if (Index
== PrivateData
->PpiData
.PpiListEnd
- 1) {
392 return EFI_OUT_OF_RESOURCES
;
396 // If some of the PPI data is invalid restore original Notify PPI database value
398 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES
) == 0) {
399 PrivateData
->PpiData
.NotifyListEnd
= LastCallbackNotify
;
400 DEBUG((EFI_D_ERROR
, "ERROR -> InstallNotify: %g %x\n", NotifyList
->Guid
, NotifyList
->Notify
));
401 return EFI_INVALID_PARAMETER
;
404 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
405 NotifyDispatchCount
++;
408 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= (EFI_PEI_NOTIFY_DESCRIPTOR
*) NotifyList
;
410 PrivateData
->PpiData
.NotifyListEnd
--;
411 DEBUG((EFI_D_INFO
, "Register PPI Notify: %g\n", NotifyList
->Guid
));
412 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
413 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
417 // Go the next descriptor. Remember the NotifyList moves down.
424 // If there is Dispatch Notify PPI installed put them on the bottom
426 if (NotifyDispatchCount
> 0) {
427 for (NotifyIndex
= LastCallbackNotify
; NotifyIndex
> PrivateData
->PpiData
.NotifyListEnd
; NotifyIndex
--) {
428 if ((PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
429 NotifyPtr
= PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
;
431 for (Index
= NotifyIndex
; Index
< PrivateData
->PpiData
.DispatchListEnd
; Index
++){
432 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= PrivateData
->PpiData
.PpiListPtrs
[Index
+ 1].Notify
;
434 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= NotifyPtr
;
435 PrivateData
->PpiData
.DispatchListEnd
--;
439 LastCallbackNotify
-= NotifyDispatchCount
;
443 // Dispatch any callback level notifies for all previously installed PPIs.
447 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
449 PrivateData
->PpiData
.PpiListEnd
,
451 PrivateData
->PpiData
.NotifyListEnd
461 Process the Notify List at dispatch level.
463 @param PrivateData PeiCore's private data structure.
468 IN PEI_CORE_INSTANCE
*PrivateData
475 // Check if the PEIM that was just dispatched resulted in any
476 // Notifies getting installed. If so, go process any dispatch
477 // level Notifies that match the previouly installed PPIs.
478 // Use "while" instead of "if" since DispatchNotify can modify
479 // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.
481 while (PrivateData
->PpiData
.LastDispatchedNotify
!= PrivateData
->PpiData
.DispatchListEnd
) {
482 TempValue
= PrivateData
->PpiData
.DispatchListEnd
;
485 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
487 PrivateData
->PpiData
.LastDispatchedInstall
,
488 PrivateData
->PpiData
.LastDispatchedNotify
,
489 PrivateData
->PpiData
.DispatchListEnd
491 PrivateData
->PpiData
.LastDispatchedNotify
= TempValue
;
496 // Check if the PEIM that was just dispatched resulted in any
497 // PPIs getting installed. If so, go process any dispatch
498 // level Notifies that match the installed PPIs.
499 // Use "while" instead of "if" since DispatchNotify can modify
500 // PpiListEnd (with InstallPpi) so we have to iterate until the same.
502 while (PrivateData
->PpiData
.LastDispatchedInstall
!= PrivateData
->PpiData
.PpiListEnd
) {
503 TempValue
= PrivateData
->PpiData
.PpiListEnd
;
506 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
507 PrivateData
->PpiData
.LastDispatchedInstall
,
508 PrivateData
->PpiData
.PpiListEnd
,
509 FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1,
510 PrivateData
->PpiData
.DispatchListEnd
512 PrivateData
->PpiData
.LastDispatchedInstall
= TempValue
;
515 if (PrivateData
->PpiData
.LastDispatchedNotify
== PrivateData
->PpiData
.DispatchListEnd
) {
524 Dispatch notifications.
526 @param PrivateData PeiCore's private data structure
527 @param NotifyType Type of notify to fire.
528 @param InstallStartIndex Install Beginning index.
529 @param InstallStopIndex Install Ending index.
530 @param NotifyStartIndex Notify Beginning index.
531 @param NotifyStopIndex Notify Ending index.
536 IN PEI_CORE_INSTANCE
*PrivateData
,
538 IN INTN InstallStartIndex
,
539 IN INTN InstallStopIndex
,
540 IN INTN NotifyStartIndex
,
541 IN INTN NotifyStopIndex
546 EFI_GUID
*SearchGuid
;
548 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
;
551 // Remember that Installs moves up and Notifies moves down.
553 for (Index1
= NotifyStartIndex
; Index1
> NotifyStopIndex
; Index1
--) {
554 NotifyDescriptor
= PrivateData
->PpiData
.PpiListPtrs
[Index1
].Notify
;
556 CheckGuid
= NotifyDescriptor
->Guid
;
558 for (Index2
= InstallStartIndex
; Index2
< InstallStopIndex
; Index2
++) {
559 SearchGuid
= PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
->Guid
;
561 // Don't use CompareGuid function here for performance reasons.
562 // Instead we compare the GUID as INT32 at a time and branch
563 // on the first failed comparison.
565 if ((((INT32
*)SearchGuid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
566 (((INT32
*)SearchGuid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
567 (((INT32
*)SearchGuid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
568 (((INT32
*)SearchGuid
)[3] == ((INT32
*)CheckGuid
)[3])) {
569 DEBUG ((EFI_D_INFO
, "Notify: PPI Guid: %g, Peim notify entry point: %x\n",
571 NotifyDescriptor
->Notify
573 NotifyDescriptor
->Notify (
574 GetPeiServicesTablePointer (),
576 (PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
)->Ppi