📄 wdrminit.asm
字号:
mov es, ax
mov ah, 2
WD_RMI_Set_Init_Time_Loop:
mov al, es:[6Ch]
WD_RMI_Wait_For_Tick_Loop:
cmp al, es:[6Ch]
je WD_RMI_Wait_For_Tick_Loop
dec ah
jnz WD_RMI_Set_Init_Time_Loop
pop es
;------------------------------------------------------------------------------
;
; Now make sure that the Int 2Fh that we need will actually work. We'll
; do this by pointing DOS at somthing bogus for the time being.
;
;------------------------------------------------------------------------------
mov ah, 13h
mov bx, OFFSET WD_RMI_Int_13h_Hook
mov dx, OFFSET WD_RMI_Int_13h_Hook
int 2Fh
mov si, ds
mov di, cs
cmp si, di
je WD_RMI_Cant_Hook_Int13
mov WORD PTR cs:[DOS_BIOS_Int13_Vec+2], ds
mov WORD PTR cs:[DOS_BIOS_Int13_Vec], dx
mov WORD PTR cs:[ROM_BIOS_Int13_Vec+2], es
mov WORD PTR cs:[ROM_BIOS_Int13_Vec], bx
mov ax, cs
mov es, ax
mov ds, ax
call Check_Hook_Addr_OK
IFNDEF SETUP
jc SHORT WD_RMI_Bad_Int_Chain
ELSE
jc short WD_RMI_Error_Exit
ENDIF
;------------------------------------------------------------------------------
;
; It is possible for Int 13h to be hooked, so there may be some point
; in loading this device.
;
;------------------------------------------------------------------------------
;
; Make sure the interrupt we plan to use is unmasked.
;
in al, 0A1h
test al, 01000000b
IFNDEF SETUP
jnz SHORT WD_RMI_Wrong_IRQ
ELSE
jnz SHORT WD_RMI_Error_Exit
ENDIF
;
; Check the status I/O port to make sure it looks right.
;
mov dx, WDIO_Def_Base_Port+WDIO_Status_Off
IO_Delay
IO_Delay
in al, dx
and al, NOT (WDStat_ECC_Corrected OR WDStat_Index)
cmp al, WDStat_Ready OR WDStat_Seek_Complete
IFNDEF SETUP
jne SHORT WD_RMI_Status_Bad
ELSE
jne SHORT WD_RMI_Error_Exit
ENDIF
;------------------------------------------------------------------------------
;
; Now read a sector from each hard disk first through Int 13h and
; then by sending a command directly to the controller.
;
; We test both drives if present and set the appropriate bit for the
; drive. WDCTRL can use ony the drive that validates, even if there
; are two drives and one doesn't validate
;
;------------------------------------------------------------------------------
mov dl, 80h
mov di, 41h*4
call WDCtrl_Validate_Drive
pushf
and bx, RF_Use_Alt_Stat_80 ; Save only alt status bit
popf ; Restore carry flag
jc SHORT WD_RMI_First_Drive_Bogus
or bl, RF_Drive_80h_Ours ; Alt status bit + good drive bit
WD_RMI_First_Drive_Bogus:
cmp [Num_Int13_Drives], 1
je SHORT WD_RMI_Do_We_Bail_Out
mov dl, 81h
mov di, 46h*4
push bx ; Save reference data
call WDCtrl_Validate_Drive
mov si, bx ; Save alt stat return from call
pop bx ; Get previous bits
jc SHORT WD_RMI_Do_We_Bail_Out
and si, RF_Use_Alt_Stat_81
or bx, si
or bl, RF_Drive_81h_Ours ; Alt status bit + good drive bit
WD_RMI_Do_We_Bail_Out:
test bl, RF_Drive_80h_Ours OR RF_Drive_81h_Ours ; Either drive good?
IFNDEF SETUP
jz SHORT WD_RMI_Validation_Failed ; No, both bad so exit
ELSE
jz SHORT WD_RMI_Error_Exit
ENDIF
WD_RMI_Have_Ref_Data:
movzx edx, bl ; Get the reference data
xor bx, bx
xor si, si
IFNDEF SETUP
mov ax, Device_Load_Ok
ENDIF
;------------------------------------------------------------------------------
;
; Common exit point for WD real mode init. At this point, all return values
; are in AX, BX, and SI. If Int 13h is hooked then this code will reset
; the hook.
;
;------------------------------------------------------------------------------
WD_RMI_Common_Exit:
call Clean_Up_Hooks
ret
IFDEF SETUP
WD_RMI_Error_Exit:
mov edx, 0
jmp short WD_RMI_Common_Exit
ENDIF
;------------------------------------------------------------------------------
;
; Error handlers
;
;------------------------------------------------------------------------------
IFNDEF SETUP
;
; No disk drives were installed
;
WD_RMI_No_Disk_Drives:
mov dx, OFFSET No_Fixed_Disk_String
jmp SHORT WD_RMI_Print_Error
ENDIF
IFNDEF SETUP
;
; Not running on Win386 verstion 3.10 or later
;
WD_RMI_Invalid_Win386:
mov dx, OFFSET Invalid_Win386_Ver_String
jmp SHORT WD_RMI_Print_Error
ENDIF
;
; The DOS Int 2Fh did not work. Assume wrong DOS version.
;
WD_RMI_Cant_Hook_Int13:
mov dx, cs
mov ds, dx
mov es, dx
IFNDEF SETUP
mov dx, OFFSET Invalid_DOS_Ver_String
jmp SHORT WD_RMI_Print_Error
ELSE
jmp SHORT WD_RMI_Error_Exit
ENDIF
IFNDEF SETUP
;
; The Int 13h chain was hooked, but it appears that someone else has
; hooked it in front of us.
;
WD_RMI_Bad_Int_Chain:
mov dx, OFFSET Invalid_Int13_Chain
jmp SHORT WD_RMI_Print_Error
;
; The controller is not using the correct IRQ or the IRQ is masked.
;
WD_RMI_Wrong_IRQ:
mov dx, OFFSET Invalid_IRQ_String
jmp SHORT WD_RMI_Print_Error
;
; The initial read of the controller status port did not match our
; expectation.
;
WD_RMI_Status_Bad:
mov cx, ax
call Clean_Up_Hooks
mov dx, OFFSET Invalid_Controller_String
mov ah, 9
int 21h
mov al, cl
call Print_Hex_Byte
jmp SHORT WD_RMI_Dont_Load
;
; The controller did not pass our tests.
;
WD_RMI_Validation_Failed:
call Clean_Up_Hooks
mov dx, OFFSET Validation_Failed_String
mov ah, 9
int 21h
mov al, cl
call Print_Hex_Byte
mov ah, 02h
mov dl, ','
int 21h
mov dl, ' '
int 21h
mov al, ch
call Print_Hex_Byte
jmp SHORT WD_RMI_Dont_Load
WD_RMI_Print_Error:
call Clean_Up_Hooks
mov ah, 9
int 21h
WD_RMI_Dont_Load:
mov dx, OFFSET Pause_String
mov ah, 9
int 21h
xor ax, ax
int 16h
WD_RMI_Dont_Load_Silent:
xor bx, bx
xor si, si
mov ax, Abort_Device_Load + No_Fail_Message
jmp WD_RMI_Common_Exit
ENDIF
EndProc WDCtrl_Real_Mode_Init
;******************************************************************************
;
; Detect_QEMM_Stealth
;
; DESCRIPTION:
; Specific check for QEMM stealth. We'll call QEMM if it is installed
; to find out if stealth is on. This is done before entering the main
; part of the detection code since we need to make DOS calls to open
; the device driver.
;
; ENTRY:
; DS=ES=CS
;
; EXIT:
; None
;
; USES:
; Flags
;
;==============================================================================
BeginProc Detect_QEMM_Stealth
pusha
;
; Open QEMM device driver
;
mov dx, OFFSET QEMMDeviceName
mov ax, 3D00h
int 21h ; Try to open QEMM386$
jc SHORT DQS_No_QEMM ; If CY, QEMM-386 not present
mov bx, ax ; Save file handle in BX
mov dx, OFFSET QPIEntryPoint ; Store the entry point here
mov cx, 4 ; We're reading 4 bytes
mov ax, 4402h ; IOCTL read control string
int 21h
pushf ; Save error code
mov ah, 3Eh ; Close the file handle
int 21h
popf
jc SHORT DQS_No_QEMM
;
; At this point QPIEntryPoint contains the address of the QEMM entry
; point. We KNOW that we're on version 6.0 or later (since the IOCTL worked)
; so we'll make the stealth install call.
;
xor cx, cx ; Set CL to zero just in case...
mov ax, 30*100h+0 ; QEMM get info call
push ds ; More paranoia...
push es
call [QPIEntryPoint] ; Call Mr. QEMM
pop es
pop ds
test cl, cl ; Q: Is stealth enabled?
jz SHORT DQS_No_Stealth ; N: Don't set falg
; Y: Set flag for use later
mov [QEMM_Stealth_Enabled], True
DQS_No_Stealth:
DQS_No_QEMM:
popa
ret
EndProc Detect_QEMM_Stealth
;******************************************************************************
;
; Check_Hook_Addr_OK
;
; DESCRIPTION:
; This procedure checks the BIOS Int 13h interrupt vector value to
; see if it is "acceptable". The address is considered acceptable
; iff the segment is >= A000h or QEMM 6.0 or greater is installed
; and stealth is enabled or the hook code responds to our Int 2Fh.
;
; ENTRY:
; DS=ES=CS
;
; EXIT:
; If carry set then
; Hook is NOT acceptable
; else (carry clear)
; Hook address looks good
;
; USES:
; Flags
;
;==============================================================================
BeginProc Check_Hook_Addr_OK
cmp WORD PTR [ROM_BIOS_Int13_Vec+2], 0A000h
jae SHORT CHAO_Quick_OK_Exit
pusha
;------------------------------------------------------------------------------
;
; Broadcast an Int 2Fh that asks DOS Int 13h hookers if they are "blockdev
; aware". If they are aware of BlockDev and want fastdisk drivers to load
; then they will return 0 in CX.
;
;------------------------------------------------------------------------------
mov ax, (W386_Int_Multiplex SHL 8) + W386_Device_Broadcast
mov bx, BlockDev_Device_ID
.ERRE BlockDev_API_Int13_Chain_Check ; Should not be 0!
mov cx, BlockDev_API_Int13_Chain_Check
int 2Fh
jcxz SHORT CHAO_Chain_Is_OK
;------------------------------------------------------------------------------
;
; Specific check for QEMM stealth. We'll call QEMM if it is installed
; to find out if stealth is on. If it is then we'll load anyway.
;
;------------------------------------------------------------------------------
;
; Now make sure that both hooks point to the same code segment as a sanity
; check.
;
mov ax, WORD PTR [ROM_BIOS_Int13_Vec+2]
cmp ax, WORD PTR [DOS_BIOS_Int13_Vec+2]
jne SHORT CHAO_QEMM_Seg_Check_Failed
cmp [QEMM_Stealth_Enabled], True ; Q: Stealth on?
jne SHORT CHAO_QEMM_Seg_Check_Failed; N: Not gonna do it!
;
; All success cases exit here
;
CHAO_Chain_Is_OK:
popa
CHAO_Quick_OK_Exit:
clc
ret
;
; All failure cases exit here
;
CHAO_QEMM_Seg_Check_Failed:
CHAO_No_Stealth:
CHAO_No_QEMM:
popa
stc
ret
EndProc Check_Hook_Addr_OK
IFNDEF SETUP
;******************************************************************************
;
; Test_Disable_Switch
;
; DESCRIPTION:
; This procedure scans the parameters passed to Win386 for /d:F which
; is a debug switch to disable "FastDisk". It if is found then
; WDCTRL will not load.
;
; ENTRY:
; None
;
; EXIT:
; If carry flag set then /D:F selected. WDCTRL should not load.
;
; USES:
; Flags
;
;==============================================================================
BeginProc Test_Disable_Switch
push ds
pusha
mov ah, 62h ; Get current PSP
int 21h
mov ds, bx ; ES -> Current PSP
;
; Get command-line debug option
;
; There are several forms for this:
;
; /d:s foo /d:p
;
; In this case, the first /d: is ours, the second isn't, the second
; is an argument to the app "foo". We detect the boundary (in this case
; the "foo") by detecting a character which is not a tab, space or '/'
; which is not part of a '/' arg. Thus:
;
; foo is a boundary
; /goooo is not a boundary
; /d:& is not a boundary and will be skipped, valid debug options
; are either 'A'-'Z' or 'a'-'z'
;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -