高通xbl创建protocol驱动,abl调用xbl中的驱动

UEFI有关的文件格式介绍:
fdf:flash definitionfile,描述flash分区地址范围

dec:package declarationfile,定义了不同模块的GUID信息

dsc:description file,主要包含需要用到的所有inf文件

inf:单个模块的编译信息,类似makefile

efi :最终编译生成的UEFI可执行文件

一、xbl创建 protocol 驱动
先看下创建一个 protocol 驱动改了哪些文件

boot_images/QcomPkg/Drivers/TestDxe 目录下创建2个文件:

TestDxe.inf //定义驱动入口点和编译内容(类似于makefile)

TestDxe.c //定义驱动内容

1、定义驱动入口
1.1 定义 QcomPkg/Drivers/TestDxe/TestDxe.inf 文件内容(类似于makefile)
加载驱动时会运行 ENTRY_POINT 入口函数

[Defines]
INF_VERSION = 0x00010005 //平台UEFI Protocol版本号
BASE_NAME = TestDxe //UEFI Protocol 名
FILE_GUID = 1e5605ad-daf5-41a8-8141-4fdb7ccbd032 //文件GUID, 可以上https://www.guidgen.com网站生成
MODULE_TYPE = UEFI_DRIVER
// 模块类型,分为DXE_DRIVER(UEFI驱动)、BASE(EDK库或PEI)、UEFI_APPLICATION(UEFI应用程序)三种
VERSION_STRING = 1.0 //驱动自定义的版本号
ENTRY_POINT = TestEntryPoint //驱动入口函数,加载该驱动时会首先运行该函数

[Sources] //驱动的C文件
TestDxe.c

[Packages] //本驱动包含的库的头文件
ArmPkg/ArmPkg.dec
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
QcomPkg/QcomPkg.dec

[LibraryClasses] //本驱动中会使用到的库
BaseLib
DevicePathLib
MemoryAllocationLib
PrintLib
UefiDriverEntryPoint
UefiLib
QcomLib

[Guids]
gEfiUfsLU0Guid

[Protocols] //本驱动中会使用到的驱动guid
gEfiTestProtocolGuid
1.2 设置 TestDxe.inf 运行
创建好 TestDxe.inf 文件后,如果需要能够运行,则需要将 inf 添加进平台配置文件中:

配置 boot_images/QcomPkg/SDMPkg/855/AU/Apriori.fdf.inc 文件
INF QcomPkg/Drivers/DDRInfoDxe/DDRInfoDxe.inf
INF QcomPkg/Drivers/ResetRuntimeDxe/ResetRuntimeDxe.inf
INF QcomPkg/Drivers/TestDxe/TestDxe.inf #新增
配置 boot_images/QcomPkg/SDMPkg/855/AU/Core.dsc 文件

ShmBridgeDxe Driver

QcomPkg/Drivers/ShmBridgeDxe/ShmBridgeDxeLA.inf

QcomPkg/Drivers/TestDxe/TestDxe.inf #新增
配置 boot_images/QcomPkg/SDMPkg/855/AU/Core.fdf 文件
INF QcomPkg/Drivers/UsbConfigDxe/UsbConfigDxe.inf
INF QcomPkg/Drivers/TestDxe/TestDxe.inf #新增
2、创建驱动的 GUID
在线生成GUID,https://www.guidgen.com,界面如下:
​​​​​​​

设置 boot_images/QcomPkg/QcomPkg.dec
[Defines]
DEC_SPECIFICATION = 0x00010005
PACKAGE_NAME = QcomPkg
PACKAGE_GUID = 8F99F539-2EE4-4A97-BD6E-FA412A26A06A
PACKAGE_VERSION = 0.1

[Protocols]

Test Protocol #新增

gEfiTestProtocolGuid = { 0x13e277b3, 0xe631, 0x41ca,{ 0xb4, 0xb5, 0x75, 0x9d, 0x7f, 0x2f, 0xed, 0xd9 } }
注意:此处的guid 和前面的FILE_GUID不是同一个,guid类似一个身份证,FILE_GUID指代的是TestDxe.inf 文件,而gEfiTestProtocolGuid 指代的是整个Test驱动。

3、定义驱动及头文件
3.1 修改 boot_images/QcomPkg/Drivers/TestDxe/TestDxe.c 文件
TestEntryPoint 入口函数
gEfiTestProtocol 驱动定义
将 gEfiTestProtocolGuid 与 gEfiTestProtocol 结构体绑定起来,通过 gEfiTestProtocolGuid 就能获取 gEfiTestProtocol 中的驱动函数和数据。

include <Uefi.h>

include <Library/BaseLib.h>

include <Library/MemoryAllocationLib.h>

include <Library/DebugLib.h>

include <Library/IoLib.h>

include <Library/PcdLib.h>

include <Library/UefiBootServicesTableLib.h>

include <Library/BaseMemoryLib.h>

include <Library/UncachedMemoryAllocationLib.h>

include <Library/ArmLib.h>

include <Library/SerialPortShLib.h>

include <Library/UefiBootServicesTableLib.h>

include <Library/StorSecApp.h>

include <Library/UefiCfgLib.h>

include <Protocol/BlockIo.h>

include <Protocol/BlockIo2.h>

include <Protocol/DevicePath.h>

include <Protocol/EFICardInfo.h>

include <Protocol/EFIClock.h>

include <Protocol/EFIHWIO.h>

include <Library/GPTListener.h>

include <Library/RpmbListener.h>

include <Library/RpmbLib.h>

include <Protocol/EFIRpmb.h>

include <Protocol/EFIEraseBlock.h>

include <Protocol/EFIStorageWriteProtect.h>

include <Protocol/EFIHALIOMMUProtocol.h>

include <Library/KernelLib.h>

include <Protocol/EFITest.h>

include <errno.h>

include <stdio.h>

/* 传递函数 */
static char s_TestData[128] = {0};

/* 传递函数 */
EFI_STATUS Test_Printf(void)
{
DEBUG((EFI_D_ERROR, "%a : test protocols \r\n", func));
return 0;
}

/* 驱动函数结构体 */
EFI_TEST_PROTOCOL gEfiTestProtocol =
{
EFI_TEST_REVISION,
Test_Printf,
s_TestData,
};

// 注册驱动:将 gEfiTestProtocolGuidgEfiTestProtocol 结构体绑定起来
EFI_STATUS EFIAPI TestEntryPoint(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS status = EFI_SUCCESS;

memcpy(s_TestData, "test data\n", sizeof("test data\n"));

/*  Install protocol */
status = gBS->InstallMultipleProtocolInterfaces(&ImageHandle,
    &gEfiTestProtocolGuid, (void *)&gEfiTestProtocol,
    NULL);

if (EFI_ERROR(status)) {
    DEBUG((EFI_D_ERROR, "%a : Failed to Install protocols \r\n", __func__));
}

return status;

}
3.2 创建头文件 boot_images/QcomPkg/Include/Protocol/EFITest.h
如果定义的驱动需要被其他应用程序调用的话,需要配置头文件,外部应用程序只需要包含当前头文件即可。

在头文件中定义了 驱动的GUID 及 驱动中包含的所有方法,如下:

ifndef _EFI_TEST_H

define _EFI_TEST_H

include <stdarg.h>

/*Protocol version. */

define EFI_TEST_REVISION 0x0000000000010000

/* Protocol GUID definition */

define EFI_TEST_PROTOCOL_GUID \

    { 0x13e277b3, 0xe631, 0x41ca,{ 0xb4, 0xb5, 0x75, 0x9d, 0x7f, 0x2f, 0xed, 0xd9 } };

extern EFI_GUID gEfiTestProtocolGuid;

/Raw Message protocal/
typedef struct _EFI_TEST_PROTOCOL EFI_TEST_PROTOCOL;

typedef EFI_STATUS (EFIAPI *EFI_TEST_PRINT)();

struct _EFI_TEST_PROTOCOL {
UINT64 Revision;
EFI_TEST_PRINT TestPrintf;
char* pData;
};

endif

二、abl如何调用xbl驱动

前面,我们在xbl中创建了 boot_images/QcomPkg/Drivers/TestDxe/ 驱动,下面,我们来看下它是怎么被应用程序调用的。

使用 Protocol 驱动,需要做如下动作:

在 c文件中包含驱动协议相关的头文件。如: #include <Protocol/EFITest.h>
定义驱动协议的结构体指针。如:EFI_TEST_PROTOCOL *TestProtocol;
加载 gEfiTestProtocolGuid 对应的驱动,将驱动结构体指针保存在TestProtocol 中
Status = gBS->LocateProtocol (&gEfiTestProtocolGuid , NULL, (VOID **)&TestProtocol );

通这 TestProtocol 结构体指针调用驱动的相关函数。
Status = TestProtocol->TestPrintf();
下面详细介绍步骤。

1、如何在abl中调用xbl中的驱动
1)新建 abl/QcomModulePkg/Include/Protocol/EFITest.h(可与xbl中 EFITest.h 相同)

ifndef _EFI_TEST_H

define _EFI_TEST_H

include <stdarg.h>

/*Protocol version. */

define EFI_TEST_REVISION 0x0000000000010000

/* Protocol GUID definition */

define EFI_TEST_PROTOCOL_GUID \

    { 0x13e277b3, 0xe631, 0x41ca,{ 0xb4, 0xb5, 0x75, 0x9d, 0x7f, 0x2f, 0xed, 0xd9 } };

extern EFI_GUID gEfiTestProtocolGuid;

/Raw Message protocal/
typedef struct _EFI_TEST_PROTOCOL EFI_TEST_PROTOCOL;

typedef EFI_STATUS (EFIAPI *EFI_TEST_PRINT)();

struct _EFI_TEST_PROTOCOL {
UINT64 Revision;
EFI_TEST_PRINT TestPrintf;
char* pData;
};

endif

2)QcomModulePkg/QcomModulePkg.dec 中 [Protocols] 添加 gEfiTestProtocolGuid(GUID值和xbl中的一定要相同)

[Protocols]

Test Protocol

gEfiTestProtocolGuid = { 0x13e277b3, 0xe631, 0x41ca,{ 0xb4, 0xb5, 0x75, 0x9d, 0x7f, 0x2f, 0xed, 0xd9 } }
此时,abl可以使用 xbl中的 gEfiTestProtocolGuid 了

3)新建 QcomModulePkg/Library/TestLib/TestLib.c 和 TestLib.inf,用来将 gEfiTestProtocolGuid 封装一层,abl调用封装后的函数即可调用xbl驱动了。

include <Uefi.h>

include <Library/DebugLib.h>

include <Library/PrintLib.h>

include <Library/UefiBootServicesTableLib.h>

include <Library/MemoryAllocationLib.h>

include <Library/CacheMaintenanceLib.h>

include <Library/UefiBootServicesTableLib.h>

include <Library/BaseMemoryLib.h>

include <Protocol/EFIScm.h>

include <Protocol/EFIScmModeSwitch.h>

include <Protocol/EFITest.h> //包含头文件

include <stdarg.h>

int test_print(void)
{
EFI_STATUS Status;
EFI_TEST_PROTOCOL *TestProtocol;

Status = gBS->LocateProtocol (&gEfiTestProtocolGuid,
							NULL,
							(VOID **)&TestProtocol);
if (EFI_ERROR(Status)) {
	DEBUG ((DEBUG_ERROR, "test Protocol Failed %d\n", Status));
	return Status;
}

Status = TestProtocol->TestPrintf();
if (Status)
	DEBUG ((DEBUG_ERROR, "test Local Failed %d\n", Status));

return Status;

}

int test_get_data(void)
{
EFI_STATUS Status;
EFI_TEST_PROTOCOL *TestProtocol;

Status = gBS->LocateProtocol (&gEfiTestProtocolGuid,
							NULL,
							(VOID **)&TestProtocol);
if (EFI_ERROR(Status)) {
	DEBUG ((DEBUG_ERROR, "test Protocol Failed %d\n", Status));
	return Status;
}

DEBUG ((DEBUG_ERROR, "get xbl data: %a\n", TestProtocol->pData));

return Status;

}
TestLib.inf 的 [Protocols] 配置 驱动协议的GUID,这里是 gEfiTestProtocolGuid

[Defines]
INF_VERSION = 0x00010005
BASE_NAME = TestLib
FILE_GUID = b0c5efb2-d180-404a-8524-8f222fb27f5c
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = TestLib

[BuildOptions]
RVCT:__CC_FLAGS = -DCONFIG_SPL_BUILD
GCC:
__CC_FLAGS = -DCONFIG_SPL_BUILD

[BuildOptions.AARCH64]
GCC:__*_CC_FLAGS = -DCONFIG_SPL_BUILD

[Sources.common]
TestLib.c //源文件

[Packages]
QcomModulePkg/QcomModulePkg.dec
ArmPkg/ArmPkg.dec
MdePkg/MdePkg.dec
StdLib/StdLib.dec
EmbeddedPkg/EmbeddedPkg.dec
ArmPlatformPkg/ArmPlatformPkg.dec
MdeModulePkg/MdeModulePkg.dec

[LibraryClasses]

[Protocols]
gEfiTestProtocolGuid //协议

[Depex]
TRUE

新建 QcomModulePkg/Include/Library/Test.h 头文件

ifndef TEST_H_

define TEST_H_

int test_print(void);
int test_get_data(void);

endif /* TEST_H_*/

4)QcomModulePkg/QcomModulePkg.dsc 中定义 LinuxLoader.inf 包含需要用到的所有inf文件,新增 TestLib.inf,之后LinuxLoader.c就能调用TestLib.c中的内容

[Components.common]
QcomModulePkg/Application/LinuxLoader/LinuxLoader.inf {

... ...
TestLib|QcomModulePkg/Library/TestLib/TestLib.inf #新增
}
此时,LinuxLoader.c可以调用 test_print() 和 test_get_data()。

[LibraryClasses]
... ...
TestLib

include <Library/Test.h>

... ...
/* 调用测试 */
test_print();
test_get_data();
三、测试结果
串口打印结果可以看到,执行了 xbl 中 protocol 驱动内容

posted @ 2024-09-02 22:32  haha222  阅读(8)  评论(0编辑  收藏  举报