VisualeBios.exe
所在目录,并改名为jre。则Visual Bios的启动不需要安装JRE。卸载JRE 1.7验证。用UEFI Shell装载驱动进行测试。受载板平台限制,测试工程放在AMI项目里。
与UEFI App开发不同,驱动代码所处项目架构应当与硬件构成映射关系。如果驱动代码与驱动硬件不在相同架构,则开发者需要手动处理固件布局才成封装成为正确的固件。我亲自踩坑证明这个说法:
关键错误消息:Build\GetPpiName.c(1) : fatal error C1083: Cannot open include file: '/RELEASE_MYTOOLS/PpiTableIA32.c': No such file or directory
。不知道驱动项目存放须按规定的开发者会认为这个问题是玄学问题,怎么生成的代码找不到生成的代码呢?建议参照下图和项目结构选择合适的UEFI驱动存储放置:
根据驱动目标选择合适的项目位置。本示例的目标为USB键盘驱动,因此选择MdeModulePkg/Bus。当然,如果你已对BIOS固件布局已非常清楚,你可以随意。
新建目录HelloWorldDxe
,新建HelloWorldDxe.inf
,代码如下:
[Defines]
INF_VERSION = 0x00010005
BASE_NAME=HelloWorldDxe
FILE_GUID = de296c9d-8bac-08bc-ac6d-db2998aff781
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 0.1
ENTRY_POINT = DriverMain
[Sources]
HelloWorldDxe.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
DebugLib
MemoryAllocationLib
PrintLib
UefiDriverEntryPoint
UefiLib
新建HelloWorldDxe.c
,代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#define HELLOWORLD_VERSION 0x10
EFI_STATUS EFIAPI HelloWorldStart(
IN EFI_DRIVER_BINDING_PROTOCOL* This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath
)
{
EFI_STATUS status = EFI_SUCCESS;
Print(L"[HelloWorldStart] HelloWorld driver started.\n");
return status;
}
EFI_STATUS EFIAPI HelloWorldSupported(
IN EFI_DRIVER_BINDING_PROTOCOL* This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath
)
{
EFI_STATUS status = EFI_SUCCESS;
Print(L"[HelloWorldSupported] HelloWorld driver supported.\n");
return status;
}
EFI_STATUS EFIAPI HelloWorldStop(
IN EFI_DRIVER_BINDING_PROTOCOL* This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE* ChildHandleBuffer
)
{
EFI_STATUS status = EFI_SUCCESS;
Print(L"[HelloWorldStop] HelloWorld driver stopped.\n");
return status;
}
EFI_DRIVER_BINDING_PROTOCOL g_helloworld_driver_binding = {
HelloWorldSupported,
HelloWorldStart,
HelloWorldStop,
HELLOWORLD_VERSION,
NULL,
NULL
};
EFI_STATUS EFIAPI DriverMain(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE* SystemTable
)
{
EFI_STATUS status = EFI_SUCCESS;
status = EfiLibInstallDriverBindingComponentName2(
ImageHandle,
SystemTable,
&g_helloworld_driver_binding,
ImageHandle,
NULL,
NULL
);
ASSERT_EFI_ERROR(status);
return status;
}
Components
、Core
、MdeModulePkg
、LibraryInstances
,右键单击,选择弹出菜单Add INF Module
。关于Select EDK Project Root
选项,选择结果无论是否正确,导入结果都存在错误。下文第2步和第3步就是纠错。sdl
文件到inf
文件所在目录,并更名。MdeModulePkg\Library\LibraryInstances.cif
\Build\GrangevillePkg\RELEASE_MYTOOLS\X64\MdeModulePkg\Bus\HelloWorldDxe\HelloWorldDxe\DEBUG\AutoGen.h(16) : fatal error C1083: Cannot open include file: 'Uefi.h': No such file or directory
。原因是HelloWorldDxe.inf
有错。具体错误是Package
依赖错误地写成dsc
,正确的做法是写成dec
VeB不允许编译单个驱动
这是假象。实际原因是VeB没有把导入INF生成的sdl
文件放到inf
所在目录。解决办法是移动sdl
文件到inf
文件所在目录并修正上级cif
文件中的错误。
load
指令可见大量的HelloWorld
输出,说明UEFI驱动管理支持一个设备绑定多个驱动,不会因为某个设备已存在绑定的驱动而停止匹配新驱动。UEFI如何选择调用哪个驱动呢?驱动的版本的如何在驱动选择中发挥作用的?HelloWorldDxe
集成进BIOS固件之前不确定它显示时CPU执行阶段。现在可以证明处于DXE阶段。那么,从通电到HelloWorldDxe
产生输出的大约10秒钟时间,很可能都处于SEC和PEI阶段。现在没有确定串口设备未初始化造成的HelloWorldDxe
无输出的时间。UEFI驱动管理在得到Supported
函数的返回结果为EFI_SUCCESS后立即调用Start
函数。上图Supported输出与Start输出成对出现无间断说明这一点。
任何驱动应在EFI Shell中先load
试运行。否则驱动出错造成很大的麻烦。DXE出错的结果是载板变砖头,救砖的办法可能只有把FLASH从电路板上焊下来,烧好程序后再焊上去。
固件烧录与固件运行时不同。以下截图的实验:
HelloWorldSupported
函数目标:以字符串形式输出所有Device关键字,尝试寻找设备特征,在特征中搜寻键盘设备。代码如下:
EFI_STATUS EFIAPI HelloWorldSupported(
IN EFI_DRIVER_BINDING_PROTOCOL* This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath
)
{
EFI_STATUS status = EFI_SUCCESS;
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* device2txt = NULL;
CHAR16* device_path = NULL;
status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (void**)&device2txt);
if (EFI_ERROR(status))
{
Print(L"[HelloWorld Driver] LocateProtocol result: %d\n", status);
return status;
}
device_path = device2txt->ConvertDeviceNodeToText(RemainingDevicePath, TRUE, TRUE);
Print(L"[HelloWorld Driver] device: %s\n", device_path);
return EFI_UNSUPPORTED;
}
这里采用VeB配置。
脚本编译的目的是为CI做准备。
@echo off
chcp 65001
title AMI UEFI Build Tool
echo Any question can be sent to [email protected]
set CCX86DIR=\software\Aptio_5.x\x86\x86
set CCX64DIR=\software\Aptio_5.x\x86\amd64
set TOOLS_DIR=\software\Aptio_5.x\BuildTools
set PATH=%PATH%;\software\Aptio_5.x\x86\x86
set PATH=%PATH%;\software\Aptio_5.x\amd64
set PATH=%PATH%;\software\Aptio_5.x\x86
set PATH=%PATH%;\software\Aptio_5.x\BuildTools
set PATH=%PATH%;\software\Aptio_5.x\BuildTools\Bin\Win32
set PATH=%PATH%;\software\Aptio_5.x\VisualeBios\jre\bin\
cd
cmd /k
编译,确认编译输出
- Done -
Build end time: 17:07:12, Sep.15 2023
Build total time: 00:00:07
运行load HelloWorldDxe.efi
,确认结果
RemainingDevicePath
的值始终为:F3 EE 00 F0
。期望的结果为不同的设备不同的值。UEFI Driver Writer’s Guide大部分示例显示,Supported
适用的流程是开发者用期望的Protocol尝试打开。结果成功就是支持,结果失败就是不支持。很多示例㫫示Start
还会把这个逻辑再运行一次。
RemainingDevicePath
不一定指设备,它还兼顾方便开发者在当前设备下挂载子设备。另外: