紀向尚 莊克良 王大慶
(海軍704廠 青島 266109)
小型計算機系統接口(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虛擬光驅技術的設計和實現。
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抽象了塊設備讀寫,與具體設備無關。

圖2 SCSI虛擬光驅頂層結構
SCSI虛擬光驅系統由兩個模塊組成,虛擬光驅驅動和Shell接口。模塊間通過固件卷(Firmware Volume)實現配置信息的傳遞。圖2給出了系統的頂層結構圖。
Shell接口通過命令行獲得配置信息,并將配置信息存入到固件卷中,比如虛擬光驅的數目,每個光驅對應的ISO鏡像文件等。驅動的內核通過讀取這些信息,動態創建出相應的數據結構來提供虛擬光驅服務,比如向用戶提供一個或多個虛擬光驅等。
從前面的論述中知道,虛擬光驅驅動在實質上虛擬SCSI總線控制器,提供Ext SCSI Pass Thru Protocol接口。雖然該驅動是總線控制器驅動,但仍然是一個設備驅動,驅動接口被總線驅動(即SCSI Bus驅動)所使用。而在總線控制器內部維持著一些數據結構,向上層總線驅動提供虛擬信息,基于這個選擇,可以得到如圖3所示的驅動內核結構。

圖3 遵循UEFI驅動模型的虛擬光驅驅動內核
虛擬光驅系統具有如下要求功能:
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接口應當將盤符信息轉化為設備驅動可以識別的信息,然后存儲。
分析上述可知,驅動內核將使用一些數據結構來表示配置信息,并提供虛擬光驅服務。驅動應當首先創建虛擬的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負責構造和析構。
圖2系統的頂層結構圖中,Shell接口和驅動內核通過固件卷進行配置信息的傳遞。在進行這種配置傳遞時需要解決兩個問題。
第一,由于UEFI規范不使用時鐘中斷外的所有中斷,因此UEFI系統應當處于單一的運行環境,即單指令流。因此,不可能同時存在驅動進程和Shell接口進程,也不可能實時傳遞配置參數。由于EFI的加載速度很快,重啟EFI并不會耗費時間,所以無論是在傳統BIOS,還是在EFI中,一些配置往往都要求重啟。本設計選擇回避該問題,配置信息設置保存后應當重新啟動UEFI系統,以便驅動內核讀取配置信息。
第二,EDK II的Shell中表示的盤符(如f8:\)屬于Shell內部表示,只有在Shell環境下可見。但驅動不在Shell環境下運行,也不能利用Shell庫讀取文件。如果簡單地向固件卷中寫入路徑f8:\sample\example1.iso,那么即使路徑信息能夠被設備驅動所獲取,驅動程序也不能從f8:\訪問任何設備。
本文主要研究了符合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/.