📄 ppi.c
字号:
/*++
Copyright (c) 2004 - 2005, 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 "Tiano.h"
#include "PeiCore.h"
#include "PeiLib.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:
Convert PPI pointers after the Hob list was migrated 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:
None.
--*/
{
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;
PEI_DEBUG((PeiServices, EFI_D_INFO, "ERROR -> InstallPpi: %g %x\n", PpiList->Guid, PpiList->Ppi));
return EFI_INVALID_PARAMETER;
}
PEI_DEBUG((PeiServices, 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.
//
PEI_DEBUG((PeiServices, 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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -