(请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365)
上一篇中,驱动BlankDrv完成了核心的EFI_DRIVER_BINDING_PROTOCOL,以及获取驱动名Protocol的处理后,整个UEFI驱动框架还有两项工作等待完成:
- 安装UEFI驱动所提供的Protocol;
- 驱动加载后是常驻内存的,应该提供UEFI驱动的卸载函数,以支持将驱动系统中移除的功能。
1 完成驱动框架
安装Protocol可以使用InstallMultipleProtocolInterfaces()函数,由于BlankDrv中有三种Protocol需要安装,所以使用了库函数EfiLibInstallDriverBindingComponentName2()来安装所有的Protocol。如示例1所示。
【示例1】安装BlankDrv所提供的Protocol
EFI_STATUS EFIAPI UefiMain(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
…..
//安装需要提供的三种Protocol
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gBlankDrvDriverBinding,
ImageHandle,
&gBlankDrvComponentName,
&gBlankDrvComponentName2
);
return Status;
}
驱动的卸载函数,在使用UEFI Shell命令unload的时候会被调用。此函数的入口在UEFI工程的INF文件中添加,由[Defines] Section的UNLOAD_IMAGE字段给出。在示例工程BlankDrv的BlankDrv.inf中,按照如下方式进行了定义:
[Defines]
……
ENTRY_POINT = UefiMain //驱动的入口函数
UNLOAD_IMAGE = DefaultUnload //驱动的卸载函数
从中可以看出,BlanDrv的卸载函数为DefaultUnload(),它定义在源文件BlankDrv.c中。在函数中,它主要实现了如下功能:
- 遍历系统的句柄数据库,并将所有设备句柄存储在缓冲区数组中;
- 对缓冲区数组中的句柄,也即对系统中所有设备句柄进行判断,如果使用了驱动,则将其与控制器断开连接;
- 卸载驱动安装的所有Protocol。包括EFI_DRIVER_BINDING_PROTOCOL、EFI_COMPONENT_NAME_PROTOCOL和EFI_COMPONENT_NAME2_PROTOCOL的卸载。
DefaultUnload()函数的代码较长,在此就不列出了,可以直接去源文件中查看其实现。
至此,UEFI驱动模型的框架就完成了。将BlankDrv的工程文件复制到文件夹RobinPkg\Drivers下,并在RobinPkg.dsc的[Components] Section中添加编译路径:
RobinPkg/Drivers/BlankDrv/BlankDrv.inf
启动UEFI的编译环境,运行如下命令即可编译IA32的UEFI驱动。
C:\UEFIWorkspace>build -t VS2015x86 -p RobinPkg\RobinPkg.dsc \
-m RobinPkg\Drivers\BlankDrv\BlankDrv.inf -a IA32
2 测试驱动
与服务型驱动不同,在BlankDrv中提供了卸载驱动的功能。因此,可以使用unload命令卸载驱动。
由于此框架并没有指定硬件设备,因此仍然可以在EDK2的模拟器中测试。测试中除了用到
UEFI开发探索67介绍的UEFI Shell命令load和dh外,还要用到命令drivers和unload,这两个命令的使用方法介绍如下。
- drivers命令用于列出系统的驱动,其语法格式为:
drivers [-l XXX] [-sfo]
参数-l用于指定所使用的语言代码,比如ISO 639-2;参数-sfo使用标准格式化输出显示信息。drivers命令是以列表的形式,将符合UEFI驱动模型的驱动信息打印出来。打印的信息中,包括如下项的显示:
DRV项表示驱动句柄的编号;
VERSION项表示驱动的版本号;
TYPE项表示驱动的类型,B为总线驱动,D为色板驱动;
CFG项表示该驱动是否支持Driver Configuration Protocol;
DIAG项表示该驱动是否支持Driver Diagnostics Protocol;
#D项显示该驱动控制的设备的数量;
#C项表示子设备的数量;
DRIVER NAME项表示驱动名称;
IMAGE PATH表示驱动来源。
- unload命令用于卸载UEFI驱动,其语法格式为:
unload [-n] [-v|-verbose] Handle
此命令用于将驱动从内存中清除,所要清除的驱动,由其加载后的句柄表示。unload命令提供了两种参数,“-n”表示执行过程中跳过所有提示信息;“-v”则在执行过程中列出指定句柄相关的信息,包括驱动文件名、驱动文件的符号文件、镜像加载基地址等。
启动EDK2的模拟器,使用load命令加载驱动,然后可以使用drivers或dh命令查看驱动加载情况,最后使用unload命令卸载驱动。运行情况示例2所示。
【示例2】在EDK2模拟器中测试BlankDrv
FS0:\> load BlankDrv.efi //加载驱动
Image ‘FS0:\BlankDrv.efi’ loaded at 6211000 – Success
FS0:\> drviers //列举系统中所有驱动
…… //其他驱动信息
87 0000000A ? – – – – My Blank Driver \BlankDrv.efi
FS0:\> dh 87 //显示设备句柄的信息
87: ComponentName2 ComponentName DriverBinding ImageDevicePath
(..8881,00000000)\BlankDrv.efi) LoadImage(\BlankDrv.efi)
FS0:\> unload 87 //卸载驱动
Unload – Handle [52E0290]. [y/n]?
y
Unload – Handle [52E0290] Result Success
至此,对UEFI驱动模型介绍完成。BlankDrv并没有实现什么实际的功能,主要是提供了一个比较完整的驱动框架。下一篇中,以一个开源的UEFI驱动GopRotate为例,为其构建测试用的UEFI应用,演示有趣的屏幕变换功能。
为方便大家进行实验,BlankDrv的源码放在了gitee仓库中了。
Gitee地址:https://gitee.com/luobing4365/uefi-explorer
项目代码位于:/69 BlankDrv/BlankDrv.zip