mirror of https://github.com/acidanthera/audk.git
659 lines
19 KiB
C
659 lines
19 KiB
C
/*++
|
|
|
|
Copyright (c) 2006, Intel Corporation
|
|
All rights reserved. This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
Module Name:
|
|
|
|
Ppi.c
|
|
|
|
Abstract:
|
|
|
|
EFI PEI Core PPI services
|
|
|
|
Revision History
|
|
|
|
--*/
|
|
|
|
#include <PeiMain.h>
|
|
|
|
VOID
|
|
InitializePpiServices (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN PEI_CORE_INSTANCE *OldCoreData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize PPI services.
|
|
|
|
Arguments:
|
|
|
|
PeiServices - The PEI core services table.
|
|
OldCoreData - Pointer to the PEI Core data.
|
|
NULL if being run in non-permament memory mode.
|
|
|
|
Returns:
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
PEI_CORE_INSTANCE *PrivateData;
|
|
|
|
if (OldCoreData == NULL) {
|
|
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
|
|
|
|
PrivateData->PpiData.NotifyListEnd = MAX_PPI_DESCRIPTORS-1;
|
|
PrivateData->PpiData.DispatchListEnd = MAX_PPI_DESCRIPTORS-1;
|
|
PrivateData->PpiData.LastDispatchedNotify = MAX_PPI_DESCRIPTORS-1;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
ConvertPpiPointers (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob,
|
|
IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Migrate the Hob list from the CAR stack to PEI installed memory.
|
|
|
|
Arguments:
|
|
|
|
PeiServices - The PEI core services table.
|
|
OldHandOffHob - The old handoff HOB list.
|
|
NewHandOffHob - The new handoff HOB list.
|
|
|
|
Returns:
|
|
|
|
--*/
|
|
{
|
|
PEI_CORE_INSTANCE *PrivateData;
|
|
UINT8 Index;
|
|
PEI_PPI_LIST_POINTERS *PpiPointer;
|
|
UINTN Fixup;
|
|
|
|
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
|
|
|
|
Fixup = (UINTN)NewHandOffHob - (UINTN)OldHandOffHob;
|
|
|
|
for (Index = 0; Index < MAX_PPI_DESCRIPTORS; Index++) {
|
|
if (Index < PrivateData->PpiData.PpiListEnd ||
|
|
Index > PrivateData->PpiData.NotifyListEnd) {
|
|
PpiPointer = &PrivateData->PpiData.PpiListPtrs[Index];
|
|
|
|
if (((UINTN)PpiPointer->Raw < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) &&
|
|
((UINTN)PpiPointer->Raw >= (UINTN)OldHandOffHob)) {
|
|
//
|
|
// Convert the pointer to the PEIM descriptor from the old HOB heap
|
|
// to the relocated HOB heap.
|
|
//
|
|
PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw + Fixup);
|
|
|
|
//
|
|
// Only when the PEIM descriptor is in the old HOB should it be necessary
|
|
// to try to convert the pointers in the PEIM descriptor
|
|
//
|
|
|
|
if (((UINTN)PpiPointer->Ppi->Guid < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) &&
|
|
((UINTN)PpiPointer->Ppi->Guid >= (UINTN)OldHandOffHob)) {
|
|
//
|
|
// Convert the pointer to the GUID in the PPI or NOTIFY descriptor
|
|
// from the old HOB heap to the relocated HOB heap.
|
|
//
|
|
PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid + Fixup);
|
|
}
|
|
|
|
//
|
|
// Assume that no code is located in the temporary memory, so the pointer to
|
|
// the notification function in the NOTIFY descriptor needs not be converted.
|
|
//
|
|
if (Index < PrivateData->PpiData.PpiListEnd &&
|
|
(UINTN)PpiPointer->Ppi->Ppi < (UINTN)OldHandOffHob->EfiFreeMemoryBottom &&
|
|
(UINTN)PpiPointer->Ppi->Ppi >= (UINTN)OldHandOffHob) {
|
|
//
|
|
// Convert the pointer to the PPI interface structure in the PPI descriptor
|
|
// from the old HOB heap to the relocated HOB heap.
|
|
//
|
|
PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi+ Fixup);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PeiInstallPpi (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN EFI_PEI_PPI_DESCRIPTOR *PpiList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Install PPI services.
|
|
|
|
Arguments:
|
|
|
|
PeiServices - Pointer to the PEI Service Table
|
|
PpiList - Pointer to a list of PEI PPI Descriptors.
|
|
|
|
Returns:
|
|
|
|
EFI_SUCCESS - if all PPIs in PpiList are successfully installed.
|
|
EFI_INVALID_PARAMETER - if PpiList is NULL pointer
|
|
EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid
|
|
EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI
|
|
|
|
--*/
|
|
{
|
|
PEI_CORE_INSTANCE *PrivateData;
|
|
INTN Index;
|
|
INTN LastCallbackInstall;
|
|
|
|
|
|
if (PpiList == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
|
|
|
|
Index = PrivateData->PpiData.PpiListEnd;
|
|
LastCallbackInstall = Index;
|
|
|
|
//
|
|
// This is loop installs all PPI descriptors in the PpiList. It is terminated
|
|
// by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
|
|
// EFI_PEI_PPI_DESCRIPTOR in the list.
|
|
//
|
|
|
|
for (;;) {
|
|
//
|
|
// Since PpiData is used for NotifyList and InstallList, max resource
|
|
// is reached if the Install reaches the NotifyList
|
|
//
|
|
if (Index == PrivateData->PpiData.NotifyListEnd + 1) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
//
|
|
// Check if it is a valid PPI.
|
|
// If not, rollback list to exclude all in this list.
|
|
// Try to indicate which item failed.
|
|
//
|
|
if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {
|
|
PrivateData->PpiData.PpiListEnd = LastCallbackInstall;
|
|
DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %x\n", PpiList->Guid, PpiList->Ppi));
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid));
|
|
PrivateData->PpiData.PpiListPtrs[Index].Ppi = PpiList;
|
|
PrivateData->PpiData.PpiListEnd++;
|
|
|
|
//
|
|
// Continue until the end of the PPI List.
|
|
//
|
|
if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
|
|
EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
|
|
break;
|
|
}
|
|
PpiList++;
|
|
Index++;
|
|
}
|
|
|
|
//
|
|
// Dispatch any callback level notifies for newly installed PPIs.
|
|
//
|
|
DispatchNotify (
|
|
PeiServices,
|
|
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
|
|
LastCallbackInstall,
|
|
PrivateData->PpiData.PpiListEnd,
|
|
PrivateData->PpiData.DispatchListEnd,
|
|
PrivateData->PpiData.NotifyListEnd
|
|
);
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PeiReInstallPpi (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN EFI_PEI_PPI_DESCRIPTOR *OldPpi,
|
|
IN EFI_PEI_PPI_DESCRIPTOR *NewPpi
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Re-Install PPI services.
|
|
|
|
Arguments:
|
|
|
|
PeiServices - Pointer to the PEI Service Table
|
|
OldPpi - Pointer to the old PEI PPI Descriptors.
|
|
NewPpi - Pointer to the new PEI PPI Descriptors.
|
|
|
|
Returns:
|
|
|
|
EFI_SUCCESS - if the operation was successful
|
|
EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL
|
|
EFI_INVALID_PARAMETER - if NewPpi is not valid
|
|
EFI_NOT_FOUND - if the PPI was not in the database
|
|
|
|
--*/
|
|
{
|
|
PEI_CORE_INSTANCE *PrivateData;
|
|
INTN Index;
|
|
|
|
|
|
if ((OldPpi == NULL) || (NewPpi == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
|
|
|
|
//
|
|
// Find the old PPI instance in the database. If we can not find it,
|
|
// return the EFI_NOT_FOUND error.
|
|
//
|
|
for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {
|
|
if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) {
|
|
break;
|
|
}
|
|
}
|
|
if (Index == PrivateData->PpiData.PpiListEnd) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Remove the old PPI from the database, add the new one.
|
|
//
|
|
DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));
|
|
PrivateData->PpiData.PpiListPtrs[Index].Ppi = NewPpi;
|
|
|
|
//
|
|
// Dispatch any callback level notifies for the newly installed PPI.
|
|
//
|
|
DispatchNotify (
|
|
PeiServices,
|
|
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
|
|
Index,
|
|
Index+1,
|
|
PrivateData->PpiData.DispatchListEnd,
|
|
PrivateData->PpiData.NotifyListEnd
|
|
);
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PeiLocatePpi (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN EFI_GUID *Guid,
|
|
IN UINTN Instance,
|
|
IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,
|
|
IN OUT VOID **Ppi
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Locate a given named PPI.
|
|
|
|
Arguments:
|
|
|
|
PeiServices - Pointer to the PEI Service Table
|
|
Guid - Pointer to GUID of the PPI.
|
|
Instance - Instance Number to discover.
|
|
PpiDescriptor - Pointer to reference the found descriptor. If not NULL,
|
|
returns a pointer to the descriptor (includes flags, etc)
|
|
Ppi - Pointer to reference the found PPI
|
|
|
|
Returns:
|
|
|
|
Status - EFI_SUCCESS if the PPI is in the database
|
|
EFI_NOT_FOUND if the PPI is not in the database
|
|
--*/
|
|
{
|
|
PEI_CORE_INSTANCE *PrivateData;
|
|
INTN Index;
|
|
EFI_GUID *CheckGuid;
|
|
EFI_PEI_PPI_DESCRIPTOR *TempPtr;
|
|
|
|
|
|
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
|
|
|
|
//
|
|
// Search the data base for the matching instance of the GUIDed PPI.
|
|
//
|
|
for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) {
|
|
TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi;
|
|
CheckGuid = TempPtr->Guid;
|
|
|
|
//
|
|
// Don't use CompareGuid function here for performance reasons.
|
|
// Instead we compare the GUID as INT32 at a time and branch
|
|
// on the first failed comparison.
|
|
//
|
|
if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) &&
|
|
(((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) &&
|
|
(((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) &&
|
|
(((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) {
|
|
if (Instance == 0) {
|
|
|
|
if (PpiDescriptor != NULL) {
|
|
*PpiDescriptor = TempPtr;
|
|
}
|
|
|
|
if (Ppi != NULL) {
|
|
*Ppi = TempPtr->Ppi;
|
|
}
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
Instance--;
|
|
}
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PeiNotifyPpi (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Install a notification for a given PPI.
|
|
|
|
Arguments:
|
|
|
|
PeiServices - Pointer to the PEI Service Table
|
|
NotifyList - Pointer to list of Descriptors to notify upon.
|
|
|
|
Returns:
|
|
|
|
Status - EFI_SUCCESS if successful
|
|
EFI_OUT_OF_RESOURCES if no space in the database
|
|
EFI_INVALID_PARAMETER if not a good decriptor
|
|
|
|
--*/
|
|
{
|
|
PEI_CORE_INSTANCE *PrivateData;
|
|
INTN Index;
|
|
INTN NotifyIndex;
|
|
INTN LastCallbackNotify;
|
|
EFI_PEI_NOTIFY_DESCRIPTOR *NotifyPtr;
|
|
UINTN NotifyDispatchCount;
|
|
|
|
|
|
NotifyDispatchCount = 0;
|
|
|
|
if (NotifyList == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
|
|
|
|
Index = PrivateData->PpiData.NotifyListEnd;
|
|
LastCallbackNotify = Index;
|
|
|
|
//
|
|
// This is loop installs all Notify descriptors in the NotifyList. It is
|
|
// terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
|
|
// EFI_PEI_NOTIFY_DESCRIPTOR in the list.
|
|
//
|
|
|
|
for (;;) {
|
|
//
|
|
// Since PpiData is used for NotifyList and InstallList, max resource
|
|
// is reached if the Install reaches the PpiList
|
|
//
|
|
if (Index == PrivateData->PpiData.PpiListEnd - 1) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// If some of the PPI data is invalid restore original Notify PPI database value
|
|
//
|
|
if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {
|
|
PrivateData->PpiData.NotifyListEnd = LastCallbackNotify;
|
|
DEBUG((EFI_D_ERROR, "ERROR -> InstallNotify: %g %x\n", NotifyList->Guid, NotifyList->Notify));
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {
|
|
NotifyDispatchCount ++;
|
|
}
|
|
|
|
PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyList;
|
|
|
|
PrivateData->PpiData.NotifyListEnd--;
|
|
DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));
|
|
if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
|
|
EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
|
|
break;
|
|
}
|
|
//
|
|
// Go the next descriptor. Remember the NotifyList moves down.
|
|
//
|
|
NotifyList++;
|
|
Index--;
|
|
}
|
|
|
|
//
|
|
// If there is Dispatch Notify PPI installed put them on the bottom
|
|
//
|
|
if (NotifyDispatchCount > 0) {
|
|
for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) {
|
|
if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) {
|
|
NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify;
|
|
|
|
for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){
|
|
PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify;
|
|
}
|
|
PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr;
|
|
PrivateData->PpiData.DispatchListEnd--;
|
|
}
|
|
}
|
|
|
|
LastCallbackNotify -= NotifyDispatchCount;
|
|
}
|
|
|
|
//
|
|
// Dispatch any callback level notifies for all previously installed PPIs.
|
|
//
|
|
DispatchNotify (
|
|
PeiServices,
|
|
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
|
|
0,
|
|
PrivateData->PpiData.PpiListEnd,
|
|
LastCallbackNotify,
|
|
PrivateData->PpiData.NotifyListEnd
|
|
);
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
VOID
|
|
ProcessNotifyList (
|
|
IN EFI_PEI_SERVICES **PeiServices
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process the Notify List at dispatch level.
|
|
|
|
Arguments:
|
|
|
|
PeiServices - Pointer to the PEI Service Table
|
|
|
|
Returns:
|
|
|
|
--*/
|
|
|
|
{
|
|
PEI_CORE_INSTANCE *PrivateData;
|
|
INTN TempValue;
|
|
|
|
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
|
|
|
|
|
|
while (TRUE) {
|
|
//
|
|
// Check if the PEIM that was just dispatched resulted in any
|
|
// Notifies getting installed. If so, go process any dispatch
|
|
// level Notifies that match the previouly installed PPIs.
|
|
// Use "while" instead of "if" since DispatchNotify can modify
|
|
// DispatchListEnd (with NotifyPpi) so we have to iterate until the same.
|
|
//
|
|
while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) {
|
|
TempValue = PrivateData->PpiData.DispatchListEnd;
|
|
DispatchNotify (
|
|
PeiServices,
|
|
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,
|
|
0,
|
|
PrivateData->PpiData.LastDispatchedInstall,
|
|
PrivateData->PpiData.LastDispatchedNotify,
|
|
PrivateData->PpiData.DispatchListEnd
|
|
);
|
|
PrivateData->PpiData.LastDispatchedNotify = TempValue;
|
|
}
|
|
|
|
|
|
//
|
|
// Check if the PEIM that was just dispatched resulted in any
|
|
// PPIs getting installed. If so, go process any dispatch
|
|
// level Notifies that match the installed PPIs.
|
|
// Use "while" instead of "if" since DispatchNotify can modify
|
|
// PpiListEnd (with InstallPpi) so we have to iterate until the same.
|
|
//
|
|
while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) {
|
|
TempValue = PrivateData->PpiData.PpiListEnd;
|
|
DispatchNotify (
|
|
PeiServices,
|
|
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,
|
|
PrivateData->PpiData.LastDispatchedInstall,
|
|
PrivateData->PpiData.PpiListEnd,
|
|
MAX_PPI_DESCRIPTORS-1,
|
|
PrivateData->PpiData.DispatchListEnd
|
|
);
|
|
PrivateData->PpiData.LastDispatchedInstall = TempValue;
|
|
}
|
|
|
|
if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) {
|
|
break;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
DispatchNotify (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN UINTN NotifyType,
|
|
IN INTN InstallStartIndex,
|
|
IN INTN InstallStopIndex,
|
|
IN INTN NotifyStartIndex,
|
|
IN INTN NotifyStopIndex
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dispatch notifications.
|
|
|
|
Arguments:
|
|
|
|
PeiServices - Pointer to the PEI Service Table
|
|
NotifyType - Type of notify to fire.
|
|
InstallStartIndex - Install Beginning index.
|
|
InstallStopIndex - Install Ending index.
|
|
NotifyStartIndex - Notify Beginning index.
|
|
NotifyStopIndex - Notify Ending index.
|
|
|
|
Returns: None
|
|
|
|
--*/
|
|
|
|
{
|
|
PEI_CORE_INSTANCE *PrivateData;
|
|
INTN Index1;
|
|
INTN Index2;
|
|
EFI_GUID *SearchGuid;
|
|
EFI_GUID *CheckGuid;
|
|
EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;
|
|
|
|
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
|
|
|
|
//
|
|
// Remember that Installs moves up and Notifies moves down.
|
|
//
|
|
for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) {
|
|
NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify;
|
|
|
|
CheckGuid = NotifyDescriptor->Guid;
|
|
|
|
for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {
|
|
SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid;
|
|
//
|
|
// Don't use CompareGuid function here for performance reasons.
|
|
// Instead we compare the GUID as INT32 at a time and branch
|
|
// on the first failed comparison.
|
|
//
|
|
if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) &&
|
|
(((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) &&
|
|
(((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) &&
|
|
(((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) {
|
|
DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %x\n",
|
|
SearchGuid,
|
|
NotifyDescriptor->Notify
|
|
));
|
|
NotifyDescriptor->Notify (
|
|
PeiServices,
|
|
NotifyDescriptor,
|
|
(PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|