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
= MAX_PPI_DESCRIPTORS
-1;
50 PrivateData
->PpiData
.DispatchListEnd
= MAX_PPI_DESCRIPTORS
-1;
51 PrivateData
->PpiData
.LastDispatchedNotify
= MAX_PPI_DESCRIPTORS
-1;
59 IN CONST EFI_PEI_SERVICES
**PeiServices
,
60 IN EFI_HOB_HANDOFF_INFO_TABLE
*OldHandOffHob
,
61 IN EFI_HOB_HANDOFF_INFO_TABLE
*NewHandOffHob
67 Migrate the Hob list from the CAR stack to PEI installed memory.
71 PeiServices - The PEI core services table.
72 OldHandOffHob - The old handoff HOB list.
73 NewHandOffHob - The new handoff HOB list.
79 PEI_CORE_INSTANCE
*PrivateData
;
81 PEI_PPI_LIST_POINTERS
*PpiPointer
;
84 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
86 Fixup
= (UINTN
)NewHandOffHob
- (UINTN
)OldHandOffHob
;
88 for (Index
= 0; Index
< MAX_PPI_DESCRIPTORS
; Index
++) {
89 if (Index
< PrivateData
->PpiData
.PpiListEnd
||
90 Index
> PrivateData
->PpiData
.NotifyListEnd
) {
91 PpiPointer
= &PrivateData
->PpiData
.PpiListPtrs
[Index
];
93 if (((UINTN
)PpiPointer
->Raw
< (UINTN
)OldHandOffHob
->EfiFreeMemoryBottom
) &&
94 ((UINTN
)PpiPointer
->Raw
>= (UINTN
)OldHandOffHob
)) {
96 // Convert the pointer to the PEIM descriptor from the old HOB heap
97 // to the relocated HOB heap.
99 PpiPointer
->Raw
= (VOID
*) ((UINTN
)PpiPointer
->Raw
+ Fixup
);
102 // Only when the PEIM descriptor is in the old HOB should it be necessary
103 // to try to convert the pointers in the PEIM descriptor
106 if (((UINTN
)PpiPointer
->Ppi
->Guid
< (UINTN
)OldHandOffHob
->EfiFreeMemoryBottom
) &&
107 ((UINTN
)PpiPointer
->Ppi
->Guid
>= (UINTN
)OldHandOffHob
)) {
109 // Convert the pointer to the GUID in the PPI or NOTIFY descriptor
110 // from the old HOB heap to the relocated HOB heap.
112 PpiPointer
->Ppi
->Guid
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Guid
+ Fixup
);
116 // Assume that no code is located in the temporary memory, so the pointer to
117 // the notification function in the NOTIFY descriptor needs not be converted.
119 if (Index
< PrivateData
->PpiData
.PpiListEnd
&&
120 (UINTN
)PpiPointer
->Ppi
->Ppi
< (UINTN
)OldHandOffHob
->EfiFreeMemoryBottom
&&
121 (UINTN
)PpiPointer
->Ppi
->Ppi
>= (UINTN
)OldHandOffHob
) {
123 // Convert the pointer to the PPI interface structure in the PPI descriptor
124 // from the old HOB heap to the relocated HOB heap.
126 PpiPointer
->Ppi
->Ppi
= (VOID
*) ((UINTN
)PpiPointer
->Ppi
->Ppi
+ Fixup
);
138 IN CONST EFI_PEI_SERVICES
**PeiServices
,
139 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
145 Install PPI services.
149 PeiServices - Pointer to the PEI Service Table
150 PpiList - Pointer to a list of PEI PPI Descriptors.
154 EFI_SUCCESS - if all PPIs in PpiList are successfully installed.
155 EFI_INVALID_PARAMETER - if PpiList is NULL pointer
156 EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid
157 EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI
161 PEI_CORE_INSTANCE
*PrivateData
;
163 INTN LastCallbackInstall
;
166 if (PpiList
== NULL
) {
167 return EFI_INVALID_PARAMETER
;
170 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
172 Index
= PrivateData
->PpiData
.PpiListEnd
;
173 LastCallbackInstall
= Index
;
176 // This is loop installs all PPI descriptors in the PpiList. It is terminated
177 // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
178 // EFI_PEI_PPI_DESCRIPTOR in the list.
183 // Since PpiData is used for NotifyList and InstallList, max resource
184 // is reached if the Install reaches the NotifyList
186 if (Index
== PrivateData
->PpiData
.NotifyListEnd
+ 1) {
187 return EFI_OUT_OF_RESOURCES
;
190 // Check if it is a valid PPI.
191 // If not, rollback list to exclude all in this list.
192 // Try to indicate which item failed.
194 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
195 PrivateData
->PpiData
.PpiListEnd
= LastCallbackInstall
;
196 DEBUG((EFI_D_ERROR
, "ERROR -> InstallPpi: %g %x\n", PpiList
->Guid
, PpiList
->Ppi
));
197 return EFI_INVALID_PARAMETER
;
200 DEBUG((EFI_D_INFO
, "Install PPI: %g\n", PpiList
->Guid
));
201 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*) PpiList
;
202 PrivateData
->PpiData
.PpiListEnd
++;
205 // Continue until the end of the PPI List.
207 if ((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
208 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
216 // Dispatch any callback level notifies for newly installed PPIs.
220 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
222 PrivateData
->PpiData
.PpiListEnd
,
223 PrivateData
->PpiData
.DispatchListEnd
,
224 PrivateData
->PpiData
.NotifyListEnd
235 IN CONST EFI_PEI_SERVICES
**PeiServices
,
236 IN CONST EFI_PEI_PPI_DESCRIPTOR
*OldPpi
,
237 IN CONST EFI_PEI_PPI_DESCRIPTOR
*NewPpi
243 Re-Install PPI services.
247 PeiServices - Pointer to the PEI Service Table
248 OldPpi - Pointer to the old PEI PPI Descriptors.
249 NewPpi - Pointer to the new PEI PPI Descriptors.
253 EFI_SUCCESS - if the operation was successful
254 EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL
255 EFI_INVALID_PARAMETER - if NewPpi is not valid
256 EFI_NOT_FOUND - if the PPI was not in the database
260 PEI_CORE_INSTANCE
*PrivateData
;
264 if ((OldPpi
== NULL
) || (NewPpi
== NULL
)) {
265 return EFI_INVALID_PARAMETER
;
268 if ((NewPpi
->Flags
& EFI_PEI_PPI_DESCRIPTOR_PPI
) == 0) {
269 return EFI_INVALID_PARAMETER
;
272 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
275 // Find the old PPI instance in the database. If we can not find it,
276 // return the EFI_NOT_FOUND error.
278 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
279 if (OldPpi
== PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
) {
283 if (Index
== PrivateData
->PpiData
.PpiListEnd
) {
284 return EFI_NOT_FOUND
;
288 // Remove the old PPI from the database, add the new one.
290 DEBUG((EFI_D_INFO
, "Reinstall PPI: %g\n", NewPpi
->Guid
));
291 PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
= (EFI_PEI_PPI_DESCRIPTOR
*) NewPpi
;
294 // Dispatch any callback level notifies for the newly installed PPI.
298 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
301 PrivateData
->PpiData
.DispatchListEnd
,
302 PrivateData
->PpiData
.NotifyListEnd
313 IN CONST EFI_PEI_SERVICES
**PeiServices
,
314 IN CONST EFI_GUID
*Guid
,
316 IN OUT EFI_PEI_PPI_DESCRIPTOR
**PpiDescriptor
,
323 Locate a given named PPI.
327 PeiServices - Pointer to the PEI Service Table
328 Guid - Pointer to GUID of the PPI.
329 Instance - Instance Number to discover.
330 PpiDescriptor - Pointer to reference the found descriptor. If not NULL,
331 returns a pointer to the descriptor (includes flags, etc)
332 Ppi - Pointer to reference the found PPI
336 Status - EFI_SUCCESS if the PPI is in the database
337 EFI_NOT_FOUND if the PPI is not in the database
340 PEI_CORE_INSTANCE
*PrivateData
;
343 EFI_PEI_PPI_DESCRIPTOR
*TempPtr
;
346 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
349 // Search the data base for the matching instance of the GUIDed PPI.
351 for (Index
= 0; Index
< PrivateData
->PpiData
.PpiListEnd
; Index
++) {
352 TempPtr
= PrivateData
->PpiData
.PpiListPtrs
[Index
].Ppi
;
353 CheckGuid
= TempPtr
->Guid
;
356 // Don't use CompareGuid function here for performance reasons.
357 // Instead we compare the GUID as INT32 at a time and branch
358 // on the first failed comparison.
360 if ((((INT32
*)Guid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
361 (((INT32
*)Guid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
362 (((INT32
*)Guid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
363 (((INT32
*)Guid
)[3] == ((INT32
*)CheckGuid
)[3])) {
366 if (PpiDescriptor
!= NULL
) {
367 *PpiDescriptor
= TempPtr
;
381 return EFI_NOT_FOUND
;
388 IN CONST EFI_PEI_SERVICES
**PeiServices
,
389 IN CONST EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyList
395 Install a notification for a given PPI.
399 PeiServices - Pointer to the PEI Service Table
400 NotifyList - Pointer to list of Descriptors to notify upon.
404 Status - EFI_SUCCESS if successful
405 EFI_OUT_OF_RESOURCES if no space in the database
406 EFI_INVALID_PARAMETER if not a good decriptor
410 PEI_CORE_INSTANCE
*PrivateData
;
413 INTN LastCallbackNotify
;
414 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyPtr
;
415 UINTN NotifyDispatchCount
;
418 NotifyDispatchCount
= 0;
420 if (NotifyList
== NULL
) {
421 return EFI_INVALID_PARAMETER
;
424 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices
);
426 Index
= PrivateData
->PpiData
.NotifyListEnd
;
427 LastCallbackNotify
= Index
;
430 // This is loop installs all Notify descriptors in the NotifyList. It is
431 // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
432 // EFI_PEI_NOTIFY_DESCRIPTOR in the list.
437 // Since PpiData is used for NotifyList and InstallList, max resource
438 // is reached if the Install reaches the PpiList
440 if (Index
== PrivateData
->PpiData
.PpiListEnd
- 1) {
441 return EFI_OUT_OF_RESOURCES
;
445 // If some of the PPI data is invalid restore original Notify PPI database value
447 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES
) == 0) {
448 PrivateData
->PpiData
.NotifyListEnd
= LastCallbackNotify
;
449 DEBUG((EFI_D_ERROR
, "ERROR -> InstallNotify: %g %x\n", NotifyList
->Guid
, NotifyList
->Notify
));
450 return EFI_INVALID_PARAMETER
;
453 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
454 NotifyDispatchCount
++;
457 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= (EFI_PEI_NOTIFY_DESCRIPTOR
*) NotifyList
;
459 PrivateData
->PpiData
.NotifyListEnd
--;
460 DEBUG((EFI_D_INFO
, "Register PPI Notify: %g\n", NotifyList
->Guid
));
461 if ((NotifyList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) ==
462 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) {
466 // Go the next descriptor. Remember the NotifyList moves down.
473 // If there is Dispatch Notify PPI installed put them on the bottom
475 if (NotifyDispatchCount
> 0) {
476 for (NotifyIndex
= LastCallbackNotify
; NotifyIndex
> PrivateData
->PpiData
.NotifyListEnd
; NotifyIndex
--) {
477 if ((PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
->Flags
& EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
) != 0) {
478 NotifyPtr
= PrivateData
->PpiData
.PpiListPtrs
[NotifyIndex
].Notify
;
480 for (Index
= NotifyIndex
; Index
< PrivateData
->PpiData
.DispatchListEnd
; Index
++){
481 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= PrivateData
->PpiData
.PpiListPtrs
[Index
+ 1].Notify
;
483 PrivateData
->PpiData
.PpiListPtrs
[Index
].Notify
= NotifyPtr
;
484 PrivateData
->PpiData
.DispatchListEnd
--;
488 LastCallbackNotify
-= NotifyDispatchCount
;
492 // Dispatch any callback level notifies for all previously installed PPIs.
496 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
498 PrivateData
->PpiData
.PpiListEnd
,
500 PrivateData
->PpiData
.NotifyListEnd
510 IN PEI_CORE_INSTANCE
*PrivateData
516 Process the Notify List at dispatch level.
520 PeiServices - Pointer to the PEI Service Table
531 // Check if the PEIM that was just dispatched resulted in any
532 // Notifies getting installed. If so, go process any dispatch
533 // level Notifies that match the previouly installed PPIs.
534 // Use "while" instead of "if" since DispatchNotify can modify
535 // DispatchListEnd (with NotifyPpi) so we have to iterate until the same.
537 while (PrivateData
->PpiData
.LastDispatchedNotify
!= PrivateData
->PpiData
.DispatchListEnd
) {
538 TempValue
= PrivateData
->PpiData
.DispatchListEnd
;
541 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
543 PrivateData
->PpiData
.LastDispatchedInstall
,
544 PrivateData
->PpiData
.LastDispatchedNotify
,
545 PrivateData
->PpiData
.DispatchListEnd
547 PrivateData
->PpiData
.LastDispatchedNotify
= TempValue
;
552 // Check if the PEIM that was just dispatched resulted in any
553 // PPIs getting installed. If so, go process any dispatch
554 // level Notifies that match the installed PPIs.
555 // Use "while" instead of "if" since DispatchNotify can modify
556 // PpiListEnd (with InstallPpi) so we have to iterate until the same.
558 while (PrivateData
->PpiData
.LastDispatchedInstall
!= PrivateData
->PpiData
.PpiListEnd
) {
559 TempValue
= PrivateData
->PpiData
.PpiListEnd
;
562 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
,
563 PrivateData
->PpiData
.LastDispatchedInstall
,
564 PrivateData
->PpiData
.PpiListEnd
,
565 MAX_PPI_DESCRIPTORS
-1,
566 PrivateData
->PpiData
.DispatchListEnd
568 PrivateData
->PpiData
.LastDispatchedInstall
= TempValue
;
571 if (PrivateData
->PpiData
.LastDispatchedNotify
== PrivateData
->PpiData
.DispatchListEnd
) {
580 IN PEI_CORE_INSTANCE
*PrivateData
,
582 IN INTN InstallStartIndex
,
583 IN INTN InstallStopIndex
,
584 IN INTN NotifyStartIndex
,
585 IN INTN NotifyStopIndex
591 Dispatch notifications.
595 PeiServices - Pointer to the PEI Service Table
596 NotifyType - Type of notify to fire.
597 InstallStartIndex - Install Beginning index.
598 InstallStopIndex - Install Ending index.
599 NotifyStartIndex - Notify Beginning index.
600 NotifyStopIndex - Notify Ending index.
609 EFI_GUID
*SearchGuid
;
611 EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
;
614 // Remember that Installs moves up and Notifies moves down.
616 for (Index1
= NotifyStartIndex
; Index1
> NotifyStopIndex
; Index1
--) {
617 NotifyDescriptor
= PrivateData
->PpiData
.PpiListPtrs
[Index1
].Notify
;
619 CheckGuid
= NotifyDescriptor
->Guid
;
621 for (Index2
= InstallStartIndex
; Index2
< InstallStopIndex
; Index2
++) {
622 SearchGuid
= PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
->Guid
;
624 // Don't use CompareGuid function here for performance reasons.
625 // Instead we compare the GUID as INT32 at a time and branch
626 // on the first failed comparison.
628 if ((((INT32
*)SearchGuid
)[0] == ((INT32
*)CheckGuid
)[0]) &&
629 (((INT32
*)SearchGuid
)[1] == ((INT32
*)CheckGuid
)[1]) &&
630 (((INT32
*)SearchGuid
)[2] == ((INT32
*)CheckGuid
)[2]) &&
631 (((INT32
*)SearchGuid
)[3] == ((INT32
*)CheckGuid
)[3])) {
632 DEBUG ((EFI_D_INFO
, "Notify: PPI Guid: %g, Peim notify entry point: %x\n",
634 NotifyDescriptor
->Notify
636 NotifyDescriptor
->Notify (
637 GetPeiServicesTablePointer (),
639 (PrivateData
->PpiData
.PpiListPtrs
[Index2
].Ppi
)->Ppi