UEFI BIOS虚拟光驱的设计实现*
2012-10-16纪向尚庄克良王大庆
纪向尚 庄克良 王大庆
(海军704厂 青岛 266109)
1 引言
小型计算机系统接口(Small Computer System Interface),简称SCSI,主要应用于计算机外围设备,如硬盘、软驱、光驱、打印机等。SCSI标准定义了命令、通讯协议以及实体的电气特性,其主要软件接口是SCSI命令。
SCSI的原始版本是SCSI-1,SCSI-1具有8位总线,数据传输率为4Mbps。目前SCSI-1已经很少使用。作为对SCSI-1的改进,SCSI-2使用了两项新技术Fast SCSI和 Wide SCSI。
Fast SCSI将传输速率提高到10MB/Sec,而Wide SCSI突破SCSI-1的单字节传输限制,将数据总线的带宽提高到16位或者32位。当使用Fast-Wide SCSI时,其理论传输速率为20MB/s或者40MB/s,SCSI-2增加了新的设备命令集,对光驱的支持也出现在SCSI-2标准文档中。
UEFI则定义了操作系统与系统硬件平台固件之间的开放接口。该规范定义的接口包括平台相关信息、启动服务例程以及操作系统运行时服务例程。操作系统装载器与操作系统可通过接口调用这些服务例程。UEFI规范是一个公开的纯接口定义,它不依赖于某个特定的BIOS制造商或某个特定的BIOS的实现,它仅仅定义了平台固件必须实现的接口,以及操作系统可能使用的一系列接口与数据结构,其实现的方式与细节均取决于该规范的实现者。UEFI规范还定义了固件驱动程序模型,使得所有遵循此模型开发的固件驱动程序能够互相协作。
目前UEFI BIOS下还没有相应的虚拟光驱方面的应用程序,本文研究的就是在UEFI接口规范下基本SCSI虚拟光驱技术的设计和实现。
2 SCSI协议分析
UEFI的所有驱动依靠协议堆叠形成协议栈,并以此组织系统中的驱动模块。SCSI作为总线控制器,要求提供控制器本身的控制协议即SCSI Pass Thru Protocol或者其扩展版本Ext Scsi Pass Thru Protocol。该协议可以驱动SCSI总线控制器,向总线控制器发出输入输出或其它控制命令。SCSI设备驱动则依赖该协议提供具体的设备输入输出控制接口。
在UEFI中,这种总线结构依赖于三个驱动实现:总线控制器驱动、总线驱动、子设备驱动。总线控制器作为一种设备,其驱动提供控制接口。总线驱动则利用这种接口查询并枚举总线控制器上的所有子设备,并为每一个子设备创建新的设备句柄,安装Device Path Protocol以及向子设备发送命令的总线IO协议。总线驱动不关心子设备类型,子设备上的总线IO只可向设备发送IO及控制信号。不同设备的驱动为了提供设备本身特有的接口,将该总线IO封装,提供工业标准中的设备控制接口。
如图1所示,SCSI总线控制器句柄SCSI Bus Controller Handle由系统或其父节点的总线驱动负责创建。SCSI总线控制器的控制接口协议Ext SCSI Pass Thru Protocol由总线控制器驱动实现并安装在该控制器句柄上。
图1 SCSI总线及设备协议栈
SCSI总线驱动使用Ext SCSI Pass Thru Protocol查询并枚举总线上的每个子设备,创建新的句柄,为这些子设备句柄安装Device Path Protocol和SCSI IO Protocol。其中,SCSI IO Protocol提供了统一的设备输入输出及控制接口。图1中Scsi Device 1Handle和SCSI Device 2Handle即为总线子设备句柄,由总线驱动创建。
由于SCSI设备的多样性,不同的设备需要特定的协议作为接口。图1中的SCSI设备为CD-Drive、磁盘等块设备。UEFI标准规定这些块设备应当提供Block IO Protocol,因此,EDK II中给出了SCSI块设备的驱动。该驱动检测通过SCSI IO Protocol检查每个设备的类型,并负责为光驱和磁盘创建块输入输出协议Block IO Protocol。
到此,SCSI总线结构的协议栈已经建立。EDK II提供Disk IO Protocol,其接口与Block IO Protocol有所不同,但一部分上层驱动同时使用这两个协议。Simple File System Protocol由文件系统相关的驱动模块负责。简单文件系统协议向Shell以及所有使用文件系统的驱动提供了文件访问接口。
根据以上分析,可以得出这样的结论:有效驱动SCSI光驱或者磁盘需要三个驱动模块完成,总线控制器驱动,总线驱动和子设备驱动。这三个驱动彼此独立地负责三个协议的安装,即 Ext Scsi Pass Thru Protocol,Scsi IO Protocol和Block IO Protocol。其中,Block IO Protocol抽象了块设备读写,与具体设备无关。
3 模块设计
3.1 顶层结构
图2 SCSI虚拟光驱顶层结构
SCSI虚拟光驱系统由两个模块组成,虚拟光驱驱动和Shell接口。模块间通过固件卷(Firmware Volume)实现配置信息的传递。图2给出了系统的顶层结构图。
Shell接口通过命令行获得配置信息,并将配置信息存入到固件卷中,比如虚拟光驱的数目,每个光驱对应的ISO镜像文件等。驱动的内核通过读取这些信息,动态创建出相应的数据结构来提供虚拟光驱服务,比如向用户提供一个或多个虚拟光驱等。
从前面的论述中知道,虚拟光驱驱动在实质上虚拟SCSI总线控制器,提供Ext SCSI Pass Thru Protocol接口。虽然该驱动是总线控制器驱动,但仍然是一个设备驱动,驱动接口被总线驱动(即SCSI Bus驱动)所使用。而在总线控制器内部维持着一些数据结构,向上层总线驱动提供虚拟信息,基于这个选择,可以得到如图3所示的驱动内核结构。
图3 遵循UEFI驱动模型的虚拟光驱驱动内核
3.2 Shell用户接口
虚拟光驱系统具有如下要求功能:
1)列出所有虚拟光驱,及其对应的ISO文件信息;
2)设置虚拟光驱数量;
3)为指定编号的虚拟光驱进行ISO镜像装载;
4)为指定编号的虚拟光驱进行ISO镜像卸载。
根据预期的四个功能,设计出如下格式的Shell命令:
其中,vscsi为Shell接口的程序名,-l选项以列表形式所有的虚拟光驱信息,-n用来设置虚拟光驱的数量,-m用来设置Num对应虚拟光驱的镜像文件,-u用来对Num指定虚拟光驱进行卸载。
虚拟光驱的Shell接口程序将遵循标准的程序结构,利用Shell相关的库和协议获得命令行参数并将其存放入固件卷中。Shell接口程序的框架如上图所示。Shell接受用户命令并分析后,将调用EFI Runtime Services向固件卷中写入配置信息。需要说明的是,命令行指定的文件路径中的盘符信息不能被设备驱动识别。比如,在f8:\sample\example1.iso这样的文件路径中,f8:\不能被设备识别。因此,在Shell接口应当将盘符信息转化为设备驱动可以识别的信息,然后存储。
3.3 虚拟设备驱动
分析上述可知,驱动内核将使用一些数据结构来表示配置信息,并提供虚拟光驱服务。驱动应当首先创建虚拟的SCSI控制器建立对应数据结构,并根据配置信息在UEFI系统堆内存中动态地创建表示子设备的数据结构。
虚拟SCSI控制器对应的数据结构将采用C面向对象的方法,扩展Ext Scsi Pass Thru Protocol结构,将需要的数据结构作为该协议私有的数据,如图4所示。
其中,扩展后的Ext Scsi Pass Thru Protocol定义如图5。
以这个结构体作为虚拟的SCSI总线控制器的核心数据结构。
图4 虚拟SCSI控制器结构
图5 虚拟SCSI总线控制器结构体定义
前四个字节为signature。因为该结构体在内存中动态创建,协议中的函数可以利用这四个字节检查数据结构的正确性,这个特性类似于信息安全领域的数字签名。
签名结束后是协议接口,在向系统注册协议时将这个地址传入UEFI系统。并且,虚拟SCSI总线控制器结构体中,只有该域对外开放。在向虚拟设备装载协议时,ExtScsiPassThruInterface域的地址将被传入系统,保证了内部数据结构的封装。因此,其它驱动或者用户在向系统请求该协议接口时,得到的不是整个 VIRTUAL_SCSI_CONTROLLER结构体地址,而是其中ExtScsiPassThruInterface的地址。
VIRTUAL_SCSI_CONTROLLER的最后部分由一个类型匿名的Private域构成。该域仅包含两项,虚拟光驱数量以及指向虚拟光驱结构体数组的指针。对该域的数据类型进行匿名,可以保证该域的封装性。
对于每个虚拟光驱,其数据结构定义如图6所示。
图6 虚拟光驱设备结构体定义
CDRomMounted用以表示该CD Drive中是否装载了CD-Rom,FileDevicePath指向文件类型的Device Path。它主要用来保存从CMOS中获得的虚拟光驱配置信息,不负责文件的相关操作。根据FileDevicePath被打开的文件由FileHandle指向,文件的访问操作也将通过FileHandle来进行。TargetID和Lun是SCSI规范中定义的两种类型的数据,TargetID用来表示SCSI目标器的编号,Lun用来表示逻辑单元号(Logical Unit Number)。需要指出的是,在本虚拟光驱系统中对于任何一个TargetID,Lun均只为0,不使用其它值。
图7 SCSI虚拟光驱驱动模块详细设计
综合UEFI驱动模型、SCSI虚拟控制器结构及虚拟光驱设备结构得出如图7的SCSI虚拟光驱驱动模块详细设计。其中镜像文件(Image File)部分是驱动的二进制可加载镜像,由代码编译得到。堆空间(Heap Memory)中的所有数据结构由驱动的Driver Binding Protocol负责构造和析构。
3.4 模块间通信
图2系统的顶层结构图中,Shell接口和驱动内核通过固件卷进行配置信息的传递。在进行这种配置传递时需要解决两个问题。
第一,由于UEFI规范不使用时钟中断外的所有中断,因此UEFI系统应当处于单一的运行环境,即单指令流。因此,不可能同时存在驱动进程和Shell接口进程,也不可能实时传递配置参数。由于EFI的加载速度很快,重启EFI并不会耗费时间,所以无论是在传统BIOS,还是在EFI中,一些配置往往都要求重启。本设计选择回避该问题,配置信息设置保存后应当重新启动UEFI系统,以便驱动内核读取配置信息。
第二,EDK II的Shell中表示的盘符(如f8:\)属于Shell内部表示,只有在Shell环境下可见。但驱动不在Shell环境下运行,也不能利用Shell库读取文件。如果简单地向固件卷中写入路径f8:\sample\example1.iso,那么即使路径信息能够被设备驱动所获取,驱动程序也不能从f8:\访问任何设备。
4 结语
本文主要研究了符合UEFI接口规范的SCSI虚拟光驱技术,并设计实现了该SCSI虚拟光驱系统。该系统可以向其它驱动或者用户提供一个虚拟的SCSI总线控制器以及连接在总线控制器上的一个或多个虚拟光驱设备,用户可以通过Shell接口配置光驱数量以及各光驱中加载的ISO 9660结构的文件镜像。该方法的实现,对于扩展基于UEFI BIOS计算机系统的多光驱应用以及扩展外部设备接口,具有非常现实的积极意义。
[1]UEFI Forum.February 2010.UEFI Specification.Version 2.3.http://www.uefi.org/specs/
[2]UEFI Forum.February 2010.UEFI Platform Initialization Specification.Version 1.2.http://www.uefi.org/specs/
[3]Vincent Zimmer.2006.Beyond BIOS.Intel corporation.17-32,143-146.
[4]Framework Open Source Community.March 2008.Pre_EFI Initialization Core Interface http://www.uefi.org/specs/.
[5]EFI技术解析.March 2010.http://www.gz-benet.com.cn/.
[6]Basic Instruction for Using EFI.January 2,2008.http://www.intel.com/.
[7]Enterprise64BIOS.March 2010.http://ami.com/.