UEFI开发学习6 - Protocol的创建

1 介绍

同样在UEFI Spec的第七章Boot Service中有两个关于Protocol创建的函数,分别是InstallProtocolInterface()和InstallMultipleProtocolInterfaces()。顾名思义,前者是只安装一个ProtocolInterface,后者可以安装一个或多个ProtocolInterface,此外,InstallMultipleProtocolInterfaces()比InstallProtocolInterface()执行更多的错误检查,因此规范建议使用InstallMultipleProtocolInterfaces()。但本文以InstallProtocolInterface()为例。

1.1 InstallProtocolInterface()

函数原型为:

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

参数:
Handle: 一个指向要安装接口的EFI_HANDLE的指针。如果Handle在输入时为NULL,则创建一个新的句柄并在输出时返回。如果Handle在输入时不为NULL,则协议被添加到句柄中,句柄未被修改就返回。类型EFI_HANDLE在“相关定义”中定义。如果*Handle不是一个有效句柄,则返回EFI_INVALID_PARAMETER。
Protocol: GUID,用来标识这个Protocol。调用方负责传递一个有效的GUID。
InterfaceType: 指示是否以native form提供Interface。该值指示请求的原始执行环境。它是一个枚举类型。这里不太明白“native form”是什么含义。
Interface: 一个指向协议接口的指针。接口必须符合协议定义的结构。如果一个结构与协议没有关联,则可以使用NULL。

1.2 InstallMultipleProtocolInterfaces()

函数原型为:

typedef
EFI_STATUS
EFIAPI *EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES) (
	IN OUT EFI_HANDLE *Handle,
	...
);

参数:
Handle: 指向要在上面安装新协议接口的句柄的指针,或者如果要分配新句柄,则指向NULL。
… : 一个变量参数列表,包含对协议guid和协议接口。

2 Protocol创建

Protocol的创建需要准备几个部分:
1)Protocol GUID;
2)构建Protocol的成员函数以及结构体;
3)实例化一个Protocol结构体类型的实例。
注意事项:Protocol的成员函数,其函数类型必须是EFIAPI修饰的,并且第一个函数参数必须为This指针。

2.1 步骤

首先创建一个Module,新建CreateProtocol.inf和CreateProtocol.c。
在EmulatorPkg.dsc文件的[Components]下添加EmulatorPkg/Application/CreateProtocol
/CreateProtocol.inf。文件内容可见后文附录。
然后编译成CreateProtocol.efi文件,在shell环境下加载。结果如图:

我们可以使用LocateProtocol()函数来验证可不可以加载我们创建的Protocol,这个内容在上文Protocol的使用中已经介绍过了。只要把这个函数里的参数IN EFI_GUID *Protocol换成我们定义的Protocol的GUID就可以了。
这时候编译会出现问题,因为还需要把我们定义的GUID也就是gEfiCreateProtocolGUID添加到/vUDK2017/MdePkg/MdePkg.dec文件的[Protocols]下。
编译完成后首先在shell下运行使用Protocol的程序,这时候程序不会Locate到我们定义的Protocol,因为我们还没有将它load进内存;然后我们使用load命令将CreateProtocol.efi加载到内存,再Locate,这时候程序可以成功找到我们定义的Protocol。结果如下图:

附录

  • CreateProtocol.c文件
#include<Uefi.h>
#include<Library/UefiDriverEntryPoint.h>
#include<Library/UefiBootServicesTableLib.h>
#include<Library/UefiLib.h>

typedef EFI_STATUS(EFIAPI* EFI_INPUT_MSG)();

//protocol结构体
struct _EFI_CREATE_PROTOCOL{
	UINT64 Revsion;  //版本
	EFI_INPUT_MSG InputMsg;  //成员函数
};

typedef struct _EFI_CREATE_PROTOCOL EFI_CREATE_PROTOCOL;
//定义GUID
#define EFI_CREATE_PROTOCOL_GUID \
{0xa32ccd8b, 0x021b, 0x4a7f, {0x9d, 0xc0, 0xe5, 0x16, 0x35, 0x63, 0x8f, 0xb7}}

EFI_GUID gEfiCreateProtocolGUID = EFI_CREATE_PROTOCOL_GUID;

//Protocol中成员函数的实现
EFI_STATUS EFIAPI InputMsg(IN EFI_CREATE_PROTOCOL *This)
{
	gST->ConOut->OutputString(gST->ConOut,L"Create Protocol\n");
	return EFI_SUCCESS;
}
//Protocol的实例
EFI_CREATE_PROTOCOL gMyProtocol;
//初始化Protocol实例函数
EFI_STATUS MyCreateProtocolInit()
{
	EFI_CREATE_PROTOCOL* myProtocol = &gMyProtocol;
	myProtocol->Revsion = 0x101;
	myProtocol->InputMsg = InputMsg;
	return EFI_SUCCESS;
}

//Driver的入口函数
EFI_STATUS
EFIAPI
CreateProtocolEntry(
	IN EFI_HANDLE ImageHandle,
	IN EFI_SYSTEM_TABLE *SystemTable
)
{
	EFI_STATUS	Status;
	MyCreateProtocolInit();
    //Install一个Protocol
	Status = gBS->InstallProtocolInterface(
						&ImageHandle,
						&gEfiCreateProtocolGUID,
						EFI_NATIVE_INTERFACE,
						&gMyProtocol
						);
	if(!EFI_ERROR(Status))
	{
		gST->ConOut->OutputString(gST->ConOut,L"Success\n");
		return Status;
	}else{
		gST->ConOut->OutputString(gST->ConOut,L"Failed\n");
	}
	return Status;
}
  • CreateProtocol.inf文件
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = CreateProtocol
FILE_GUID = 2d7ee62a-8f25-4a0c-bcc7-a0c8edc31643
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = CreateProtocolEntry
 
[Sources]
CreateProtocol.c
 
[Packages]
MdePkg/MdePkg.dec
 
[LibraryClasses]
UefiDriverEntryPoint
UefiLib
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值