UEFI开发学习5 - Protocol的简单使用

1 介绍

在UEFI Spec的第七章可以看到,Boot Service中提供了丰富的服务供开发者操作Protocol,本文主要介绍如何使用Protocol。
使用Protocol一般分为三个步骤:
1、通过启动服务找出Protocol对象;
2、使用这个Protocol提供的服务;
3、关闭打开的Protocol。
先介绍一下一些相关的服务,有:HandleProtocol、OpenProtocol、LoacalHandleBuffer和LocateProtocol。

1.1 HandleProtocol

这个服务的作用是查询Handle以确定它是否支持某个Protocol。如果支持,那么在返回时,参数Interface指向一个相应Protocol Interface的指针。然后可以将Interface传递给任何protocol service,以标识请求的上下文。
函数原型为:

typedef
EFI_STATUS
(EFIAPI *EFI_HANDLE_PROTOCOL) (
	IN EFI_HANDLE Handle,
	IN EFI_GUID *Protocol,
	OUT VOID **Interface
);

Note:所有新的applications和drivers推荐使用OpenProtocol()来代替HandleProtocol()。

1.2 OpenProtocol

OpenProtocol用于查询指定的Handle中是否支持指定的Protocol,如果支持,则打开该Protocol,否则返回错误代码。它是HandleProtocol的扩展版本。它与HandleProtocol的区别是,打开protocol interface的代理在EFI内部的handle数据库中被跟踪。UEFI驱动模型使用跟踪功能,也用于确定卸载或重新安装协议接口是否安全。
打开protocol interface的代理由AgentHandle、ControllerHandle和Attributes确定。如果protocol interface可以打开,AgentHandle、ControllerHandle和Attributes将会添加到使用Handle和Protocol指定的protocol interface的代理列表中。
这个函数调用可能返回错误的原因有很多。如果出错就仔细对照Spec吧。
函数原型为:

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
);

1.3 LocateHandleBuffer

在池中分配的缓冲区中返回支持请求的protocol的handle数组。这个函数返回一个或多个匹配参数SearchType要求的handle。
函数原型为:

typedef
EFI_STATUS
(EFIAPI *EFI_LOCATE_HANDLE_BUFFER) (
	IN EFI_LOCATE_SEARCH_TYPE SearchType,
	IN EFI_GUID *Protocol OPTIONAL,
	IN VOID *SearchKey OPTIONAL,
	OUT UINTN *NoHandles,
	OUT EFI_HANDLE **Buffer
);

1.4 LocateProtocol

返回匹配给定protocol的第一个protocol实例。LocateProtocol()函数找到第一个支持Protocol的设备句柄,并在参数interface中返回一个指向protocol interface的指针,如果没有找到协议实例,则参数interface设置为NULL。
函数原型:

typedef
EFI_STATUS
(EFIAPI *EFI_LOCATE_PROTOCOL) (
	IN EFI_GUID *Protocol,
	IN VOID *Registration OPTIONAL,
	OUT VOID **Interface
);

2 使用

以LocateProtocol为例,首先创建一个Module,新建MyUseProtocol.inf和MyUseProtocol.c。
在EmulatorPkg.dsc文件的[Components]下添加EmulatorPkg/Application/MyUseProtocol
/MyUseProtocol.inf。
注意inf文件中的FILE_GUID不能自己瞎编造一个,本来我以为只要满足这个格式就行,但发现编译不通过,可能GUID的生成还是有一些规则的。然后在inf文件的[Protocols]下加上我们需要使用的Protocol的guid。这里我使用的是gEfiDevicePathProtocolGuid。
MyUseProtocol.c文件内容为:

#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiApplicationEntryPoint.h>

EFI_STATUS 
EFIAPI
UefiMain(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE *SystemTable)
{
    EFI_STATUS Status;
    VOID *Protocol;
    Status = SystemTable->BootServices->LocateProtocol (
						&gEfiDevicePathProtocolGuid,
						NULL,
						(VOID**) &Protocol
						);
    if (EFI_ERROR(Status))
    {
        SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Use Fail!\n");   
    } else {
        SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Use Success!\n");
    }	
    return EFI_SUCCESS;
}

编译之后生成efi文件在shell下运行的结果如下:
结果图
这里只是简单地使用了LocateProtocol服务,也没有使用匹配到的protocol的服务,如例子中的DevicePathProtocol。当然除了使用已有的protocol,我们也可以创建protocol,这个稍微复杂一点。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值