高通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 驱动定义

gEfiTestProtocolGuidgEfiTestProtocol 结构体绑定起来,通过 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,
};

// 注册驱动:将 `gEfiTestProtocolGuid` 与 `gEfiTestProtocol` 结构体绑定起来
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.cTestLib.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 {
                <LibraryClasses>
                        ... ...
                    	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 驱动内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值