MS-DOS Device Driver >> Assembly >> Basic
发布日期:2025-01-04 12:36 点击次数:137
MS-DOS Device Driver >> Assembly >> Basic
I/O Request Packet(IRP)
DOS系統決定要呼叫驅動程式做事情時,會採取兩個階段的呼叫動作,而這兩個階段的關連就是依靠ES:BX的資料(IRP),Strategy Callback副程式必須先把這個IRP保存起來,等到Interrupt Callback副程式被呼叫時,再去存取該IRP的資料。
司徒使用一個Command 0(Initialization)說明一下處理流程:
Step 1. 系統將Command 0的IRP資料位址儲存在ES:BX
Step 2. 系統呼叫驅動程式的Strategy Callback副程式
Step 3. 驅動程式儲存IRP的位址
Step 4. 系統呼叫驅動程式的Interrupt Callback副程式
Step 5. 驅動程式從IRP得知這是一個Command 0的命令
Step 6. 驅動程式跳到本身處理Command 0的副程式去處理
Step 7. 驅動程式處理完後並返回控制權給DOS系統
每個IRP都是經由Header和Data Structure這兩個部份組合而成,Header的Structure是固定的格式,而Data Structure的部份,則會因IRP的不同而有所改變,意思就是Data Structure的欄位不是固定的,有些IRP甚至沒有Data Structure的欄位。
為了更容易瞭解,司徒使用Command 0(Initialization)的IRP解說一下:
CMD0_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD0_DATA dup(?)
CMD0_IRP ends
從上面的Structure可以看出,IRP是由Header和Data兩個部份組合而成,Header的部份是固定的Structure,如下表示:
IRP_HEADER struc
Length db ?
UnitCode db ?
Command db ?
Status dw ?
Reserved1 dd ?
Reserved2 dd ?
IRP_HEADER ends
Length說明IRP Header的資料長度
UnitCode代表設備的順序號碼,例如:磁碟機有兩部,第一部就是0
Command說明要處理的命令
Command
DOS
Driver
Description
0
2.0+
Char and Block
Initialization
1
2.0+
Block
Media Check
2
2.0+
Block
Get BIOS Parameter Block
3
2.0+
Char and Block
IOCTL
4
2.0+
Char and Block
Input
5
2.0+
Char
Nondestructive Input
6
2.0+
Char
Input Status
7
2.0+
Char
Input Flush
8
2.0+
Char and Block
Output
9
2.0+
Char and Block
Output With Verify
10
2.0+
Char
Output Status
11
2.0+
Char
Output Flush
12
2.0+
Char and Block
IOCTL Output
13
3.0+
Char and Block
Open
14
3.0+
Char and Block
Close
15
3.0+
Block
Removable Media
16
3.0+
Char
Output Til Busy
17
3.2+
Char and Block
Undefined
18
3.2+
Char and Block
Undefined
19
3.2+3.3+
BlockChar and Block
Generic IOCTL
20
3.2+
Char and Block
Undefined
21
3.2+
Char and Block
Undefined
22
3.2+
Char and Block
Undefined
23
3.2+
Block
Get Logical Device
24
3.2+
Block
Get Logical Device
25
5.0+
Char and Block
IOCTL Query
Status是驅動程式回傳給系統的狀態,如下表:
Bit15
Bit14~Bit10
Bit9
Bit8
Bit7~Bit0
Error
Reserved
Busy
Done
Error Code
0 (Write protect violation)
1 (Unknown unit)
2 (Drive not ready)
3 (Unknown command)
4 (CRC error)
5 (Bad drive request structure length)
6 (Seek error)
7 (Unknown media)
8 (Sector not found)
9 (Printer out of paper)
10 (Write fault)
11 (Read fault)
12 (General failure)
13 (Reserved)
14 (Reserved)
15 (Invalid disk change)
Reserved1和Reserved2則是保留欄位
Data Structure的部份則因IRP的不同而有所差異,Command 0的Data Structure如下表示:
CMD0_DATA struc
UnitNum db ?
BreakOffset dw ?
BreakSegment dw ?
BPBOffset dw ?
BPBSegment dw ?
FirstDrive db ?
CMD0_DATA ends
經由上面的解說,使用者應該對IRP有了基本的認知。
接著司徒針對那25個Command依序列出它們的IRP Structure,基本上,這部份使用者可先跳過,等之後需要使用該Command時,再回頭來參考即可。
Command 0: Initialization
初始化設定的Command,在驅動程式被載入到記憶體之後,系統會馬上傳送這個Command給驅動程式,這是驅動程式唯一可以做初始化的Command,而且使用者必須記得一點,只有該Command可以執行DOS的系統服務常式(0x01~0x0c, 0x30)
CMD0_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD0_DATA dup(?)
CMD0_IRP ends
CMD0_DATA struc
UnitNum db ?
BreakOffset dw ?
BreakSegment dw ?
BPBOffset dw ?
BPBSegment dw ?
FirstDrive db ?
CMD0_DATA ends
Command 1: Media Check
這個命令是DOS在存取所有磁碟機前,都會先執行的命令,用以確認是否目錄或FAT資料有被更改過
CMD1_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD1_DATA dup(?)
CMD1_IRP ends
CMD1_DATA struc
MediaDescriptor db ?
RetStatus db ?
CMD1_DATA ends
Command 2: Get BPB Parameter
這個命令用於取得磁碟機的BPB資料
CMD2_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD2_DATA dup(?)
CMD2_IRP ends
CMD2_DATA struc
MediaDescriptor db ?
BPBArrayOffset dw ?
BPBArraySegment dw ?
BPBInfoOffset dw ?
BPBInfoSegment dw ?
CMD2_DATA ends
Command 3: IOCTL Input
Input Output Control(IOCTL)命令是應用程式用於跟驅動程式做為溝通傳輸的命令,所以會有Input跟Output兩種方向,DOS的系統呼叫常式44H就是用於此目的,驅動程式想要提供IOCTL命令給應用程式呼叫時,檔頭資訊中的Attribute第14位元(SUPPORT IOCTL),必須先設定為1
CMD3_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD3_DATA dup(?)
CMD3_IRP ends
CMD3_DATA struc
MediaDescriptor db ?
BufferOffset dw ?
BufferSegment dw ?
Count dw ?
StartSectorNum dw ?
CMD3_DATA ends
Command 4: Input
從驅動程式讀取資料
CMD4_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD4_DATA dup(?)
CMD4_IRP ends
CMD4_DATA struc
MediaDescriptor db ?
BufferOffset dw ?
BufferSegment dw ?
Count dw ?
StartSectorNum dw ?
VolumeIDOffset dw ?
VolumeIDSegment dw ?
StartSector32 dd ?
CMD4_DATA ends
Command 5: Nondestructive Input
應用程式可以使用DOS的系統呼叫常式0B取得Input Buffer裡面的資料,但是不清除Input Buffer,如果沒有資料在Input Buffer,則設定IRP Header的Status狀態(Busy=1)
CMD5_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD5_DATA dup(?)
CMD5_IRP ends
CMD5_DATA struc
Buffer db ?
CMD5_DATA ends
Command 6: Input Status
取得Input Buffer的狀態,如果Input Buffer有資料,則設定IRP Header的Status狀態(Busy=0),反之則設定Busy=1,設定值是跟Nondestructive Input相反
CMD6_IRP struc
Header db size IRP_HEADER dup(?)
CMD6_IRP ends
Command 7: Input Flush
清除驅動程式的Input Buffer
CMD7_IRP struc
Header db size IRP_HEADER dup(?)
CMD7_IRP ends
Command 8: Output
傳送資料給驅動程式
CMD8_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD8_DATA dup(?)
CMD8_IRP ends
CMD8_DATA struc
MediaDescriptor db ?
BufferOffset dw ?
BufferSegment dw ?
Count dw ?
StartSectorNum dw ?
VolumeIDOffset dw ?
VolumeIDSegment dw ?
StartSector32 dd ?
CMD8_DATA ends
Command 9: Output with Verify
基本上,這個命令跟Command 8是一樣的,差別僅在於Verify這個功能,DOS的VERIFY旗標若被ON時,該命令才會被呼叫到,該命令能夠讓驅動程式讀回剛剛被寫出的資料,用以確保資料的正確性
CMD9_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD9_DATA dup(?)
CMD9_IRP ends
CMD9_DATA struc
MediaDescriptor db ?
BufferOffset dw ?
BufferSegment dw ?
Count dw ?
StartSectorNum dw ?
VolumeIDOffset dw ?
VolumeIDSegment dw ?
StartSector32 dd ?
CMD9_DATA ends
Command 10: Output Status
此命令用以得知驅動程式的設備輸出狀態,如:印表機,假設印表機的輸出緩衝區有字元等待列印,則此命令可以得知緩衝區的狀態(透過IRP Header的Busy Status狀態得知)
CMD10_IRP struc
Header db size IRP_HEADER dup(?)
CMD10_IRP ends
Command 11: Output Flush
清除Output Bufferi
CMD11_IRP struc
Header db size IRP_HEADER dup(?)
CMD11_IRP ends
Command 12: IOCTL Output
IOCTL的Ouput輸出(到驅動程式),驅動程式如要提供IOCTL命令給應用程式呼叫時,檔頭資訊中的Attribute第14位元(SUPPORT IOCTL),必須先設定為1
CMD12_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD12_DATA dup(?)
CMD12_IRP ends
CMD12_DATA struc
MediaDescriptor db ?
BufferOffset dw ?
BufferSegment dw ?
Count dw ?
StartSectorNum dw ?
CMD12_DATA ends
Command 13: Open
該命令就是當應用程式開啟該驅動程式時,DOS會透過此命令呼叫該驅動程式,至於應用程式如何知道它要開啟該驅動程式的名稱為何呢?答案就是驅動程式的檔頭資訊,在檔頭資訊中,有一個DriverName的欄位,該欄位就是代表該驅動程式的名稱,應用程式只要使用該名稱開啟即可,不過大家還是要注意一點,想要支援此功能,檔頭資訊中的Attribute第11位元(支援OPEN/CLOSE/REMOVABLE MEDIA設備),必須先設定為1
CMD13_IRP struc
Header db size IRP_HEADER dup(?)
CMD13_IRP ends
Command 14: Close
該命令就是用來關閉剛剛使用Open命令開啟的驅動程式,想要支援此功能,該驅動程式的檔頭資訊中的Attribute第11位元(支援OPEN/CLOSE/REMOVABLE MEDIA設備),必須先設定為1
CMD14_IRP struc
Header db size IRP_HEADER dup(?)
CMD14_IRP ends
Command 15: Removable Media
這個命令提供磁片是否可以更換的訊息給應用程式,應用程式可以使用DOS系統服務常式44H來詢問磁片是否可更換(08H),想要支援此功能,檔頭資訊中的Attribute第11位元(支援OPEN/CLOSE/REMOVABLE MEDIA設備),必須先設定為1,驅動程式回應在IRP Header的Status欄位(Busy)
CMD15_IRP struc
Header db size IRP_HEADER dup(?)
CMD15_IRP ends
Command 16: Output til Busy
輸出字元並等待所有字元寫完或設備發出Busy信號為止
CMD16_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD16_DATA dup(?)
CMD16_IRP ends
CMD16_DATA struc
MediaDescriptor db ?
BufferOffset dw ?
BufferSegment dw ?
Count dw ?
CMD16_DATA ends
Command 19: Generic IOCTL
這個IOCTL命令跟IOCTL Output命令是類似的觀念,差別僅在於此命令是以控制碼的觀念傳輸給驅動程式,一般應用程式可以使用DOS系統服務常式44H並指定使用Generic IOCTL(0DH),驅動程式想要提供此命令給應用程式呼叫時,檔頭資訊中的Attribute第6位元(GENERIC IOCTL),必須先設定為1
CMD19_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD19_DATA dup(?)
CMD19_IRP ends
CMD19_DATA struc
Major db ?
Minor db ?
SI dw ?
DI dw ?
PacketOffset dw ?
PacketSegment dw ?
CMD19_DATA ends
Command 23: Get Logical Device
取得邏輯設備的資料
CMD23_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD23_DATA dup(?)
CMD23_IRP ends
CMD23_DATA struc
IO db ?
Command db ?
RetStatus dw ?
Reserved dd ?
CMD23_DATA ends
Command 24: Set Logical Device
設定邏輯設備的資料
CMD24_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD24_DATA dup(?)
CMD24_IRP ends
CMD24_DATA struc
IO db ?
Command db ?
RetStatus dw ?
Reserved dd ?
CMD24_DATA ends
Command 25: IOCTL Query
該命令用來詢問驅動程式是否支援某些IOCTL,一般應用程式可以呼叫DOS的系統服務常式4401H和4411H要求驅動程式執行此要求,要使用該命令功能時,檔案標頭的Attribute第7位元必須被設定為1
CMD25_IRP struc
Header db size IRP_HEADER dup(?)
Data db size CMD25_DATA dup(?)
CMD25_IRP ends
CMD25_DATA struc
Major db ?
Minor db ?
SI dw ?
DI dw ?
PacketOffset dw ?
PacketSegment dw ?
CMD25_DATA ends
返回上一頁