📄 ppi.c
字号:
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;
PEI_DEBUG((PeiServices, EFI_D_INFO, "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--;
PEI_DEBUG((PeiServices, 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])) {
PEI_DEBUG (
(
PeiServices,
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -