UEFI开发探索69- YIE001PCIe开发板(05 UEFI驱动)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

上一篇中,驱动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

1,801 total views, 2 views today

发表评论

电子邮件地址不会被公开。