Step to UEFI (99)使用 Protocol的总结

前面很多程序一直在使用各种 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;


 

《Step to UEFI (99)使用 Protocol的总结》有2个想法

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注