UEFI基础概念2——Handle和Protocol

一、Handle

Handle Database是由Handle和Protocol组成。Handle(句柄)是一个或多个协议的集合,Protocol(协议)是由GUID命名的数据结构。
在平台初始化过程中,系统固件、UEFI兼容驱动程序和UEFI应用程序创建句柄,并将一个或多个协议附加到句柄上。
句柄数据库是UEFI句柄的列表,是维护基于UEFI固件的对象的中央存储库。每个由唯一句柄号标识的UEFI句柄由系统固件维护。句柄号为句柄数据库中的条目提供数据库“键”。句柄数据库中的每个条目都是一个或多个协议的集合。由GUID命名的协议类型附加到UEFI句柄并确定句柄类型。
UEFI句柄可以表示以下组件:

1) 可执行映像(如UEFI驱动程序和UEFI应用程序)

2) 设备(如网络控制器和硬盘分区)

3) 作为驱动程序访问的UEFI服务(如EFI解压缩和EBC解释器)

如上图所示,只有一个Handle Database,所有的Handle 都在其中。值得注意的是Handle database并不区分Hanble的类型。Handle是由相关联的Protocol类型区分的。

使用协议的GUID名称在句柄数据库中注册协议服务,通过使用与协议关联的GUID名称在句柄数据库中查找协议来发现协议服务,以执行查找操作。

二、Protocol

2.1 Protocold的概念

UEFI的可扩展性很大程度上是围绕Protocol建立的。Protocol能够在独立的模块(包括驱动)之间进行通信。

驱动程序创建由两部分组成的protocol。Protocol的主体是一种C风格的数据结构,称为“协议接口结构”,简称为“接口”。接口通常包含一组相关的函数指针和数据结构。每个协议都有一个GUID,GUID作为协议名称,同样可以指示协议的数据结构。但是GUID不是数据结构的一部分。

下图是一个Protocol示例,包含两个函数和一个数据

协议被收集到一个数据库中,数据库将协议分为很多组,每组称为作为一个Handle,Handle也可以看成组的数据类型。句柄是动态分配的,即Handle不是启动时预先分配好的,而是需要的时候由UEFI固件动态创建的。每个句柄中不能有两个相同的GUID的Protocol。 

2.2 Protocol的产生与消耗

 Protocol用于模块之间的通信。为了建立这种通信吗,其中一个模块需要produce Protocol,而另外一个模块需要consume Protocol。

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

1、通过启动服务找到protocol实例

2、使用这个protocol提供的服务

3、关闭打开的protocol

常用过的Protocol接口函数如下所示:

 一般来说,生产者需要利用InstallProtocolInterface()或InstallMutipleProtocolInterface()在设备句柄上安装protocol接口,如果没有这个句柄,将创建这个句柄并添加到系统句柄列表中。InstallMutipleProtocolInterface()会执行更多的检查工作。调用者需要利用LocateProcotol\HandleProtocol\OpenProtocol找到协议实例。但是三者的使用是由区别的。

LocateProcotol():返回第一个与Protocol匹配的Protocol接口的指针,这个函数会查找第一个支持Protocol的设备句柄,并返回该协议的指针。

typedef
EFI_STATUS
(EFIAPI *EFI_LOCATE_PROTOCOL)(
  IN  EFI_GUID  *Protocol, //协议的GUID
  IN  VOID      *Registration  OPTIONAL, //RegisterProtocolNotify()返回的注册码
  OUT VOID      **Interface //On return, a pointer to the first interface that matches Protocol and Registration.输出参数,指向第一个与协议匹配的protocol接口,如果接口没有实例,接口为NULL
  );

HandleProtocol():查询Handle是否支持指定的Protocol,如果支持返回指向protocol 接口的指针。在使用这个函数的时候可以先利用LocateHandle()返回支持指定协议的handle,再去寻找Protocol接口。

typedef
EFI_STATUS
(EFIAPI *EFI_HANDLE_PROTOCOL)(
  IN  EFI_HANDLE               Handle, //要查询的句柄
  IN  EFI_GUID                 *Protocol, //要查询的protocol的GUID
  OUT VOID                     **Interface //输出参数,指向与protocol匹配的接口的指针
  );

OpenProtocol():会查询句柄是否支持指定的protocol。如果支持将会代替调用者打开protocol。它是HandleProtocol的扩展版本,区别在于OpenProtocol打开protocol interface的代理在EFI的句柄数据库中被跟踪。UEFI驱动模型使用跟踪功能,也用于确定卸载或重新安装协议接口是否安全。

typedef
EFI_STATUS
(EFIAPI *EFI_OPEN_PROTOCOL)(
  IN  EFI_HANDLE                Handle, //要查询的句柄
  IN  EFI_GUID                  *Protocol, //指定的协议
  OUT VOID                      **Interface  OPTIONAL,//输出参数,指向protocol
  IN  EFI_HANDLE                AgentHandle,
  IN  EFI_HANDLE                ControllerHandle,
  IN  UINT32                    Attributes
  );

Protocol的简单使用见博客UEFI——Protocol的简单使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值