Index: bootcd/isolinux/syslinux-6.03/dosutil/Makefile
===================================================================
--- bootcd/isolinux/syslinux-6.03/dosutil/Makefile	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/dosutil/Makefile	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,71 @@
+#
+# OpenWatcom compile and link utility
+#
+VPATH = $(SRC)
+include $(MAKEDIR)/syslinux.mk
+
+WCL	= wcl
+WCLOPT	= -6 -osx -mt -bt=DOS -l=COM
+
+WCL_IS_GOOD := $(shell $(WCL) $(WCLOPT) \
+        -o hello.exe $(SRC)/../win/hello.c >/dev/null 2>&1 ; echo $$?)
+
+UPX     = upx
+
+NASM    = nasm
+NASMOPT = -Ox
+
+WCTARGETS = mdiskchk.com
+NSTARGETS = eltorito.sys copybs.com
+WCOBJS    = $(addprefix $(SRC)/,$(WCTARGETS))
+NSOBJS    = $(addprefix $(OBJ)/,$(NSTARGETS))
+TARGETS   = $(WCTARGETS) $(NSTARGETS)
+
+%.obj: %.c
+	$(WCL) $(WCLOPT) -c -fo=$@ $<
+
+%.com: %.obj
+	$(WCL) $(WCLOPT) -fe=$@ $<
+	$(UPX) --ultra-brute --lzma $@ || \
+		$(UPX) --ultra-brute $@ || \
+		true
+	rm -f $*.0*
+	chmod a-x $@
+
+%.sys: %.asm
+	$(NASM) $(NASMOPT) -f bin -o $@ -l $*.lst $<
+	$(UPX) --ultra-brute --lzma $@ || \
+		$(UPX) --ultra-brute $@ || \
+		true
+	rm -f $*.0*
+	chmod a-x $@
+
+%.com: %.asm
+	$(NASM) $(NASMOPT) -f bin -o $@ -l $*.lst $<
+	$(UPX) --ultra-brute --lzma $@ || \
+		$(UPX) --ultra-brute $@ || \
+		true
+	rm -f $*.0*
+	chmod a-x $@
+
+ifeq ($(WCL_IS_GOOD),0)
+all: $(TARGETS)
+else
+all: $(NSTARGETS)
+	rm -f $(WCTARGETS)
+endif
+
+tidy dist:
+	-rm -f *.obj *.lst *.o *.0*
+
+clean: tidy
+
+spotless: clean
+	-rm -f $(NSTARGETS) *~
+
+installer: all
+
+install: installer
+	mkdir -m 755 -p $(INSTALLROOT)$(AUXDIR)/dosutil
+	install -m 644 $(WCOBJS) $(INSTALLROOT)$(AUXDIR)/dosutil
+	install -m 644 $(NSOBJS) $(INSTALLROOT)$(AUXDIR)/dosutil
Index: bootcd/isolinux/syslinux-6.03/dosutil/README
===================================================================
--- bootcd/isolinux/syslinux-6.03/dosutil/README	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/dosutil/README	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,10 @@
+This directory contains utilities for use under DOS.
+Although not part of Syslinux per se, they might be useful with MEMDISK.
+
+eltorito.sys	- Generic El Torito CD-ROM driver
+		  Written by Gary Tong and Bart Lagerweij.
+		  Ported to NASM by H. Peter Anvin.
+
+mdiskchk.com	- Simple program to query for the existence of a
+		  MEMDISK and display parameters.
+
Index: bootcd/isolinux/syslinux-6.03/dosutil/copybs.asm
===================================================================
--- bootcd/isolinux/syslinux-6.03/dosutil/copybs.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/dosutil/copybs.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,271 @@
+; -*- fundamental -*- (asm-mode sucks)
+; -----------------------------------------------------------------------
+;
+;   Copyright 1998-2008 H. Peter Anvin - All Rights Reserved
+;
+;   This program is free software; you can redistribute it and/or modify
+;   it under the terms of the GNU General Public License as published by
+;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+;   Boston MA 02111-1307, USA; either version 2 of the License, or
+;   (at your option) any later version; incorporated herein by reference.
+;
+; -----------------------------------------------------------------------
+
+;
+; copybs.asm
+;
+; Small DOS program to copy the boot sector from a drive
+; to a file
+;
+; Usage: copybs <drive>: <file>
+;
+
+		absolute 0
+pspInt20:		resw 1
+pspNextParagraph:	resw 1
+			resb 1		; reserved
+pspDispatcher:		resb 5
+pspTerminateVector:	resd 1
+pspControlCVector:	resd 1
+pspCritErrorVector:	resd 1
+			resw 11		; reserved
+pspEnvironment:		resw 1
+			resw 23		; reserved
+pspFCB_1:		resb 16
+pspFCB_2:		resb 16
+			resd 1		; reserved
+pspCommandLen:		resb 1
+pspCommandArg:		resb 127
+
+		section .text
+		org 100h			; .COM format
+_start:
+		mov ax,3000h			; Get DOS version
+		int 21h
+		xchg al,ah
+		mov [DOSVersion],ax
+		cmp ax,0200h			; DOS 2.00 minimum
+		jae dosver_ok
+		mov dx,msg_ancient_err
+		jmp die
+
+		section .bss
+		alignb 2
+DOSVersion:	resw 1
+
+		section .text
+;
+; Scan command line for a drive letter followed by a colon
+;
+dosver_ok:
+		xor cx,cx
+		mov si,pspCommandArg
+		mov cl,[pspCommandLen]
+
+cmdscan1:	jcxz bad_usage			; End of command line?
+		lodsb				; Load character
+		dec cx
+		cmp al,' '			; White space
+		jbe cmdscan1
+		or al,020h			; -> lower case
+		cmp al,'a'			; Check for letter
+		jb bad_usage
+		cmp al,'z'
+		ja bad_usage
+		sub al,'a'			; Convert to zero-based index
+		mov [DriveNo],al		; Save away drive index
+
+		section .bss
+DriveNo:	resb 1
+
+		section .text
+;
+; Got the leading letter, now the next character must be a colon
+;
+got_letter:	jcxz bad_usage
+		lodsb
+		dec cx
+		cmp al,':'
+		jne bad_usage
+;
+; Got the colon; now we should have at least one whitespace
+; followed by a filename
+;
+got_colon:	jcxz bad_usage
+		lodsb
+		dec cx
+		cmp al,' '
+		ja bad_usage
+
+skipspace:	jcxz bad_usage
+		lodsb
+		dec cx
+		cmp al,' '
+		jbe skipspace
+
+		mov di,FileName
+copyfile:	stosb
+		jcxz got_cmdline
+		lodsb
+		dec cx
+		cmp al,' '
+		ja copyfile
+		jmp short got_cmdline
+
+;
+; We end up here if the command line doesn't parse
+;
+bad_usage:	mov dx,msg_unfair
+		jmp die
+
+		section .data
+msg_unfair:	db 'Usage: copybs <drive>: <filename>', 0Dh, 0Ah, '$'
+
+		section .bss
+		alignb 4
+FileName	resb 256
+
+;
+; Parsed the command line OK.  Get device parameter block to get the
+; sector size.
+;
+		struc DPB
+dpbDrive:	resb 1
+dpbUnit:	resb 1
+dpbSectorSize:	resw 1
+dpbClusterMask:	resb 1
+dpbClusterShift: resb 1
+dpbFirstFAT:	resw 1
+dpbFATCount:	resb 1
+dpbRootEntries:	resw 1
+dpbFirstSector:	resw 1
+dpbMaxCluster:	resw 1
+dpbFATSize:	resw 1
+dpbDirSector:	resw 1
+dpbDriverAddr:	resd 1
+dpbMedia:	resb 1
+dpbFirstAccess:	resb 1
+dpbNextDPB:	resd 1
+dpbNextFree:	resw 1
+dpbFreeCnt:	resw 1
+		endstruc
+
+		section .bss
+		alignb 2
+SectorSize	resw 1
+
+		section .text
+got_cmdline:
+		xor al,al			; Zero-terminate filename
+		stosb
+
+		mov dl,[DriveNo]
+		inc dl				; 1-based
+		mov ah,32h
+		int 21h				; Get Drive Parameter Block
+
+		and al,al
+		jnz filesystem_error
+
+		mov dx,[bx+dpbSectorSize]	; Save sector size
+;
+; Read the boot sector.
+;
+		section .data
+		align 4, db 0
+DISKIO		equ $
+diStartSector:	dd 0				; Absolute sector 0
+diSectors:	dw 1				; One sector
+diBuffer:	dw SectorBuffer			; Buffer offset
+		dw 0				; Buffer segment
+
+		section .text
+read_bootsect:
+		mov ax,cs			; Set DS <- CS
+		mov ds,ax
+
+		mov [SectorSize],dx		; Saved sector size from above
+
+		cmp word [DOSVersion],0400h	; DOS 4.00 has a new interface
+		jae .new
+.old:
+		mov bx,SectorBuffer
+		mov cx,1			; One sector
+		jmp short .common
+.new:
+		mov [diBuffer+2],ax		; == DS
+		mov bx,DISKIO
+		mov cx,-1
+.common:
+		xor dx,dx			; Absolute sector 0
+		mov al,[DriveNo]
+		int 25h				; DOS absolute disk read
+		pop ax				; Remove flags from stack
+		jc disk_read_error
+
+;
+; Open the file and write the boot sector to the file.
+;
+		mov dx,FileName
+		mov cx,0020h			; Attribute = ARCHIVE
+		mov ah,3Ch			; Create file
+		int 21h
+		jc file_write_error
+
+		mov bx,ax
+		push ax				; Handle
+
+		mov cx,[SectorSize]
+		mov dx,SectorBuffer
+		mov ah,40h			; Write file
+		int 21h
+		jc file_write_error
+		cmp ax,[SectorSize]
+		jne file_write_error
+
+		pop bx				; Handle
+		mov ah,3Eh			; Close file
+		int 21h
+		jc file_write_error
+;
+; We're done!
+;
+		mov ax,4C00h			; exit(0)
+		int 21h
+
+;
+; Error routine jump
+;
+filesystem_error:
+		mov dx,msg_filesystem_err
+		jmp short die
+disk_read_error:
+		mov dx,msg_read_err
+		jmp short die
+file_write_error:
+		mov dx,msg_write_err
+die:
+		push cs
+		pop ds
+		push dx
+		mov dx,msg_error
+		mov ah,09h
+		int 21h
+		pop dx
+
+		mov ah,09h			; Write string
+		int 21h
+
+		mov ax,4C01h			; Exit error status
+		int 21h
+
+		section .data
+msg_error:		db 'ERROR: $'
+msg_ancient_err:	db 'DOS version 2.00 or later required', 0Dh, 0Ah, '$'
+msg_filesystem_err:	db 'Filesystem not found on disk', 0Dh, 0Ah, '$'
+msg_read_err:		db 'Boot sector read failed', 0Dh, 0Ah, '$'
+msg_write_err:		db 'File write failed', 0Dh, 0Ah, '$'
+
+		section .bss
+		alignb 4
+SectorBuffer:	resb 4096
Index: bootcd/isolinux/syslinux-6.03/dosutil/eltorito.asm
===================================================================
--- bootcd/isolinux/syslinux-6.03/dosutil/eltorito.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/dosutil/eltorito.asm	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,1099 @@
+
+;-----------------------------------------------------------------------------
+; 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
+
+
+;=============================================================================
Index: bootcd/isolinux/syslinux-6.03/dosutil/eltorito.txt
===================================================================
--- bootcd/isolinux/syslinux-6.03/dosutil/eltorito.txt	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/dosutil/eltorito.txt	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,50 @@
+
+Change log for eltorito.asm, by Bart Lagerweij
+
+Jun 25, 2009 - License source code under the MIT license
+
+Jun 6, 2002 - v1.2
+Eltorito.sys does now also finds the correct driver number for the booted CD-Rom
+on a Dell PC with very buggy BIOS. It does not clear the carry flag after a
+succesfull call to int13/ax=4b01h call. Other PC's also using Phoenix BIOS
+version 1.10 A14, or alike maybe also benefit from this "workaround".
+
+Mar 9, 2002
+- All read requests are now retried 5 times.
+- Bug fix, had...
+	cmp	ax, 3FFFh		;Too large?
+	ja	ReadLBad		;If yes
+  seperated from...
+	mov	ax,es:[bx+18]		;Get number of sectors to read
+	mov	word ptr [SpecPkt+2],ax
+  so, it was checking "wild" ax values...
+- Some cleanup and small changes
+- The tracers give trouble when using SHCD..
+- Reverted proc ReadL back to Rev. 0.15BETA
+
+Mar 5, 2002
+- Bug fix, when changing CD media some machines would "hang" in the PriVolDesc
+  routine.
+- Added printing of TRACER characters to trace the bug above
+- Major cleanup and now using ASCIIZ strings
+
+May 9, 2001
+- Fixed a "pad devicename with spaces" bug, this only happened when a device
+  name was used with less than 8 characters, for example, "MSCD000" became
+  "MSCD000("
+- Bug fix, when eltorito.sys was called with invalid command line parameters,
+  garbage was printed and sometimes followed by "system halted" that has been
+  there since the very first version of eltorito.sys. I know that because I
+  had the bug back then. When loading eltorito.sys using a device loader,
+  for example "device.com eltorito.sys /test:123" garbage was printed instead
+  of "No device name found." "driver not installed".
+  Changed the error message to include a "usage" string.
+
+May 8, 2001
+- If diskemu.bin is loaded eltorito.sys uses the drivenumber from diskemu
+  A call is made to "diskemu/Get status" (INT13/AX=5400) and the drivenumber is returned in CL
+  This should fix boot problems on Dell PCs (YES!)
+  When diskemu.bin is not loaded, eltorito still loops all drive numbers using eltorito calls.
+- Removed "press Escape..."
+- When the Alt-key is pressed (and holded) more info is printed and eltorito.sys halts
+
Index: bootcd/isolinux/syslinux-6.03/dosutil/mdiskchk.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/dosutil/mdiskchk.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/dosutil/mdiskchk.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,357 @@
+/* -*- c -*- ------------------------------------------------------------- *
+ *
+ *   Copyright 2003-2008 H. Peter Anvin - All Rights Reserved
+ *   Portions copyright 2010 Shao Miller
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * mdiskchk.c
+ *
+ * DOS program to check for the existence of a memdisk.
+ *
+ * This program can be compiled for DOS with the OpenWatcom compiler
+ * (http://www.openwatcom.org/):
+ *
+ * wcl -3 -osx -mt mdiskchk.c
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <i86.h>		/* For MK_FP() */
+
+typedef unsigned long uint32_t;
+typedef unsigned short uint16_t;
+typedef unsigned char uint8_t;
+
+/* Pull in MEMDISK common structures */
+#include "../memdisk/mstructs.h"
+
+struct memdiskinfo {
+    struct mdi mdi;
+
+    /* We add our own fields at the end */
+    int cylinders;
+    int heads;
+    int sectors;
+};
+
+struct memdiskinfo *query_memdisk(int drive)
+{
+    static struct memdiskinfo mm;
+    uint32_t _eax, _ebx, _ecx, _edx;
+    uint16_t _es, _di;
+    unsigned char _dl = drive;
+    uint16_t bytes;
+
+    __asm {
+	.386;
+	mov eax, 454d0800h;
+	mov ecx, 444d0000h;
+	mov edx, 53490000h;
+	mov dl, _dl;
+	mov ebx, 3f4b0000h;
+	int 13h;
+	mov _eax, eax;
+	mov _ecx, ecx;
+	mov _edx, edx;
+	mov _ebx, ebx;
+	mov _es, es;
+	mov _di, di;
+    }
+
+    if (_eax >> 16 != 0x4d21 ||
+	_ecx >> 16 != 0x4d45 || _edx >> 16 != 0x4944 || _ebx >> 16 != 0x4b53)
+	return NULL;
+
+    memset(&mm, 0, sizeof mm);
+
+    bytes = *(uint16_t far *) MK_FP(_es, _di);
+
+    /* 27 is the most we know how to handle */
+    if (bytes > 27)
+	bytes = 27;
+
+    _fmemcpy((void far *)&mm, (void far *)MK_FP(_es, _di), bytes);
+
+    mm.cylinders = ((_ecx >> 8) & 0xff) + ((_ecx & 0xc0) << 2) + 1;
+    mm.heads = ((_edx >> 8) & 0xff) + 1;
+    mm.sectors = (_ecx & 0x3f);
+
+    return &mm;
+}
+
+const char *bootloadername(uint8_t id)
+{
+    static const struct {
+	uint8_t id, mask;
+	const char *name;
+    } *lp, list[] = {
+	{0x00, 0xf0, "LILO"}, 
+	{0x10, 0xf0, "LOADLIN"},
+	{0x31, 0xff, "SYSLINUX"},
+	{0x32, 0xff, "PXELINUX"},
+	{0x33, 0xff, "ISOLINUX"},
+	{0x34, 0xff, "EXTLINUX"},
+	{0x30, 0xf0, "SYSLINUX family"},
+	{0x40, 0xf0, "Etherboot"},
+	{0x50, 0xf0, "ELILO"},
+	{0x70, 0xf0, "GrUB"},
+	{0x80, 0xf0, "U-Boot"},
+	{0xA0, 0xf0, "Gujin"},
+	{0xB0, 0xf0, "Qemu"},
+	{0x00, 0x00, "unknown"}
+    };
+
+    for (lp = list;; lp++) {
+	if (((id ^ lp->id) & lp->mask) == 0)
+	    return lp->name;
+    }
+}
+
+/* The function type for an output function */
+#define OUTPUT_FUNC_DECL(x) \
+void x(const int d, const struct memdiskinfo * const m)
+typedef OUTPUT_FUNC_DECL((*output_func));
+
+/* Show MEMDISK information for the passed structure */
+static OUTPUT_FUNC_DECL(normal_output)
+{
+    if (m == NULL)
+	return;
+    printf("Drive %02X is MEMDISK %u.%02u:\n"
+	   "\tAddress = 0x%08lx, len = %lu sectors, chs = %u/%u/%u,\n"
+	   "\tloader = 0x%02x (%s),\n"
+	   "\tcmdline = %Fs\n",
+	   d, m->mdi.version_major, m->mdi.version_minor,
+	   m->mdi.diskbuf, m->mdi.disksize, m->cylinders, m->heads, m->sectors,
+	   m->mdi.bootloaderid, bootloadername(m->mdi.bootloaderid),
+	   MK_FP(m->mdi.cmdline.seg_off.segment,
+		 m->mdi.cmdline.seg_off.offset));
+}
+
+/* Yield DOS SET command(s) as output for each MEMDISK kernel argument */
+static OUTPUT_FUNC_DECL(batch_output)
+{
+    if (m != NULL) {
+	char buf[256], *bc;
+	const char far *c =
+	    MK_FP(m->mdi.cmdline.seg_off.segment,
+		  m->mdi.cmdline.seg_off.offset);
+	const char *have_equals, is_set[] = "=1";
+
+	while (*c != '\0') {
+	    /* Skip whitespace */
+	    while (isspace(*c))
+		c++;
+	    if (*c == '\0')
+		/* Trailing whitespace.  That's enough processing */
+		break;
+	    /* Walk the kernel arguments while filling the buffer,
+	     * looking for space or NUL or checking for a full buffer
+	     */
+	    bc = buf;
+	    have_equals = is_set;
+	    while ((*c != '\0') && !isspace(*c) &&
+		   (bc < &buf[sizeof(buf) - 1])) {
+		/* Check if the param is "x=y" */
+		if (*c == '=')
+		    /* "=1" not needed */
+		    have_equals = &is_set[sizeof(is_set) - 1];
+		*bc = *c;
+		c++;
+		bc++;
+	    }
+	    /* Found the end of the parameter and optional value sequence */
+	    *bc = '\0';
+	    printf("set %s%s\n", buf, have_equals);
+	}
+    }
+}
+
+/* We do not output batch file output by default.  We show MEMDISK info */
+static output_func show_memdisk = normal_output;
+
+/* A generic function type */
+#define MDISKCHK_FUNC_DECL(x) \
+void x(void)
+typedef MDISKCHK_FUNC_DECL((*mdiskchk_func));
+
+static MDISKCHK_FUNC_DECL(do_nothing)
+{
+    return;
+}
+
+static MDISKCHK_FUNC_DECL(show_usage)
+{
+    printf("\nUsage: mdiskchk [--safe-hooks] [--mbfts] [--batch-output]\n"
+	   "\n"
+	   "Action: --safe-hooks . . Will scan INT 13h \"safe hook\" chain\n"
+	   "        --mbfts . . . .  Will scan memory for MEMDISK mBFTs\n"
+	   "        --batch-output . Will output SET command output based\n"
+	   "                         on MEMDISK kernel arguments\n"
+	   "        --no-sequential  Suppresses probing all drive numbers\n");
+}
+
+/* Search memory for mBFTs and report them via the output method */
+static MDISKCHK_FUNC_DECL(show_mbfts)
+{
+    const uint16_t far * const free_base_mem =
+	MK_FP(0x0040, 0x0013);
+    int seg;
+    uint8_t chksum;
+    uint32_t i;
+    const struct mBFT far *mbft;
+    struct memdiskinfo m;
+    struct patch_area far *patch_area;
+
+    for (seg = *free_base_mem / 16; seg < 0x9FFF; seg++) {
+	mbft = MK_FP(seg, 0);
+	/* Check for signature */
+	if (mbft->acpi.signature[0] != 'm' ||
+	    mbft->acpi.signature[1] != 'B' ||
+	    mbft->acpi.signature[2] != 'F' ||
+	    mbft->acpi.signature[3] != 'T')
+	    continue;
+	if (mbft->acpi.length != sizeof(struct mBFT))
+	    continue;
+	/* Check sum */
+	chksum = 0;
+	for (i = 0; i < sizeof(struct mBFT); i++)
+	    chksum += ((const uint8_t far *)mbft)[i];
+	if (chksum)
+	    continue;
+	/* Copy the MDI from the mBFT */
+	_fmemcpy((void far *)&m, &mbft->mdi, sizeof(struct mdi));
+	/* Adjust C/H/S since we actually know
+	 * it directly for any MEMDISK with an mBFT
+	 */
+	patch_area = (struct patch_area far *)&mbft->mdi;
+	m.cylinders = patch_area->cylinders;
+	m.heads = patch_area->heads;
+	m.sectors = patch_area->sectors;
+	show_memdisk(patch_area->driveno, &m);
+    }
+}
+
+/* Walk the "safe hook" chain as far as possible
+ * and report MEMDISKs that we find via the output method
+ */
+static MDISKCHK_FUNC_DECL(show_safe_hooks)
+{
+    const real_addr_t far * const int13 =
+	MK_FP(0x0000, 0x0013 * sizeof(real_addr_t));
+    const struct safe_hook far *hook =
+	MK_FP(int13->seg_off.segment, int13->seg_off.offset);
+
+    while ((hook->signature[0] == '$') &&
+	   (hook->signature[1] == 'I') &&
+	   (hook->signature[2] == 'N') &&
+	   (hook->signature[3] == 'T') &&
+	   (hook->signature[4] == '1') &&
+	   (hook->signature[5] == '3') &&
+	   (hook->signature[6] == 'S') &&
+	   (hook->signature[7] == 'F')) {
+	/* Found a valid "safe hook" */
+	if ((hook->vendor[0] == 'M') &&
+	    (hook->vendor[1] == 'E') &&
+	    (hook->vendor[2] == 'M') &&
+	    (hook->vendor[3] == 'D') &&
+	    (hook->vendor[4] == 'I') &&
+	    (hook->vendor[5] == 'S') &&
+	    (hook->vendor[6] == 'K')) {
+	    /* Found a valid MEMDISK "safe hook".  It will have an mBFT */
+	    const struct mBFT far *mbft;
+	    struct memdiskinfo m;
+	    struct patch_area far *patch_area;
+
+	    /* Copy the MDI from the mBFT.  Offset is a misnomer here */
+	    mbft = MK_FP(hook->mbft >> 4, 0);	/* Always aligned */
+	    _fmemcpy((void far *)&m, &mbft->mdi, sizeof(struct mdi));
+	    /* Adjust C/H/S since we actually know
+	     * it directly for any MEMDISK with an mBFT
+	     */
+	    patch_area = (struct patch_area far *)&mbft->mdi;
+	    m.cylinders = patch_area->cylinders;
+	    m.heads = patch_area->heads;
+	    m.sectors = patch_area->sectors;
+	    show_memdisk(patch_area->driveno, &m);
+	} /* if */
+	/* Step to the next hook in the "safe hook" chain */
+	hook = MK_FP(hook->old_hook.seg_off.segment,
+		     hook->old_hook.seg_off.offset);
+    } /* while */
+}
+
+int main(int argc, char *argv[])
+{
+    int d;
+    int found = 0;
+    int sequential_scan = 1;	/* Classic behaviour */
+    const struct memdiskinfo *m;
+
+    /* Default behaviour */
+    mdiskchk_func usage = do_nothing,
+	safe_hooks = do_nothing,
+	mbfts = do_nothing;
+
+    /* For each argument */
+    while (--argc) {
+	/* Argument should begin with one of these chars */
+	if ((*argv[argc] != '/') && (*argv[argc] != '-')) {
+	    /* It doesn't.  Print usage soon */
+	    usage = show_usage;
+	    break;
+	}
+	argv[argc]++;
+
+	/* Next char might be '-' as in "--safe-hooks" */
+	if (*argv[argc] == '-')
+	    argv[argc]++;
+
+	switch (*argv[argc]) {
+	    case 'S':
+	    case 's':
+		safe_hooks = show_safe_hooks;
+		break;
+	    case 'M':
+	    case 'm':
+		mbfts = show_mbfts;
+		break;
+	    case 'B':
+	    case 'b':
+		show_memdisk = batch_output;
+		break;
+	    case 'N':
+	    case 'n':
+		sequential_scan = 0;
+		break;
+	    default:
+		usage = show_usage;
+	} /* switch */
+   } /* while */
+
+    safe_hooks();
+    mbfts();
+    if (!sequential_scan)
+	goto skip_sequential;
+    for (d = 0; d <= 0xff; d++) {
+	m = query_memdisk(d);
+	if (m != NULL) {
+	    found++;
+	    show_memdisk(d, m);
+	}
+    }
+skip_sequential:
+    usage();
+
+    return found;
+}
+
