PEIM安装PPI和调用其他PPI的相关函数

安装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;
}

获取到接口指针之后进行安装

相关推荐
一只侯子5 小时前
Tuning——CC调试(适用高通)
开发语言·图像处理·笔记·学习·算法
迷途呀5 小时前
Latex中的错误汇总
论文阅读·笔记·学习·其他·编辑器
Larry_Yanan5 小时前
QML学习笔记(四十六)QML与C++交互:Q_PROPERTY宏映射
c++·笔记·qt·学习·ui·交互
JJJJ_iii5 小时前
【机器学习07】 激活函数精讲、Softmax多分类与优化器进阶
人工智能·笔记·python·算法·机器学习·分类·线性回归
啊森要自信6 小时前
【MySQL 数据库】使用C语言操作MySQL
linux·c语言·开发语言·数据库·mysql
新子y6 小时前
【小白笔记】最大化安全评分
笔记
新子y6 小时前
【小白笔记】关于 Python 类、初始化以及 PyTorch 数据处理的问题
pytorch·笔记·python
yuuki2332336 小时前
【C语言】预处理详解
c语言·windows·后端
小立爱学习6 小时前
Linux 内存 --- get_user_pages/pin_user_pages函数
linux·c语言