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.
21 @param PrivateData Pointer to the PEI Core data.
22 @param OldCoreData Pointer to old PEI Core data.
23 NULL if being run in non-permament memory mode.
27 InitializePpiServices (
28 IN PEI_CORE_INSTANCE
*PrivateData
,
29 IN PEI_CORE_INSTANCE
*OldCoreData
32 if (OldCoreData
== NULL
) {
33 PrivateData
->PpiData
.NotifyListEnd
= FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1;
34 PrivateData
->PpiData
.DispatchListEnd
= FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1;
35 PrivateData
->PpiData
.LastDispatchedNotify
= FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1;
41 Migrate the Hob list from the CAR stack to PEI installed memory.
43 @param PeiServices The PEI core services table.
44 @param OldCheckingBottom The old checking bottom.
45 @param OldCheckingTop The old checking top.
46 @param Fixup The address difference between
47 the new Hob list and old Hob list.
52 IN PEI_CORE_INSTANCE
*PrivateData
,
53 IN UINTN OldCheckingBottom
,
54 IN UINTN OldCheckingTop
,
59 PEI_PPI_LIST_POINTERS
*PpiPointer
;
61 for (Index
= 0; Index
< FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
); Index
++) {
62 if (Index
< PrivateData
->PpiData
.PpiListEnd
||
63 Index
> PrivateData
->PpiData
.NotifyListEnd
) {
64 PpiPointer
= &PrivateData
->PpiData
.PpiListPtrs
[Index
];
66 if (((UINTN
)PpiPointer
->Raw
< OldCheckingTop
) &&
67 ((UINTN
)PpiPointer
->Raw
>= OldCheckingBottom
)) {
69 // Convert the pointer to the PEIM descriptor from the old HOB heap
70 // to the relocated HOB heap.
72 PpiPointer
->Raw
= (VOID
*) ((UINTN
)PpiPointer
->Raw
+ Fixup
);
75 // Only when the PEIM descriptor is in the old HOB should it be necessary
76 // to try to convert the pointers in the PEIM descriptor
79 if (((UINTN
)PpiPointer
->Ppi
->Guid
< OldCheckingTop
) &&
80 ((UINTN
)PpiPointer
->Ppi
->Guid
>= OldCheckingBottom
)) {
82 // Convert the pointer to the GUID in the PPI or NOTIFY descriptor
83 // from the old HOB heap to the relocated HOB heap.
85 PpiPointer
->Ppi
->Guid
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Guid
+ Fixup
);
89 // Assume that no code is located in the temporary memory, so the pointer to
90 // the notification function in the NOTIFY descriptor needs not be converted.
92 if (Index
< PrivateData
->PpiData
.PpiListEnd
&&
93 (UINTN
)PpiPointer
->Ppi
->Ppi
< OldCheckingTop
&&
94 (UINTN
)PpiPointer
->Ppi
->Ppi
>= OldCheckingBottom
) {
96 // Convert the pointer to the PPI interface structure in the PPI descriptor
97 // from the old HOB heap to the relocated HOB heap.
99 PpiPointer
->Ppi
->Ppi
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Ppi
+ Fixup
);
108 Install PPI services.
110 @param PeiServices - Pointer to the PEI Service Table
111 @param PpiList - Pointer to a list of PEI PPI Descriptors.
113 @retval EFI_SUCCESS - if all PPIs in PpiList are successfully installed.
114 @retval EFI_INVALID_PARAMETER - if PpiList is NULL pointer
115 @retval EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid
116 @retval EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI
122 IN CONST EFI_PEI_SERVICES
**PeiServices
,
123 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
126 PEI_CORE_INSTANCE
*PrivateData
;
128 INTN LastCallbackInstall
;
131 if (PpiList
== NULL
) {
132 return EFI_INVALID_PARAMETER
;
135 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
137 Index
= PrivateData
->PpiData
.PpiListEnd
;
138 LastCallbackInstall
= Index
;
141 // This is loop installs all PPI descriptors in the PpiList. It is terminated
142 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
143 // EFI_PEI_PPI_DESCRIPTOR in the list.
148 // Since PpiData is used for NotifyList and InstallList, max resource
149 // is reached if the Install reaches the NotifyList
151 if (Index
== PrivateData
->PpiData
.NotifyListEnd
+ 1) {
152 return EFI_OUT_OF_RESOURCES
;
155 // Check if it is a valid PPI.
156 // If not, rollback list to exclude all in this list.
157 // Try to indicate which item failed.
159 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
160 PrivateData
->PpiData
.PpiListEnd
= LastCallbackInstall
;
161 DEBUG((EFI_D_ERROR
, "ERROR -> InstallPpi: %g %x\n", PpiList
->Guid
, PpiList
->Ppi
));
162 return EFI_INVALID_PARAMETER
;
165 DEBUG((EFI_D_INFO
, "Install PPI: %g\n", PpiList
->Guid
));
166 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*) PpiList
;
167 PrivateData
->PpiData
.PpiListEnd
++;
170 // Continue until the end of the PPI List.
172 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
173 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
181 // Dispatch any callback level notifies for newly installed PPIs.
185 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
187 PrivateData
->PpiData
.PpiListEnd
,
188 PrivateData
->PpiData
.DispatchListEnd
,
189 PrivateData
->PpiData
.NotifyListEnd
198 Re-Install PPI services.
200 @param PeiServices - Pointer to the PEI Service Table
201 @param OldPpi - Pointer to the old PEI PPI Descriptors.
202 @param NewPpi - Pointer to the new PEI PPI Descriptors.
204 @retval EFI_SUCCESS - if the operation was successful
205 @retval EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL
206 @retval EFI_INVALID_PARAMETER - if NewPpi is not valid
207 @retval EFI_NOT_FOUND - if the PPI was not in the database
213 IN CONST EFI_PEI_SERVICES
**PeiServices
,
214 IN CONST EFI_PEI_PPI_DESCRIPTOR
*OldPpi
,
215 IN CONST EFI_PEI_PPI_DESCRIPTOR
*NewPpi
218 PEI_CORE_INSTANCE
*PrivateData
;
222 if ((OldPpi
== NULL
) || (NewPpi
== NULL
)) {
223 return EFI_INVALID_PARAMETER
;
226 if ((NewPpi
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
227 return EFI_INVALID_PARAMETER
;
230 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
233 // Find the old PPI instance in the database. If we can not find it,
234 // return the EFI_NOT_FOUND error.
236 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
237 if (OldPpi
== PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
) {
241 if (Index
== PrivateData
->PpiData
.PpiListEnd
) {
242 return EFI_NOT_FOUND
;
246 // Remove the old PPI from the database, add the new one.
248 DEBUG((EFI_D_INFO
, "Reinstall PPI: %g\n", NewPpi
->Guid
));
249 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*) NewPpi
;
252 // Dispatch any callback level notifies for the newly installed PPI.
256 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
259 PrivateData
->PpiData
.DispatchListEnd
,
260 PrivateData
->PpiData
.NotifyListEnd
269 Locate a given named PPI.
272 @param PeiServices - Pointer to the PEI Service Table
273 @param Guid - Pointer to GUID of the PPI.
274 @param Instance - Instance Number to discover.
275 @param PpiDescriptor - Pointer to reference the found descriptor. If not NULL,
276 returns a pointer to the descriptor (includes flags, etc)
277 @param Ppi - Pointer to reference the found PPI
279 @retval EFI_SUCCESS if the PPI is in the database
280 @retval EFI_NOT_FOUND if the PPI is not in the database
286 IN CONST EFI_PEI_SERVICES
**PeiServices
,
287 IN CONST EFI_GUID
*Guid
,
289 IN OUT EFI_PEI_PPI_DESCRIPTOR
**PpiDescriptor
,
293 PEI_CORE_INSTANCE
*PrivateData
;
296 EFI_PEI_PPI_DESCRIPTOR
*TempPtr
;
299 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
302 // Search the data base for the matching instance of the GUIDed PPI.
304 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
305 TempPtr
= PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
;
306 CheckGuid
= TempPtr
->Guid
;
309 // Don't use CompareGuid function here for performance reasons.
310 // Instead we compare the GUID as INT32 at a time and branch
311 // on the first failed comparison.
313 if ((((INT32
*)Guid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
314 (((INT32
*)Guid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
315 (((INT32
*)Guid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
316 (((INT32
*)Guid
)[3] == ((INT32
*)CheckGuid
)[3])) {
319 if (PpiDescriptor
!= NULL
) {
320 *PpiDescriptor
= TempPtr
;
334 return EFI_NOT_FOUND
;
339 Install a notification for a given PPI.
341 @param PeiServices - Pointer to the PEI Service Table
342 @param NotifyList - Pointer to list of Descriptors to notify upon.
344 @retval EFI_SUCCESS if successful
345 @retval EFI_OUT_OF_RESOURCES if no space in the database
346 @retval EFI_INVALID_PARAMETER if not a good decriptor
352 IN CONST EFI_PEI_SERVICES
**PeiServices
,
353 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyList
356 PEI_CORE_INSTANCE
*PrivateData
;
359 INTN LastCallbackNotify
;
360 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyPtr
;
361 UINTN NotifyDispatchCount
;
364 NotifyDispatchCount
= 0;
366 if (NotifyList
== NULL
) {
367 return EFI_INVALID_PARAMETER
;
370 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
372 Index
= PrivateData
->PpiData
.NotifyListEnd
;
373 LastCallbackNotify
= Index
;
376 // This is loop installs all Notify descriptors in the NotifyList. It is
377 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
378 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.
383 // Since PpiData is used for NotifyList and InstallList, max resource
384 // is reached if the Install reaches the PpiList
386 if (Index
== PrivateData
->PpiData
.PpiListEnd
- 1) {
387 return EFI_OUT_OF_RESOURCES
;
391 // If some of the PPI data is invalid restore original Notify PPI database value
393 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES
) == 0) {
394 PrivateData
->PpiData
.NotifyListEnd
= LastCallbackNotify
;
395 DEBUG((EFI_D_ERROR
, "ERROR -> InstallNotify: %g %x\n", NotifyList
->Guid
, NotifyList
->Notify
));
396 return EFI_INVALID_PARAMETER
;
399 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
400 NotifyDispatchCount
++;
403 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= (EFI_PEI_NOTIFY_DESCRIPTOR
*) NotifyList
;
405 PrivateData
->PpiData
.NotifyListEnd
--;
406 DEBUG((EFI_D_INFO
, "Register PPI Notify: %g\n", NotifyList
->Guid
));
407 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
408 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
412 // Go the next descriptor. Remember the NotifyList moves down.
419 // If there is Dispatch Notify PPI installed put them on the bottom
421 if (NotifyDispatchCount
> 0) {
422 for (NotifyIndex
= LastCallbackNotify
; NotifyIndex
> PrivateData
->PpiData
.NotifyListEnd
; NotifyIndex
--) {
423 if ((PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
424 NotifyPtr
= PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
;
426 for (Index
= NotifyIndex
; Index
< PrivateData
->PpiData
.DispatchListEnd
; Index
++){
427 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= PrivateData
->PpiData
.PpiListPtrs
[Index
+ 1].Notify
;
429 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= NotifyPtr
;
430 PrivateData
->PpiData
.DispatchListEnd
--;
434 LastCallbackNotify
-= NotifyDispatchCount
;
438 // Dispatch any callback level notifies for all previously installed PPIs.
442 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
444 PrivateData
->PpiData
.PpiListEnd
,
446 PrivateData
->PpiData
.NotifyListEnd
455 Process the Notify List at dispatch level.
457 @param PrivateData PeiCore's private data structure.
462 IN PEI_CORE_INSTANCE
*PrivateData
469 // Check if the PEIM that was just dispatched resulted in any
470 // Notifies getting installed. If so, go process any dispatch
471 // level Notifies that match the previouly installed PPIs.
472 // Use "while" instead of "if" since DispatchNotify can modify
473 // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.
475 while (PrivateData
->PpiData
.LastDispatchedNotify
!= PrivateData
->PpiData
.DispatchListEnd
) {
476 TempValue
= PrivateData
->PpiData
.DispatchListEnd
;
479 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
481 PrivateData
->PpiData
.LastDispatchedInstall
,
482 PrivateData
->PpiData
.LastDispatchedNotify
,
483 PrivateData
->PpiData
.DispatchListEnd
485 PrivateData
->PpiData
.LastDispatchedNotify
= TempValue
;
490 // Check if the PEIM that was just dispatched resulted in any
491 // PPIs getting installed. If so, go process any dispatch
492 // level Notifies that match the installed PPIs.
493 // Use "while" instead of "if" since DispatchNotify can modify
494 // PpiListEnd (with InstallPpi) so we have to iterate until the same.
496 while (PrivateData
->PpiData
.LastDispatchedInstall
!= PrivateData
->PpiData
.PpiListEnd
) {
497 TempValue
= PrivateData
->PpiData
.PpiListEnd
;
500 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
501 PrivateData
->PpiData
.LastDispatchedInstall
,
502 PrivateData
->PpiData
.PpiListEnd
,
503 FixedPcdGet32 (PcdPeiCoreMaxPpiSupported
)-1,
504 PrivateData
->PpiData
.DispatchListEnd
506 PrivateData
->PpiData
.LastDispatchedInstall
= TempValue
;
509 if (PrivateData
->PpiData
.LastDispatchedNotify
== PrivateData
->PpiData
.DispatchListEnd
) {
518 Dispatch notifications.
520 @param PrivateData PeiCore's private data structure
521 @param NotifyType Type of notify to fire.
522 @param InstallStartIndex Install Beginning index.
523 @param InstallStopIndex Install Ending index.
524 @param NotifyStartIndex Notify Beginning index.
525 @param NotifyStopIndex Notify Ending index.
530 IN PEI_CORE_INSTANCE
*PrivateData
,
532 IN INTN InstallStartIndex
,
533 IN INTN InstallStopIndex
,
534 IN INTN NotifyStartIndex
,
535 IN INTN NotifyStopIndex
540 EFI_GUID
*SearchGuid
;
542 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
;
545 // Remember that Installs moves up and Notifies moves down.
547 for (Index1
= NotifyStartIndex
; Index1
> NotifyStopIndex
; Index1
--) {
548 NotifyDescriptor
= PrivateData
->PpiData
.PpiListPtrs
[Index1
].Notify
;
550 CheckGuid
= NotifyDescriptor
->Guid
;
552 for (Index2
= InstallStartIndex
; Index2
< InstallStopIndex
; Index2
++) {
553 SearchGuid
= PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
->Guid
;
555 // Don't use CompareGuid function here for performance reasons.
556 // Instead we compare the GUID as INT32 at a time and branch
557 // on the first failed comparison.
559 if ((((INT32
*)SearchGuid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
560 (((INT32
*)SearchGuid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
561 (((INT32
*)SearchGuid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
562 (((INT32
*)SearchGuid
)[3] == ((INT32
*)CheckGuid
)[3])) {
563 DEBUG ((EFI_D_INFO
, "Notify: PPI Guid: %g, Peim notify entry point: %x\n",
565 NotifyDescriptor
->Notify
567 NotifyDescriptor
->Notify (
568 GetPeiServicesTablePointer (),
570 (PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
)->Ppi