欢迎关注全是干货的技术号
JavaEdge
1 UEFI 内核下的 Protocol
1.1 EFI_HANDLE
指向某种对象的指针,UEFI用其表示某个对象。
UefiBaseType.h
// 相关接口的集合.
typedef VOID *EFI_HANDLE;
UEFI 扫描总线后,为每个设备建立一个Controller对象,来控制该设备,
所有该设备的驱动以Protocol的形式安装到该Controller上,这个Controller就是一个EFI_HANDLE对象。
在UEFI内部,EFI_HANDLE被理解为IHANDLE,其结构如下:
edk2/MdeModulePkg/Core/Dxe/Hand/Handle.h
// IHANDLE -包含Protocol handle 链表
typedef struct {
UINTN Signature;
// 所有IHandle组成的链表
LIST_ENTRY AllHandles;
// List of PROTOCOL_INTERFACE's for this handle 该Handle下的Protocol链表
LIST_ENTRY Protocols;
UINTN LocateRequest;
// The Handle Database Key value when this handle was last created or modified
// 上次创建或修改此handle 时的Handle Database Key值
UINT64 Key;
} IHANDLE;
在该结构体中,重要的为
1.2 LIST_ENTRY
edk2/MdePkg/Include/Base.h
// LIST_ENTRY 结构定义.
typedef struct _LIST_ENTRY LIST_ENTRY;
// _LIST_ENTRY 结构定义.
struct _LIST_ENTRY {
LIST_ENTRY *ForwardLink;
LIST_ENTRY *BackLink;
};
由此可见 IHANDLE 包含两个双向链表
- 一条用于串联所有 IHANDLE 实例,因为串联的是两个 IHANDLE 结构体中 AllHandles 成员变量,因此会利用到 _CR 宏
宏主要利用成员在结构体中的偏移量得到结构体的基地址
具体实现在./BaseTools/Source/C/Include/Common/BaseTypes.h - 另外一条用于串联该handle所有的 PROTOCOL_INTERFACE
1.3 PROTOCOL_INTERFACE
edk2/MdeModulePkg/Core/Dxe/Hand/Handle.h
// PROTOCOL_INTERFACE - 使用该结构跟踪安装在 handle 上的每个 protocol
typedef struct {
UINTN Signature;
/// Link on IHANDLE.Protocols
LIST_ENTRY Link;
/// Back pointer
IHANDLE *Handle;
/// Link on PROTOCOL_ENTRY.Protocols
LIST_ENTRY ByProtocol;
/// The protocol ID
PROTOCOL_ENTRY *Protocol;
/// The interface value
VOID *Interface;
/// OPEN_PROTOCOL_DATA list
LIST_ENTRY OpenList;
UINTN OpenListCount;
} PROTOCOL_INTERFACE;
其中PROTOCOL_ENTRY的定义,在同文件内可以看到定义
// PROTOCOL_ENTRY - Each handler that supports this protocol is listed, along with a list of registered notifies.
// 每个不同的 protocol 在 protocol 数据库中都有1个 entry
// 列出了支持该 protocol 的每个处理程序以及已注册通知的链表
typedef struct {
UINTN Signature;
/// Link Entry inserted to mProtocolDatabase
LIST_ENTRY AllEntries;
/// ID of the protocol
EFI_GUID ProtocolID;
/// All protocol interfaces
LIST_ENTRY Protocols;
/// Registerd notification handlers
LIST_ENTRY Notify;
} PROTOCOL_ENTRY;
在该结构体中可以找到对应Protocol的 GUID
GUID的三种形式
一:3a738b36-b9c5-4763-abbd-6cbd4b25f9ff
二:{ 0x36, 0x8b, 0x73, 0x3a, 0xc5, 0xb9, 0x63, 0x47, 0xab, 0xbd, 0x6c, 0xbd, 0x4b, 0x25, 0xf9, 0xff }
三:{ 0x368b733a, 0xc5b9, 0x630x47, { 0xab, 0xbd, 0x6c, 0xbd, 0x4b, 0x25, 0xf9, 0xff } }
生成GUID的网站
https://www.guidgen.com
1.4 小结
IHANDLE内的Protocol组织图
总体来说主要由三条链表将这些数据结构串在一起
- 一条为所有Handle串成的链表Handle Database
- 一条为Protocol串起的Protocol Database
- 第三条为PROTOCOL_INTERFACE串起的链表
如下图