如何调用Protocal?

        一:以Graphics Output Protocol 为例来讲解如何调用一个Protocol

步骤如下:        

        1:搜索定位支持特定Protocol的设备,获取Handle。

                有很多方式:此处选择gBs->LocateHandleBuffer,获得一个设备指针数组。会自己创建一个Buffer来存储结果,不用咱们操心。

        2:打开Prototcol,  将内存中的Driver绑定到给定的ControllerHandler。

                此处选择gBs->OpenProtocol,获得目标Protocol的指针。

先放代码!!!代码如下(包含task1.c和task1.inf文件),其中task1.c如下所示:

/*
使用的是EFI_GRAPHICS_OUTPUT_PROTOCAL 
*/
#include<Uefi.h>
#include<Library/UefiLib.h>
#include<Library/UefiBootServicesTableLib.h>
EFI_STATUS
EFIAPI
UefiMain(
        IN EFI_HANDLE ImageHandle,
        IN EFI_SYSTEM_TABLE *SystemTable
)
{
        //搜索定位支持特定Protocol的设备,即获取Handle
        EFI_STATUS Status = EFI_SUCCESS;
        UINTN NoHandles = 0;
        EFI_HANDLE *Buffer = NULL;
        Status=gBS->LocateHandleBuffer(
                        ByProtocol,
                        &gEfiGraphicsOutputProtocolGuid,
                        NULL,
                        &NoHandles,
                        &Buffer
);
         Print(L"Status=%d\n",Status);
        if(EFI_ERROR(Status))
        {
                Print(L"Fail to use LocateHandlesBuff\n");
        }
        Print(L"NoHandles=%d\n",NoHandles);
        
        //打开Protocol,将内存中的Drivers绑定到指定的ControllHandler
        EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
        Status=gBS->OpenProtocol(
                Buffer[0],
                &gEfiGraphicsOutputProtocolGuid,
                (VOID**)&Gop,
                ImageHandle,
                NULL,
                0x00000002      //EFI_OPEN_PROTPCOL_GET_PROTOCOL
        );
        Print(L"Status=%d\n",Status);
 
        if(EFI_ERROR(Status))
        {
                Print(L"Fail to use OpenProtocol\n");
        }
        Print(L"Hello_tangrenhui_test\n");
        return EFI_SUCCESS;
}                                      

        其中的task1.inf如下:

[Defines]
        INF_VERSION = 0x00010005
        BASE_NAME =task1
        ENTRY_POINT =UefiMain
        FILE_GUID = 39B12C61-1C87-4FC3-9375-6EF19FBBA137
        VERSION_STRING = 1.0
        MODULE_TYPE = UEFI_APPLICATION
[Sources]
        task1.c
[Packages]
        MdePkg/MdePkg.dec
[LibraryClasses]
        UefiApplicationEntryPoint
        UefiLib

        编译后,在虚拟机运行task1.efi,结果如下:

        在写task1.c时,注意事项有以下几点:

        1:若要使用BootServers,要取得指向它具体的指针。

        有两种方式:第一种是加头文件,第二种是通过UefiMain的第二个参数来访问。分别如下。之后就可以使用gBS这个全局变量来访问BootServers,上述代码使用第一种方式。

#include<Library/UefiBootServicesTableLib.h>
EFI_BOOT_SERVERS *gBS = SystemTable->BootServers;

        2:使用LocateHandleBuffer时候,可以参考UEFI_Spec_2_10中相关部分,如下图所示:

         如图所示,该Protocol共有五个参数,第一个参数为SearchType,有三种类型。第二个参数为EFI_GUID类型的*Protocol,即&gEfiGraphicsOutputProtocolGuid,第三个参数为*searchKey,由于第一个参数已经确定的原因,此参数为NULL。第一个参数三种类型,如下图所示。第四个参数为UINTN类型的 *BufferSize,定义一个同样类型的变量去接收它。第五个参数为EFI_HANDLE类型的*Buffer,定义一个同样类型的Buffer去接收它。

         3:使用OpenProtocol的时候,可以参考如下图:

        如图所示,该Protocol共有六个参数,第一个参数为上一步获得的Handle对象,即存在数组中的对象,如果上一步找到Handle,则一定会有一个,因此这里填写Buffer[0]。第二个参数为对应的Protocol的GUID,即&gEfiGraphicsOutputProtocolGuid。第三个参数为void**类型的Interface,目的是为了传出指针可以指向任意对象,因此定义一个变量去接收它,即EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;同时要进行强制类型转换为(VOID**)。相应部分可参考UEFI_Spec如下图所示:

第四个参数为AgentHandle,就填写ImageHandle,第五个参数为ContrillerHandle,由于是应用程序所以此处写NULL,相应部分可参考下图:

第六个参数为Attributes,相应参考(UEFI_Spec)如下:此处选择0x00000002。

        4:每次调用Protocol时候都要去判断是否调用成功,使用if语句判断EFI_ERROR(Status),注意:Status得到入口函数的返回值类型是EFI_STATUS。在UEFI程序中基本所有的返回值类型都是EFI_STATUS。它的本质是无符号长整数最高位为1时其值为错误代码,为0时表示非错误值。通过宏EFI_ERROR(Status)可以判断返回值Status时候为错误代码。若Status为错误代码EFI_ERROR(Status)返回值为真,否则为假。写到这里的时候就可以编译验证一下是否可以调用成功,如果Status返回等于0,表示调用Protocol成功。

        5:在打印验证的时候Print中一定要加L,否则会报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值