紀(jì)向尚 莊克良 王大慶
(海軍704廠 青島 266109)
小型計算機系統(tǒng)接口(Small Computer System Interface),簡稱SCSI,主要應(yīng)用于計算機外圍設(shè)備,如硬盤、軟驅(qū)、光驅(qū)、打印機等。SCSI標(biāo)準(zhǔn)定義了命令、通訊協(xié)議以及實體的電氣特性,其主要軟件接口是SCSI命令。
SCSI的原始版本是SCSI-1,SCSI-1具有8位總線,數(shù)據(jù)傳輸率為4Mbps。目前SCSI-1已經(jīng)很少使用。作為對SCSI-1的改進(jìn),SCSI-2使用了兩項新技術(shù)Fast SCSI和 Wide SCSI。
Fast SCSI將傳輸速率提高到10MB/Sec,而Wide SCSI突破SCSI-1的單字節(jié)傳輸限制,將數(shù)據(jù)總線的帶寬提高到16位或者32位。當(dāng)使用Fast-Wide SCSI時,其理論傳輸速率為20MB/s或者40MB/s,SCSI-2增加了新的設(shè)備命令集,對光驅(qū)的支持也出現(xiàn)在SCSI-2標(biāo)準(zhǔn)文檔中。
UEFI則定義了操作系統(tǒng)與系統(tǒng)硬件平臺固件之間的開放接口。該規(guī)范定義的接口包括平臺相關(guān)信息、啟動服務(wù)例程以及操作系統(tǒng)運行時服務(wù)例程。操作系統(tǒng)裝載器與操作系統(tǒng)可通過接口調(diào)用這些服務(wù)例程。UEFI規(guī)范是一個公開的純接口定義,它不依賴于某個特定的BIOS制造商或某個特定的BIOS的實現(xiàn),它僅僅定義了平臺固件必須實現(xiàn)的接口,以及操作系統(tǒng)可能使用的一系列接口與數(shù)據(jù)結(jié)構(gòu),其實現(xiàn)的方式與細(xì)節(jié)均取決于該規(guī)范的實現(xiàn)者。UEFI規(guī)范還定義了固件驅(qū)動程序模型,使得所有遵循此模型開發(fā)的固件驅(qū)動程序能夠互相協(xié)作。
目前UEFI BIOS下還沒有相應(yīng)的虛擬光驅(qū)方面的應(yīng)用程序,本文研究的就是在UEFI接口規(guī)范下基本SCSI虛擬光驅(qū)技術(shù)的設(shè)計和實現(xiàn)。
UEFI的所有驅(qū)動依靠協(xié)議堆疊形成協(xié)議棧,并以此組織系統(tǒng)中的驅(qū)動模塊。SCSI作為總線控制器,要求提供控制器本身的控制協(xié)議即SCSI Pass Thru Protocol或者其擴展版本Ext Scsi Pass Thru Protocol。該協(xié)議可以驅(qū)動SCSI總線控制器,向總線控制器發(fā)出輸入輸出或其它控制命令。SCSI設(shè)備驅(qū)動則依賴該協(xié)議提供具體的設(shè)備輸入輸出控制接口。
在UEFI中,這種總線結(jié)構(gòu)依賴于三個驅(qū)動實現(xiàn):總線控制器驅(qū)動、總線驅(qū)動、子設(shè)備驅(qū)動??偩€控制器作為一種設(shè)備,其驅(qū)動提供控制接口??偩€驅(qū)動則利用這種接口查詢并枚舉總線控制器上的所有子設(shè)備,并為每一個子設(shè)備創(chuàng)建新的設(shè)備句柄,安裝Device Path Protocol以及向子設(shè)備發(fā)送命令的總線IO協(xié)議??偩€驅(qū)動不關(guān)心子設(shè)備類型,子設(shè)備上的總線IO只可向設(shè)備發(fā)送IO及控制信號。不同設(shè)備的驅(qū)動為了提供設(shè)備本身特有的接口,將該總線IO封裝,提供工業(yè)標(biāo)準(zhǔn)中的設(shè)備控制接口。
如圖1所示,SCSI總線控制器句柄SCSI Bus Controller Handle由系統(tǒng)或其父節(jié)點的總線驅(qū)動負(fù)責(zé)創(chuàng)建。SCSI總線控制器的控制接口協(xié)議Ext SCSI Pass Thru Protocol由總線控制器驅(qū)動實現(xiàn)并安裝在該控制器句柄上。
圖1 SCSI總線及設(shè)備協(xié)議棧
SCSI總線驅(qū)動使用Ext SCSI Pass Thru Protocol查詢并枚舉總線上的每個子設(shè)備,創(chuàng)建新的句柄,為這些子設(shè)備句柄安裝Device Path Protocol和SCSI IO Protocol。其中,SCSI IO Protocol提供了統(tǒng)一的設(shè)備輸入輸出及控制接口。圖1中Scsi Device 1Handle和SCSI Device 2Handle即為總線子設(shè)備句柄,由總線驅(qū)動創(chuàng)建。
由于SCSI設(shè)備的多樣性,不同的設(shè)備需要特定的協(xié)議作為接口。圖1中的SCSI設(shè)備為CD-Drive、磁盤等塊設(shè)備。UEFI標(biāo)準(zhǔn)規(guī)定這些塊設(shè)備應(yīng)當(dāng)提供Block IO Protocol,因此,EDK II中給出了SCSI塊設(shè)備的驅(qū)動。該驅(qū)動檢測通過SCSI IO Protocol檢查每個設(shè)備的類型,并負(fù)責(zé)為光驅(qū)和磁盤創(chuàng)建塊輸入輸出協(xié)議Block IO Protocol。
到此,SCSI總線結(jié)構(gòu)的協(xié)議棧已經(jīng)建立。EDK II提供Disk IO Protocol,其接口與Block IO Protocol有所不同,但一部分上層驅(qū)動同時使用這兩個協(xié)議。Simple File System Protocol由文件系統(tǒng)相關(guān)的驅(qū)動模塊負(fù)責(zé)。簡單文件系統(tǒng)協(xié)議向Shell以及所有使用文件系統(tǒng)的驅(qū)動提供了文件訪問接口。
根據(jù)以上分析,可以得出這樣的結(jié)論:有效驅(qū)動SCSI光驅(qū)或者磁盤需要三個驅(qū)動模塊完成,總線控制器驅(qū)動,總線驅(qū)動和子設(shè)備驅(qū)動。這三個驅(qū)動彼此獨立地負(fù)責(zé)三個協(xié)議的安裝,即 Ext Scsi Pass Thru Protocol,Scsi IO Protocol和Block IO Protocol。其中,Block IO Protocol抽象了塊設(shè)備讀寫,與具體設(shè)備無關(guān)。
圖2 SCSI虛擬光驅(qū)頂層結(jié)構(gòu)
SCSI虛擬光驅(qū)系統(tǒng)由兩個模塊組成,虛擬光驅(qū)驅(qū)動和Shell接口。模塊間通過固件卷(Firmware Volume)實現(xiàn)配置信息的傳遞。圖2給出了系統(tǒng)的頂層結(jié)構(gòu)圖。
Shell接口通過命令行獲得配置信息,并將配置信息存入到固件卷中,比如虛擬光驅(qū)的數(shù)目,每個光驅(qū)對應(yīng)的ISO鏡像文件等。驅(qū)動的內(nèi)核通過讀取這些信息,動態(tài)創(chuàng)建出相應(yīng)的數(shù)據(jù)結(jié)構(gòu)來提供虛擬光驅(qū)服務(wù),比如向用戶提供一個或多個虛擬光驅(qū)等。
從前面的論述中知道,虛擬光驅(qū)驅(qū)動在實質(zhì)上虛擬SCSI總線控制器,提供Ext SCSI Pass Thru Protocol接口。雖然該驅(qū)動是總線控制器驅(qū)動,但仍然是一個設(shè)備驅(qū)動,驅(qū)動接口被總線驅(qū)動(即SCSI Bus驅(qū)動)所使用。而在總線控制器內(nèi)部維持著一些數(shù)據(jù)結(jié)構(gòu),向上層總線驅(qū)動提供虛擬信息,基于這個選擇,可以得到如圖3所示的驅(qū)動內(nèi)核結(jié)構(gòu)。
圖3 遵循UEFI驅(qū)動模型的虛擬光驅(qū)驅(qū)動內(nèi)核
虛擬光驅(qū)系統(tǒng)具有如下要求功能:
1)列出所有虛擬光驅(qū),及其對應(yīng)的ISO文件信息;
2)設(shè)置虛擬光驅(qū)數(shù)量;
3)為指定編號的虛擬光驅(qū)進(jìn)行ISO鏡像裝載;
4)為指定編號的虛擬光驅(qū)進(jìn)行ISO鏡像卸載。
根據(jù)預(yù)期的四個功能,設(shè)計出如下格式的Shell命令:
其中,vscsi為Shell接口的程序名,-l選項以列表形式所有的虛擬光驅(qū)信息,-n用來設(shè)置虛擬光驅(qū)的數(shù)量,-m用來設(shè)置Num對應(yīng)虛擬光驅(qū)的鏡像文件,-u用來對Num指定虛擬光驅(qū)進(jìn)行卸載。
虛擬光驅(qū)的Shell接口程序?qū)⒆裱瓨?biāo)準(zhǔn)的程序結(jié)構(gòu),利用Shell相關(guān)的庫和協(xié)議獲得命令行參數(shù)并將其存放入固件卷中。Shell接口程序的框架如上圖所示。Shell接受用戶命令并分析后,將調(diào)用EFI Runtime Services向固件卷中寫入配置信息。需要說明的是,命令行指定的文件路徑中的盤符信息不能被設(shè)備驅(qū)動識別。比如,在f8:\sample\example1.iso這樣的文件路徑中,f8:\不能被設(shè)備識別。因此,在Shell接口應(yīng)當(dāng)將盤符信息轉(zhuǎn)化為設(shè)備驅(qū)動可以識別的信息,然后存儲。
分析上述可知,驅(qū)動內(nèi)核將使用一些數(shù)據(jù)結(jié)構(gòu)來表示配置信息,并提供虛擬光驅(qū)服務(wù)。驅(qū)動應(yīng)當(dāng)首先創(chuàng)建虛擬的SCSI控制器建立對應(yīng)數(shù)據(jù)結(jié)構(gòu),并根據(jù)配置信息在UEFI系統(tǒng)堆內(nèi)存中動態(tài)地創(chuàng)建表示子設(shè)備的數(shù)據(jù)結(jié)構(gòu)。
虛擬SCSI控制器對應(yīng)的數(shù)據(jù)結(jié)構(gòu)將采用C面向?qū)ο蟮姆椒?,擴展Ext Scsi Pass Thru Protocol結(jié)構(gòu),將需要的數(shù)據(jù)結(jié)構(gòu)作為該協(xié)議私有的數(shù)據(jù),如圖4所示。
其中,擴展后的Ext Scsi Pass Thru Protocol定義如圖5。
以這個結(jié)構(gòu)體作為虛擬的SCSI總線控制器的核心數(shù)據(jù)結(jié)構(gòu)。
圖4 虛擬SCSI控制器結(jié)構(gòu)
圖5 虛擬SCSI總線控制器結(jié)構(gòu)體定義
前四個字節(jié)為signature。因為該結(jié)構(gòu)體在內(nèi)存中動態(tài)創(chuàng)建,協(xié)議中的函數(shù)可以利用這四個字節(jié)檢查數(shù)據(jù)結(jié)構(gòu)的正確性,這個特性類似于信息安全領(lǐng)域的數(shù)字簽名。
簽名結(jié)束后是協(xié)議接口,在向系統(tǒng)注冊協(xié)議時將這個地址傳入UEFI系統(tǒng)。并且,虛擬SCSI總線控制器結(jié)構(gòu)體中,只有該域?qū)ν忾_放。在向虛擬設(shè)備裝載協(xié)議時,ExtScsiPassThruInterface域的地址將被傳入系統(tǒng),保證了內(nèi)部數(shù)據(jù)結(jié)構(gòu)的封裝。因此,其它驅(qū)動或者用戶在向系統(tǒng)請求該協(xié)議接口時,得到的不是整個 VIRTUAL_SCSI_CONTROLLER結(jié)構(gòu)體地址,而是其中ExtScsiPassThruInterface的地址。
VIRTUAL_SCSI_CONTROLLER的最后部分由一個類型匿名的Private域構(gòu)成。該域僅包含兩項,虛擬光驅(qū)數(shù)量以及指向虛擬光驅(qū)結(jié)構(gòu)體數(shù)組的指針。對該域的數(shù)據(jù)類型進(jìn)行匿名,可以保證該域的封裝性。
對于每個虛擬光驅(qū),其數(shù)據(jù)結(jié)構(gòu)定義如圖6所示。
圖6 虛擬光驅(qū)設(shè)備結(jié)構(gòu)體定義
CDRomMounted用以表示該CD Drive中是否裝載了CD-Rom,F(xiàn)ileDevicePath指向文件類型的Device Path。它主要用來保存從CMOS中獲得的虛擬光驅(qū)配置信息,不負(fù)責(zé)文件的相關(guān)操作。根據(jù)FileDevicePath被打開的文件由FileHandle指向,文件的訪問操作也將通過FileHandle來進(jìn)行。TargetID和Lun是SCSI規(guī)范中定義的兩種類型的數(shù)據(jù),TargetID用來表示SCSI目標(biāo)器的編號,Lun用來表示邏輯單元號(Logical Unit Number)。需要指出的是,在本虛擬光驅(qū)系統(tǒng)中對于任何一個TargetID,Lun均只為0,不使用其它值。
圖7 SCSI虛擬光驅(qū)驅(qū)動模塊詳細(xì)設(shè)計
綜合UEFI驅(qū)動模型、SCSI虛擬控制器結(jié)構(gòu)及虛擬光驅(qū)設(shè)備結(jié)構(gòu)得出如圖7的SCSI虛擬光驅(qū)驅(qū)動模塊詳細(xì)設(shè)計。其中鏡像文件(Image File)部分是驅(qū)動的二進(jìn)制可加載鏡像,由代碼編譯得到。堆空間(Heap Memory)中的所有數(shù)據(jù)結(jié)構(gòu)由驅(qū)動的Driver Binding Protocol負(fù)責(zé)構(gòu)造和析構(gòu)。
圖2系統(tǒng)的頂層結(jié)構(gòu)圖中,Shell接口和驅(qū)動內(nèi)核通過固件卷進(jìn)行配置信息的傳遞。在進(jìn)行這種配置傳遞時需要解決兩個問題。
第一,由于UEFI規(guī)范不使用時鐘中斷外的所有中斷,因此UEFI系統(tǒng)應(yīng)當(dāng)處于單一的運行環(huán)境,即單指令流。因此,不可能同時存在驅(qū)動進(jìn)程和Shell接口進(jìn)程,也不可能實時傳遞配置參數(shù)。由于EFI的加載速度很快,重啟EFI并不會耗費時間,所以無論是在傳統(tǒng)BIOS,還是在EFI中,一些配置往往都要求重啟。本設(shè)計選擇回避該問題,配置信息設(shè)置保存后應(yīng)當(dāng)重新啟動UEFI系統(tǒng),以便驅(qū)動內(nèi)核讀取配置信息。
第二,EDK II的Shell中表示的盤符(如f8:\)屬于Shell內(nèi)部表示,只有在Shell環(huán)境下可見。但驅(qū)動不在Shell環(huán)境下運行,也不能利用Shell庫讀取文件。如果簡單地向固件卷中寫入路徑f8:\sample\example1.iso,那么即使路徑信息能夠被設(shè)備驅(qū)動所獲取,驅(qū)動程序也不能從f8:\訪問任何設(shè)備。
本文主要研究了符合UEFI接口規(guī)范的SCSI虛擬光驅(qū)技術(shù),并設(shè)計實現(xiàn)了該SCSI虛擬光驅(qū)系統(tǒng)。該系統(tǒng)可以向其它驅(qū)動或者用戶提供一個虛擬的SCSI總線控制器以及連接在總線控制器上的一個或多個虛擬光驅(qū)設(shè)備,用戶可以通過Shell接口配置光驅(qū)數(shù)量以及各光驅(qū)中加載的ISO 9660結(jié)構(gòu)的文件鏡像。該方法的實現(xiàn),對于擴展基于UEFI BIOS計算機系統(tǒng)的多光驅(qū)應(yīng)用以及擴展外部設(shè)備接口,具有非?,F(xiàn)實的積極意義。
[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技術(shù)解析.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/.