一種在BIOS中嵌入應用程序的方法及實現
本文針對Award公司開發的計算機係統BIOS提出了一種嵌入應用程序的方法,其基本原理對別的品牌的BIOS也一樣適用,僅需稍加修改。文中作者給出並討論一個完整的例子程序,該程序已經通過實驗驗證。正文
一. BIOS簡述
這裏所講的BIOS是指計算機主板上的BIOS,是整個計算機的關鍵和靈魂,計算機一啟動就是執行BIOS程序,它負責加電自檢,初始化計算係統,響應用戶對係統配置的修改,記錄數據到CMOS中,將常駐程序庫(Runtime Program)常駐於內存中,提供給係統和應用程序調用,經過一係列複雜操作後,最後將控製權轉移給操作係統。
一開始BIOS容量僅有8K,隨著計算機複雜程度的提高,以及即插即用、高級電源管理等方麵的需要,再加上個別主板廠商添加的輔助功能,BIOS容量迅速增大,目前通常主板上BIOS容量為256Kb,有些已經達到512Kb,這些BIOS中常常還會有幾十Kb的剩餘空間,而且由於BIOS多采用FlashRom作為存儲芯片,便於修改,這就為我們在BIOS中嵌入自己的程序提供了便利。
在BIOS中嵌入程序具有多方麵的應用,有些主板廠商在BIOS中嵌入殺毒程序,硬盤恢複精靈,超頻工具等,提高了產品的競爭力;台灣威勝公司和Elegent公司聯合開發出了嵌入在BIOS中的小型瀏覽器操作係統,整個BIOS大小僅有512Kb,計算機無需硬盤即可上網衝浪;有些監控係統由於功能簡單,完全可以把程序做到BIOS中,一開機就自動運行,既提高了可靠性,又降低了成本。另一方麵,將病毒嵌入到BIOS中,一開機就常駐內存也完全可以做到。
BIOS代碼雖短,但技術含量相當高,全世界僅有AWARD、PHOENIX、AMI、ACER等幾家公司有研發BIOS係統的能力(AWARD 已被PHOENIX收購),其他主板廠商有的是直接購買,有的也會在以上幾家公司提供的平台上進行少量功能擴展。作為個別應用的場合,就要完全靠自己對BIOS進行改造。
二. 嵌入程序的基礎知識
在進行工作前需要幾個必備的工具,一個是AWARD公司的BIOS刷新工具AwdFlash;另一個Award BIOS 察看修改工具Cbrom;還有一個是MicroSoft 的匯編工具Masm6.11;最後是作者推薦的二進製文本編輯器HexWorkshop,這些工具都可以從網上下載,下麵假定讀者已經熟練使用這些工具,具體操作步驟不再祥述。
前麵提到BIOS程序是存放在FlashROM芯片中的,實際上它是經過壓縮後再存放進去的,僅留下少量啟動代碼和解壓縮程序保持原樣,BIOS的執行過程其實相當複雜,好在我們無需去了解其中的詳細流程,但有一點應當清楚,BIOS程序實際上也是采用的模塊化設計思想,用Cbrom可以察看到BIOS中各個子模塊的名稱,性質,壓縮率等信息,BIOS在執行過程中會將這些模塊解壓縮到內存中,驗證模塊的合法性和正確性,如果滿足條件,就會轉到模塊的入口處執行。這裏麵的詳細機製和由來需要參考PNPBIOS協議、PNPISA協議、PCI總線協議和EISA總線協議,內容繁多,本文不擬做深入探討。
BIOS中有一種模塊是ISA模塊,來源於ISA協議,由於ISA協議屬於早期的協議,內容相對簡單,BIOS對ISA模塊的驗證也較為簡單,容易滿足,我們可以將自己的程序做成ISA模塊掛到BIOS中,這樣機器一啟動,我們的程序就會啟動,而且我們程序的運行是先於操作係統的。
三. 程序設計詳細步驟
1. 設計準備
由於係統固有的限製,BIOS中每個模塊的大小不能超過64Kb,這裏是指沒有壓縮前的大小,這和DOS下COM程序的限製很相似,實際上我們在用MASM6.11進行編程時的確采用是COM程序的模板,由編譯器生成COM文件。然而它又和一般的COM文件具有以下幾點不同:
1. 首先它有自己的堆棧段,堆棧大小默認為1K,而COM文件的堆棧是在64K之內的,默認是從段內偏移量0FFFEh處開始。
2. COM文件一開始就是執行代碼,而模塊一開始是模塊頭,儲存有與模塊相關的信息。模塊執行代碼的入口點在模塊中的某一處。
3. COM文件執行完後返回到操作係統,通常通過子功能號4ch的中斷INT21h返回到DOS,而模塊是遠程調用返回,也就是說必須用RETF返回。
4. ISA模塊最後一個字節是校驗碼,所有的字節相加必須為0,BIOS利用這點來驗證一個ISA模塊的正確性。COM文件沒有這點要求。
5. COM文件執行時是先被完整地複製到段內偏移量100h處,然後再執行,而模塊的段內偏移量不能確定,有的模塊會是0。所以涉及到段內偏移量的匯編指令,如LEA、OFFSET要謹慎適用。
下表是ISA模塊頭的格式,其中僅列出了幾個最基本的相關字段,這是協議中的內容,我們在編寫模塊頭時,需要嚴格遵循下表的格式:
偏 移 長 度 值 說 明
0h 1 55h 模塊標簽字節1
1h 1 AAh 模塊標簽字節2
2h 1 * 模塊長度(以512字節為單位)
3h 3 * 入口點,BIOS對此位置做遠調用,這裏往往放一條跳轉指令
6h~19h 20 * 保留
表一 模塊頭格式
通常一個BIOS嵌入程序設計的基本流程如下,每一步都很關鍵,有必要給出詳細說明:
1. 首先用匯編編寫DOS下的COM程序,必須注意到程序是先於操作係統執行的,所以程序中不能調用任何DOS的中斷服務。為了程序轉化方便,也不要用.code,.startup等匯編偽指令,盡量采用早期的匯編編寫方式,爭取對整個程序結構的完全控製。
2. 調試通過後,在COM文件前加上文件頭,改變返回指令為RETF,控製文件大小為512字節的整數倍,重新編譯生成COM文件。
3. 在HexWorkshop中調入剛生成的COM文件,利用其中的checksum工具生成文件的校驗碼,用100h減去該8位校驗碼後填入文件最後一個字節。再次生成文件的校驗碼,確認為零。
4. 用Cbrom將文件作為ISA模塊嵌入到BIOS中,在本文中的操作為 “Cbrom save.bin/isa hello.com”,其中save.bin是事先用AwdFlash備份的BIOS文件。注意反複操作時,要先將前一個給釋放掉,操作為“Cbrom save.bin/isa release”。
5. 用AwdFlash將新的BIOS文件燒錄到FlashROM中。重起計算機,檢驗程序。
進行以上實驗前,最好自備編程器,萬一計算機不能正常啟動,也可以重新恢複BIOS,如果可以用本身具有雙BIOS保護功能的計算機進行實驗則更加保險。
下麵設計兩個簡單的Hello程序,分別采用了兩種不同的方式,兩個程序都是在屏幕上顯示一行字“Hello!Press F1 to continue…”,當按下F1功能鍵後,程序退出,計算機繼續啟動。
2. Hello程序一
下麵給出的源代碼是在上麵流程2中的文件,所以已經添加了文件頭,編譯後生成的COM文件是不能在DOS下執行的,請讀者務必注意。另外由於程序功能簡單,所以在這裏文件大小限製為512字節,對不同規模的程序,會有一些小小的變動。程序中所有的中斷調用都是BIOS中斷服務調用,具體調用規則不做詳細說明,請讀者查閱有關資料。
;Hello源程序一
code segment
assume cs:code,ds:code
start:
signature db 55h,0aah
comlength db 01h ;文件長512字節
jmp near ptr begin0
reserved db 20 dup(?)
begin0:
mov di,25
mov ah,2
mov bh,0
mov dx,di
mov dh,10 ;將光標移至屏幕
int 10h ;10行25列處
mov si,offset string
;在DOS下調試時應在這裏添加 add si,100h
showstr:
mov ah,9
mov al,[si]
and al,0ffh
jz kbinput
mov bh,0
mov bl,0DAh
mov cx,1
int 10h
,
mov ah,2
mov bh,0
inc di
mov dx,di
mov dh,10
int 10h
jmp showstr ;輸出字符串
kbinput:
mov ah,0
int 16h
cmp ah,3bh ;接受鍵盤輸入
jne kbinput ;按F1往下執行
mov ax,0 ;返回參數
retf ;遠程調用返回
string db 'Hello! Press F1 to continue...',00h ;00h標誌字符串結束
org 511 ;文件末尾
checksum db ?
code ends
end start
將上述程序燒入BIOS中運行時,在第一屏信息顯示過後,會在第二屏正中央顯示一條紅底白字的信息,提示按F1鍵繼續,按F1鍵後,BIOS繼續下麵的啟動步驟。顯示第三屏啟動信息,即原先的第二屏信息,最後加載操作係統。
以上程序假定了BIOS會將模塊解壓至段首運行,事實也確是如此,但由於沒查到相關資料,目前還不能肯定總會如此。這一點將在下一個Hello程序中有所改進。
3. Hello程序二
Hello程序一在BIOS沒有初始化完全的時候即進入運行,所以對程序功能有更多限製,有些BIOS中斷服務還不具備,任何對這些服務的調用都會產生意想不到的結果。考慮到BIOS在加載操作係統時實際上是用的INT 19h,Hello程序二就利用掛鉤19h中斷的方法搶在操作係統之前,BIOS初始化之後運行,這樣就可以完整地利用整個計算機係統的所有資源了。
另外必須指出的是,模塊本身有責任保持整個模塊的校驗和為零,也就是說,ISA模塊進駐內存中後就不能卸出,BIOS會在模塊返回後檢查整個模塊的檢驗和,判斷模塊的正確性,如果錯誤,則會死機。模塊在初始運行時可以更改自己段內的數據,而在BIOS初始化完畢後,模塊就不能再有改變自身數據的操作。
;Hello源程序二
.model tiny
.386
code segment
assume cs:code,ds:code
start:
signature db 55h,0aah
comlength db 01h ;文件長512字節
jmp near ptr begin0
reserved db 20 dup(?)
begin0:
call getip ;得到模塊的起始段內偏移量
;保存在參數ipstart中
mov ax,0 ;掛鉤19h中斷
最後更新:2017-04-03 12:55:47