www.pudn.com > bootmenu.zip > BOOTAUTO.ASM


	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 
	call	putn 
	call	putnl 
 
	pop	ax 
	pop	si 
	add	si,8 
	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 
pnames	db	32 dup(?) 
 
; 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