PEI阶段扩展

您所在的位置:网站首页 efi啥意思 PEI阶段扩展

PEI阶段扩展

2023-09-04 04:18| 来源: 网络整理| 查看: 265

PEI阶段扩展 OVERVIEWPEIMPPIUSE PPIInstall PPILocatePPI()Notifyppi() HOBHOB的使用

OVERVIEW

本篇补充相关PEI到DXE阶段的一写知识 在PEI阶段,PEIM 、PPI、 HOB组成了PEI阶段的最重要的部分,PEI阶段的module也可以理解为Driver就是PEIM,PEI阶段就是由一个一个的PEIM组成的;PPI是PEIM之间互相调用的接口,由惟一的GUID引导,内部也包含一些接口,HOB相当于信件在PEI阶段创建,会记载当前系统的信息,可以自定义HOB,然后在DXE阶段读取。框图如下: 在这里插入图片描述 简单解读: PEI Core主要包括Core Services和Core Dispatcher。

Core Services包括PEI及后面phase要用到的各种Services, 比如Status Code, HOBs,Memory Services,Boot Mode Services等。在PEi阶段get当前计算机启动的boot Mode是有直接定义好的PEI Service函数,在DXE以及后面的阶段要通过HOB方式,通过get HOB LIST然后拆解信息进行get启动的boot Mode。Core Dispatcher负责派发各PEIMs,意思是将PEIM按照既定的顺序Load并执行。这里的既定顺序即Dependency顺序,就是inf文件里面的depx,只有满足条件才会执行。各PEIM Entry可能使用其它PEIM的PPI, 也可能使用自己的PPI。PEI Core最后会找到DXE IPL PPI,(IPL是一个很重要的知识点)进入下一阶段DXE。DXE获得之前phase Data的是从HOB里拿,PEI Core会创建HOB,PEI和DXE都可以使用HOB的Data。 PEIM

PEIM(PEI Module), 会被编译成efi binary,在一套完整的BIOS code编译完之后进入到build目录就可以找到这个PEIM具体的efi,.inf + .c +.h >build> .efi是为了硬件相关的初始化,PEIM 也提供各自提供接口(interface)给别的PEIM使用 在这里插入图片描述

PPI

PPIs (PEIM-to-PEIM Interfaces)

PEIMs被调用是通过PPI,Interface。Interface是UEFI重要的概念,会经常出现。简单来说,PPI只是一个接口,接口里面有成员函数,想调用某个函数必须通过该接口。PPI的名字:GUID (128-bits value)PPIs被定义成结构体的形式,在code里看PPI就是一个Struct,其中可能包括功能、数据,或者两者的混合。PEIM会把它的PPI注册到PEI Foundation,PEI Foundation管理着庞大的PPI数据库 USE PPI

几个重要的PPI Services

InstallPpi() 安装PPI到PEI foundation,protocol install完后是放到Handle Datebase里面LocatePpi() 根据PPI名字GUID从PEI foundation找InterfaceNotifyPpi() PPI里的function不会在派发时就执行,会有一个判定条件,通知系统这个PPI会在某个PPI被安装时才执行。 Install PPI /** Install PPI services. It is implementation of EFI_PEI_SERVICE.InstallPpi. 这是个service,PEI foundation提供的。 通过GUID安装。目的是让别人调用。 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. 标准格式,入口第一人参数是铁定的EFI_PEI_SERVICES指针 @param PpiList Pointer to PPI array that want to be installed. 第二个参数是PPI List, LIST里包括Flag、GUID和函数 参考.h里的EFI_PEI_PPI_DESCRIPTOR定义 @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed. @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer if any PPI in PpiList is not valid @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI **/ EFI_STATUS EFIAPI PeiInstallPpi ( IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList );

实例: 以下面的PPI为例,一个给Capsule服务的PPI,里面有三个成员 CapsuleCoalesce, CheckCapsuleUpdate, CreateState。

CONST EFI_PEI_CAPSULE_PPI mCapsulePpi = { CapsuleCoalesce, CheckCapsuleUpdate, CreateState };

给InstallPPI传递的第二个参数:*PpiList。Descriptor有三个值,第一个为属性,第二个为绑定的GUID用于后面locate调用,第三个参数放入struct接口,这样就定义好了ppiList。 在这里插入图片描述 安装PpiList, 通常代码会用Library封装(*PeiServices)->InstallPpi 成PeiServicesInstallPpi 在这里插入图片描述

PeiServicesInstallPpi原型函数,还是那个标准的InstallPpi,传了两个参数This指针和PpiList 在这里插入图片描述

EFI_PEI_PPI_DESCRIPTOR

// // PEI Ppi Services List Descriptors // #define EFI_PEI_PPI_DESCRIPTOR_PIC 0x00000001 #define EFI_PEI_PPI_DESCRIPTOR_PPI 0x00000010 #define EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK 0x00000020 #define EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH 0x00000040 #define EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES 0x00000060 #define EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST 0x80000000 /// /// The data structure through which a PEIM describes available services to the PEI Foundation. /// typedef struct { /// /// This field is a set of flags describing the characteristics of this imported table entry. /// All flags are defined as EFI_PEI_PPI_DESCRIPTOR_***, which can also be combined into one. /// 上面描述的属性。 UINTN Flags; /// /// The address of the EFI_GUID that names the interface. /// 所绑定的GUID EFI_GUID *Guid; /// /// A pointer to the PPI. It contains the information necessary to install a service. /// 所需要install的PPI VOID *Ppi; } EFI_PEI_PPI_DESCRIPTOR; LocatePPI() /** Locate a given named PPI. 用GUID从Database中找想要的PPI @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. @param Guid Pointer to GUID of the PPI. @param Instance Instance Number to discover. @param PpiDescriptor Pointer to reference the found descriptor. If not NULL, returns a pointer to the descriptor (includes flags, etc) @param Ppi Pointer to reference the found PPI @retval EFI_SUCCESS if the PPI is in the database @retval EFI_NOT_FOUND if the PPI is not in the database **/ 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 ); //第一个参数是固定的EFI_PEI_SERVICES第二个参数为GUID,第三个参数通常为0,第四个参数为NULL最重要是拿到第五个参数,通过这个指针可以得到Interface。

实例: 以Capsule为例:Guid为gEfiPeiCapsulePpiGuid,通过这个GUID从Database中找想要的PPI, 想要的PPI都在这个Capsule指针里,Locate之后就可以调用PPI里的函数实现CheckCapsuleUpdate功能 在这里插入图片描述 这也是封装过的LocatePpi,原型函数是下面这样,标准的LocatePpi,当然直接用PeiService->也是可以的 在这里插入图片描述

Notifyppi() /** Install a notification for a given PPI. 注册一个notification服务,当给定的那个PPI被安装或者再安装时,执行notify里的函数。 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. @param NotifyList Pointer to list of Descriptors to notify upon. @retval EFI_SUCCESS if successful @retval EFI_OUT_OF_RESOURCES if no space in the database @retval EFI_INVALID_PARAMETER if not a good descriptor NotifyList里包括Flag,GUID和Notify Routine **/ EFI_STATUS EFIAPI PeiNotifyPpi ( IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList );

实例:当这个gEfiEndOfPeiSignalPpiGuid指向的PPI被安装时才会触发S3EndOfPeiNotify() 在这里插入图片描述 1->首先将要做的事情写到这个函数中, 2->定义好Notify Descriptor :FLAG 、所需加载的PPI GUID、需要执行的函数 3->调用封装后的PeiServiceNotifyPpi => (*PeiServices)->NotifyPpi(PeiServices,NotifyList); 注:在自定义的函数中在确定的点运行相关ppi最好自己写一个Ppi作为触发条件,否则在使用code中定义好的Ppi时需确保不会被其他函数影响或影响其它函数 在这里插入图片描述

HOB

HOB (Hand-Off Blocks )传输信息的载体,相比于其他Phase之间的联系,Pei到DXE之间联系比较薄弱,PEI一些初始化硬件、内存的数据等,DXE需要知道,HOB便作为桥梁应运而生。

HOB producer phase (PEI phase)HOB consumer phase (PEI & DXE phase) (如getbootmodehob就是在PEI阶段调用的,但DXE阶段是不能产生HOB的)

HOB实际上就是一个链表,当我们找到一个hoblist的头,那么整个链表的数据都能get到,比如说GetHobList(),会直接获取hoblist的指针,而且第一个HOB总是为PHIT == Phase Handoff Information Table,里面是boot mode 其它HOB可能出现在List任意位置, 最重要的是System Memory HOB & Firmware Volumes, HOB列表总是会以END_OF_HOB_LIST结束 在这里插入图片描述 所以判定是否是HOBlist的最后一个一般都是while (!END_OF_HOB_LIST (Hob))。 在这里插入图片描述

下图中没有显示的另一个HOB类型是GUID HOB,它允许PEIM将私有数据传递给DXE驱动程序。 在这里插入图片描述 HOB TYPE 在这里插入图片描述 GUID类型的HOB是自定义HOB时候会用到的类型,通常用于自己写一些HOB信息。

HOB的使用 /** Add a new HOB to the HOB List. @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. @param Type Type of the new HOB. @param Length Length of the new HOB to allocate. @param Hob Pointer to the new HOB. @return EFI_SUCCESS Success to create HOB. @retval EFI_INVALID_PARAMETER if Hob is NULL @retval EFI_NOT_AVAILABLE_YET if HobList is still not available. @retval EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. **/ EFI_STATUS EFIAPI PeiCreateHob ( IN CONST EFI_PEI_SERVICES **PeiServices, IN UINT16 Type, //对于自定义的HOB 一般使用EFI_HOB_GUID_TYPE IN UINT16 Length, IN OUT VOID **Hob );

在这里插入图片描述 GetHobList()返回整个HOB列表中匹配GUID HOB的第一个实例 由于阶段不一样,PEI直接拿到HOB List Pointer, DXE通过System Configuration Table (gST)拿。

在这里插入图片描述

传入的参数第一个为Hob的GUID,所有的UEFI元素都有自己的GUID,传入得到的返回结果就是HOBlist ,通过的是configration table去抓的(属于systemtable的成员),每个DXE Driver的entrypoint都有两个参数imaginehandle 和systemtable,故而可以通过systemtable可以访问整个系统的资源。 在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3