//在设备句柄上安装协议接口。如果句柄不存在,则创建它并将其添加到系统中的句柄列表中。InstallMultipleProtocolInterfaces()比InstallProtocolInterface()执行更多的错误检查,所以建议使用InstallMultipleProtocolInterfaces()来代替InstallProtocolInterface()
EFI_STATUS
EFIAPI
CoreInstallProtocolInterface (
IN OUT EFI_HANDLE *UserHandle,
IN EFI_GUID *Protocol,
IN EFI_INTERFACE_TYPE InterfaceType,
IN VOID *Interface
)
//在设备句柄上重新安装协议接口
EFI_STATUS
EFIAPI
CoreReinstallProtocolInterface (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *Protocol,
IN VOID *OldInterface,
IN VOID *NewInterface
)
//从设备句柄中移除协议接口。建议使用uninstallmultipleprotocolinterface()来代替UninstallProtocolInterface()。
EFI_STATUS
EFIAPI
CoreUninstallProtocolInterface (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *Protocol,
IN VOID *Interface
)
//查询句柄以确定它是否支持指定的协议。
EFI_STATUS
EFIAPI
CoreHandleProtocol (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *Protocol,
OUT VOID **Interface
)
//查询句柄以确定它是否支持指定的协议。如果句柄支持协议,则它代表调用代理打开协议。
EFI_STATUS
EFIAPI
CoreOpenProtocol (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *Protocol,
OUT VOID **Interface OPTIONAL,
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ControllerHandle,
IN UINT32 Attributes
)
//关闭使用OpenProtocol()打开的句柄上的协议。
EFI_STATUS
EFIAPI
CoreCloseProtocol (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *Protocol,
IN EFI_HANDLE AgentHandle,
IN EFI_HANDLE ControllerHandle
)
//检索当前已打开协议接口的代理的列表。
EFI_STATUS
EFIAPI
CoreOpenProtocolInformation (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *Protocol,
OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
OUT UINTN *EntryCount
)
//检索安装在从池中分配的缓冲区句柄上的协议接口guid列表。
EFI_STATUS
EFIAPI
CoreProtocolsPerHandle (
IN EFI_HANDLE UserHandle,
OUT EFI_GUID ***ProtocolBuffer,
OUT UINTN *ProtocolBufferCount
)
//返回与给定协议匹配的第一个协议实例
EFI_STATUS
EFIAPI
CoreLocateProtocol (
IN EFI_GUID *Protocol,
IN VOID *Registration OPTIONAL,
OUT VOID **Interface
)
//将一个或多个协议接口安装到引导服务环境中。
EFI_STATUS
EFIAPI
CoreInstallMultipleProtocolInterfaces (
IN OUT EFI_HANDLE *Handle,
...
)
//将一个或多个协议接口移到启动服务环境中
EFI_STATUS
EFIAPI
CoreUninstallMultipleProtocolInterfaces (
IN EFI_HANDLE Handle,
...
)
-------------------------------------
1,安装Protocol
MdeModulePkg/Core/Dxe/Hand/Handle.c
CoreInstallProtocolInterface (
IN OUT EFI_HANDLE *UserHandle, // 将Protocol安装到本handle上,可为 NULL,必须指定
IN EFI_GUID *Protocol, // 待安装的Protocol,必须指定
IN EFI_INTERFACE_TYPE InterfaceType, // 直接是 EFI_NATIVE_INTERFACE,必须指定
IN VOID *Interface // 正在添加的协议的接口
)
---->MdeModulePkg/Core/Dxe/Hand/Handle.c
CoreInstallProtocolInterfaceNotify (
IN OUT EFI_HANDLE *UserHandle,
IN EFI_GUID *Protocol,
IN EFI_INTERFACE_TYPE InterfaceType,
IN VOID *Interface,
IN BOOLEAN Notify // 指示是否通知此协议的通知列表,这里是 TRUE.
)
/*1/若UserHandle为NULL,就分配IHANDLE空间,并填充结构IHANDLE。并添加到全局的管理链表gHandleList。
/*2/根据请求的协议EFI_GUID查找协议项PROTOCOL_ENTRY结构体。CoreFindProtocolEntry()
/*3/分派 PROTOCOL_INTERFACE 空间结构体。
/*4/将此协议接口添加到此句柄支持的协议列表的头部,将分派的PROTOCOL_INTERFACE结构,加入到handle管理链表中。
/*5/初始化OpenProtocol数据库。PROTOCOL_INTERFACE结构中的OpenList会维护一个打开本接口的列表。
/*6/将此协议接口添加到协议条目的末尾。将PROTOCOL_INTERFACE结构通过ByProtocol加入到PROTOCOL_ENTRY结构中的管理链表中,表示本接口已经被本protocol所管理。
/*7/通知此协议PROTOCOL_ENTRY的通知列表。协议入口中每个协议的信号事件。CoreNotifyProtocolEntry(),实际上是将所有的notify加入到待通知执行队列。
2,安装多个Protocol
MdeModulePkg/Core/Dxe/Hand/Handle.c
3,查询句柄以确定它是否支持指定的协议。
CoreHandleProtocol (
IN EFI_HANDLE UserHandle, //待查询句柄
IN EFI_GUID *Protocol, // 指定的协议
OUT VOID **Interface //提供指向相应协议接口的指针返回的地址。
)
---->
CoreOpenProtocol (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *Protocol,
OUT VOID **Interface OPTIONAL,
IN EFI_HANDLE ImageHandle, // 正在打开协议和接口指定的协议接口的映像的句柄。 gDxeCoreImageHandle
IN EFI_HANDLE ControllerHandle, //需要此接口的控制器句柄。 NULL
IN UINT32 Attributes //由句柄和协议指定的协议接口打开模式。EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
)
/*1/校验 UserHandle,Protocol,Interface ,Attributes。
/*2/校验Attributes
Check for invalid Attributes | ImageHandle | ControllerHandle | other |
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | √ | √ | UserHandle != ControllerHandle |
EFI_OPEN_PROTOCOL_GET_PROTOCOL | - | - | - |
EFI_OPEN_PROTOCOL_TEST_PROTOCOL | - | - | - |
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER | - | - | - |
EFI_OPEN_PROTOCOL_BY_DRIVER | √ | √ | - |
EFI_OPEN_PROTOCOL_EXCLUSIVE | √ | √ | - |
注意:校验实现
CoreValidateHandle (
IN EFI_HANDLE UserHandle
)//在 gHandleList 链表上,查询属于 EFI_HANDLE_SIGNATURE(“hndl”)的 EFI_HANDLE,是否与UserHandle相等。
/*3/在句柄的协议中定位某个GUID协议接口,返回 PROTOCOL_INTERFACE *Prot;指针。
CoreGetProtocolInterface (
IN EFI_HANDLE UserHandle, //获取协议接口的句柄
IN EFI_GUID *Protocol //The GUID
)//遍历UserHandle上所有的PROTOCOL_INTERFACE结构,然后获得PROTOCOL_ENTRY,对比Protocol ,也就是GUID。相等返回PROTOCOL_ENTRY结构地址。
/*4/查看每个协议接口是否匹配,遍历协议接口PROTOCOL_ENTRY,的openlist链表上所有的OPEN_PROTOCOL_DATA结构,如果本结构的AgentHandle,Attributes,ControllerHandle的与传入的是否均相等。
OpenData->Attributes | EFI_OPEN_PROTOCOL_EXCLUSIVE | !EFI_OPEN_PROTOCOL_EXCLUSIVE |
EFI_OPEN_PROTOCOL_BY_DRIVER | 相等:驱动已被管理&独占=done 不相等:驱动已被管理&独占 |
相等:驱动已被管理&独占=done 不相等:驱动已被管理&共享 |
!EFI_OPEN_PROTOCOL_BY_DRIVER | 相等:驱动未被管理&独占=done 不相等:驱动未被管理&独占 |
相等:驱动未被管理&共享 不相等: |
/*5/如果驱动是共享的,不是独占访问的,且驱动已经被管理。再次遍历链表上所有的OPEN_PROTOCOL_DATA结构,并执行CoreDisconnectController()。
/*6/对于情况下,创建新的OPEN_PROTOCOL_DATA结构,并填充添加到openlist链表中。
/*7/若驱动 不是EFI_OPEN_PROTOCOL_TEST_PROTOCOL打开方式。返回 PROTOCOL_INTERFACE中的接口指针。
4,打开Protocol
MdeModulePkg/Core/Dxe/Hand/Handle.c
见CoreHandleProtocol()。