编写自己的Protocol
步骤1:在Package的Include/Protocol中编写CreateProtocol.h文件。
步骤2:在EmulatorPkg/Application中创建CreateProtocol文件,里面编写CreateProtocol.c和CreateProtocol.inf文件,其中在c文件中分配内存并安装。
步骤3:使用自己上一篇使用的程序,在此基础上调用创建的Protocol。
先放代码,然后分别在各个部分重要的地方解释一下。
CreateProtocol.h:
#ifndef __CREATE_PROTOCOL_H__
#define __CREATE_PROTOCOL_H__
#include <Uefi.h>
//定义Protocol的GUID
#define EFI_HELLO_WORLD_GUID {0x038f1af5, 0x1c8d, 0x408f, { 0xab, 0x25, 0x30, 0xae, 0xb5, 0x96, 0x5d, 0x6e }}
//定义Protocol的结构体
typedef struct _EFI_HELLO_WORLD_PROTOCOL EFI_HELLO_WORLD_PROTOCOL;
//函数指针
typedef
EFI_STATUS
(EFIAPI *HELLO)(
IN EFI_HELLO_WORLD_PROTOCOL *This
);
struct _EFI_HELLO_WORLD_PROTOCOL{
UINTN Version;
HELLO Hello;
};
extern EFI_GUID gEfiHelloWorldProtocolGuid;
#endif
如上代码所示,主要定义了一个Protocol结构体,里面有一个Version和一个函数指针。同时定义了一个EFI_GUID。同时要在对应的.dec文件中Protocols下定义gEfiHelloWorldProtocolGuid,本文在EmulatorPkg.dec下添加。
CreateProtocol.c:
//Protocol的实现和安装
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Protocol/CreateProtocol.h>
//创建函数
EFI_STATUS
EFIAPI
Hello(
IN EFI_HELLO_WORLD_PROTOCOL *This
)
{
//Debug((EFI_D_ERROR,"Hello world tangrenhui!!!"));
Print(L"Hello world tangrenhui!!!\n");
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
ProtocolServerEntry(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *Systemtable
)
{
EFI_STATUS Status;
EFI_HELLO_WORLD_PROTOCOL *Protocol;
//开始分配空间和安装
Protocol = AllocatePool(sizeof(EFI_HELLO_WORLD_PROTOCOL));
//判断是否分配成功
if(NULL == Protocol)//没有分配成功
{
DEBUG ((EFI_D_ERROR, "[%a][%d]: Out of resource.", __FUNCTION__, __LINE__));
return EFI_OUT_OF_RESOURCES;
}
//分配成功
Protocol->Version = 0x01;
Protocol->Hello = Hello;
//安装
Status=gBS->InstallProtocolInterface(
&ImageHandle,
&gEfiHelloWorldProtocolGuid,
EFI_NATIVE_INTERFACE,
Protocol
);
//判断
if(EFI_ERROR(Status))
{
//DEBUG ((EFI_D_ERROR, "Install EFI_HELLO_WORLD_PROTOCOL failed. - %r\n", Status));
DEBUG((EFI_D_ERROR, "InstallProtocol failed\n"));
FreePool(Protocol);
return Status;
}
return EFI_SUCCESS;
}
如上述代码所示,先分配空间AllocatePool(sizeof(EFI_HELLO_WORLD_PROTOCOL)),使用EFI_HELLO_WORLD_PROTOCOL *Protocol的Protocol来接收返回值,然后判断是否分配成功,如果分配成功那就对他的成员进行赋值即Protocol->Version = 0x01、 Protocol->Hello = Hello;。然后开始安装,使用InstallProtocolInterface,参考对应UEFI手册,如下图所示
第一个参数为ImageHandle,第二个参数为EFI_GUID,第三个参数参考手册对应的如图。
第四个参数为本模块实现的Protocol实例。
CreateProtocol.inf:
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = ProtocolServer
FILE_GUID = 3d8ee62a-8f25-4a0c-bcc7-a0c8edc31643
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = ProtocolServerEntry
[Sources]
CreateProtocol.c
[Packages]
MdePkg/MdePkg.dec
EmulatorPkg/EmulatorPkg.dec
[LibraryClasses]
UefiDriverEntryPoint
UefiBootServicesTableLib
UefiLib
MemoryAllocationLib
DebugLib
[Protocols]
gEfiHelloWorldProtocolGuid
调用的时候:在上一个博客使用的文件里面新增内容。
Print(L"Using Protocol\n");
EFI_HELLO_WORLD_PROTOCOL *Protocol;
Status = gBS->LocateProtocol(
&gEfiHelloWorldProtocolGuid,
NULL,
(VOID **)&Protocol
);
if(EFI_ERROR(Status)){
//DEBUG((EFI_ERROR, "Locate EFI_HELLO_WORLD_PROTOCOL failed. %r\n", Status));
DEBUG((EFI_D_ERROR, "LocateProtocol Status: %r\n", Status));
return Status;
}
Status = Protocol->Hello(Protocol);
if(EFI_ERROR(Status)){
//DEBUG((EFI_ERROR, "Protocol->Hello world failed. %r\n" , Status));a
DEBUG((EFI_D_ERROR, "UseProtocol Status: %r\n", Status));
return Status;
}
Print(L"My Protocol be used!!\n");
此部分重要地方,在上一个文件中也基本都有讲述,此处不给予阐述,直接编译,编译之后先运行由于Protocol创建的.efi文件,再运行测试的efi文件,由于我写的是DXE_DRIVER,所以运行时候需要输入load,结果如下图所示。证明调用成功。