一句话总结: OpenProtocol() 需要传入handle 作为参数, 而LocateProtocol 不需要。
LocateProtocol() 和 OpenProtocol() 都是找到一个自己想要的interface . 对于consumer(driver)来说,可以通过
GUID 在handle database 里面找到自己想要的protocol, 对于service protocol 如果在handle database 里面只存在一份
instance(实列,即函数实现), consumer 可以使用LocateProtocol() 来达到目的。如果在handle database 里面,多个
handle 上面都有我们想要找的那个protocol , 那么我们可以先用LocateHandleBuffer() 找到所有符合条件的handle(handle
上面有我们想要找的protocol) , 然后通过通过OpenProtocol()在一个特定的handle 上面找到我们想要的protocol.
函数原型如下:
/** 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. Protocol is NULL. **/ typedef EFI_STATUS (EFIAPI *EFI_LOCATE_PROTOCOL)( IN EFI_GUID *Protocol, IN VOID *Registration, OPTIONAL OUT VOID **Interface );可以看到 LocateProtocol 只需要传入一个参数(GUID) 即可。
而对于OpenProtocol ,传入的第一个参数即为Handle
/** 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, IN EFI_GUID *Protocol, OUT VOID **Interface, OPTIONAL IN EFI_HANDLE AgentHandle, IN EFI_HANDLE ControllerHandle, IN UINT32 Attributes );
典型用法举例:
// // Retrieve the array of handles that support Protocol // Status = gBS->LocateHandleBuffer ( ByProtocol, Protocol, NULL, &NoHandles, &HandleBuffer ); if (EFI_ERROR (Status)) { return Status; } // // Allocate array of protocol instances // Status = gBS->AllocatePool ( EfiBootServicesData, NoHandles * sizeof (VOID *), (VOID **)Buffer ); if (EFI_ERROR (Status)) { // // Free the handle buffer // gBS->FreePool (HandleBuffer); return EFI_OUT_OF_RESOURCES; } ZeroMem (*Buffer, NoHandles * sizeof (VOID *)); // // Lookup Protocol on each handle in HandleBuffer to fill in the array of // protocol instances. Handle case where protocol instance was present when // LocateHandleBuffer() was called, but is not present when HandleProtocol() // is called. // for (Index = 0, *NoProtocols = 0; Index < NoHandles; Index++) { Status = gBS->HandleProtocol ( HandleBuffer[Index], Protocol, &((*Buffer)[*NoProtocols]) ); if (!EFI_ERROR (Status)) { (*NoProtocols)++; } }即分两步:
1. // Retrieve the array of handles that support Protocol
2. // // Lookup Protocol on each handle in HandleBuffer to fill in the array of // protocol instances. Handle case where protocol instance was present when // LocateHandleBuffer() was called, but is not present when HandleProtocol() // is called. //
翻译成中文就是, 先找到所有符合条件的Handle, 然后从每个符合条件的handler 中取出自己想要的protocol (interface).