OpenProtocol 和LocateProtocol() 的区别

一句话总结: 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
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值