Protocol 在 UEFI 内核中的表示
typedef VOID *EFI_HANDLE;
EFI_HANDLE是指向某种对象的指针,UEFI 用它来表示某个对象。
 UEFI 扫描总线后,会为每个设备建立一个 Controller 对象,用于控制设备,所有该设备的驱动以 Protocol 的形式安装到这个 Controller 中,这个 Controller 就是一个 EFI_HANDLE 对象。当我们将-个.ef文件加载到内存中时,UEFI 也会为该文件建立一个Image对象,这个 Image 对象也是一个EFI_HANDLE对象。在 UEFI内部,EFI_HANDLE 被理解为IHANDLE。
每个 IHANDLE 中都有一个Protocols链表,存放属于自己的 Protocol。所有的IHANDLE通过AllHandles链接起来。
 IHANDLE的Protocols是一个双向链表,链表中每一个元素是PROTOCOL_INTERFACE,通过PROTOCOL_INTERFACE的Protocol指针可以得到这个Protocol的GUID,通过Interface指针可以得到这个Protocol的实例。
 
使用 Protocol 服务
启动服务提供了丰富的服务供开发者操作 Protocol,操作分两种,一种是使用 Protocol 另一种是产生 Protocol。
要使用 Protocol,首先要根据 GUID 找到 Protocol 对象,启动服务提供了 OpenProtocol(...)、HandleProtocl(...)和LocateProtocol(...) 三种服务用于找出指定的 Protocol。
 OpenProtocol 用于打开指定句柄上的 Protocol;HandleProtocol 是 OpenProtocol 的简化版;
 LocateProtocol 用于找出指定的 Potocol 在系统中的第一个实例。
 使用完 Protocol 后还要关闭打开的 Protocol,否则可能会造成内存泄漏。
除了打开和关闭 Protocol,有时还需要找出能支持某个 Protocol 的所有设备,这时就要用到启动服务提供的LocalHandleBuffer 服务。
使用 Protocol 的三个步骤:
 1)通过 gBS->OpenProtocol(或 HandleProtocol、LocateProtocol)找出 Protocol 对象;
 2)使用这个 Protocol 提供的服务;
 3)通过 gBS->CloseProtocol 关闭打开的 Protocol。
如果想知道某个 Protocol 被哪些设备打开了,那么可以使用OpenProtocolInformation 服务。
OpenProtocol 服务
OpenProtocol 用于查询指定的Handle中是否支持指定的Protocol,如果支持,则打开该Protocol,否则返回错误代码。
Status = gBS->OpenProtocol(…)
Handle 是 Protocol 的提供者,如果 Handle 的 Protocols 链表中有该 Protocol,则 Protocol 对象的指针写到 *Interface,并返回EFI_SUCCESS;否则返回EFI_UNSUPPORTED。

如果在驱动中调用 OpenProtocol(),则 ControllerHandle是拥有该驱动的控制器,也就是请求使用这个 Protocol 的控制器;AgentHandle 是拥有该EFI_DRIVER_BINDING_PROTOCOL对象的 HandIe。
 EFI_DRIVER_BINDING_PROTOCOL是UEFI驱动开发中一定会用到的一个Protocol,它负责驱动的安装与卸载。
如果调用 OpenProtocol 的是应用程序,那么AgentHandle 是该应用程序的 Handle,也就是 UefiMain 函数的第一个参数,ControllerHandle 此时可以忽略。

Attributes可以取以下 6 种值:

HandleProtocol 服务
OpenProtocol 功能很强大,但使用起来也比较复杂,除了要提供Handle和Protocol的GUID,还要提供 AgentHandle、ControllerHandle和Attributes。
 大部分情况下,开发者只是想通过 Protocol的 GUID得到 Protocol对象,并不关心打开方式的细节。
 HandleProtocol 是OpenProtocol的简化版,在调用HandleProtocol时不必再传入AgentHandle、ControllerHandle 和 Attributes 的值。
 AgentHandle 使用gDxeCorelmageHandle,ControllerHandle 使用NULL值,Attributes 则使用EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL


LocateProtocol 服务
LocateProtocol(...)服务,它可以从 UEFI 内核中找出指定 Protocol 的第一个实例。
 
 
 UEFI 内核中某个 Protocol 的实例可能不止一个。LocateProtocol 顺序搜索 HANDLE链表,返回找到的第一个该 Protocol的实例。
LocateHandleBuffer 服务
有时候需要找出支持某个 Protocol 的所有设备,例如找出系统中的所有安装了Blocklo的设备,LocateHandleBuffer和LocateHandle服务提供了这个功能。
 
SearchType 有三种:

 AllHandles 用于找出系统中的所有Handle;
 ByRegisterNotify用于从 RegisterProtocolNotify 中找出匹配 SearchKey的Handle;
 ByProtocol 用于从系统 Handle 数据库中找出支持指定Protocol的HANDLE。

LocateHandle 服务与 LocateHandleBuffer的最大区别是需有调用者负责管理 Buffer 数组占用的内存。
其他 Protocol 服务
-  ProtocolsPerHandle用于获得指定设备所支持的所有Protocol。这些Protocol的GUID通过ProtocolBuffer返回给调用者,UEFI 负责分配内存给ProtocolBuffer,调用者负责释放该内存;
-  OpenProtocollnformation用于获得指定设备上指定Protocol的打开信息;
-  Protocol使用完毕后要通过CloseProtocol关闭打开的Protocol。- 通过 HandleProtocol和LocateProtocol打开的Protocol因为没有指定 AgentHandle,所以无法关闭。如果一定要关闭它,则要调用OpenProtocolInformation()获得AgentHandle和ControllerHandle,然后关闭它。
 
- 通过 
总结

内容来自于《UEFI 原理与编程》。。。













![[网安靶场] [更新中] UPLOAD LABS —— 靶场笔记合集](https://csdnimg.cn/release/blog_editor_html/release2.3.7/ckeditor/plugins/CsdnLink/icons/icon-default.png?t=O83A)





