UEFI Protocol使用

UEFI Protocol使用,第1张

启动服务提供了丰富的服务供开发者 *** 作Protocol,我们可以使用Protocol也可以开发Protocol。本文主要介绍如何使用Protocol。

  使用Protocol一般分为下面三个步骤:

    1. 通过启动服务找出Protocol对象;

    2. 使用这个Protocol提供的服务;

    3. 关闭打开的Protocol

  可以使用OpenProtocolInformation服务查看打开某个Protocol的所有设备。

  启动服务,有四种,分别为:OpenProtocol、HandleProtocol、LocateProtocol和LocalHandleBuffer。下面分别介绍它们

一、OpenProtocol 服务

  OpenProtocol 用于查询指定的Handle中是否支持指定的Protocol,如果支持,则打开该Protocol,否则返回错误代码。

  BS(启动时服务)中的OpenProtocol函数原型:

typedef

EFI_STATUS

(EFIAPI *EFI_OPEN_PROTOCOL) (

IN EFI_HANDLE Handle,

IN EFI_GUID *Protocol,

OUT VOID **Interface , OPTIONAL

IN EFI_HANDLE AgentHandle,

IN EFI_HANDLE ControllerHandle,

IN UINT32 Attributes

);

Handle:查询次Handle提供的Protocol

Protocol:要打开的Protocol(指向次Protocol GUID的指针)**Interface:返回打开的Protocol的对象AgentHandle:打开此Protocol的ImageControllerHandle:打开此Protocol的控制器Attributes:打开此Protocol的方式  Handle是Protocol的提供者,如果Handle的Protocols链表中有该Protocol,则Protocol对象的指针写到Interface,并返回EFI_SUCCESS,否则返回EFI_UNSUPPORTED。

  如果在驱动中调用OpenProtocol,则ControllerHandle是拥有该驱动的控制器,也就是请求使用这个Protocol的控制器;AgentHandle是拥有该EFI_DRIVER_BINDING_PROTOCOL对象的Handle。EFI_DRIVER_BINDING_PROTOCOL是UEFI驱动开发一定会用到的一个Protocol,它负责驱动的安装与卸载。

  如果调用OpenProtocol的是应用程序,那么AgentHandle是该用用程序的Handle,也就是UefiMain的第一个参数,ControllerHandle此时可以忽略。

二、HandleProtocol 服务

  OpenProtocol功能比较强大,但是使用比较复杂,需要提供Handle和Protocol的GUID,还要提供AgentHandle、ControllerHandle和Attributes。但是开发者大多时候只是想通过Protocol的GUID得到Protocol对象,并不关心打开方式细节。为了方便开发者使用Protocol,启动服务提供了HandleProtocol以简化打开Protocol。

  HandleProtocol服务的函数原型:

typedef

EFI_STATUS

(EFIAPI *EFI_HANDLE_PROTOCOL) (

IN EFI_HANDLE Handle,

IN EFI_GUID *Protocol,

OUT VOID **Interface

);

HandleProtocol 是OpenProtocol的简化版,在调用HandleProtocol时不必再传入AgentHandle、ControllerHandle和Attribute。它的内部其实仍是调用了OpenProtocol。

三、LocateProtocol 服务

  OpenProtocol和HandleProtocol用于打开指定设备上的某个Protocol,要使用这两个函数,首先要得到这个设备的句柄 。有时开发者并不关心Protocol在哪个设备上,尤其是系统仅有一个该Protocol的实例时。启动服务提供了LocateProtocol(…)服务,它可以从UEFI内核中找到指定Protocol的第一个实例。

  LocateProtocol服务函数原型:

typedef

EFI_STATUS

(EFIAPI *EFI_LOCATE_PROTOCOL) (

IN EFI_GUID *Protocol,

IN VOID *Registration,OPTIONAL

OUT VOID **Interface

);

UEFI内核中某个Protocol的实例可能不止一个,例如,每个硬盘及每个分区都有一个EFI_DISK_IO_PROTOCOL实例。LocateProtocol顺序搜索HANDLE链表,返回找到的第一个该Protocol的实例。

四、LocateProtocolBuffer服务

  前面三种是从设备上找出Protocol的方法。有时候开发者需要找出支持某个Protocol的所有设备,例如找出系统中所有安装了BlockIo的设备。LocateHandle和LocateProtocolBuffer提供这个服务。

typedef

EFI_STATUS

(EFIAPI *EFI_LOCATE_HANDLE_BUFFER) (

IN EFI_LOCATE_SEARCH_TYPE SearchType, //查找方式

IN EFI_GUID *Protocol OPTIONAL, //指定的Protocol

IN VOID *SearchKey OPTIONAL, //PROTOCOL_NOTIFY的类型

IN OUT UINTN *NoHandles, //返回找到的HANDLE数量

OUT EFI_HANDLE **Buffer //分配Handle数组并返回

);

五、其它Protocol 服务

  除了Protocol和根据Protocol找出设备这些常用服务,启动服务关于使用Protocol的服务还有ProtocolsPerHandle和OpenProtocolInformation。

六、CloseProtocol 服务

  Protocol使用完毕之后需要通过CloseProtocol关闭打开的Protocol。

  CloseProtocol函数原型:

typedef

EFI_STATUS

(EFIAPI *EFI_CLOSE_PROTOCOL) (

IN EFI_HANDLE Handle,

IN EFI_GUID *Protocol,

IN EFI_HANDLE AgentHandle,

IN EFI_HANDLE ControllerHandle

);

七、总结

  本部分,不住要讲解了Protocol的使用方法。Protocol提供了一种在UEFI应用程序以及UEFI驱动之间的通信方式。通过Protocol,用户可以使用驱动提供的服务,以及系统提供的其他服务。要熟悉自己使用的Protocol的数据结构。

一 、dec dsc inf文件

https://blog.csdn.net/yg2496194392/article/details/112199105

1 .inf文件

以下面 .inf文件为例

[Defines] # 块用于定义模块的属性和其他变量,块内定义的变量可被其他块引用

INF_VERSION = 0x00010006 #INF 标准的版本号, 前半部分主版本号,后半次版本号

BASE_NAME = Main #模块名字字符串,不能包含空格。它通常也是输出文件的名字 Main.efi

FILE_GUID = 4ea97c46-7491-4dfd-b442-747010f3ce5f#每个工程文件必须有一个8-4-4-4-12格式的GUID,用于生成固件

MODULE_TYPE = UEFI_APPLICATION # 定义模块的模块类型

VERSION_STRING = 0.1 # 模块的版本号字符串

ENTRY_POINT = ShellCEntryLib # 定义模块的入口函数

[Sources] # 用于列出模块的所有源文件和资源文件。 可选项体系结构相关块

Main.c # 块内每一行表示一个文件,根路径是工程文件所在的目录

[Packages] # 列出本模块引用到的所有包的包声明文件(.dec 文件)。

StdLib/StdLib.dec

MdePkg/MdePkg.dec

ShellPkg/ShellPkg.dec # 文件使用相对路径,相对路径的根路径为EDK2的根目录

[LibraryClasses] #块列出本模块要链接的库模块

LibC

LibStdio # 块内每一行声明一个要链接的库(库定义在包的.dsc 文件中,定义方法将在下文讲述

inf文件是模块的工程文件,其作用相当于Makefile 文件或Visual Studio 的.proj 文件,用于指导EDK2 编译工具自动编译模块;

工程文件分为多个块,每个块以“[ 块名]”开头,“[ 块名]”必须单独占一行。块又分为 工程文件必需块 和 工程文件非必需块

2 .dsc文件

.inf 用于编译一个模块, 而.dsc 文件用于编译一个Package, 它包含了[Defines]、

[LibraryClasses]、[Components] 几个必需部分以及[PCD]、[BuildOptions] 等几个可选部分。

3 .dec 文件

.dec 文件定义了公开的数据和接口,供其他模块使用。它包含了必需区块[Defines] 以及可选区块[Includes]、[LibraryClasses]、[Guids]、[Protocols]、[Ppis] 和[PCD] 几个部分。

.dec文件需要被调用模块.inf文件所包含。

实例:

vendor\qcom\nonhlos\BOOT.XF.4.2\boot_images\QcomPkg\SocPkg\StraitPkg\Library\MDPPlatformLib\MDPPlatformLibPanelCommon.c

调用了 TLLM中的 configgpio 接口

1、利用 LocateProtocol 接口,根据 gEfiTLMMProtocolGuid 查找 TLMMProtocol

gBS->LocateProtocol(&gEfiTLMMProtocolGuid, NULL, (void **)&TLMMProtocol)

2、然后利用 TLMMProtocol 的 ConfigGpio 接口,配置GPIO

TLMMDxe.c 中定义 protocol 的接口,其他模块想要调用里面的接口,只需在对应的 INF 文件中包含 TLLM 的 GUID 就可以

vendor/qcom/nonhlos/BOOT.XF.4.2/boot_images/QcomPkg/SocPkg/StraitPkg/Library/MDPPlatformLib/MDPPlatformLib.inf

vendor/qcom/nonhlos/BOOT.XF.4.2/boot_images/QcomPkg/Drivers/TLMMDxe$ ls

TLMMDxe.c TLMMDxe.inf

接口在如下定义

EFITLlmm.h 头文件定义GUID

QcomPkg.dec 中定义别名为 gEfiTLMMProtocolGuid,实质上和 .h头文件中定义的GUID值一样

参考了如下两篇:

https://blog.csdn.net/yg2496194392/article/details/112199105

UEFI原理与编程(九):UEFI中的Protocol使用方法_kaliopensourcextu的博客-CSDN博客_locateprotocol

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/722214.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-26
下一篇 2022-04-26

发表评论

登录后才能评论

评论列表(0条)

保存