added freeldr isoboot code as well as openfirmware boot code. Added freeldr debugger by Brian Palmer
Added: trunk/reactos/boot/freeldr/bootsect/
Added: trunk/reactos/boot/freeldr/bootsect/isoboot.asm
Added: trunk/reactos/boot/freeldr/bootsect/ofwboot.s
Added: trunk/reactos/boot/freeldr/fdebug/
Added: trunk/reactos/boot/freeldr/fdebug/De.rc
Added: trunk/reactos/boot/freeldr/fdebug/En.rc
Added: trunk/reactos/boot/freeldr/fdebug/Hu.rc
Added: trunk/reactos/boot/freeldr/fdebug/Ja.rc
Added: trunk/reactos/boot/freeldr/fdebug/Pl.rc
Added: trunk/reactos/boot/freeldr/fdebug/Tr.rc
Added: trunk/reactos/boot/freeldr/fdebug/fdebug.c
Added: trunk/reactos/boot/freeldr/fdebug/fdebug.ico
Added: trunk/reactos/boot/freeldr/fdebug/fdebug.rc
Added: trunk/reactos/boot/freeldr/fdebug/resource.h
Added: trunk/reactos/boot/freeldr/fdebug/rs232.c
Added: trunk/reactos/boot/freeldr/fdebug/rs232.h

Added: trunk/reactos/boot/freeldr/bootsect/isoboot.asm
--- trunk/reactos/boot/freeldr/bootsect/isoboot.asm	2006-01-31 07:37:05 UTC (rev 63)
+++ trunk/reactos/boot/freeldr/bootsect/isoboot.asm	2006-01-31 18:58:49 UTC (rev 64)
@@ -0,0 +1,1015 @@
+; ****************************************************************************
+;
+;  isolinux.asm
+;
+;  A program to boot Linux kernels off a CD-ROM using the El Torito
+;  boot standard in "no emulation" mode, making the entire filesystem
+;  available.  It is based on the SYSLINUX boot loader for MS-DOS
+;  floppies.
+;
+;   Copyright (C) 1994-2001  H. Peter Anvin
+;
+;  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., 675 Mass Ave, Cambridge MA 02139,
+;  USA; either version 2 of the License, or (at your option) any later
+;  version; incorporated herein by reference.
+; 
+; ****************************************************************************
+;
+; THIS FILE IS A MODIFIED VERSION OF ISOLINUX.ASM
+; MODIFICATION DONE BY MICHAEL K TER LOUW
+; LAST UPDATED 3-9-2002
+; SEE "COPYING" FOR INFORMATION ABOUT THE LICENSE THAT APPLIES TO THIS RELEASE
+;
+; ****************************************************************************
+;
+; This file is a modified version of ISOLINUX.ASM.
+; Modification done by Eric Kohl
+; Last update 04-25-2002
+;
+; ****************************************************************************
+
+; Note: The Makefile builds one version with DEBUG_MESSAGES automatically.
+;%define DEBUG_MESSAGES                ; Uncomment to get debugging messages
+
+%define WAIT_FOR_KEY
+
+
+; ---------------------------------------------------------------------------
+;   BEGIN THE BIOS/CODE/DATA SEGMENT
+; ---------------------------------------------------------------------------
+
+		absolute 0400h
+serial_base	resw 4			; Base addresses for 4 serial ports
+		absolute 0413h
+BIOS_fbm	resw 1			; Free Base Memory (kilobytes)
+		absolute 046Ch
+BIOS_timer	resw 1			; Timer ticks
+		absolute 0472h
+BIOS_magic	resw 1			; BIOS reset magic
+		absolute 0484h
+BIOS_vidrows	resb 1			; Number of screen rows
+
+;
+; Memory below this point is reserved for the BIOS and the MBR
+;
+		absolute 1000h
+trackbuf	resb 8192		; Track buffer goes here
+trackbufsize	equ $-trackbuf
+;		trackbuf ends at 3000h
+
+		struc open_file_t
+file_sector	resd 1			; Sector pointer (0 = structure free)
+file_left	resd 1			; Number of sectors left
+		endstruc
+
+		struc dir_t
+dir_lba		resd 1			; Directory start (LBA)
+dir_len		resd 1			; Length in bytes
+dir_clust	resd 1			; Length in clusters
+		endstruc
+
+
+MAX_OPEN_LG2	equ 2			; log2(Max number of open files)
+MAX_OPEN	equ (1 << MAX_OPEN_LG2)
+SECTORSIZE_LG2	equ 11			; 2048 bytes/sector (El Torito requirement)
+SECTORSIZE	equ (1 << SECTORSIZE_LG2)
+CR		equ 13			; Carriage Return
+LF		equ 10			; Line Feed
+retry_count	equ 6			; How patient are we with the BIOS?
+
+
+
+	absolute 5000h				; Here we keep our BSS stuff
+
+DriveNo		resb 1			; CD-ROM BIOS drive number
+DiskError	resb 1			; Error code for disk I/O
+RetryCount	resb 1			; Used for disk access retries
+TimeoutCount	resb 1			; Timeout counter
+ISOFlags	resb 1			; Flags for ISO directory search
+RootDir		resb dir_t_size		; Root directory
+CurDir		resb dir_t_size		; Current directory
+ISOFileName	resb 64			; ISO filename canonicalization buffer
+ISOFileNameEnd	equ $
+
+
+		alignb open_file_t_size
+Files		resb MAX_OPEN*open_file_t_size
+
+
+
+	section .text
+	org 7000h
+
+start:
+	cli					; Disable interrupts
+	xor	ax, ax				; ax = segment zero
+	mov	ss, ax				; Initialize stack segment
+	mov	sp, start			; Set up stack
+	mov	ds, ax				; Initialize other segment registers
+	mov	es, ax
+	mov	fs, ax
+	mov	gs, ax
+	sti					; Enable interrupts
+	cld					; Increment pointers
+
+	mov	cx, 2048 >> 2			; Copy the bootsector
+	mov	si, 0x7C00			; from 0000:7C00
+	mov	di, 0x7000			; to 0000:7000
+	rep	movsd				; copy the program
+	jmp	0:relocate			; jump into relocated code
+
+relocate:
+	; Display the banner and copyright
+%ifdef DEBUG_MESSAGES
+	mov	si, isolinux_banner		; si points to hello message
+	call	writestr			; display the message
+	mov	si,copyright_str
+	call	writestr
+%endif
+
+
+	; Make sure the keyboard buffer is empty
+%ifdef WAIT_FOR_KEY
+.kbd_buffer_test:
+	call	pollchar
+	jz	.kbd_buffer_empty
+	call	getchar
+	jmp	.kbd_buffer_test
+.kbd_buffer_empty:
+
+	; Check if there is harddisk
+	pusha
+	mov	ax, 0800h
+	mov	dx, 0080h
+	int	13h
+	popa
+	jc	.boot_cdrom
+
+	; Display the 'Press key' message and wait for a maximum of 5 seconds
+	call	crlf
+	mov	si, presskey_msg		; si points to 'Press key' message
+	call	writestr			; display the message
+
+	mov	byte [TimeoutCount], 5
+.next_second:
+	mov	eax, [BIOS_timer]		; load current tick counter
+	add	eax, 19				; 
+
+.poll_again:
+	call	pollchar
+	jnz	.boot_cdrom
+
+	mov	ebx, [BIOS_timer]
+	cmp	eax, ebx
+	jnz	.poll_again
+
+	mov	si, dot_msg			; print '.'
+	call	writestr
+	dec	byte [TimeoutCount]		; decrement timeout counter
+	jz	.boot_harddisk
+	jmp	.next_second
+
+.boot_harddisk:
+	call	crlf
+
+	; Boot first harddisk (drive 0x80)
+	mov	ax, 0201h
+	mov	dx, 0080h
+	mov	cx, 0001h
+	mov	bx, 7C00h
+	int	13h
+	jnc	.go_hd
+	jmp	kaboom
+.go_hd:
+	mov	ax, cs
+	mov	ds, ax
+	mov	es, ax
+	mov	fs, ax
+	mov	gs, ax
+	mov	dx, 0080h
+
+	jmp	0:0x7C00
+%endif
+
+.boot_cdrom:
+%ifdef WAIT_FOR_KEY
+	call	crlf
+	call	crlf
+%endif
+
+	; Save and display the boot drive number
+	mov	[DriveNo], dl
+%ifdef DEBUG_MESSAGES
+	mov	si, startup_msg
+	call	writemsg
+	mov	al, dl
+	call	writehex2
+	call	crlf
+%endif
+
+	; Now figure out what we're actually doing
+	; Note: use passed-in DL value rather than 7Fh because
+	; at least some BIOSes will get the wrong value otherwise
+	mov	ax, 4B01h			; Get disk emulation status
+	mov	dl, [DriveNo]
+	mov	si, spec_packet
+	int	13h
+	jc	near spec_query_failed		; Shouldn't happen (BIOS bug)
+	mov	dl, [DriveNo]
+	cmp	[sp_drive], dl			; Should contain the drive number
+	jne	near spec_query_failed
+
+%ifdef DEBUG_MESSAGES
+	mov	si, spec_ok_msg
+	call	writemsg
+	mov	al, byte [sp_drive]
+	call	writehex2
+	call	crlf
+%endif
+
+found_drive:
+	; Get drive information
+	mov	ah, 48h
+	mov	dl, [DriveNo]
+	mov	si, drive_params
+	int	13h
+	jnc	params_ok
+
+	; mov	si, nosecsize_msg	No use in reporting this
+	; call	writemsg
+
+params_ok:
+	; Check for the sector size (should be 2048, but
+	; some BIOSes apparently think we're 512-byte media)
+	;
+	; FIX: We need to check what the proper behaviour
+	; is for getlinsec when the BIOS thinks the sector
+	; size is 512!!!  For that, we need such a BIOS, though...
+%ifdef DEBUG_MESSAGES
+	mov	si, secsize_msg
+	call	writemsg
+	mov	ax, [dp_secsize]
+	call	writehex4
+	call	crlf
+%endif
+
+
+	;
+	; Clear Files structures
+	;
+	mov	di, Files
+	mov	cx, (MAX_OPEN*open_file_t_size)/4
+	xor	eax, eax
+	rep	stosd
+
+	;
+	; Now, we need to sniff out the actual filesystem data structures.
+	; mkisofs gave us a pointer to the primary volume descriptor
+	; (which will be at 16 only for a single-session disk!); from the PVD
+	; we should be able to find the rest of what we need to know.
+	;
+get_fs_structures:
+	mov	eax, 16			; Primary Volume Descriptor (sector 16)
+	mov	bx, trackbuf
+	call	getonesec
+
+	mov	eax, [trackbuf+156+2]
+	mov	[RootDir+dir_lba],eax
+	mov	[CurDir+dir_lba],eax
+%ifdef DEBUG_MESSAGES
+	mov	si, rootloc_msg
+	call	writemsg
+	call	writehex8
+	call	crlf
+%endif
+
+	mov	eax,[trackbuf+156+10]
+	mov	[RootDir+dir_len],eax
+	mov	[CurDir+dir_len],eax
+%ifdef DEBUG_MESSAGES
+	mov	si, rootlen_msg
+	call	writemsg
+	call	writehex8
+	call	crlf
+%endif
+	add	eax,SECTORSIZE-1
+	shr	eax,SECTORSIZE_LG2
+	mov	[RootDir+dir_clust],eax
+	mov	[CurDir+dir_clust],eax
+%ifdef DEBUG_MESSAGES
+	mov	si, rootsect_msg
+	call	writemsg
+	call	writehex8
+	call	crlf
+%endif
+
+	; Look for the "REACTOS" directory, and if found,
+	; make it the current directory instead of the root
+	; directory.
+	mov	di,isolinux_dir
+	mov	al,02h				; Search for a directory
+	call	searchdir_iso
+	jnz	.dir_found
+	mov	si,no_dir_msg
+	call	writemsg
+	jmp	kaboom
+
+.dir_found:
+	mov	[CurDir+dir_len],eax
+	mov	eax,[si+file_left]
+	mov	[CurDir+dir_clust],eax
+	xor	eax,eax				; Free this file pointer entry
+	xchg	eax,[si+file_sector]
+	mov	[CurDir+dir_lba],eax
+
+
+	mov	di, isolinux_bin		; di points to Isolinux filename
+	call	searchdir			; look for the file
+	jnz	.isolinux_opened		; got the file
+	mov	si, no_isolinux_msg		; si points to error message
+	call	writemsg			; display the message
+	jmp	kaboom				; fail boot
+
+.isolinux_opened:
+	mov	di, si				; save file pointer
+
+%ifdef DEBUG_MESSAGES
+	mov	si, filelen_msg
+	call	writemsg
+	call	writehex8
+	call	crlf
+%endif
+
+	mov ecx, eax			; calculate sector count
+	shr ecx, 11
+	test eax, 0x7FF
+	jz .full_sector
+	inc ecx
+.full_sector:
+
+%ifdef DEBUG_MESSAGES
+	mov eax, ecx
+	mov	si, filesect_msg
+	call	writemsg
+	call	writehex8
+	call	crlf
+%endif
+
+	mov	bx, 0x8000			; bx = load address
+	mov	si, di				; restore file pointer
+	mov	cx, 0xFFFF			; load the whole file
+	call	getfssec			; get the whole file
+
+%ifdef DEBUG_MESSAGES
+	mov	si, startldr_msg
+	call	writemsg
+	call	crlf
+%endif
+
+	mov	dl, [DriveNo]			; dl = boot drive
+	mov dh, 0					; dh = boot partition
+	jmp	0:0x8000			; jump into OSLoader
+
+
+
+;
+; searchdir:
+;
+; Open a file
+;
+;  On entry:
+;	DS:DI	= filename
+;  If successful:
+;	ZF clear
+;	SI		= file pointer
+;	DX:AX or EAX	= file length in bytes
+;  If unsuccessful
+;	ZF set
+;
+
+;
+; searchdir_iso is a special entry point for ISOLINUX only.  In addition
+; to the above, searchdir_iso passes a file flag mask in AL.  This is useful
+; for searching for directories.
+;
+alloc_failure:
+	xor	ax,ax				; ZF <- 1
+	ret
+
+searchdir:
+	xor	al,al
+searchdir_iso:
+	mov	[ISOFlags],al
+	call	allocate_file			; Temporary file structure for directory
+	jnz	alloc_failure
+	push	es
+	push	ds
+	pop	es				; ES = DS
+	mov	si,CurDir
+	cmp	byte [di],'\'			; If filename begins with slash
+	jne	.not_rooted
+	inc	di				; Skip leading slash
+	mov	si,RootDir			; Reference root directory instead
+.not_rooted:
+	mov	eax,[si+dir_clust]
+	mov	[bx+file_left],eax
+	mov	eax,[si+dir_lba]
+	mov	[bx+file_sector],eax
+	mov	edx,[si+dir_len]
+
+.look_for_slash:
+	mov	ax,di
+.scan:
+	mov	cl,[di]
+	inc	di
+	and	cl,cl
+	jz	.isfile
+	cmp	cl,'\'
+	jne	.scan
+	mov	[di-1],byte 0			; Terminate at directory name
+	mov	cl,02h				; Search for directory
+	xchg	cl,[ISOFlags]
+	push	di
+	push	cx
+	push	word .resume			; Where to "return" to
+	push	es
+.isfile:
+	xchg	ax,di
+
+.getsome:
+	; Get a chunk of the directory
+	mov	si,trackbuf
+	pushad
+	xchg	bx,si
+	mov	cx,1				; load one sector
+	call	getfssec
+	popad
+
+.compare:
+	movzx	eax, byte [si]			; Length of directory entry
+	cmp	al, 33
+	jb	.next_sector
+	mov	cl, [si+25]
+	xor	cl, [ISOFlags]
+	test	cl, byte 8Eh			; Unwanted file attributes!
+	jnz	.not_file
+	pusha
+	movzx	cx, byte [si+32]		; File identifier length
+	add	si, byte 33			; File identifier offset
+	call	iso_compare_names
+	popa
+	je	.success
+.not_file:
+	sub	edx, eax			; Decrease bytes left
+	jbe	.failure
+	add	si, ax				; Advance pointer
+
+.check_overrun:
+	; Did we finish the buffer?
+	cmp	si, trackbuf+trackbufsize
+	jb	.compare			; No, keep going
+
+	jmp	short .getsome			; Get some more directory
+
+.next_sector:
+	; Advance to the beginning of next sector
+	lea	ax, [si+SECTORSIZE-1]
+	and	ax, ~(SECTORSIZE-1)
+	sub	ax, si
+	jmp	short .not_file			; We still need to do length checks
+
+.failure:
+%ifdef DEBUG_MESSAGES
+	mov	si, findfail_msg
+	call	writemsg
+	call	crlf
+%endif
+	xor	eax, eax			; ZF = 1
+	mov	[bx+file_sector], eax
+	pop	es
+	ret
+
+.success:
+	mov	eax, [si+2]			; Location of extent
+	mov	[bx+file_sector], eax
+	mov	eax, [si+10]			; Data length
+	push	eax
+	add	eax, SECTORSIZE-1
+	shr	eax, SECTORSIZE_LG2
+	mov	[bx+file_left], eax
+	pop	eax
+	mov	edx, eax
+	shr	edx, 16
+	and	bx, bx				; ZF = 0
+	mov	si, bx
+	pop	es
+	ret
+
+.resume:
+	; We get here if we were only doing part of a lookup
+	; This relies on the fact that .success returns bx == si
+	xchg	edx, eax			; Directory length in edx
+	pop	cx				; Old ISOFlags
+	pop	di				; Next filename pointer
+
+	mov	byte [di-1], '\'		; restore the backslash in the filename
+
+	mov	[ISOFlags], cl			; Restore the flags
+	jz	.failure			; Did we fail?  If so fail for real!
+	jmp	.look_for_slash			; Otherwise, next level
+
+;
+; allocate_file: Allocate a file structure
+;
+;		If successful:
+;		  ZF set
+;		  BX = file pointer
+;		In unsuccessful:
+;		  ZF clear
+;
+allocate_file:
+	push	cx
+	mov	bx, Files
+	mov	cx, MAX_OPEN
+.check:
+	cmp	dword [bx], byte 0
+	je	.found
+	add	bx, open_file_t_size		; ZF = 0
+	loop	.check
+	; ZF = 0 if we fell out of the loop
+.found:
+	pop	cx
+	ret
+
+;
+; iso_compare_names:
+;	Compare the names DS:SI and DS:DI and report if they are
+;	equal from an ISO 9660 perspective.  SI is the name from
+;	the filesystem; CX indicates its length, and ';' terminates.
+;	DI is expected to end with a null.
+;
+;	Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment
+;
+iso_compare_names:
+	; First, terminate and canonicalize input filename
+	push	di
+	mov	di, ISOFileName
+.canon_loop:
+	jcxz	.canon_end
+	lodsb
+	dec	cx
+	cmp	al, ';'
+	je	.canon_end
+	and	al, al
+	je	.canon_end
+	stosb
+	cmp	di, ISOFileNameEnd-1		; Guard against buffer overrun
+	jb	.canon_loop
+.canon_end:
+	cmp	di, ISOFileName
+	jbe	.canon_done
+	cmp	byte [di-1], '.'		; Remove terminal dots
+	jne	.canon_done
+	dec	di
+	jmp	short .canon_end
+.canon_done:
+	mov	[di], byte 0			; Null-terminate string
+	pop	di
+	mov	si, ISOFileName
+.compare:
+	lodsb
+	mov	ah, [di]
+	inc	di
+	and	ax, ax
+	jz	.success			; End of string for both
+	and	al, al				; Is either one end of string?
+	jz	.failure			; If so, failure
+	and	ah, ah
+	jz	.failure
+	or	ax, 2020h			; Convert to lower case
+	cmp	al, ah
+	je	.compare
+.failure:
+	and	ax, ax				; ZF = 0 (at least one will be nonzero)
+.success:
+	ret
+
+
+
+
+
+
+
+;
+; getfssec: Get multiple clusters from a file, given the file pointer.
+;
+;  On entry:
+;	ES:BX	-> Buffer
+;	SI	-> File pointer
+;	CX	-> Cluster count; 0FFFFh = until end of file
+;  On exit:
+;	SI	-> File pointer (or 0 on EOF)
+;	CF = 1	-> Hit EOF
+;
+getfssec:
+	cmp	cx, [si+file_left]
+	jna	.ok_size
+	mov	cx, [si+file_left]
+
+.ok_size:
+	mov	bp, cx
+	push	cx
+	push	si
+	mov	eax, [si+file_sector]
+	call	getlinsec
+	xor	ecx, ecx
+	pop	si
+	pop	cx
+
+	add	[si+file_sector], ecx
+	sub	[si+file_left], ecx
+	ja	.not_eof			; CF = 0
+
+	xor	ecx, ecx
+	mov	[si+file_sector], ecx		; Mark as unused
+	xor	si,si
+	stc
+
+.not_eof:
+	ret
+
+
+
+; INT 13h, AX=4B01h, DL=<passed in value> failed.
+; Try to scan the entire 80h-FFh from the end.
+spec_query_failed:
+	mov	si,spec_err_msg
+	call	writemsg
+
+	mov	dl, 0FFh
+.test_loop:
+	pusha
+	mov	ax, 4B01h
+	mov	si, spec_packet
+	mov	byte [si], 13			; Size of buffer
+	int	13h
+	popa
+	jc	.still_broken
+
+	mov	si, maybe_msg
+	call	writemsg
+	mov	al, dl
+	call	writehex2
+	call	crlf
+
+	cmp	byte [sp_drive], dl
+	jne	.maybe_broken
+
+	; Okay, good enough...
+	mov	si, alright_msg
+	call	writemsg
+	mov	[DriveNo], dl
+.found_drive:
+	jmp	found_drive
+
+	; Award BIOS 4.51 apparently passes garbage in sp_drive,
+	; but if this was the drive number originally passed in
+	; DL then consider it "good enough"
+.maybe_broken:
+	cmp	byte [DriveNo], dl
+	je	.found_drive
+
+.still_broken:
+	dec dx
+	cmp	dl, 80h
+	jnb	.test_loop
+
+fatal_error:
+	mov	si, nothing_msg
+	call	writemsg
+
+.norge:
+	jmp	short .norge
+
+
+
+	; Information message (DS:SI) output
+	; Prefix with "isolinux: "
+	;
+writemsg:
+	push	ax
+	push	si
+	mov	si, isolinux_str
+	call	writestr
+	pop	si
+	call	writestr
+	pop	ax
+	ret
+
+;
+; crlf: Print a newline
+;
+crlf:
+	mov	si, crlf_msg
+	; Fall through
+
+;
+; writestr: write a null-terminated string to the console, saving
+;           registers on entry.
+;
+writestr:
+	pushfd
+	pushad
+.top:
+	lodsb
+	and	al, al
+	jz	.end
+	call	writechr
+	jmp	short .top
+.end:
+	popad
+	popfd
+	ret
+
+
+;
+; writehex[248]: Write a hex number in (AL, AX, EAX) to the console
+;
+writehex2:
+	pushfd
+	pushad
+	shl	eax, 24
+	mov	cx, 2
+	jmp	short writehex_common
+writehex4:
+	pushfd
+	pushad
+	shl	eax, 16
+	mov	cx, 4
+	jmp	short writehex_common
+writehex8:
+	pushfd
+	pushad
+	mov	cx, 8
+writehex_common:
+.loop:
+	rol	eax, 4
+	push	eax
+	and	al, 0Fh
+	cmp	al, 10
+	jae	.high
+.low:
+	add	al, '0'
+	jmp	short .ischar
+.high:
+	add	al, 'A'-10
+.ischar:
+	call	writechr
+	pop	eax
+	loop	.loop
+	popad
+	popfd
+	ret
+
+;
+; Write a character to the screen.  There is a more "sophisticated"
+; version of this in the subsequent code, so we patch the pointer
+; when appropriate.
+;
+
+writechr:
+	pushfd
+	pushad
+	mov	ah, 0Eh
+	xor	bx, bx
+	int	10h
+	popad
+	popfd
+	ret
+
+;
+; Get one sector.  Convenience entry point.
+;
+getonesec:
+	mov	bp, 1
+	; Fall through to getlinsec
+
+;
+; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
+;
+; Note that we can't always do this as a single request, because at least
+; Phoenix BIOSes has a 127-sector limit.  To be on the safe side, stick
+; to 32 sectors (64K) per request.
+;
+; Input:
+;	EAX	- Linear sector number
+;	ES:BX	- Target buffer
+;	BP	- Sector count
+;
+getlinsec:
+	mov si,dapa			; Load up the DAPA
+	mov [si+4],bx
+	mov bx,es
+	mov [si+6],bx
+	mov [si+8],eax
+.loop2:
+	push bp				; Sectors left
+	cmp bp,[MaxTransfer]
+	jbe .bp_ok
+	mov bp,[MaxTransfer]
+.bp_ok:
+	mov [si+2],bp
+	push si
+	mov dl,[DriveNo]
+	mov ah,42h			; Extended Read
+	call xint13
+	pop si
+	pop bp
+	movzx eax,word [si+2]		; Sectors we read
+	add [si+8],eax			; Advance sector pointer
+	sub bp,ax			; Sectors left
+	shl ax,SECTORSIZE_LG2-4		; 2048-byte sectors -> segment
+	add [si+6],ax			; Advance buffer pointer
+	and bp,bp
+	jnz .loop2
+	mov eax,[si+8]			; Next sector
+	ret
+
+	; INT 13h with retry
+xint13:
+	mov	byte [RetryCount], retry_count
+.try:
+	pushad
+	int	13h
+	jc	.error
+	add	sp, byte 8*4			; Clean up stack
+	ret
+.error:
+	mov	[DiskError], ah		; Save error code
+	popad
+	dec byte [RetryCount]
+	jz .real_error
+	push ax
+	mov al,[RetryCount]
+	mov ah,[dapa+2]			; Sector transfer count
+	cmp al,2			; Only 2 attempts left
+	ja .nodanger
+	mov ah,1			; Drop transfer size to 1
+	jmp short .setsize
+.nodanger:
+	cmp al,retry_count-2
+	ja .again			; First time, just try again
+	shr ah,1			; Otherwise, try to reduce
+	adc ah,0			; the max transfer size, but not to 0
+.setsize:
+	mov [MaxTransfer],ah
+	mov [dapa+2],ah
+.again:
+	pop ax
+	jmp .try
+
+.real_error:
+	mov	si, diskerr_msg
+	call	writemsg
+	mov	al, [DiskError]
+	call	writehex2
+	mov	si, ondrive_str
+	call	writestr
+	mov	al, dl
+	call	writehex2
+	call	crlf
+	; Fall through to kaboom
+
+;
+; kaboom: write a message and bail out.  Wait for a user keypress,
+;	  then do a hard reboot.
+;
+kaboom:
+	mov	ax, cs
+	mov	ds, ax
+	mov	es, ax
+	mov	fs, ax
+	mov	gs, ax
+	sti
+	mov	si, err_bootfailed
+	call	writestr
+	call	getchar
+	cli
+	mov	word [BIOS_magic], 0	; Cold reboot
+	jmp	0F000h:0FFF0h		; Reset vector address
+
+getchar:
+.again:
+	mov	ah, 1		; Poll keyboard
+	int	16h
+	jz	.again
+.kbd:
+	xor	ax, ax		; Get keyboard input
+	int	16h
+.func_key:
+	ret
+
+
+;
+; pollchar: check if we have an input character pending (ZF = 0)
+;
+pollchar:
+	pushad
+	mov ah,1		; Poll keyboard
+	int 16h
+	popad
+	ret
+
+
+
+isolinux_banner	db CR, LF, 'Loading IsoBoot...', CR, LF, 0
+copyright_str	db ' Copyright (C) 1994-2002 H. Peter Anvin', CR, LF, 0
+presskey_msg	db 'Press any key to boot from CD', 0
+dot_msg		db '.',0
+
+%ifdef DEBUG_MESSAGES
+startup_msg:	db 'Starting up, DL = ', 0
+spec_ok_msg:	db 'Loaded spec packet OK, drive = ', 0
+secsize_msg:	db 'Sector size appears to be ', 0
+rootloc_msg:	db 'Root directory location: ', 0
+rootlen_msg:	db 'Root directory length: ', 0
+rootsect_msg:	db 'Root directory length(sectors): ', 0
+fileloc_msg:	db 'SETUPLDR.SYS location: ', 0
+filelen_msg:	db 'SETUPLDR.SYS length: ', 0
+filesect_msg:	db 'SETUPLDR.SYS length(sectors): ', 0
+findfail_msg:	db 'Failed to find file!', 0
+startldr_msg:	db 'Starting SETUPLDR.SYS', 0
+%endif
+
+nosecsize_msg:	db 'Failed to get sector size, assuming 0800', CR, LF, 0
+spec_err_msg:	db 'Loading spec packet failed, trying to wing it...', CR, LF, 0
+maybe_msg:	db 'Found something at drive = ', 0
+alright_msg:	db 'Looks like it might be right, continuing...', CR, LF, 0
+nothing_msg:	db 'Failed to locate CD-ROM device; boot failed.', CR, LF, 0
+isolinux_str	db 'IsoBoot: ', 0
+crlf_msg	db CR, LF, 0
+diskerr_msg:	db 'Disk error ', 0
+ondrive_str:	db ', drive ', 0
+err_bootfailed	db CR, LF, 'Boot failed: press a key to retry...'
+isolinux_dir	db '\LOADER', 0
+no_dir_msg	db 'Could not find the LOADER directory.', CR, LF, 0
+isolinux_bin	db 'SETUPLDR.SYS', 0
+no_isolinux_msg	db 'Could not find SETUPLDR.SYS.', CR, LF, 0
+
+;
+; El Torito spec packet
+;
+		align 8, db 0
+spec_packet:	db 13h				; Size of packet
+sp_media:	db 0				; Media type
+sp_drive:	db 0				; Drive number
+sp_controller:	db 0				; Controller index
+sp_lba:		dd 0				; LBA for emulated disk image
+sp_devspec:	dw 0				; IDE/SCSI information
+sp_buffer:	dw 0				; User-provided buffer
+sp_loadseg:	dw 0				; Load segment
+sp_sectors:	dw 0				; Sector count
+sp_chs:		db 0,0,0			; Simulated CHS geometry
+sp_dummy:	db 0				; Scratch, safe to overwrite
+
+;
+; EBIOS drive parameter packet
+;
+		align 8, db 0
+drive_params:	dw 30				; Buffer size
+dp_flags:	dw 0				; Information flags
+dp_cyl:		dd 0				; Physical cylinders
+dp_head:	dd 0				; Physical heads
+dp_sec:		dd 0				; Physical sectors/track
+dp_totalsec:	dd 0,0				; Total sectors
+dp_secsize:	dw 0				; Bytes per sector
+dp_dpte:	dd 0				; Device Parameter Table
+dp_dpi_key:	dw 0				; 0BEDDh if rest valid
+dp_dpi_len:	db 0				; DPI len
+		db 0
+		dw 0
+dp_bus:		times 4 db 0			; Host bus type
+dp_interface:	times 8 db 0			; Interface type
+db_i_path:	dd 0,0				; Interface path
[truncated at 1000 lines; 3426 more skipped]