Home | History | Annotate | Download | only in dosutil
      1 
      2 ;-----------------------------------------------------------------------------
      3 ; ElTorito.asm
      4 ;
      5 ; El Torito Bootable CD-ROM driver which does not reset the CD-ROM drive upon
      6 ; loading, but instead accesses the drive through BIOS system calls
      7 ;
      8 ; MIT License
      9 ;
     10 ; (c) 2000 by Gary Tong
     11 ; (c) 2001-2009 by Bart Lagerweij
     12 ;
     13 ; Permission is hereby granted, free of charge, to any person obtaining a copy
     14 ; of this software and associated documentation files (the "Software"), to deal
     15 ; in the Software without restriction, including without limitation the rights
     16 ; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     17 ; copies of the Software, and to permit persons to whom the Software is
     18 ; furnished to do so, subject to the following conditions:
     19 ;
     20 ; The above copyright notice and this permission notice shall be included in
     21 ; all copies or substantial portions of the Software.
     22 ;
     23 ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     24 ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     25 ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     26 ; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     27 ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     28 ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     29 ; THE SOFTWARE.
     30 ;
     31 ;-----------------------------------------------------------------------------
     32 
     33 ; To assemble and link, use these commands with NASM 2.x:
     34 ;   nasm -Ox -f bin -o eltorito.sys eltorito.asm
     35 
     36 ; To enable Trace markers uncomment the line below
     37 ; DEBUG_TRACERS=1
     38 
     39 ; To enable debug info uncomment the line below
     40 ; DEBUG=1
     41 
     42 %ifdef DEBUG_TRACERS
     43  %macro	TRACER	1
     44 	call debug_tracer
     45 	db %1
     46  %endmacro
     47 %else
     48  %macro	TRACER	1
     49  %endmacro
     50 %endif	; DEBUG_TRACERS
     51 
     52 %define	Ver	'1.5'
     53 %define CR	0DH, 0Ah
     54 RPolyH		equ	0EDB8h
     55 RPolyL		equ	08320h
     56 
     57 		section .text align=16
     58 		org	0
     59 
     60 ;=============================================================================
     61 
     62 Cdrom:
     63 
     64 NextDriver	dd	-1			;-+
     65 Attributes	dw	0C800h			; |
     66 Pointers	dw	Strategy		; |
     67 		dw	Commands		; |   MSCDEX requires this
     68 DeviceName	db	'ELTORITO'		; |  data in these locations
     69 		dw	0			; |
     70 DriveLetter	db	0			; |
     71 NumUnitsSupp	db	1			;-+
     72 
     73 DriverName	db	'El-Torito CD-ROM Device Driver',0
     74 		align 4, db 0
     75 ReqHdrLoc	dd	0
     76 XferAddr	dd	0
     77 Checksum	dd	-1
     78 DriveNumber	db	0
     79 ReadBytes	db	0			;0 --> 2048 bytes/sector
     80 						;1 --> 1024 bytes/sector
     81 						;2 -->  512 bytes/sector
     82 
     83 Routines	dw	Init		;Init		;0
     84 		dw	Unsupported	;MediaCheck	;1
     85 		dw	Unsupported	;BuildBPB	;2
     86 		dw	IoctlInput	;IoctlInput	;3
     87 		dw	Unsupported	;Input		;4
     88 		dw	Unsupported	;NonDesInput	;5
     89 		dw	Unsupported	;InputStatus	;6
     90 		dw	Unsupported	;InputFlush	;7
     91 		dw	Unsupported	;Output		;8
     92 		dw	Unsupported	;OutputVerify	;9
     93 		dw	Unsupported	;OutputStatus	;10
     94 		dw	Unsupported	;OutputFlush	;11
     95 		dw	IoctlOutput	;IoctlOutput	;12
     96 		dw	DoNothing	;DeviceOpen	;13
     97 		dw	DoNothing	;DeviceClose	;14
     98 		dw	ReadL		;ReadL		;128
     99 
    100 IoctlICtrl	dw	Raddr		;Raddr		;0
    101 		dw	Unsupported	;LocHead	;1
    102 		dw	Unsupported	;(Reserved)	;2
    103 		dw	Unsupported	;ErrStat	;3
    104 		dw	Unsupported	;AudInfo	;4
    105 		dw	DrvBytes		;DrvBytes	;5
    106 		dw	DevStat		;DevStat	;6
    107 		dw	SectSize		;SectSize	;7
    108 		dw	VolSize		;VolSize	;8
    109 		dw	MedChng		;MedChng	;9
    110 
    111 SpecPkt		times	19	db	0	; offset 77h in 1.4
    112 		times	13	db	0	; unknown extra 00s in 1.4
    113 
    114 Greeting	db	'El-Torito Bootable CD-ROM Driver for Dos v',Ver,', http://www.nu2.nu/eltorito/',CR
    115 		db	'  (c) 2000 by Gary Tong',CR
    116 		db	'  (c) 2001-2002 by Bart Lagerweij',CR,0
    117 DblSpace	db	'  ',0
    118 
    119 ;=============================================================================
    120 
    121 Strategy:
    122 
    123 		mov	word [cs:ReqHdrLoc],bx
    124 		mov	word [cs:ReqHdrLoc+2],es
    125 		retf
    126 
    127 
    128 ;=============================================================================
    129 
    130 Commands:
    131 
    132 		push	ax
    133 		push	bx
    134 		push	cx
    135 		push	dx
    136 		push	si
    137 		push	di
    138 		push	bp
    139 ;		pushad
    140 		push	ds
    141 		push	es
    142 		TRACER 'C'
    143 
    144 		cld				;Clear direction
    145 		sti				;Enable interrupts
    146 
    147 		mov	ax, cs			;ds=cs
    148 		mov	ds, ax
    149 
    150 		les	bx,[ReqHdrLoc]	;seg:offset ptr into es:bx
    151 		xor	ax,ax
    152 		mov	al,[es:bx+2]		;Get Command code
    153 %ifdef DEBUG
    154 		call	print_hex8
    155 %endif
    156 		cmp	al,15
    157 		jb	Mult2			;If 0-14
    158 		cmp	al,128
    159 		jb 	UnknownCmd		;If 15-127
    160 		cmp	al,129
    161 		jb	ShiftDown		;If 128
    162 UnknownCmd:	mov	al,121			;8 = Unsupported (Reserved)
    163 ShiftDown:	sub	al,113			;128 --> 15, 121 --> 8
    164 Mult2:		shl	al,1			;Convert into offset (*2)
    165 		mov	di,Routines
    166 		add	di,ax
    167 		call 	word [di]		;Execute desired command
    168 		or	ax,100h			;Set Return Status's Done bit
    169 		lds	bx,[ReqHdrLoc]		;seg:offset ptr into ds:bx
    170 		mov	[bx+3],ax		;Save Status
    171 
    172 %ifdef DEBUG
    173 		cmp	byte [cs:buffer+2048], 96h
    174 		je	buffer_ok
    175 		mov	al, '!'
    176 		call	print_char
    177 		jmp	$
    178 buffer_ok:
    179 %endif
    180 
    181 		TRACER 'c'
    182 		pop	es
    183 		pop	ds
    184 ;		popad
    185 		pop	bp
    186 		pop	di
    187 		pop	si
    188 		pop	dx
    189 		pop	cx
    190 		pop	bx
    191 		pop	ax
    192 		retf
    193 
    194 
    195 ;=============================================================================
    196 
    197 Unsupported:			;Unsupported Command
    198 
    199 		mov	ax,8003h		;Set Status Error bit,
    200 		TRACER 'U'
    201 		TRACER 'C'
    202 		retn				;   Error 3 = Unknown Command
    203 
    204 
    205 ;=============================================================================
    206 
    207 IoctlInput:			;IOCTL Input Routine
    208 
    209 		mov	di,[es:bx+14]		;es:bx --> Request Header
    210 		mov	es,[es:bx+16]		;Get Xfer Address into es:di
    211 		xor	ax,ax			;Get Control Block Code
    212 		mov	al,[es:di]
    213 %ifdef DEBUG
    214 	TRACER 'I'
    215 	TRACER 'O'
    216 	call	print_hex8
    217 %endif
    218 		cmp	al,10
    219 		jb	UnkIoctlI		;If 0-9
    220 		mov	al,2			;Map to Unsupported
    221 UnkIoctlI:	shl	al,1			;Convert into offset (*2)
    222 		mov	si,IoctlICtrl
    223 		add	si,ax
    224 		call 	word [si]		;Execute desired command
    225 		retn
    226 
    227 
    228 ;=============================================================================
    229 
    230 Raddr:			;Return Device Header Address
    231 
    232 		TRACER 'A'
    233 		mov	word [es:di+1],0
    234 		mov	[es:di+3],cs
    235 		xor	ax, ax			;Set Return Status = success
    236 		TRACER 'a'
    237 		retn
    238 
    239 
    240 ;=============================================================================
    241 
    242 DrvBytes:			;Read Drive Bytes
    243 
    244 		TRACER 'B'
    245 		push	di			;Save original Xfer Addr
    246 		add	di,2			;Point to 1st dest byte
    247 		mov	si,Greeting	;Point to Greeting
    248 DrvB:		movsb				;Copy over a byte
    249 		cmp	byte [si],13	;Is next char a CR?
    250 		jne	DrvB			;Loop if not
    251 
    252 		sub	di,2			;Get #bytes copied into ax
    253 		mov	ax,di
    254 		pop	di			;Retrieve original Xfer Addr
    255 		sub	ax,di
    256 		mov	byte [es:di+1],al	;and save it
    257 		mov	ax,0			;Set Return Status = success
    258 		TRACER 'b'
    259 		retn
    260 
    261 
    262 ;=============================================================================
    263 
    264 DevStat:			;Return Device Status
    265 
    266 		TRACER 'D'
    267 		mov	word [es:di+1],202h	;Door closed
    268 		mov	word [es:di+3],0	;Door unlocked
    269 						;Supports only cooked reading
    270 						;Read only
    271 						;Data read only
    272 						;No interleaving
    273 						;No prefetching
    274 						;No audio channel manipulation
    275 						;Supports both HSG and Redbook
    276 						;  addressing modes
    277 
    278 		xor	ax, ax			;Set Return Status = success
    279 		TRACER 'd'
    280 		retn
    281 
    282 
    283 ;=============================================================================
    284 
    285 SectSize:			;Return Sector Size
    286 
    287 		TRACER 'S'
    288 		mov	word [es:di+2],2048
    289 		mov	ax,0			;Set Return Status = success
    290 		TRACER 's'
    291 		retn
    292 
    293 
    294 ;=============================================================================
    295 
    296 VolSize:			;Return Volume Size
    297 
    298 		TRACER 'V'
    299 		call	PriVolDesc		;Get and Check Primary Volume
    300 						;  Descriptor
    301 		mov	ax,800Fh		;Assume Invalid Disk Change
    302 		jc	VolExit			;If Read Failure
    303 
    304 		mov	ax,word [Buffer+80]	;Read Successful
    305 		mov	word [es:di+1],ax	;Copy over Volume Size
    306 		mov	ax,word [Buffer+82]
    307 		mov	word [es:di+3],ax
    308 		mov	ax,0			;Set Return Status = success
    309 VolExit:
    310 		TRACER 'v'
    311 		retn
    312 
    313 
    314 ;=============================================================================
    315 
    316 MedChng:			;Return Media Changed Status
    317 
    318 		TRACER 'M'
    319 		call	PriVolDesc		;Get and Check Primary Volume
    320 						;  Descriptor
    321 		mov	byte [es:di+1],-1	;Assume Media Changed
    322 		mov	ax,800Fh		;  and Invalid Disk Change
    323 		jc	MedExit			;If Media Changed or Bad
    324 
    325 		mov	byte [es:di+1],1	;Media has not changed
    326 		mov	ax,0			;Set Return Status = success
    327 MedExit:
    328 		TRACER 'm'
    329 		retn
    330 
    331 
    332 ;=============================================================================
    333 
    334 PriVolDesc:			;Get and Check Primary Volume
    335 						;  Descriptor
    336 		TRACER 'P'
    337 		mov	ax,cs			;Set ds:si --> SpecPkt
    338 		mov	ds,ax
    339 
    340 		mov	cx, 5
    341 PriVolAgain:
    342 		mov	byte [SpecPkt],16	;SpecPkt Size
    343 		mov	byte [SpecPkt+1],0	;Reserved
    344 		mov	word [SpecPkt+2],1	;Transfer one 2048-byte sector
    345 		push	cx
    346 		mov	cl,byte [ReadBytes]	;Multiply by 4 if reading 512
    347 		shl	word [SpecPkt+2],cl	;  bytes at a time
    348 		pop	cx
    349 		mov	word [SpecPkt+6],cs	;Into our Buffer
    350 		mov	word [SpecPkt+4], Buffer
    351 		mov	word [SpecPkt+8],16	;From CD Sector 16
    352 		mov	word [SpecPkt+10],0
    353 		mov	word [SpecPkt+12],0
    354 		mov	word [SpecPkt+14],0
    355 
    356 		mov	si, SpecPkt
    357 		mov	dl, [DriveNumber]
    358 		mov	ah, 42h			;Extended Read
    359 		int	13h
    360 		jnc	PriVolPass		;If success
    361 
    362 ;		TRACER '1'
    363 		; read error
    364 		loop	PriVolAgain
    365 
    366 		TRACER '2'
    367 		; read retries exhausted
    368 		; flow into below
    369 		jmp	PriReadErr
    370 
    371 PriVolPass:
    372 		mov	si,Buffer	;Point input to Buffer
    373 		mov	ax,-1			;Init Checksum registers
    374 		mov	bx,ax			;  bx,ax = 0FFFFFFFFh
    375 		jc	PriNew			;If Read Failure
    376 
    377 		push	di			;Read Successful,
    378 						;  so Calculate Checksum
    379 		mov	di,1024			;Init Word counter
    380 PriWord:	mov	dx,[cs:si]		;Grab next word from buffer
    381 		mov	cx,16			;Init bit counter
    382 PriBit:		shr	dx,1			;Shift everything right 1 bit
    383 		rcr	bx,1
    384 		rcr	ax,1
    385 		jnc	NoMult			;If a zero shifted out
    386 
    387 		xor	bx,RPolyH		;A one shifted out, so XOR
    388 		xor	ax,RPolyL		;  Checksum with RPoly
    389 NoMult:
    390 		loop	PriBit
    391 
    392 		add	si,2			;Inc Word Pointer
    393 		dec	di
    394 		ja	PriWord
    395 		TRACER '3'
    396 
    397 		pop	di			;Checksum calculation complete
    398 		cmp	bx,[Checksum+2]		;Has Checksum changed?
    399 		jne	PriNew			;If Checksum Changed
    400 
    401 		cmp	ax,[Checksum]
    402 		jne	PriNew			;If Checksum Changed
    403 
    404 		clc				;Checksum not changed, CF=0
    405 		mov	ax,0			;Status = success
    406 		jmp	PriOld
    407 
    408 PriReadErr:
    409 		mov	WORD [Checksum+2],bx		;Save New Checksum
    410 		mov	[Checksum],ax		;  or 0FFFFFFFFh if bad read
    411 		stc				;Checksum change, CF=1
    412 		mov	ax, 800bh		;Status = read fault
    413 		jmp	PriOld
    414 
    415 PriNew:		mov	WORD [Checksum+2],bx		;Save New Checksum
    416 		mov	[Checksum],ax		;  or 0FFFFFFFFh if bad read
    417 		stc				;Checksum Changed, CF=1
    418 		mov	ax,800Fh		;Status = Invalid Media Change
    419 PriOld:
    420 		TRACER 'p'
    421 		retn
    422 
    423 
    424 ;=============================================================================
    425 
    426 IoctlOutput:			;IOCTL Output Routine
    427 
    428 		TRACER 'O'
    429 		mov	di,[es:bx+14]		;es:bx --> Request Header
    430 		mov	es,[es:bx+16]		;Get Xfer Address into es:di
    431 		xor	ax,ax			;Get Control Block Code
    432 		mov	al,[es:di]
    433 		cmp	al,2
    434 		jne	UnkIoctlO		;If not 2 (ResetDrv)
    435 		call	DoNothing		;Reset Drive
    436 		jmp	IoctlODone
    437 UnkIoctlO:
    438 		call	Unsupported		;Unsupported command
    439 IoctlODone:
    440 		TRACER 'o'
    441 		retn
    442 
    443 
    444 ;=============================================================================
    445 
    446 DoNothing:			;Do Nothing Command
    447 
    448 		mov	ax,0			;Set Return Status = success
    449 		retn
    450 
    451 
    452 ;=============================================================================
    453 
    454 ReadL:			;Read Long Command
    455 
    456 		TRACER 'R'
    457 		mov	ax,cs			;Set ds=cs
    458 		mov	ds,ax
    459 						;es:bx --> Request Header
    460 		cmp	byte [es:bx+24],0	;Check Data Read Mode
    461 		jne	ReadLErr		;If Cooked Mode
    462 
    463 		cmp	byte [es:bx+13],2	;Check Addressing Mode
    464 		jb	ReadLOK			;If HSG or Redbook Mode
    465 
    466 ReadLErr:
    467 		TRACER '8'
    468 		mov	ax,8003h		;Set Return Status = Unknown
    469 		jmp	ReadLExit		;  Command Error and exit
    470 
    471 ReadLOK:
    472 		mov	ax,[es:bx+20]		;Get Starting Sector Number,
    473 		mov	dx,[es:bx+22]		;  Assume HSG Addressing Mode
    474 		cmp	byte [es:bx+13],0	;Check Addressing Mode again
    475 		je	ReadLHSG		;If HSG Addressing Mode
    476 
    477 		TRACER '7'
    478 		;Using Redbook Addressing Mode.  Convert to HSG format
    479 		mov	al,dl			;Get Minutes
    480 		mov	dl,60
    481 		mul	dl			;ax = Minutes * 60
    482 		add	al,byte [es:bx+21]	;Add in Seconds
    483 		adc	ah,0
    484 		mov	dx,75			;dx:ax =
    485 		mul	dx			;  ((Min * 60) + Sec) * 75
    486 		add	al,byte [es:bx+20]	;Add in Frames
    487 		adc	ah,0
    488 		adc	dx,0
    489 		sub	ax,150			;Subtract 2-Second offset
    490 		sbb	dx,0			;dx:ax = HSG Starting Sector
    491 
    492 ReadLHSG:
    493 		mov	word [SpecPkt+8], ax	;Store Starting
    494 		mov	word [SpecPkt+10], dx	;  Sector Number
    495 		mov	word [SpecPkt+12], 0	;  (HSG Format)
    496 		mov	word [SpecPkt+14], 0
    497 
    498 		mov	ax,[es:bx+14]		;Get Transfer Address
    499 		mov	word [SpecPkt+4],ax
    500 		mov	ax,[es:bx+16]
    501 		mov	word [SpecPkt+6],ax
    502 
    503 		mov	byte [SpecPkt],16	;Size of Disk Address Packet
    504 		mov	byte [SpecPkt+1],0	;Reserved
    505 
    506 		mov	cx, 5
    507 ReadLAgain:
    508 		mov	ax,[es:bx+18]		;Get number of sectors to read
    509 		mov	word [SpecPkt+2],ax
    510 		cmp	ax, 3FFFh		;Too large?
    511 		ja	ReadLBad		;If yes
    512 
    513 		push	cx
    514 		mov	cl,byte [ReadBytes]	;Multiply by 4 if reading 512
    515 		shl	word [SpecPkt+2],cl	;  bytes at a time
    516 		pop	cx
    517 
    518 %ifdef DEBUG
    519 		push	ax
    520 		push	cx
    521 		push	si
    522 		mov	cx, 16
    523 		mov	si,SpecPkt
    524 ReadDump:	mov	al, ' '
    525 		call	print_char
    526 		mov	al, byte [si]	;Hexdump a SpecPkt byte
    527 		call	print_hex8
    528 		inc	si			;Point to next byte
    529 		loop	ReadDump
    530 		pop	si
    531 		pop	cx
    532 		pop	ax
    533 %endif
    534 		mov	si,SpecPkt
    535 		mov	dl,[DriveNumber]
    536 		mov	ah,42h			;Extended Read
    537 		int	13h
    538 		jnc	ReadLGd			;If success
    539 
    540 ;hang:
    541 ;		jmp	hang
    542 ;		TRACER '1'
    543 		loop	ReadLAgain
    544 		TRACER '2'
    545 		jmp short ReadLBad
    546 ReadLGd:
    547 		TRACER '3'
    548 		xor	ax, ax 			;Status 0 = success
    549 		jmp short ReadLExit
    550 
    551 ReadLBad:
    552 		TRACER '9'
    553 		mov	ax, 800Bh		;Set Read Fault Error
    554 		; flow into ReadLExit
    555 ReadLExit:
    556 		TRACER 'r'
    557 		retn
    558 
    559 
    560 
    561 %ifdef DEBUG_TRACERS
    562 debug_tracer:	pushad
    563 		pushfd
    564 
    565 		mov	al, '['
    566 		mov	ah,0Eh			;BIOS video teletype output
    567 		xor	bh, bh
    568 		int	10h			;Print it
    569 
    570 		mov	bp,sp
    571 		mov	bx,[bp+9*4]		; Get return address
    572 		mov	al,[cs:bx]		; Get data byte
    573 		inc	word [bp+9*4]	; Return to after data byte
    574 
    575 		mov	ah,0Eh			;BIOS video teletype output
    576 		xor	bh, bh
    577 		int	10h			;Print it
    578 
    579 		mov	al, ']'
    580 		mov	ah,0Eh			;BIOS video teletype output
    581 		xor	bh, bh
    582 		int	10h			;Print it
    583 
    584 		popfd
    585 		popad
    586 		retn
    587 %endif
    588 
    589 ;-----------------------------------------------------------------------------
    590 ; PRINT_HEX4
    591 ;-----------------------------------------------------------------------------
    592 ; print a 4 bits integer in hex
    593 ;
    594 ; Input:
    595 ;	AL - 4 bits integer to print (low)
    596 ;
    597 ; Output: None
    598 ;
    599 ; Registers destroyed: None
    600 ;
    601 print_hex4:
    602 
    603 	push	ax
    604 	and	al, 0fh		; we only need the first nibble
    605 	cmp	al, 10
    606 	jae	hex_A_F
    607 	add	al, '0'
    608 	jmp	hex_0_9
    609 hex_A_F:
    610 	add	al, 'A'-10
    611 hex_0_9:
    612 	call	print_char
    613 	pop	ax
    614 	retn
    615 
    616 
    617 ;-----------------------------------------------------------------------------
    618 ; print_hex8
    619 ;-----------------------------------------------------------------------------
    620 ; print	a 8 bits integer in hex
    621 ;
    622 ; Input:
    623 ;	AL - 8 bits integer to print
    624 ;
    625 ; Output: None
    626 ;
    627 ; Registers destroyed: None
    628 ;
    629 print_hex8:
    630 
    631 	push	ax
    632 	push	bx
    633 
    634 	mov	ah, al
    635 	shr	al, 4
    636 	call	print_hex4
    637 
    638 	mov	al, ah
    639 	and	al, 0fh
    640 	call	print_hex4
    641 
    642 	pop	bx
    643 	pop	ax
    644 	retn
    645 
    646 
    647 ;=============================================================================
    648 ; print_hex16 - print a 16 bits integer in hex
    649 ;
    650 ; Input:
    651 ;	AX - 16 bits integer to print
    652 ;
    653 ; Output: None
    654 ;
    655 ; Registers destroyed: None
    656 ;=============================================================================
    657 print_hex16:
    658 
    659 	push	ax
    660 	push	bx
    661 	push	cx
    662 
    663 	mov	cx, 4
    664 print_hex16_loop:
    665 	rol	ax, 4
    666 	call	print_hex4
    667 	loop	print_hex16_loop
    668 
    669 	pop	cx
    670 	pop	bx
    671 	pop	ax
    672 	retn
    673 
    674 ;=============================================================================
    675 ; print_hex32 - print a 32 bits integer in hex
    676 ;
    677 ; Input:
    678 ;	EAX - 32 bits integer to print
    679 ;
    680 ; Output: None
    681 ;
    682 ; Registers destroyed: None
    683 ;=============================================================================
    684 print_hex32:
    685 
    686 	push	eax
    687 	push	bx
    688 	push	cx
    689 
    690 	mov	cx, 8
    691 print_hex32_loop:
    692 	rol	eax, 4
    693 	call	print_hex4
    694 	loop	print_hex32_loop
    695 
    696 	pop	cx
    697 	pop	bx
    698 	pop	eax
    699 	retn
    700 
    701 ;=============================================================================
    702 ; print_string - print string at current cursor location
    703 ;
    704 ; Input:
    705 ;	DS:SI - ASCIIZ string to print
    706 ;
    707 ; Output: None
    708 ;
    709 ; Registers destroyed: None
    710 ;=============================================================================
    711 print_string:
    712 		push	ax
    713 		push	si
    714 
    715 print_string_again:
    716 		mov	al, [si]
    717 		or	al, al
    718 		jz	print_string_exit
    719 		call	print_char
    720 		inc	si
    721 		jmp	print_string_again
    722 
    723 print_string_exit:
    724 		pop	si
    725 		pop	ax
    726 		retn
    727 
    728 ;-----------------------------------------------------------------------------
    729 ; PRINT_CHAR
    730 ;-----------------------------------------------------------------------------
    731 ; Print's a character at current cursor position
    732 ;
    733 ; Input:
    734 ;	AL - Character to print
    735 ;
    736 ; Output: None
    737 ;
    738 ; Registers destroyed: None
    739 ;
    740 print_char:
    741 
    742 		push	ax
    743 		push	bx
    744 
    745 		mov	ah,0Eh			;BIOS video teletype output
    746 		xor	bh, bh
    747 		int	10h			;Print it
    748 
    749 print_char_exit:
    750 		pop	bx
    751 		pop	ax
    752 		retn
    753 
    754 
    755 ;=============================================================================
    756 
    757 ;This space is used as a 2048-byte read buffer plus one test byte.
    758 ;The 96h data is used for testing the number of bytes returned by an Extended
    759 ;  CD-ROM sector read
    760 
    761 		align	16, db 0
    762 Buffer		times	2049	db	96h
    763 
    764 ;=============================================================================
    765 
    766 Init:			;Initialization Routine
    767 
    768 		TRACER 'I'
    769 		mov	ax,cs			;ds=cs
    770 		mov	ds,ax
    771 
    772 %ifdef DEBUG
    773 ; print CS value (load segment)
    774 		call	print_hex16
    775 %endif
    776 
    777 		mov	si, Greeting	;Display Greeting
    778 		call	print_string
    779 
    780 		mov	ax,Unsupported	;Init is executed only once
    781 		mov	[Routines],ax
    782 
    783 		mov	ax, 5400h
    784 		int	13h			; Get diskemu status
    785 		jc	FindBoot		; If CF=1 no diskemu loaded
    786 
    787 		mov	[DriveNumber], cl		; Store drive number
    788 
    789 		call	keyflag
    790 		and	al, 8			; alt key ?
    791 		jz	extread
    792 
    793 		mov	si, DrvNumMsg	; Display "drive number="
    794 		call	print_string
    795 		mov	al, [DriveNumber]
    796 		call	print_hex8
    797 		mov	si, LineEnd	; CR/LF
    798 		call	print_string
    799 		jmp	extread
    800 
    801 ; Diskemu is not loaded
    802 ; so loop to find drive number
    803 		; *** start of 1.4 changes ***
    804 		; ??? mov dl, 0ffh		;Start at Drive 0xff
    805 		; *** FindBoot at c47 in 1.4, at c0c in 1.3 ***
    806 FindBoot:	call	ScanDrives		; call new helper in 1.4
    807 		jnc	FoundBoot		; ded*df3
    808 ;		mov	si,offset SpecPkt	;Locate booted CD-ROM drive
    809 ;		mov	[SpecPkt],0		;Clear 1st byte of SpecPkt
    810 ;		mov	ax,4B01h		;Get Bootable CD-ROM Status
    811 ;		int	13h
    812 ;		jnc	FindPass		;If booted CD found
    813 ;
    814 ; Carry is not cleared in buggy Dell BIOSes,
    815 ; so I'm checking packet size byte
    816 ; some bogus bioses (Dell Inspiron 2500) returns packet size 0xff when failed
    817 ; Dell Dimension XPsT returns packet size 0x14 when OK
    818 
    819 ;		cmp	[SpecPkt], 0
    820 ;		jne	FoundBoot
    821 
    822 ;		cmp	[SpecPkt], 13h	; anything between 13h and 20h should be OK
    823 ;		jb	FindFail
    824 ;		cmp	[SpecPkt], 20h
    825 ;		ja	FindFail
    826 ;		jmp	short FoundBoot
    827 ;
    828 ; FindFail:
    829 ;		dec	dl			;Next drive
    830 ;		cmp	dl, 80h
    831 ;		jae	FindBoot		;Check from ffh..80h
    832 		; *** end of 1.4 changes ***
    833 
    834 		mov	si,NoBootCD	;No booted CD found,
    835 		call	print_string
    836 		jmp	NoEndAddr		;Do not install driver
    837 
    838 FoundBoot:
    839 ;		mov	dl, [SpecPkt+2]		; 1.4 change
    840 		; *** next line at c57 in 1.4, at c3d in 1.3 ***
    841 		mov	[DriveNumber],dl		;Booted CD-ROM found,
    842 						;  so save Drive #
    843 
    844 		call	keyflag
    845 		and	al, 8			; alt key ?
    846 		jz	extread
    847 
    848 		mov	si, CDStat
    849 		call	print_string
    850 		mov	si, SpecPkt	;Point to returned CD SpecPkt
    851 		mov	cx, 19			;  containing 19 bytes
    852 StatDump:	mov	al, ' '			;Print a space
    853 		call	print_char
    854 		mov	al, byte [si]	;Hexdump a SpecPkt byte
    855 		call	print_hex8
    856 		inc	si			;Point to next byte
    857 		loop	StatDump
    858 
    859 		mov	si, LineEnd	;Print a CR/LF
    860 		call	print_string
    861 
    862 extread:
    863 ;See how many CD Sector bytes are returned by an Extended Read
    864 		mov	byte [SpecPkt],16	;SpecPkt Size
    865 		mov	byte [SpecPkt+1],0	;Reserved
    866 		mov	word [SpecPkt+2],1	;Transfer one sector
    867 		mov	word [SpecPkt+6],cs	;Into our Buffer
    868 		mov	word [SpecPkt+4],Buffer
    869 		mov	word [SpecPkt+8],16	;From CD Sector 16
    870 		mov	word [SpecPkt+10],0
    871 		mov	word [SpecPkt+12],0
    872 		mov	word [SpecPkt+14],0
    873 
    874 		mov	si, SpecPkt	;Set ds:si --> SpecPkt
    875 		mov	dl, [DriveNumber]
    876 		mov	ah, 42h			;Extended Read
    877 		int	13h
    878 		jnc	SecSize			;If success
    879 
    880 		mov	ah, 42h			;Always make 2 read attempts
    881 		int	13h
    882 						;How many bytes did we get?
    883 SecSize:	std				;Count down
    884 		mov	ax,cs			;Point to end of Buffer
    885 		mov	es,ax
    886 		mov	di,Buffer+2047	;Find end of read data
    887 		mov	si,Buffer+2048
    888 		mov	cx,2049
    889 		repe	cmpsb			;cx = number of bytes read
    890 
    891 		cld				;Restore count direction to up
    892 		mov	si,CDBytes	;Display number of bytes read
    893 		call	print_string
    894 
    895 		mov	al, [DriveNumber]
    896 		call	print_hex8
    897 
    898 		mov	si,CDBytesA	;Remainder A of message
    899 		call	print_string
    900 
    901 		mov	al,ch			;Hex-dump cx
    902 		and	al,0Fh			;Second nibble
    903 		call	print_hex8		;  (don't need the First)
    904 		mov	al,cl
    905 		call	print_hex8		;  (don't need the First)
    906 
    907 		mov	si,CDBytesB	;Remainder B of message
    908 		call	print_string
    909 
    910 		cmp	cx,2048			;Did we read 2048 bytes?
    911 		je	ParseParm		;If yes <-- O.K.
    912 
    913 		mov	byte [ReadBytes],1
    914 		cmp	cx,1024			;Did we read 1024 bytes?
    915 		je	ParseParm		;If yes <-- O.K.
    916 
    917 		mov	byte [ReadBytes],2
    918 		cmp	cx,512			;Did we read 512 bytes?
    919 		jne	NoEndAddr		;If not, do not load driver
    920 
    921 ParseParm:	mov	bx,word [cs:ReqHdrLoc]	;Parse command line
    922 		mov	es,word [cs:ReqHdrLoc+2]	;  parameters
    923 		mov	si,[es:bx+18]		;Get BPB array ptr into DS:SI
    924 		mov	ds,[es:bx+20]
    925 FindParm:	inc	si
    926 FindParm1:	cmp	byte [si],0Dh	;CR? (End of parameters)
    927 		je	EndOfParms
    928 
    929 		cmp	byte [si],0Ah	;LF?
    930 		je	EndOfParms
    931 
    932 		cmp	byte [si],'/'	;A parameter?
    933 		jne	FindParm
    934 
    935 		inc	si
    936 		cmp	byte [si],'D'	;Device Name parameter?
    937 		jne	FindParm1
    938 
    939 		inc	si
    940 		cmp	byte [si],':'
    941 		jne	FindParm1
    942 
    943 ;bbb
    944 		push	si
    945 		mov	si, DevName	;Device Name is at ds:si
    946 		push	ds			;Keep ptr to Device Name
    947 		mov	ax, cs
    948 		mov	ds, ax
    949 		call	print_string
    950 		pop	ds			;Retrieve Device Name ptr
    951 		pop	si
    952 		mov	cx, 8			;Get next 8 chars
    953 		inc	si			;  = Device Name
    954 		mov	ax, cs
    955 		mov	es, ax
    956 		mov	di, DeviceName
    957 NextChar:	cmp	byte [si],' '
    958 		ja	AboveSpace
    959 
    960 		mov	ax,cs			;Pad end of Device Name with
    961 		mov	ds,ax			;  spaces if necessary
    962 		mov	si,DblSpace	;A space
    963 AboveSpace:	mov	al, [si]
    964 		call	print_char
    965 		movsb				;ds:[si] --> es:[di]
    966 		loop 	NextChar
    967 
    968 		mov	si,LineEnd
    969 		mov	ax,cs
    970 		mov	ds,ax
    971 		call	print_string
    972 
    973 		mov	ax,Init-2	;Last byte of driver to keep
    974 		jmp	EndAddr			;Install driver
    975 
    976 EndOfParms:
    977 		mov	ax, cs			; Restore segment registers (fix)
    978 		mov	ds, ax
    979 		mov	es, ax
    980 
    981 		mov	si,NoDevName	;No Device Name Found
    982 		call	print_string
    983 
    984 NoEndAddr:	mov	ax,0			;Do not install driver
    985 
    986 EndAddr:	mov	es,[ReqHdrLoc+2]		;Write End Address
    987 		mov	bx,[ReqHdrLoc]
    988 		mov	[es:bx+14],ax
    989 		mov	[es:bx+16],cs
    990 		mov	bx,ax			;Hold onto install status
    991 
    992 		mov	si, DrvInst	;Display driver install status
    993 		call	print_string
    994 		mov	si, DrvInst1	;Assume driver installed
    995 		cmp	bx,0			;Was driver installed?
    996 		jne	DrvStatus		;If yes
    997 		mov	si, NoDrvInst	;Driver not installed
    998 DrvStatus:	call	print_string
    999 
   1000 		mov	ax,0			;Set Return Status = success
   1001 		cmp	bx,0			;Was INIT successful?
   1002 		jne	InitStat		;If yes
   1003 		mov	ax,800Ch		;Status = General Failure
   1004 InitStat:
   1005 		push	ax			;Save Return Status
   1006 
   1007 		call	keyflag
   1008 		and	al, 8			; alt key ?
   1009 		jz	InitExit
   1010 
   1011 WaitHere:
   1012 		mov	si, WaitMsg	;Display Halted message
   1013 		call	print_string
   1014 
   1015 AltWait:
   1016 		call	keyflag
   1017 		and	al, 8			; Alt key?
   1018 		jnz	AltWait			; Pressed? yes -> wait
   1019 
   1020 InitExit:
   1021 		pop	ax			;Retrieve Return Status
   1022 		TRACER 'i'
   1023 		retn				;That's it for Init!
   1024 
   1025 		; *** start 1.4 changes at ded ***
   1026 SpecGo:		mov	si,SpecPkt
   1027 		int	13h
   1028 		retn
   1029 
   1030 ScanDrives:	push	ax		; at df3 in 1.4
   1031 		push	si
   1032 		mov dl, 7fh		;Start at Drive 0x80
   1033 NextDrv:	inc	dl
   1034 		clc
   1035 		mov	ax,4B01h	;Get Bootable CD-ROM Status
   1036 		mov	BYTE [SpecPkt],0	;Clear 1st byte of SpecPkt
   1037 		call	SpecGo
   1038 ; Carry is not cleared in buggy Dell BIOSes,
   1039 ; so I'm checking packet size byte
   1040 ; some bogus bioses (Dell Inspiron 2500) returns packet size 0xff when failed
   1041 ; Dell Dimension XPsT returns packet size 0x14 when OK
   1042 
   1043 		cmp	BYTE [SpecPkt], 13h	; anything between 13h and 20h should be OK
   1044 		jb	FindFail
   1045 		cmp	BYTE [SpecPkt], 20h
   1046 		ja	FindFail	; in 1.4 at e16
   1047 		jmp	short SendFound	; in 1.4 at e26
   1048 
   1049 FindFail:	cmp	dl, 0ffh
   1050 		je	SendFail		; Check from 80h..ffh
   1051 		jmp	short NextDrv		;Next drive
   1052 SendFail:	xor	dl,dl
   1053 		stc
   1054 		jmp	short ThingDone
   1055 SendFound:	mov	dl, [SpecPkt+2]
   1056 		clc
   1057 ThingDone:	pop	si
   1058 		pop	ax
   1059 		retn
   1060 		; *** end 1.4 changes ***
   1061 
   1062 ;=============================================================================
   1063 
   1064 ;------------------------------------------------------------
   1065 ; keyboard flags - return keyboard flags in AL
   1066 ; bit 3 = ALT key
   1067 keyflag:	; at dbc in 1.3, at e2e in 1.4
   1068 	push	bx
   1069 	mov	ah, 2
   1070 	int	16h
   1071 	pop	bx
   1072 	retn
   1073 
   1074 ;=============================================================================
   1075 
   1076 DrvNumMsg	db	'  Diskemxx.bin returned drive number=', 0
   1077 NoBootCD	db	'  No booted CD-ROM found.',CR,0
   1078 
   1079 CDStat		db	'  INT 13h / AX=4B01h Specification Packet for '
   1080 		db	'Booted CD-ROM:',CR,'     ', 0
   1081 
   1082 CDBytes		db	'  Drive ', 0
   1083 CDBytesA	db	' returns ', 0
   1084 CDBytesB	db	'h bytes per Sector.',CR,0
   1085 
   1086 DevName		db	'  Device Name: ', 0
   1087 NoDevName	db	'  No Device Name found. '
   1088 		db	'Usage: device=eltorito.sys /D:<DevName>',CR,0
   1089 
   1090 DrvInst		db	'  Driver ', 0
   1091 NoDrvInst	db	7,'not '		;7 = Ctrl-G = Beep
   1092 DrvInst1	db	'installed',CR,0
   1093 
   1094 WaitMsg		db	'  Alt pressed, waiting...', CR, 0
   1095 ;ContMsg		db	'  Continuing...'
   1096 LineEnd		db	CR,0
   1097 
   1098 
   1099 ;=============================================================================
   1100