OpenProtocol 和LocateProtocol() 的区别

it2022-05-05  152

一句话总结: 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).


最新回复(0)