前面很多程序一直在使用各种 Protocol 提供的服务,《UEFI 原理与编程》第五章是关于 UEFI基础服务的,正好借着本章,总结一下如何查找和调用 Protocol。
要使用Protocol,首先要知道使用哪个 Protocol ,它的名字就是 GUID。比如:gEfLoadedImageProtocolGuid ,他是 EFI_GUID类型。
启动服务(Boot Services)提供了下面一些服务用来查找指定的 Protocol。
OpenProtocol | 打开指定句柄上面的 Protocol |
HandleProtocol | 上面的OpenProtocol对于参数要求比较复杂,HandleProtocol可以看做是前者的简化版本。 |
LocateProtocol | 用于找出给定的 Protocol 在系统中的第一个实例。当你确定系统中只有一个 Protocol 的时候可以使用这个函数。比如,查找系统中的 EfiShellProtocol |
LocateHandleBuffer | 和上面的类似,差别在于这个函数能够给出系统中所有的支持给定 Protocol 设备的 Handle。比如,找到系统中所有支持 BlockIO 的设备 |
下面分别介绍每个函数:
1. OpenProtocol 原型定义可以在这支文件中看到 \MdePkg\Include\Uefi\UefiSpec.h
/** Queries a handle to determine if it supports a specified protocol. If the protocol is supported by the handle, it opens the protocol on behalf of the calling agent. @param[in] Handle The handle for the protocol interface that is being opened. @param[in] Protocol The published unique identifier of the protocol. @param[out] Interface Supplies the address where a pointer to the corresponding Protocol Interface is returned. @param[in] AgentHandle The handle of the agent that is opening the protocol interface Specified by Protocol and Interface. @param[in] ControllerHandle If the agent that is opening a protocol is a driver that follows the UEFI Driver Model, then this parameter is the controller handle that requires the protocol interface. If the agent does not follow the UEFI Driver Model, then this parameter is optional and may be NULL. @param[in] Attributes The open mode of the protocol interface specified by Handle and Protocol. @retval EFI_SUCCESS An item was added to the open list for the protocol interface, and the protocol interface was returned in Interface. @retval EFI_UNSUPPORTED Handle does not support Protocol. @retval EFI_INVALID_PARAMETER One or more parameters are invalid. @retval EFI_ACCESS_DENIED Required attributes can't be supported in current environment. @retval EFI_ALREADY_STARTED Item on the open list already has requierd attributes whose agent handle is the same as AgentHandle. **/ typedef EFI_STATUS (EFIAPI *EFI_OPEN_PROTOCOL)( IN EFI_HANDLE Handle, //指定在哪个 Handle 上查找 Protocol IN EFI_GUID *Protocol,//查找哪个 Protocol OUT VOID **Interface, OPTIONAL //返回打开的 Protocol 对象 IN EFI_HANDLE AgentHandle, //打开此 Protocol 的Image(书上说的,我并不理解) IN EFI_HANDLE ControllerHandle, //使用此 Protocol的控制器 IN UINT32 Attributes //打开 Protocol 的方式 );
2. HandleProtocol 和前面的那个函数相比,调用参数上简单多了。 原型定义可以在这支文件中看到 \MdePkg\Include\Uefi\UefiSpec.h
/** Queries a handle to determine if it supports a specified protocol. @param[in] Handle The handle being queried. @param[in] Protocol The published unique identifier of the protocol. @param[out] Interface Supplies the address where a pointer to the corresponding Protocol Interface is returned. @retval EFI_SUCCESS The interface information for the specified protocol was returned. @retval EFI_UNSUPPORTED The device does not support the specified protocol. @retval EFI_INVALID_PARAMETER Handle is NULL. @retval EFI_INVALID_PARAMETER Protocol is NULL. @retval EFI_INVALID_PARAMETER Interface is NULL. **/ typedef EFI_STATUS (EFIAPI *EFI_HANDLE_PROTOCOL)( IN EFI_HANDLE Handle, //打开 Handle上面的 IN EFI_GUID *Protocol, //GUID给定的Protocol OUT VOID **Interface //打开之后放在这里 );
3. LocateProtocol 前面两个函数都是用来打开特定 Handle 上的Protocol,如果我们不知道需要的Protocol 在哪个Handle上,就可以用这个函数。调用参数上简单多了. 原型定义可以在这支文件中看到\MdePkg\Include\Uefi\UefiSpec.h
/** Returns the first protocol instance that matches the given protocol. @param[in] Protocol Provides the protocol to search for. @param[in] Registration Optional registration key returned from RegisterProtocolNotify(). @param[out] Interface On return, a pointer to the first interface that matches Protocol and Registration. @retval EFI_SUCCESS A protocol instance matching Protocol was found and returned in Interface. @retval EFI_NOT_FOUND No protocol instances were found that match Protocol and Registration. @retval EFI_INVALID_PARAMETER Interface is NULL. **/ typedef EFI_STATUS (EFIAPI *EFI_LOCATE_PROTOCOL)( IN EFI_GUID *Protocol, //要打开的 Protocol IN VOID *Registration, OPTIONAL //从 RegisgerProtocolNotify() 获得的Key (不懂) OUT VOID **Interface //返回找到的对个匹配的 Protocol 实例 );
4. LocateHandleBuffer 这个函数用来找出支持某个 Protocol的所有设备, 原型定义可以在这支文件中看到 \MdePkg\Include\Uefi\UefiSpec.h
/** Returns an array of handles that support a specified protocol. @param[in] SearchType Specifies which handle(s) are to be returned. @param[in] Protocol Specifies the protocol to search by. @param[in] SearchKey Specifies the search key. @param[in, out] BufferSize On input, the size in bytes of Buffer. On output, the size in bytes of the array returned in Buffer (if the buffer was large enough) or the size, in bytes, of the buffer needed to obtain the array (if the buffer was not large enough). @param[out] Buffer The buffer in which the array is returned. @retval EFI_SUCCESS The array of handles was returned. @retval EFI_NOT_FOUND No handles match the search. @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small for the result. @retval EFI_INVALID_PARAMETER SearchType is not a member of EFI_LOCATE_SEARCH_TYPE. @retval EFI_INVALID_PARAMETER SearchType is ByRegisterNotify and SearchKey is NULL. @retval EFI_INVALID_PARAMETER SearchType is ByProtocol and Protocol is NULL. @retval EFI_INVALID_PARAMETER One or more matches are found and BufferSize is NULL. @retval EFI_INVALID_PARAMETER BufferSize is large enough for the result and Buffer is NULL. **/ typedef EFI_STATUS (EFIAPI *EFI_LOCATE_HANDLE)( IN EFI_LOCATE_SEARCH_TYPE SearchType, //查找方法 IN EFI_GUID *Protocol, OPTIONAL //指定的 Protocol IN VOID *SearchKey, OPTIONAL //PROTOCOL_NOTIFY 类型 IN OUT UINTN *BufferSize, //找到的Handle数量 OUT EFI_HANDLE *Buffer //返回的 Handle Buffer );
其中EFI_LOCATE_SEARCH_TYPE 可以定义为下面几种类型
/// /// Enumeration of EFI Locate Search Types /// typedef enum { /// /// Retrieve all the handles in the handle database. /// AllHandles, //返回当前系统中的全部 Handle /// /// Retrieve the next handle fron a RegisterProtocolNotify() event. /// ByRegisterNotify, //搜索从 RegisterProtocolNodify 中找出匹配SearchKey的 Handle /// /// Retrieve the set of handles from the handle database that support a /// specified protocol. /// ByProtocol //返回系统Handle数据可中支持指定Protocol的HANDLE } EFI_LOCATE_SEARCH_TYPE;
楼主,我使用LocateProtocol 返回EFI_NOT_FOUND,怎么查找原因,用的是一个自己定义的GUID
你试试 dh 看看有没有你定义的 guid 如果没有那应该是你没有加载成功