	PAGE 60,132
;	bootauto:  Auto-boot version of BOOTMENU program
;	by Gordon W. Ross, Aug 1990
;
;	See the file bootmenu.doc for user instructions.
;
;	The following is an outline of the program:
;
;	Relocate self from 0x7C00 to 0x0600
;	Display message "Booting from HD0,"
;	Search partition table for an active entry
;	If an active partition is found,
;		Delay while watching for key press (5 sec.)
;		If (key pressed) GOTO menu:
;		Else GOTO boot:
;		EndIf
;	Else (no active partition)
; menu:		Display partition menu
;		Prompt for and read user selection
;	EndIf
; boot:	Boot from the selected partition:
;	(was selected by user, or was active)
;	Read first sector of selected partition into 0x7c00
;	Verify good second-stage boot sector (magic word)
;	Set-up correct register values and jump to it.
;	If (Errors during boot) { complain; GOTO menu: }
;

DELAY	equ	5*18	; in ticks (1/18 sec.)
CODEORG	equ 0600h	; offset of this code in code seg
; All values computed from offsets in codeseg need to be
; adjusted by adding CODEORG to each.  The obvious method,
; using "org CODEORG" causes MASM/LINK to fill in the space.

codeseg	segment
	assume cs:codeseg, ds:codeseg

; Initial program entry point
; (Assembler is told this is at offset zero.)

main:
	; Set up the stack
	xor	ax,ax
	mov	si,7C00h	; just before load location
	cli
	mov	ss,ax
	mov	sp,si
	sti

; Relocate this code from 0:7C00h to 0:CODEORG
	mov	ds,ax
	mov	es,ax
	mov	si,7C00h	; where this program is initially loaded
	mov	di,CODEORG
	mov	cx,0100h
	cld
	rep	movsw

; Jump to relocated code (0:CODEORG)
	jmp	far ptr begin1
begin	equ	$
	mov	bp,sp	; frame pointer = 0x7C00
	sub	sp,4
; 2 words of local storage:
;	[bp-2] = ptable index [0-3]
;	[bp-4] = temporary value

; Display message "Boot device: HD0"
	mov	si, offset bootdev + CODEORG
	call	puts

; Search partition table for an active entry
	mov	al,0
search:
	call	addr_pt	; si = & ptable[AL]
	mov	DL,[si]
	cmp	DL,80h
	jz	found
	inc	al
	cmp	al,04
	jb	search
; Active partition not found
	jmp	menu

found:	; Found a partition marked active.
	mov	[bp-2],ax	; Save the ptable array index

; Delay while watching for key press (2 sec.)
; Get start time, compute end time.
	mov	ah,00
	int	1Ah		; BIOS get time of day
	add	dx, DELAY	; compute end time
	mov	[bp-4],dx	; save expiration time

; Check for key press
waitkey:
	mov	ah,1
	int	16h		; BIOS Keyboard
	jnz	menu	; key pressed

; Check for expiration of delay
	mov	ah,00
	int	1Ah		; BIOS get time of day
	sub	dx,[bp-4]
	js	waitkey	; delay not expired

; Delay has expired, so boot the active partition
	mov	al,','
	call	putc
	mov	ax,[bp-2]	; ptable index
	; the index and newline are printed later
	jmp	boot

; Display partition menu
menu:
	mov	ah,1		; flush input
	int	16h
	jz	fl_done
	mov	ah,0
	int	16h
	jmp	menu
fl_done:

; Print partition menu from name table

	call	putnl		; print newline
	mov	si, offset pnames ; no org fix-up here
	mov	al, '1'
prname:
	push	si
	push	ax

	call	putc
	mov	al,' '
	call	putc
;	mov	cx,8		; maximum name length Saul 
	mov	cx,5		; maximum name length Saul
	call	putn
	call	putnl

	pop	ax
	pop	si
;	add	si,8; Saul
	add	si,5; Saul
	inc	al
	cmp	al,'4'
	jbe	prname

; Prompt for and read user selection
select:
	call	putnl
	mov	si, offset prompt + CODEORG
	call	puts
	; Read a key and convert it to a number
	mov	ah,0
	int	16h
	sub	al,'1'
	cmp	al,04
	jnb	select
	; The key and a newline are printed below

boot:
; Boot from the selected partition.
; On entry to this section:  AL = index of ptable element

	; get address of ptable element
	call	addr_pt	; si = & ptable[AL]

	; print the parition index and a newline
	add	al,'1'
	call	putc
	call	putnl

; Check for valid system ID (non-zero)

	mov	al,[si+4]
	cmp	al,0
	jnz	id_ok
	mov	si, offset msgempty + CODEORG
	jmp	error
id_ok:

; Read first sector of selected partition into 0x7c00
; Also, mark this entry active (in RAM only) in case the
; secondary boot program looks at it (which it may).

	mov	al,80h	; active flag
	mov	[si], al
	mov	cx,5	; retry count
retry:	push	cx
	mov	dx,[si]	; drive, head
	mov	cx,[si+2]	; cyl, sector
	mov	bx,7C00h	; destination (es=0)
	mov	ax,0201h	; BIOS read one sector
	int	13h
	jnc	rd_ok
	xor	ax,ax	; reset disk
	int	13h
	pop	cx
	loop	retry
	mov	si, offset msgread + CODEORG
	jmp	error
rd_ok:	pop	cx

; Check for valid magic number in secondary boot sector
	mov	ax, 0AA55h
	assume	ds:seg0		; Actually, codeseg == seg0
	cmp	ax, magic2
	assume	ds:codeseg
	jz	magic_ok
	mov	si, offset msginvalid + CODEORG
	jmp	error
magic_ok:

; Make sure ds:si points to the booted partition, and
; Jump to the secondary boot program.
	jmp	far ptr begin2

; Jump here with si=error-message
error:
	call	puts
	call	putnl
	jmp	menu

;*************************************************************
; Subroutines
;*************************************************************
CR	EQU	13
LF	EQU	10
TAB	EQU	 9

putc	proc	near		; print char in AL
	mov	ah, 0Eh		; uses: ax, bx
	mov	bx, 07
	int	10h
	ret
putc	endp

putnl	proc	near		; print a newline
	mov	al, CR		; uses: ax, bx
	call	putc
	mov	al, LF
	call	putc
	ret
putnl	endp

puts	proc	near		; print string at address SI
	mov	cx,80		; Stop at null or CX chars
putn:	lodsb			; uses: ax, bx, cx, si
	cmp	al,0
	jz	puts_e
	push	cx
	call	putc
	pop	cx
	loop	putn
puts_e:	ret
puts	endp

addr_pt	proc	near		; set SI = address of ptable[al]
	push	ax		; uses: cx (but preserves ax)
	mov	si, offset ptable ; no org fix-up here
	mov	cl,16	; size of array element
	mul	cl		; ax = al * cl
	add	si,ax
	pop	ax
	ret
addr_pt	endp

;**********************************************************
; Strings
;**********************************************************

bootdev		db	"Boot device: hd0",0
prompt		db	"Boot partition? (1-4) ",0
msgempty	db	"Empty!",0
msgread		db	"Read error!",0
msginvalid	db	"Invalid!",0
	org	180h	; this pads the length (it seems)
codeseg	ends

; Declares some offsets in segment zero
seg0	segment	at 0

	org	CODEORG + (offset begin - offset main)
begin1	equ	$

; Here is the name table used for the partition menu.
; The accompanying fdisk program updates this table.
;	org	CODEORG + 180h Saul
	org	CODEORG + 1AAh ;Saul
;pnames	db	32 dup(?) Saul
pnames	db	20 dup(?); Saul

; The locations after 1AE are (reportedly) used by some
; Western Digital controllers in "auto-configure" mode.
; Don't put anything critical between here and ptable.

; Here is the partition table
	org	CODEORG + 1BEh
ptable	db	(4 * 16) dup(?)

; Here is where the secondary boot sector is loaded.
	org	7C00h
begin2	equ	$

	org	7DFEh
magic2	dw	?

seg0	ends

	end	main
