blob: d6b6b50e228474df6e21af2297b7cad637359d0f [file] [log] [blame]
;-----------------------------------------------------------------------------
; 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
;=============================================================================