PEIM,PPI理解
1)下面框图是PEI阶段的PEIM,PPI。
对上面框图简单解读:
- PEI Core主要包含Core Services和Core Dispatcher;
- Core Services包括PEI及后面phase要用到的各种Servies,比如Status Code,Hobs,Memory Services,Boot Mode Services等;
- Core Dispatcher负责派发各PEIMs,意思是将PEIM按照既定的顺序Load并执行;
- 这里的既定顺序即Dependency顺序;
- 各PEIM Entry可能使用其他PEIM的PPI,也可能使用自己的PPI;
- PEI Core最后会找到DXE IPL PPI,进入下一阶段DXE;
2)PEIM概念。
- PEIM == PEI Module
- PEIM会被编译成efi binary
- PEIM是为了硬件相关的初始化
- PEIM欸共各自接口(PPI)给别的PEIM使用
3)PPI概念
- PPIs == PEIM - to - PEIM Interfaces
- PEIMs被调用是通过PPI,Interface是UEFI重要的概念
- PPI的名字:GUID(128-bits value)
- PPIs被定义成结构体的形式,其中可能包括功能/数据/或者两者混合
- PEIM会把它的PPI注册到PEI Foundation,PEI Foundation管理着庞大的PPI数据库
4)如何使用PPI
- InstallPpi()安装PPI到PEI Foundation
- LocatePpi()根据PPI名字GUID从PEI Foundation捞Interface
- NotifyPpi()接到通知这个PPI才会在某个PPI被安装时才执行
5)代码演示
- InstallPpi
函数结构体,成员有三个函数,实现三个不同的功能:
CONST EFI_PEI_CAPSULE_PPI mCapsulePpi = {
CapsuleCoalesce,
CheckCapsuleUpdate,
CreateState
};
PpiList结构体成员Flag,GUID和函数结果体指针:
CONST EFI_PEI_PPI_DESCRIPTOR mUefiPpiListCapsule = {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiPeiCapsulePpiGuis,
(EFI_PEI_CAPSULE_PPI *) &mCapsulePpi
};
安装PpiList,通常我们代码会用Library封装(*PeiServices)->InstallPpi成PeiServicesInstallPpi
PeiServicesInstallPpi(&mUefiPpiListCapsule);
PeiServicesInstallPpi原型函数:
(*PeiServices)->InstallPpi(PeiServices,PpiList);
- LocatePpi
封装过后的PeiServicesLocatePpi
Status = PeiServeicsLocatePpi (
&gEfiPeiCapsulePpiGuid,
0,
NULL,
(VOID **) &Capsule
);
标准的LocatePpi,第一个参数是固定的EFI_PEI_SERVICES,第二个参数是GUID,第三个参数通常是0,第四个参数参演为NULL,最重要的是要拿到第五个参数,通过这个指针可以得到Interface。
(*PeiServices)->LocatePpi(PeiServices,Guid,Instance,PpiDescriptor,Ppi);
- NotifyPpi
EFI_STATUS
EFIAPI
S3EndOfPeiNotify(
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
IN VOID *Ppi
);
EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc = {
(EFI_PEI_DESCRITPOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiEndOfPeiSingalPpiGuid,
S3EndOfPeiNotify
};