uefi driver 大致实现方法 1. 使用OpenProtocol() 打开所有需要用到的protocol, OpenProtoco参数列表里面有一个 Attribute。 如果这个driver 允许打开的 protocol 和其他的driver 共用,这时候,就用EFI_OPEN_PROTOCOL_BY_DRIVER 作为Attribute, 反之,如果这个driver 不允许其他的 driver 共享打开的protocol, 就用 OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE. 2. 如果第一步OpenProtocol 执行出现了任何差错,要用CloseProtocol 关掉所有已经打开的Protocol, 并返回错误代码。 3. 创建RemaingDevicePath 指定的子设备。 4. 初始化ControllerHandle 指定的device. 5. 按 ControllerHandle 分配并初始化所有的数据结构(结构体)。 6. 使用InstallProtocolInterface() 向ControllerHandle 上安装相应的protocol. 7. 返回 EFI_SUCCESS
在符合EFI driver 模型的驱动里,不可避免的要用到 gBS->OpenProtocol. 这篇文章就详细说说Open protocol 的实现。 OpenProtocol 的原型是 CoreOpenProtocol , 它的实现在Handle.c 里面。
函数原型及参数解释: 首先: 多个protocol 构成的handle, 如果handle的protocol 链表里面有想要找的Protocol, 则Protocol 对象的指针写到*Interface。从handle 上去找到想要的Protocol,利用(invoke) 它去获得相应的interface. 最后将相关信息注册到 protocol 数据库里面(通过向链表插入的方法InsertTailList (&Prot->OpenList, &OpenData->Link);) 962: 获得protocol 的handle.我们将要在这个handle 上面去找我们想要的protocol. 963: Protocl 的guid. 964: 得到的interface 的位置(应该是在内存中的地址) 963 和 964 搭配起来,一般长成这个样子: 09576E91-6D3F-11D2-8E39-00A0C969723B 8A60B918 后面是 interface 的位置。 965:打开此protocol 的Image。 966: 需要这个interface 的controller handle. 970 : 打开模式(方式),一共有六个取值。
独占这个protocol, 不与其它driver 共享,如果Protocol已经打开,则再次打开时将失败
#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020
#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002
#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004
#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008
#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010
独占这个protocol, 不与其它driver 共享,如果Protocol已经打开,则再次打开时将失败
#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020
接下来,是一系列的参数(合法性)检查:
997-1002: 如果想要查找的protocol 为空,则返回 EFI_INVALID_PARAMETER
1004-1013: 如果Attribute 为 EFI_OPEN_PROTOCOL_TEST_PROTOCOL , 那么仅仅只要检查UserHandle上是否有安装有我们想要的protocol.
1015-1021: 对UserHandle 合法性进行检查。就是看 Handle的Signature 是否为 EFI_HANDLE_SIGNATURE
接下来,还是参数检查,不过这回根据不同的Attribute会作简单的区分。
1065-1068 : 锁住protocol 数据库
1070-1083 : 在Userhandle 上面去找由guid 所指定的protocol.通过compareGuid .个人认为,这几行是openprotocol 的核心部分。前半部分是在UserHandle 上面找到了 Protocol, 后半部分将找到的Protocol 赋值给Interface。
1089-1093 : 遍历openlist, 为每一个OpenData 赋值。
1094-1095: 如果打开请求为BY_DRIVER , 将ByDriver 置1.
1096-1099: 表示同一个 AgentHandle 和ControllerHandle 被第二次打开,返回 EFI_ALREADY_STARTED;
1101-1108:如果已经存在Exclusive的打开请求,将Exclusive 置1. 如果不是,将OpenCount 加1
断开已经存在的链接。
1160-1175: 分配一个entry, 并往其结构中填充相应的值,最后插入到Openlist中。
1181: 释放协议数据库锁。
|