1100 lines
24 KiB
NASM
1100 lines
24 KiB
NASM
|
|
;-----------------------------------------------------------------------------
|
|
; ElTorito.asm
|
|
;
|
|
; El Torito Bootable CD-ROM driver which does not reset the CD-ROM drive upon
|
|
; loading, but instead accesses the drive through BIOS system calls
|
|
;
|
|
; MIT License
|
|
;
|
|
; (c) 2000 by Gary Tong
|
|
; (c) 2001-2009 by Bart Lagerweij
|
|
;
|
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
; of this software and associated documentation files (the "Software"), to deal
|
|
; in the Software without restriction, including without limitation the rights
|
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
; copies of the Software, and to permit persons to whom the Software is
|
|
; furnished to do so, subject to the following conditions:
|
|
;
|
|
; The above copyright notice and this permission notice shall be included in
|
|
; all copies or substantial portions of the Software.
|
|
;
|
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
; THE SOFTWARE.
|
|
;
|
|
;-----------------------------------------------------------------------------
|
|
|
|
; To assemble and link, use these commands with NASM 2.x:
|
|
; nasm -Ox -f bin -o eltorito.sys eltorito.asm
|
|
|
|
; To enable Trace markers uncomment the line below
|
|
; DEBUG_TRACERS=1
|
|
|
|
; To enable debug info uncomment the line below
|
|
; DEBUG=1
|
|
|
|
%ifdef DEBUG_TRACERS
|
|
%macro TRACER 1
|
|
call debug_tracer
|
|
db %1
|
|
%endmacro
|
|
%else
|
|
%macro TRACER 1
|
|
%endmacro
|
|
%endif ; DEBUG_TRACERS
|
|
|
|
%define Ver '1.5'
|
|
%define CR 0DH, 0Ah
|
|
RPolyH equ 0EDB8h
|
|
RPolyL equ 08320h
|
|
|
|
section .text align=16
|
|
org 0
|
|
|
|
;=============================================================================
|
|
|
|
Cdrom:
|
|
|
|
NextDriver dd -1 ;-+
|
|
Attributes dw 0C800h ; |
|
|
Pointers dw Strategy ; |
|
|
dw Commands ; | MSCDEX requires this
|
|
DeviceName db 'ELTORITO' ; | data in these locations
|
|
dw 0 ; |
|
|
DriveLetter db 0 ; |
|
|
NumUnitsSupp db 1 ;-+
|
|
|
|
DriverName db 'El-Torito CD-ROM Device Driver',0
|
|
align 4, db 0
|
|
ReqHdrLoc dd 0
|
|
XferAddr dd 0
|
|
Checksum dd -1
|
|
DriveNumber db 0
|
|
ReadBytes db 0 ;0 --> 2048 bytes/sector
|
|
;1 --> 1024 bytes/sector
|
|
;2 --> 512 bytes/sector
|
|
|
|
Routines dw Init ;Init ;0
|
|
dw Unsupported ;MediaCheck ;1
|
|
dw Unsupported ;BuildBPB ;2
|
|
dw IoctlInput ;IoctlInput ;3
|
|
dw Unsupported ;Input ;4
|
|
dw Unsupported ;NonDesInput ;5
|
|
dw Unsupported ;InputStatus ;6
|
|
dw Unsupported ;InputFlush ;7
|
|
dw Unsupported ;Output ;8
|
|
dw Unsupported ;OutputVerify ;9
|
|
dw Unsupported ;OutputStatus ;10
|
|
dw Unsupported ;OutputFlush ;11
|
|
dw IoctlOutput ;IoctlOutput ;12
|
|
dw DoNothing ;DeviceOpen ;13
|
|
dw DoNothing ;DeviceClose ;14
|
|
dw ReadL ;ReadL ;128
|
|
|
|
IoctlICtrl dw Raddr ;Raddr ;0
|
|
dw Unsupported ;LocHead ;1
|
|
dw Unsupported ;(Reserved) ;2
|
|
dw Unsupported ;ErrStat ;3
|
|
dw Unsupported ;AudInfo ;4
|
|
dw DrvBytes ;DrvBytes ;5
|
|
dw DevStat ;DevStat ;6
|
|
dw SectSize ;SectSize ;7
|
|
dw VolSize ;VolSize ;8
|
|
dw MedChng ;MedChng ;9
|
|
|
|
SpecPkt times 19 db 0 ; offset 77h in 1.4
|
|
times 13 db 0 ; unknown extra 00s in 1.4
|
|
|
|
Greeting db 'El-Torito Bootable CD-ROM Driver for Dos v',Ver,', http://www.nu2.nu/eltorito/',CR
|
|
db ' (c) 2000 by Gary Tong',CR
|
|
db ' (c) 2001-2002 by Bart Lagerweij',CR,0
|
|
DblSpace db ' ',0
|
|
|
|
;=============================================================================
|
|
|
|
Strategy:
|
|
|
|
mov word [cs:ReqHdrLoc],bx
|
|
mov word [cs:ReqHdrLoc+2],es
|
|
retf
|
|
|
|
|
|
;=============================================================================
|
|
|
|
Commands:
|
|
|
|
push ax
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push si
|
|
push di
|
|
push bp
|
|
; pushad
|
|
push ds
|
|
push es
|
|
TRACER 'C'
|
|
|
|
cld ;Clear direction
|
|
sti ;Enable interrupts
|
|
|
|
mov ax, cs ;ds=cs
|
|
mov ds, ax
|
|
|
|
les bx,[ReqHdrLoc] ;seg:offset ptr into es:bx
|
|
xor ax,ax
|
|
mov al,[es:bx+2] ;Get Command code
|
|
%ifdef DEBUG
|
|
call print_hex8
|
|
%endif
|
|
cmp al,15
|
|
jb Mult2 ;If 0-14
|
|
cmp al,128
|
|
jb UnknownCmd ;If 15-127
|
|
cmp al,129
|
|
jb ShiftDown ;If 128
|
|
UnknownCmd: mov al,121 ;8 = Unsupported (Reserved)
|
|
ShiftDown: sub al,113 ;128 --> 15, 121 --> 8
|
|
Mult2: shl al,1 ;Convert into offset (*2)
|
|
mov di,Routines
|
|
add di,ax
|
|
call word [di] ;Execute desired command
|
|
or ax,100h ;Set Return Status's Done bit
|
|
lds bx,[ReqHdrLoc] ;seg:offset ptr into ds:bx
|
|
mov [bx+3],ax ;Save Status
|
|
|
|
%ifdef DEBUG
|
|
cmp byte [cs:buffer+2048], 96h
|
|
je buffer_ok
|
|
mov al, '!'
|
|
call print_char
|
|
jmp $
|
|
buffer_ok:
|
|
%endif
|
|
|
|
TRACER 'c'
|
|
pop es
|
|
pop ds
|
|
; popad
|
|
pop bp
|
|
pop di
|
|
pop si
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
retf
|
|
|
|
|
|
;=============================================================================
|
|
|
|
Unsupported: ;Unsupported Command
|
|
|
|
mov ax,8003h ;Set Status Error bit,
|
|
TRACER 'U'
|
|
TRACER 'C'
|
|
retn ; Error 3 = Unknown Command
|
|
|
|
|
|
;=============================================================================
|
|
|
|
IoctlInput: ;IOCTL Input Routine
|
|
|
|
mov di,[es:bx+14] ;es:bx --> Request Header
|
|
mov es,[es:bx+16] ;Get Xfer Address into es:di
|
|
xor ax,ax ;Get Control Block Code
|
|
mov al,[es:di]
|
|
%ifdef DEBUG
|
|
TRACER 'I'
|
|
TRACER 'O'
|
|
call print_hex8
|
|
%endif
|
|
cmp al,10
|
|
jb UnkIoctlI ;If 0-9
|
|
mov al,2 ;Map to Unsupported
|
|
UnkIoctlI: shl al,1 ;Convert into offset (*2)
|
|
mov si,IoctlICtrl
|
|
add si,ax
|
|
call word [si] ;Execute desired command
|
|
retn
|
|
|
|
|
|
;=============================================================================
|
|
|
|
Raddr: ;Return Device Header Address
|
|
|
|
TRACER 'A'
|
|
mov word [es:di+1],0
|
|
mov [es:di+3],cs
|
|
xor ax, ax ;Set Return Status = success
|
|
TRACER 'a'
|
|
retn
|
|
|
|
|
|
;=============================================================================
|
|
|
|
DrvBytes: ;Read Drive Bytes
|
|
|
|
TRACER 'B'
|
|
push di ;Save original Xfer Addr
|
|
add di,2 ;Point to 1st dest byte
|
|
mov si,Greeting ;Point to Greeting
|
|
DrvB: movsb ;Copy over a byte
|
|
cmp byte [si],13 ;Is next char a CR?
|
|
jne DrvB ;Loop if not
|
|
|
|
sub di,2 ;Get #bytes copied into ax
|
|
mov ax,di
|
|
pop di ;Retrieve original Xfer Addr
|
|
sub ax,di
|
|
mov byte [es:di+1],al ;and save it
|
|
mov ax,0 ;Set Return Status = success
|
|
TRACER 'b'
|
|
retn
|
|
|
|
|
|
;=============================================================================
|
|
|
|
DevStat: ;Return Device Status
|
|
|
|
TRACER 'D'
|
|
mov word [es:di+1],202h ;Door closed
|
|
mov word [es:di+3],0 ;Door unlocked
|
|
;Supports only cooked reading
|
|
;Read only
|
|
;Data read only
|
|
;No interleaving
|
|
;No prefetching
|
|
;No audio channel manipulation
|
|
;Supports both HSG and Redbook
|
|
; addressing modes
|
|
|
|
xor ax, ax ;Set Return Status = success
|
|
TRACER 'd'
|
|
retn
|
|
|
|
|
|
;=============================================================================
|
|
|
|
SectSize: ;Return Sector Size
|
|
|
|
TRACER 'S'
|
|
mov word [es:di+2],2048
|
|
mov ax,0 ;Set Return Status = success
|
|
TRACER 's'
|
|
retn
|
|
|
|
|
|
;=============================================================================
|
|
|
|
VolSize: ;Return Volume Size
|
|
|
|
TRACER 'V'
|
|
call PriVolDesc ;Get and Check Primary Volume
|
|
; Descriptor
|
|
mov ax,800Fh ;Assume Invalid Disk Change
|
|
jc VolExit ;If Read Failure
|
|
|
|
mov ax,word [Buffer+80] ;Read Successful
|
|
mov word [es:di+1],ax ;Copy over Volume Size
|
|
mov ax,word [Buffer+82]
|
|
mov word [es:di+3],ax
|
|
mov ax,0 ;Set Return Status = success
|
|
VolExit:
|
|
TRACER 'v'
|
|
retn
|
|
|
|
|
|
;=============================================================================
|
|
|
|
MedChng: ;Return Media Changed Status
|
|
|
|
TRACER 'M'
|
|
call PriVolDesc ;Get and Check Primary Volume
|
|
; Descriptor
|
|
mov byte [es:di+1],-1 ;Assume Media Changed
|
|
mov ax,800Fh ; and Invalid Disk Change
|
|
jc MedExit ;If Media Changed or Bad
|
|
|
|
mov byte [es:di+1],1 ;Media has not changed
|
|
mov ax,0 ;Set Return Status = success
|
|
MedExit:
|
|
TRACER 'm'
|
|
retn
|
|
|
|
|
|
;=============================================================================
|
|
|
|
PriVolDesc: ;Get and Check Primary Volume
|
|
; Descriptor
|
|
TRACER 'P'
|
|
mov ax,cs ;Set ds:si --> SpecPkt
|
|
mov ds,ax
|
|
|
|
mov cx, 5
|
|
PriVolAgain:
|
|
mov byte [SpecPkt],16 ;SpecPkt Size
|
|
mov byte [SpecPkt+1],0 ;Reserved
|
|
mov word [SpecPkt+2],1 ;Transfer one 2048-byte sector
|
|
push cx
|
|
mov cl,byte [ReadBytes] ;Multiply by 4 if reading 512
|
|
shl word [SpecPkt+2],cl ; bytes at a time
|
|
pop cx
|
|
mov word [SpecPkt+6],cs ;Into our Buffer
|
|
mov word [SpecPkt+4], Buffer
|
|
mov word [SpecPkt+8],16 ;From CD Sector 16
|
|
mov word [SpecPkt+10],0
|
|
mov word [SpecPkt+12],0
|
|
mov word [SpecPkt+14],0
|
|
|
|
mov si, SpecPkt
|
|
mov dl, [DriveNumber]
|
|
mov ah, 42h ;Extended Read
|
|
int 13h
|
|
jnc PriVolPass ;If success
|
|
|
|
; TRACER '1'
|
|
; read error
|
|
loop PriVolAgain
|
|
|
|
TRACER '2'
|
|
; read retries exhausted
|
|
; flow into below
|
|
jmp PriReadErr
|
|
|
|
PriVolPass:
|
|
mov si,Buffer ;Point input to Buffer
|
|
mov ax,-1 ;Init Checksum registers
|
|
mov bx,ax ; bx,ax = 0FFFFFFFFh
|
|
jc PriNew ;If Read Failure
|
|
|
|
push di ;Read Successful,
|
|
; so Calculate Checksum
|
|
mov di,1024 ;Init Word counter
|
|
PriWord: mov dx,[cs:si] ;Grab next word from buffer
|
|
mov cx,16 ;Init bit counter
|
|
PriBit: shr dx,1 ;Shift everything right 1 bit
|
|
rcr bx,1
|
|
rcr ax,1
|
|
jnc NoMult ;If a zero shifted out
|
|
|
|
xor bx,RPolyH ;A one shifted out, so XOR
|
|
xor ax,RPolyL ; Checksum with RPoly
|
|
NoMult:
|
|
loop PriBit
|
|
|
|
add si,2 ;Inc Word Pointer
|
|
dec di
|
|
ja PriWord
|
|
TRACER '3'
|
|
|
|
pop di ;Checksum calculation complete
|
|
cmp bx,[Checksum+2] ;Has Checksum changed?
|
|
jne PriNew ;If Checksum Changed
|
|
|
|
cmp ax,[Checksum]
|
|
jne PriNew ;If Checksum Changed
|
|
|
|
clc ;Checksum not changed, CF=0
|
|
mov ax,0 ;Status = success
|
|
jmp PriOld
|
|
|
|
PriReadErr:
|
|
mov WORD [Checksum+2],bx ;Save New Checksum
|
|
mov [Checksum],ax ; or 0FFFFFFFFh if bad read
|
|
stc ;Checksum change, CF=1
|
|
mov ax, 800bh ;Status = read fault
|
|
jmp PriOld
|
|
|
|
PriNew: mov WORD [Checksum+2],bx ;Save New Checksum
|
|
mov [Checksum],ax ; or 0FFFFFFFFh if bad read
|
|
stc ;Checksum Changed, CF=1
|
|
mov ax,800Fh ;Status = Invalid Media Change
|
|
PriOld:
|
|
TRACER 'p'
|
|
retn
|
|
|
|
|
|
;=============================================================================
|
|
|
|
IoctlOutput: ;IOCTL Output Routine
|
|
|
|
TRACER 'O'
|
|
mov di,[es:bx+14] ;es:bx --> Request Header
|
|
mov es,[es:bx+16] ;Get Xfer Address into es:di
|
|
xor ax,ax ;Get Control Block Code
|
|
mov al,[es:di]
|
|
cmp al,2
|
|
jne UnkIoctlO ;If not 2 (ResetDrv)
|
|
call DoNothing ;Reset Drive
|
|
jmp IoctlODone
|
|
UnkIoctlO:
|
|
call Unsupported ;Unsupported command
|
|
IoctlODone:
|
|
TRACER 'o'
|
|
retn
|
|
|
|
|
|
;=============================================================================
|
|
|
|
DoNothing: ;Do Nothing Command
|
|
|
|
mov ax,0 ;Set Return Status = success
|
|
retn
|
|
|
|
|
|
;=============================================================================
|
|
|
|
ReadL: ;Read Long Command
|
|
|
|
TRACER 'R'
|
|
mov ax,cs ;Set ds=cs
|
|
mov ds,ax
|
|
;es:bx --> Request Header
|
|
cmp byte [es:bx+24],0 ;Check Data Read Mode
|
|
jne ReadLErr ;If Cooked Mode
|
|
|
|
cmp byte [es:bx+13],2 ;Check Addressing Mode
|
|
jb ReadLOK ;If HSG or Redbook Mode
|
|
|
|
ReadLErr:
|
|
TRACER '8'
|
|
mov ax,8003h ;Set Return Status = Unknown
|
|
jmp ReadLExit ; Command Error and exit
|
|
|
|
ReadLOK:
|
|
mov ax,[es:bx+20] ;Get Starting Sector Number,
|
|
mov dx,[es:bx+22] ; Assume HSG Addressing Mode
|
|
cmp byte [es:bx+13],0 ;Check Addressing Mode again
|
|
je ReadLHSG ;If HSG Addressing Mode
|
|
|
|
TRACER '7'
|
|
;Using Redbook Addressing Mode. Convert to HSG format
|
|
mov al,dl ;Get Minutes
|
|
mov dl,60
|
|
mul dl ;ax = Minutes * 60
|
|
add al,byte [es:bx+21] ;Add in Seconds
|
|
adc ah,0
|
|
mov dx,75 ;dx:ax =
|
|
mul dx ; ((Min * 60) + Sec) * 75
|
|
add al,byte [es:bx+20] ;Add in Frames
|
|
adc ah,0
|
|
adc dx,0
|
|
sub ax,150 ;Subtract 2-Second offset
|
|
sbb dx,0 ;dx:ax = HSG Starting Sector
|
|
|
|
ReadLHSG:
|
|
mov word [SpecPkt+8], ax ;Store Starting
|
|
mov word [SpecPkt+10], dx ; Sector Number
|
|
mov word [SpecPkt+12], 0 ; (HSG Format)
|
|
mov word [SpecPkt+14], 0
|
|
|
|
mov ax,[es:bx+14] ;Get Transfer Address
|
|
mov word [SpecPkt+4],ax
|
|
mov ax,[es:bx+16]
|
|
mov word [SpecPkt+6],ax
|
|
|
|
mov byte [SpecPkt],16 ;Size of Disk Address Packet
|
|
mov byte [SpecPkt+1],0 ;Reserved
|
|
|
|
mov cx, 5
|
|
ReadLAgain:
|
|
mov ax,[es:bx+18] ;Get number of sectors to read
|
|
mov word [SpecPkt+2],ax
|
|
cmp ax, 3FFFh ;Too large?
|
|
ja ReadLBad ;If yes
|
|
|
|
push cx
|
|
mov cl,byte [ReadBytes] ;Multiply by 4 if reading 512
|
|
shl word [SpecPkt+2],cl ; bytes at a time
|
|
pop cx
|
|
|
|
%ifdef DEBUG
|
|
push ax
|
|
push cx
|
|
push si
|
|
mov cx, 16
|
|
mov si,SpecPkt
|
|
ReadDump: mov al, ' '
|
|
call print_char
|
|
mov al, byte [si] ;Hexdump a SpecPkt byte
|
|
call print_hex8
|
|
inc si ;Point to next byte
|
|
loop ReadDump
|
|
pop si
|
|
pop cx
|
|
pop ax
|
|
%endif
|
|
mov si,SpecPkt
|
|
mov dl,[DriveNumber]
|
|
mov ah,42h ;Extended Read
|
|
int 13h
|
|
jnc ReadLGd ;If success
|
|
|
|
;hang:
|
|
; jmp hang
|
|
; TRACER '1'
|
|
loop ReadLAgain
|
|
TRACER '2'
|
|
jmp short ReadLBad
|
|
ReadLGd:
|
|
TRACER '3'
|
|
xor ax, ax ;Status 0 = success
|
|
jmp short ReadLExit
|
|
|
|
ReadLBad:
|
|
TRACER '9'
|
|
mov ax, 800Bh ;Set Read Fault Error
|
|
; flow into ReadLExit
|
|
ReadLExit:
|
|
TRACER 'r'
|
|
retn
|
|
|
|
|
|
|
|
%ifdef DEBUG_TRACERS
|
|
debug_tracer: pushad
|
|
pushfd
|
|
|
|
mov al, '['
|
|
mov ah,0Eh ;BIOS video teletype output
|
|
xor bh, bh
|
|
int 10h ;Print it
|
|
|
|
mov bp,sp
|
|
mov bx,[bp+9*4] ; Get return address
|
|
mov al,[cs:bx] ; Get data byte
|
|
inc word [bp+9*4] ; Return to after data byte
|
|
|
|
mov ah,0Eh ;BIOS video teletype output
|
|
xor bh, bh
|
|
int 10h ;Print it
|
|
|
|
mov al, ']'
|
|
mov ah,0Eh ;BIOS video teletype output
|
|
xor bh, bh
|
|
int 10h ;Print it
|
|
|
|
popfd
|
|
popad
|
|
retn
|
|
%endif
|
|
|
|
;-----------------------------------------------------------------------------
|
|
; PRINT_HEX4
|
|
;-----------------------------------------------------------------------------
|
|
; print a 4 bits integer in hex
|
|
;
|
|
; Input:
|
|
; AL - 4 bits integer to print (low)
|
|
;
|
|
; Output: None
|
|
;
|
|
; Registers destroyed: None
|
|
;
|
|
print_hex4:
|
|
|
|
push ax
|
|
and al, 0fh ; we only need the first nibble
|
|
cmp al, 10
|
|
jae hex_A_F
|
|
add al, '0'
|
|
jmp hex_0_9
|
|
hex_A_F:
|
|
add al, 'A'-10
|
|
hex_0_9:
|
|
call print_char
|
|
pop ax
|
|
retn
|
|
|
|
|
|
;-----------------------------------------------------------------------------
|
|
; print_hex8
|
|
;-----------------------------------------------------------------------------
|
|
; print a 8 bits integer in hex
|
|
;
|
|
; Input:
|
|
; AL - 8 bits integer to print
|
|
;
|
|
; Output: None
|
|
;
|
|
; Registers destroyed: None
|
|
;
|
|
print_hex8:
|
|
|
|
push ax
|
|
push bx
|
|
|
|
mov ah, al
|
|
shr al, 4
|
|
call print_hex4
|
|
|
|
mov al, ah
|
|
and al, 0fh
|
|
call print_hex4
|
|
|
|
pop bx
|
|
pop ax
|
|
retn
|
|
|
|
|
|
;=============================================================================
|
|
; print_hex16 - print a 16 bits integer in hex
|
|
;
|
|
; Input:
|
|
; AX - 16 bits integer to print
|
|
;
|
|
; Output: None
|
|
;
|
|
; Registers destroyed: None
|
|
;=============================================================================
|
|
print_hex16:
|
|
|
|
push ax
|
|
push bx
|
|
push cx
|
|
|
|
mov cx, 4
|
|
print_hex16_loop:
|
|
rol ax, 4
|
|
call print_hex4
|
|
loop print_hex16_loop
|
|
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
retn
|
|
|
|
;=============================================================================
|
|
; print_hex32 - print a 32 bits integer in hex
|
|
;
|
|
; Input:
|
|
; EAX - 32 bits integer to print
|
|
;
|
|
; Output: None
|
|
;
|
|
; Registers destroyed: None
|
|
;=============================================================================
|
|
print_hex32:
|
|
|
|
push eax
|
|
push bx
|
|
push cx
|
|
|
|
mov cx, 8
|
|
print_hex32_loop:
|
|
rol eax, 4
|
|
call print_hex4
|
|
loop print_hex32_loop
|
|
|
|
pop cx
|
|
pop bx
|
|
pop eax
|
|
retn
|
|
|
|
;=============================================================================
|
|
; print_string - print string at current cursor location
|
|
;
|
|
; Input:
|
|
; DS:SI - ASCIIZ string to print
|
|
;
|
|
; Output: None
|
|
;
|
|
; Registers destroyed: None
|
|
;=============================================================================
|
|
print_string:
|
|
push ax
|
|
push si
|
|
|
|
print_string_again:
|
|
mov al, [si]
|
|
or al, al
|
|
jz print_string_exit
|
|
call print_char
|
|
inc si
|
|
jmp print_string_again
|
|
|
|
print_string_exit:
|
|
pop si
|
|
pop ax
|
|
retn
|
|
|
|
;-----------------------------------------------------------------------------
|
|
; PRINT_CHAR
|
|
;-----------------------------------------------------------------------------
|
|
; Print's a character at current cursor position
|
|
;
|
|
; Input:
|
|
; AL - Character to print
|
|
;
|
|
; Output: None
|
|
;
|
|
; Registers destroyed: None
|
|
;
|
|
print_char:
|
|
|
|
push ax
|
|
push bx
|
|
|
|
mov ah,0Eh ;BIOS video teletype output
|
|
xor bh, bh
|
|
int 10h ;Print it
|
|
|
|
print_char_exit:
|
|
pop bx
|
|
pop ax
|
|
retn
|
|
|
|
|
|
;=============================================================================
|
|
|
|
;This space is used as a 2048-byte read buffer plus one test byte.
|
|
;The 96h data is used for testing the number of bytes returned by an Extended
|
|
; CD-ROM sector read
|
|
|
|
align 16, db 0
|
|
Buffer times 2049 db 96h
|
|
|
|
;=============================================================================
|
|
|
|
Init: ;Initialization Routine
|
|
|
|
TRACER 'I'
|
|
mov ax,cs ;ds=cs
|
|
mov ds,ax
|
|
|
|
%ifdef DEBUG
|
|
; print CS value (load segment)
|
|
call print_hex16
|
|
%endif
|
|
|
|
mov si, Greeting ;Display Greeting
|
|
call print_string
|
|
|
|
mov ax,Unsupported ;Init is executed only once
|
|
mov [Routines],ax
|
|
|
|
mov ax, 5400h
|
|
int 13h ; Get diskemu status
|
|
jc FindBoot ; If CF=1 no diskemu loaded
|
|
|
|
mov [DriveNumber], cl ; Store drive number
|
|
|
|
call keyflag
|
|
and al, 8 ; alt key ?
|
|
jz extread
|
|
|
|
mov si, DrvNumMsg ; Display "drive number="
|
|
call print_string
|
|
mov al, [DriveNumber]
|
|
call print_hex8
|
|
mov si, LineEnd ; CR/LF
|
|
call print_string
|
|
jmp extread
|
|
|
|
; Diskemu is not loaded
|
|
; so loop to find drive number
|
|
; *** start of 1.4 changes ***
|
|
; ??? mov dl, 0ffh ;Start at Drive 0xff
|
|
; *** FindBoot at c47 in 1.4, at c0c in 1.3 ***
|
|
FindBoot: call ScanDrives ; call new helper in 1.4
|
|
jnc FoundBoot ; ded*df3
|
|
; mov si,offset SpecPkt ;Locate booted CD-ROM drive
|
|
; mov [SpecPkt],0 ;Clear 1st byte of SpecPkt
|
|
; mov ax,4B01h ;Get Bootable CD-ROM Status
|
|
; int 13h
|
|
; jnc FindPass ;If booted CD found
|
|
;
|
|
; Carry is not cleared in buggy Dell BIOSes,
|
|
; so I'm checking packet size byte
|
|
; some bogus bioses (Dell Inspiron 2500) returns packet size 0xff when failed
|
|
; Dell Dimension XPsT returns packet size 0x14 when OK
|
|
|
|
; cmp [SpecPkt], 0
|
|
; jne FoundBoot
|
|
|
|
; cmp [SpecPkt], 13h ; anything between 13h and 20h should be OK
|
|
; jb FindFail
|
|
; cmp [SpecPkt], 20h
|
|
; ja FindFail
|
|
; jmp short FoundBoot
|
|
;
|
|
; FindFail:
|
|
; dec dl ;Next drive
|
|
; cmp dl, 80h
|
|
; jae FindBoot ;Check from ffh..80h
|
|
; *** end of 1.4 changes ***
|
|
|
|
mov si,NoBootCD ;No booted CD found,
|
|
call print_string
|
|
jmp NoEndAddr ;Do not install driver
|
|
|
|
FoundBoot:
|
|
; mov dl, [SpecPkt+2] ; 1.4 change
|
|
; *** next line at c57 in 1.4, at c3d in 1.3 ***
|
|
mov [DriveNumber],dl ;Booted CD-ROM found,
|
|
; so save Drive #
|
|
|
|
call keyflag
|
|
and al, 8 ; alt key ?
|
|
jz extread
|
|
|
|
mov si, CDStat
|
|
call print_string
|
|
mov si, SpecPkt ;Point to returned CD SpecPkt
|
|
mov cx, 19 ; containing 19 bytes
|
|
StatDump: mov al, ' ' ;Print a space
|
|
call print_char
|
|
mov al, byte [si] ;Hexdump a SpecPkt byte
|
|
call print_hex8
|
|
inc si ;Point to next byte
|
|
loop StatDump
|
|
|
|
mov si, LineEnd ;Print a CR/LF
|
|
call print_string
|
|
|
|
extread:
|
|
;See how many CD Sector bytes are returned by an Extended Read
|
|
mov byte [SpecPkt],16 ;SpecPkt Size
|
|
mov byte [SpecPkt+1],0 ;Reserved
|
|
mov word [SpecPkt+2],1 ;Transfer one sector
|
|
mov word [SpecPkt+6],cs ;Into our Buffer
|
|
mov word [SpecPkt+4],Buffer
|
|
mov word [SpecPkt+8],16 ;From CD Sector 16
|
|
mov word [SpecPkt+10],0
|
|
mov word [SpecPkt+12],0
|
|
mov word [SpecPkt+14],0
|
|
|
|
mov si, SpecPkt ;Set ds:si --> SpecPkt
|
|
mov dl, [DriveNumber]
|
|
mov ah, 42h ;Extended Read
|
|
int 13h
|
|
jnc SecSize ;If success
|
|
|
|
mov ah, 42h ;Always make 2 read attempts
|
|
int 13h
|
|
;How many bytes did we get?
|
|
SecSize: std ;Count down
|
|
mov ax,cs ;Point to end of Buffer
|
|
mov es,ax
|
|
mov di,Buffer+2047 ;Find end of read data
|
|
mov si,Buffer+2048
|
|
mov cx,2049
|
|
repe cmpsb ;cx = number of bytes read
|
|
|
|
cld ;Restore count direction to up
|
|
mov si,CDBytes ;Display number of bytes read
|
|
call print_string
|
|
|
|
mov al, [DriveNumber]
|
|
call print_hex8
|
|
|
|
mov si,CDBytesA ;Remainder A of message
|
|
call print_string
|
|
|
|
mov al,ch ;Hex-dump cx
|
|
and al,0Fh ;Second nibble
|
|
call print_hex8 ; (don't need the First)
|
|
mov al,cl
|
|
call print_hex8 ; (don't need the First)
|
|
|
|
mov si,CDBytesB ;Remainder B of message
|
|
call print_string
|
|
|
|
cmp cx,2048 ;Did we read 2048 bytes?
|
|
je ParseParm ;If yes <-- O.K.
|
|
|
|
mov byte [ReadBytes],1
|
|
cmp cx,1024 ;Did we read 1024 bytes?
|
|
je ParseParm ;If yes <-- O.K.
|
|
|
|
mov byte [ReadBytes],2
|
|
cmp cx,512 ;Did we read 512 bytes?
|
|
jne NoEndAddr ;If not, do not load driver
|
|
|
|
ParseParm: mov bx,word [cs:ReqHdrLoc] ;Parse command line
|
|
mov es,word [cs:ReqHdrLoc+2] ; parameters
|
|
mov si,[es:bx+18] ;Get BPB array ptr into DS:SI
|
|
mov ds,[es:bx+20]
|
|
FindParm: inc si
|
|
FindParm1: cmp byte [si],0Dh ;CR? (End of parameters)
|
|
je EndOfParms
|
|
|
|
cmp byte [si],0Ah ;LF?
|
|
je EndOfParms
|
|
|
|
cmp byte [si],'/' ;A parameter?
|
|
jne FindParm
|
|
|
|
inc si
|
|
cmp byte [si],'D' ;Device Name parameter?
|
|
jne FindParm1
|
|
|
|
inc si
|
|
cmp byte [si],':'
|
|
jne FindParm1
|
|
|
|
;bbb
|
|
push si
|
|
mov si, DevName ;Device Name is at ds:si
|
|
push ds ;Keep ptr to Device Name
|
|
mov ax, cs
|
|
mov ds, ax
|
|
call print_string
|
|
pop ds ;Retrieve Device Name ptr
|
|
pop si
|
|
mov cx, 8 ;Get next 8 chars
|
|
inc si ; = Device Name
|
|
mov ax, cs
|
|
mov es, ax
|
|
mov di, DeviceName
|
|
NextChar: cmp byte [si],' '
|
|
ja AboveSpace
|
|
|
|
mov ax,cs ;Pad end of Device Name with
|
|
mov ds,ax ; spaces if necessary
|
|
mov si,DblSpace ;A space
|
|
AboveSpace: mov al, [si]
|
|
call print_char
|
|
movsb ;ds:[si] --> es:[di]
|
|
loop NextChar
|
|
|
|
mov si,LineEnd
|
|
mov ax,cs
|
|
mov ds,ax
|
|
call print_string
|
|
|
|
mov ax,Init-2 ;Last byte of driver to keep
|
|
jmp EndAddr ;Install driver
|
|
|
|
EndOfParms:
|
|
mov ax, cs ; Restore segment registers (fix)
|
|
mov ds, ax
|
|
mov es, ax
|
|
|
|
mov si,NoDevName ;No Device Name Found
|
|
call print_string
|
|
|
|
NoEndAddr: mov ax,0 ;Do not install driver
|
|
|
|
EndAddr: mov es,[ReqHdrLoc+2] ;Write End Address
|
|
mov bx,[ReqHdrLoc]
|
|
mov [es:bx+14],ax
|
|
mov [es:bx+16],cs
|
|
mov bx,ax ;Hold onto install status
|
|
|
|
mov si, DrvInst ;Display driver install status
|
|
call print_string
|
|
mov si, DrvInst1 ;Assume driver installed
|
|
cmp bx,0 ;Was driver installed?
|
|
jne DrvStatus ;If yes
|
|
mov si, NoDrvInst ;Driver not installed
|
|
DrvStatus: call print_string
|
|
|
|
mov ax,0 ;Set Return Status = success
|
|
cmp bx,0 ;Was INIT successful?
|
|
jne InitStat ;If yes
|
|
mov ax,800Ch ;Status = General Failure
|
|
InitStat:
|
|
push ax ;Save Return Status
|
|
|
|
call keyflag
|
|
and al, 8 ; alt key ?
|
|
jz InitExit
|
|
|
|
WaitHere:
|
|
mov si, WaitMsg ;Display Halted message
|
|
call print_string
|
|
|
|
AltWait:
|
|
call keyflag
|
|
and al, 8 ; Alt key?
|
|
jnz AltWait ; Pressed? yes -> wait
|
|
|
|
InitExit:
|
|
pop ax ;Retrieve Return Status
|
|
TRACER 'i'
|
|
retn ;That's it for Init!
|
|
|
|
; *** start 1.4 changes at ded ***
|
|
SpecGo: mov si,SpecPkt
|
|
int 13h
|
|
retn
|
|
|
|
ScanDrives: push ax ; at df3 in 1.4
|
|
push si
|
|
mov dl, 7fh ;Start at Drive 0x80
|
|
NextDrv: inc dl
|
|
clc
|
|
mov ax,4B01h ;Get Bootable CD-ROM Status
|
|
mov BYTE [SpecPkt],0 ;Clear 1st byte of SpecPkt
|
|
call SpecGo
|
|
; Carry is not cleared in buggy Dell BIOSes,
|
|
; so I'm checking packet size byte
|
|
; some bogus bioses (Dell Inspiron 2500) returns packet size 0xff when failed
|
|
; Dell Dimension XPsT returns packet size 0x14 when OK
|
|
|
|
cmp BYTE [SpecPkt], 13h ; anything between 13h and 20h should be OK
|
|
jb FindFail
|
|
cmp BYTE [SpecPkt], 20h
|
|
ja FindFail ; in 1.4 at e16
|
|
jmp short SendFound ; in 1.4 at e26
|
|
|
|
FindFail: cmp dl, 0ffh
|
|
je SendFail ; Check from 80h..ffh
|
|
jmp short NextDrv ;Next drive
|
|
SendFail: xor dl,dl
|
|
stc
|
|
jmp short ThingDone
|
|
SendFound: mov dl, [SpecPkt+2]
|
|
clc
|
|
ThingDone: pop si
|
|
pop ax
|
|
retn
|
|
; *** end 1.4 changes ***
|
|
|
|
;=============================================================================
|
|
|
|
;------------------------------------------------------------
|
|
; keyboard flags - return keyboard flags in AL
|
|
; bit 3 = ALT key
|
|
keyflag: ; at dbc in 1.3, at e2e in 1.4
|
|
push bx
|
|
mov ah, 2
|
|
int 16h
|
|
pop bx
|
|
retn
|
|
|
|
;=============================================================================
|
|
|
|
DrvNumMsg db ' Diskemxx.bin returned drive number=', 0
|
|
NoBootCD db ' No booted CD-ROM found.',CR,0
|
|
|
|
CDStat db ' INT 13h / AX=4B01h Specification Packet for '
|
|
db 'Booted CD-ROM:',CR,' ', 0
|
|
|
|
CDBytes db ' Drive ', 0
|
|
CDBytesA db ' returns ', 0
|
|
CDBytesB db 'h bytes per Sector.',CR,0
|
|
|
|
DevName db ' Device Name: ', 0
|
|
NoDevName db ' No Device Name found. '
|
|
db 'Usage: device=eltorito.sys /D:<DevName>',CR,0
|
|
|
|
DrvInst db ' Driver ', 0
|
|
NoDrvInst db 7,'not ' ;7 = Ctrl-G = Beep
|
|
DrvInst1 db 'installed',CR,0
|
|
|
|
WaitMsg db ' Alt pressed, waiting...', CR, 0
|
|
;ContMsg db ' Continuing...'
|
|
LineEnd db CR,0
|
|
|
|
|
|
;=============================================================================
|