安装PPI
通过PeiServicesInstallPpi、PeiServicesNotifyPpi、PeiServicesReInstallPpi函数进行安装
PeiServicesInstallPpi
C
EFI_STATUS
EFIAPI
PeiServicesInstallPpi (
IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList
)
{
CONST EFI_PEI_SERVICES **PeiServices;
PeiServices = GetPeiServicesTablePointer ();
return (*PeiServices)->InstallPpi (PeiServices, PpiList);
}
GetPeiServicesTablePointer
C
CONST EFI_PEI_SERVICES **
EFIAPI
GetPeiServicesTablePointer (
VOID
)
{
CONST EFI_PEI_SERVICES **PeiServices;
IA32_DESCRIPTOR Idtr;
AsmReadIdtr (&Idtr);
PeiServices = (CONST EFI_PEI_SERVICES **)(*(UINTN *)(Idtr.Base - sizeof (UINTN)));
DEBUG((DEBUG_INFO,"sizeof (UINTN) @ %u",sizeof (UINTN)));
ASSERT (PeiServices != NULL);
return PeiServices;
}
PeiInstallPpi
C
EFI_STATUS
EFIAPI
PeiInstallPpi (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList
)
{
return InternalPeiInstallPpi (PeiServices, PpiList, FALSE);
}
InternalPeiInstallPpi
C
EFI_STATUS
InternalPeiInstallPpi (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,
IN BOOLEAN Single
)
{
PEI_CORE_INSTANCE *PrivateData;
PEI_PPI_LIST *PpiListPointer;
UINTN Index;
UINTN LastCount;
VOID *TempPtr;
if (PpiList == NULL) {
return EFI_INVALID_PARAMETER;
}
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
PpiListPointer = &PrivateData->PpiData.PpiList;
Index = PpiListPointer->CurrentCount;
LastCount = 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 ( ; ;) {
//
// 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) {
PpiListPointer->CurrentCount = LastCount;
DEBUG ((DEBUG_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi));
return EFI_INVALID_PARAMETER;
}
if (Index >= PpiListPointer->MaxCount) {
//
// Run out of room, grow the buffer.
//
TempPtr = AllocateZeroPool (
sizeof (PEI_PPI_LIST_POINTERS) * (PpiListPointer->MaxCount + PPI_GROWTH_STEP)
);
ASSERT (TempPtr != NULL);
CopyMem (
TempPtr,
PpiListPointer->PpiPtrs,
sizeof (PEI_PPI_LIST_POINTERS) * PpiListPointer->MaxCount
);
PpiListPointer->PpiPtrs = TempPtr;
PpiListPointer->MaxCount = PpiListPointer->MaxCount + PPI_GROWTH_STEP;
}
DEBUG ((DEBUG_INFO, "Install PPI: %g\n", PpiList->Guid));
PpiListPointer->PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *)PpiList;
Index++;
PpiListPointer->CurrentCount++;
if (Single) {
//
// Only single entry in the PpiList.
//
break;
} else if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)
{
//
// Continue until the end of the PPI List.
//
break;
}
//
// Go to the next descriptor.
//
PpiList++;
}
//
// Process any callback level notifies for newly installed PPIs.
//
ProcessNotify (
PrivateData,
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
LastCount,
PpiListPointer->CurrentCount,
0,
PrivateData->PpiData.CallbackNotifyList.CurrentCount
);
return EFI_SUCCESS;
}
ProcessNotify
C
VOID
ProcessNotify (
IN PEI_CORE_INSTANCE *PrivateData,
IN UINTN NotifyType,
IN INTN InstallStartIndex,
IN INTN InstallStopIndex,
IN INTN NotifyStartIndex,
IN INTN NotifyStopIndex
)
{
INTN Index1;
INTN Index2;
EFI_GUID *SearchGuid;
EFI_GUID *CheckGuid;
EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;
for (Index1 = NotifyStartIndex; Index1 < NotifyStopIndex; Index1++) {
if (NotifyType == EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) {
NotifyDescriptor = PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index1].Notify;
} else {
NotifyDescriptor = PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index1].Notify;
}
CheckGuid = NotifyDescriptor->Guid;
for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {
SearchGuid = PrivateData->PpiData.PpiList.PpiPtrs[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 ((
DEBUG_INFO,
"Notify: PPI Guid: %g, Peim notify entry point: %p\n",
SearchGuid,
NotifyDescriptor->Notify
));
NotifyDescriptor->Notify (
(EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),
NotifyDescriptor,
(PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi)->Ppi
);
}
}
}
}
- EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
安装动作当场立即回调,先于任何后续 PEIM 调度 - EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH
回调被推迟到当前 PEIM 执行完毕后,由 ProcessDispatchNotifyList() 批量处理
PeiServicesNotifyPpi
C
EFI_STATUS
EFIAPI
PeiServicesNotifyPpi (
IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList
)
{
CONST EFI_PEI_SERVICES **PeiServices;
PeiServices = GetPeiServicesTablePointer ();
return (*PeiServices)->NotifyPpi (PeiServices, NotifyList);
}
GetPeiServicesTablePointer
PeiNotifyPpi
InternalPeiNotifyPpi
C
EFI_STATUS
InternalPeiNotifyPpi (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList,
IN BOOLEAN Single
)
{
PEI_CORE_INSTANCE *PrivateData;
PEI_CALLBACK_NOTIFY_LIST *CallbackNotifyListPointer;
UINTN CallbackNotifyIndex;
UINTN LastCallbackNotifyCount;
PEI_DISPATCH_NOTIFY_LIST *DispatchNotifyListPointer;
UINTN DispatchNotifyIndex;
UINTN LastDispatchNotifyCount;
VOID *TempPtr;
if (NotifyList == NULL) {
return EFI_INVALID_PARAMETER;
}
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
CallbackNotifyListPointer = &PrivateData->PpiData.CallbackNotifyList;
CallbackNotifyIndex = CallbackNotifyListPointer->CurrentCount;
LastCallbackNotifyCount = CallbackNotifyIndex;
DispatchNotifyListPointer = &PrivateData->PpiData.DispatchNotifyList;
DispatchNotifyIndex = DispatchNotifyListPointer->CurrentCount;
LastDispatchNotifyCount = DispatchNotifyIndex;
//
// 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 ( ; ;) {
//
// If some of the PPI data is invalid restore original Notify PPI database value
//
if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {
CallbackNotifyListPointer->CurrentCount = LastCallbackNotifyCount;
DispatchNotifyListPointer->CurrentCount = LastDispatchNotifyCount;
DEBUG ((DEBUG_ERROR, "ERROR -> NotifyPpi: %g %p\n", NotifyList->Guid, NotifyList->Notify));
return EFI_INVALID_PARAMETER;
}
if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) != 0) {
if (CallbackNotifyIndex >= CallbackNotifyListPointer->MaxCount) {
//
// Run out of room, grow the buffer.
//
TempPtr = AllocateZeroPool (
sizeof (PEI_PPI_LIST_POINTERS) * (CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP)
);
ASSERT (TempPtr != NULL);
CopyMem (
TempPtr,
CallbackNotifyListPointer->NotifyPtrs,
sizeof (PEI_PPI_LIST_POINTERS) * CallbackNotifyListPointer->MaxCount
);
CallbackNotifyListPointer->NotifyPtrs = TempPtr;
CallbackNotifyListPointer->MaxCount = CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP;
}
CallbackNotifyListPointer->NotifyPtrs[CallbackNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *)NotifyList;
CallbackNotifyIndex++;
CallbackNotifyListPointer->CurrentCount++;
} else {
if (DispatchNotifyIndex >= DispatchNotifyListPointer->MaxCount) {
//
// Run out of room, grow the buffer.
//
TempPtr = AllocateZeroPool (
sizeof (PEI_PPI_LIST_POINTERS) * (DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP)
);
ASSERT (TempPtr != NULL);
CopyMem (
TempPtr,
DispatchNotifyListPointer->NotifyPtrs,
sizeof (PEI_PPI_LIST_POINTERS) * DispatchNotifyListPointer->MaxCount
);
DispatchNotifyListPointer->NotifyPtrs = TempPtr;
DispatchNotifyListPointer->MaxCount = DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP;
}
DispatchNotifyListPointer->NotifyPtrs[DispatchNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *)NotifyList;
DispatchNotifyIndex++;
DispatchNotifyListPointer->CurrentCount++;
}
DEBUG ((DEBUG_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));
if (Single) {
//
// Only single entry in the NotifyList.
//
break;
} else if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)
{
//
// Continue until the end of the Notify List.
//
break;
}
//
// Go to the next descriptor.
//
NotifyList++;
}
//
// Process any callback level notifies for all previously installed PPIs.
//
ProcessNotify (
PrivateData,
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
0,
PrivateData->PpiData.PpiList.CurrentCount,
LastCallbackNotifyCount,
CallbackNotifyListPointer->CurrentCount
);
return EFI_SUCCESS;
}
PeiServicesReInstallPpi
C
EFI_STATUS
EFIAPI
PeiServicesReInstallPpi (
IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi,
IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi
)
{
CONST EFI_PEI_SERVICES **PeiServices;
PeiServices = GetPeiServicesTablePointer ();
return (*PeiServices)->ReInstallPpi (PeiServices, OldPpi, NewPpi);
}
GetPeiServicesTablePointer
PeiReInstallPpi
C
EFI_STATUS
EFIAPI
PeiReInstallPpi (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi,
IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi
)
{
PEI_CORE_INSTANCE *PrivateData;
UINTN 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.PpiList.CurrentCount; Index++) {
if (OldPpi == PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi) {
break;
}
}
if (Index == PrivateData->PpiData.PpiList.CurrentCount) {
return EFI_NOT_FOUND;
}
//
// Replace the old PPI with the new one.
//
DEBUG ((DEBUG_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));
PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *)NewPpi;
//
// Process any callback level notifies for the newly installed PPI.
//
ProcessNotify (
PrivateData,
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
Index,
Index+1,
0,
PrivateData->PpiData.CallbackNotifyList.CurrentCount
);
return EFI_SUCCESS;
}
调用其他PPI
首先拿到接口指针
PeiServicesLocatePpi
C
EFI_STATUS
EFIAPI
PeiServicesLocatePpi (
IN CONST EFI_GUID *Guid,
IN UINTN Instance,
IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor OPTIONAL,
IN OUT VOID **Ppi
)
{
CONST EFI_PEI_SERVICES **PeiServices;
PeiServices = GetPeiServicesTablePointer ();
return (*PeiServices)->LocatePpi (PeiServices, Guid, Instance, PpiDescriptor, Ppi);
}
GetPeiServicesTablePointer
PeiLocatePpi
C
EFI_STATUS
EFIAPI
PeiLocatePpi (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN CONST EFI_GUID *Guid,
IN UINTN Instance,
IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,
IN OUT VOID **Ppi
)
{
PEI_CORE_INSTANCE *PrivateData;
UINTN 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.PpiList.CurrentCount; Index++) {
TempPtr = PrivateData->PpiData.PpiList.PpiPtrs[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;
}