To: INFO-IBMPC@usc-isib.ARPA
Subject: Re: BOOTCODE.ASM
Date: Tue, 28 Jan 86 14:38:52 -0500
From: Dan Grim <grim@huey.udel.EDU>

I have discovered through my own sad experience that BOOTCODE.ASM is
not able to deal with newer DOS partitions that use the 16-bit FAT
format.  BOOTCODE.ASM understands DOS with 12-bit FAT's (ID byte = 1)
and Xenix (ID byte = 2).  DOS with 16-bit FAT's has an ID byte = 4
which BOOTCODE doesn't recognize.  The fix is trivial: simply change
the line following the label 'lddos' from

	mov	al,1			;id for dos

to

	mov	al,4			;id for dos with 16-bit FAT's

Of course, once you do that BOOTCODE won't handle 12-bit FAT DOS any
longer.

					Dan

ORIGINAL CODE IS AS FOLLOWS:


	page	60,132
	title	Write prompting boot to hard disk
;
;	This program will write a new boot sector to drive C:
;	that prompts whether you wish to boot xenix
;	or dos:
;
;		X=Xenix, D=Dos
;
;	The reply is the one character first initial of the system.
;
;	This program is written as a .com file so it should be assembled
;	and linked, ignoring the missing stack segment message from the linker.
;	It should then be converted to a com file with exe2bin.
;
;
;	MASM	BOOTCODE,,,;
;	LINK	BOOTCODE;
;	EXE2BIN BOOTCODE.EXE BOOTCODE.COM
;	ERASE	BOOTCODE.EXE
;
;	Now the program is ready to run.  It produces a message at the
;	start telling you what it is going to do, to allow aborting before
;	touching your hard disk.
;
;	The boot only runs on an AT or a pc with Enhanced Graphics Adapter,
;	since it uses subfunction 19 of the video call, Write String.
;
;	Distribution of this program in any way is acceptable to me.
;
;		W.D. Cagle   75206,2701
;
code	segment 'code'
	assume	cs:code,ds:code
video	equ	10h
kbd	equ	16h
diskio	equ	13h
basic	equ	18h
dos	equ	21h
;
cr	equ	0dh
lf	equ	0ah
base	equ	$
bootloc equ	7c00h
;
	org	100h
writboot proc	near
	jmp	start			;jump around constants
bootsec proc	near
bcode	equ	$
adjust	equ	600h-103h		;stupid adjustment
	cli				;disable interrupts
	xor	ax,ax			;clear
	mov	ss,ax			;place in stack segment
	mov	sp,offset bootloc	;get my address
	mov	si,sp			;place in source
	push	ax			;
	pop	es			;put in extra segment
	push	ax			;now for ds
	pop	ds			;load it
	sti				;enable interrupts
	cld				;make move direction positive
	mov	di,600h 		;place to move to
	mov	cx,100h 		;how many words to move
	rep	movsw			;move it
	mov	ax,offset relboot+adjust ;this gets rid of exe2bin
	push	ax			;wanting a fixup, cs=0 anyway
	ret
;
relboot:
	mov	byte ptr p1+adjust,0
	mov	byte ptr p2+adjust,0
	mov	byte ptr p3+adjust,0
	mov	byte ptr p4+adjust,0
wrprmpt:
	mov	si,offset msg4+adjust	;go ask question
	xor	ch,ch			;clear
	lodsb				;get message length
	mov	cl,al			;to cl
	mov	ax,1301h		;say write message
	mov	bx,7			;use normal attribute
	sub	dx,dx			;row 0 col 0
	mov	bp,si			;get location of message
	int	video			;print message
	mov	al,' '                  ;blank out response
	mov	cx,1			;1 byte
	mov	ah,10			;say write char only
	int	video			;do it
	mov	ah,0			;get keyboard input
	int	kbd
	and	al,7fh-20h		;make upper case
	push	ax
	mov	ah,10			;say write char
	mov	cx,1			;1 byte
	int	video			;let 'em see what they typed
	pop	ax
	cmp	al,'D'                  ;want dos?
	je	lddos			;yes
	cmp	al,'X'                  ;want xenix
	je	xenix			;yes
	jmp	wrprmpt 		;ask again
;
lddos:
	mov	al,1			;id for dos
	mov	si,offset dosnm+adjust	;dos name
	jmp	short gotact1		;continue
;
xenix:
	mov	al,2			;id for xenix
	mov	si,offset xenixnm+adjust ;xenix name
gotact1:
	mov	di,offset msg5nm+adjust ;put name in message
	mov	cx,6			;length of name
	cld				;positive direction
	rep	movsb			;move it
	mov	bl,4			;max 4 to search
	mov	si,offset parttbl+adjust  ;point to first entry
getpart_a:
	cmp	byte ptr[si+4],al	;is this the one
	je	gotact2 		;yes
	add	si,16			;to next
	dec	bl			;count em
	jnz	getpart_a		;not end yet
	mov	si,offset msg5+adjust	;
	xor	ch,ch			;clear
	lodsb				;get message length
	mov	cl,al			;to cl
	mov	ax,1301h		;say write message
	mov	bx,7			;use normal attribute
	sub	dx,dx			;row 0 col 0
	mov	bp,si			;get location of message
	int	video			;print message
lupe1:	jmp	lupe1			;and hang
;
gotact2:
	mov	byte ptr[si],80h	;say active
	push	si
	push	bx
	mov	ax,0301h
	mov	bx,600h
	mov	cx,1
	mov	dx,80h
	int	diskio
	pop	bx
	pop	si
;
gotact:
	mov	dx,[si] 		;drive in dh, head in dl
	mov	cx,[si+2]		;get track in ch, sector in cl
	mov	bp,si			;save indicator
;
;
finis:
	mov	di,5			;retry count
rdboot:
	mov	bx,bootloc		;location for boot
	mov	ax,0201h		;say read 1 sector
	push	di			;
	int	diskio			;go do it
;
	pop	di			;
	jnc	goodrd			;good read
;
	xor	ax,ax			;say recalibrate
	int	diskio			;do it
	dec	di			;count retries
	jnz	rdboot			;continue trying
	mov	si,offset msg2+adjust	;point to bad disk message
wrmsg:
	xor	ch,ch			;clear
	lodsb				;get message length
	mov	cl,al			;to cl
	mov	ax,1301h		;say write message
	mov	bx,7			;use normal attribute
	sub	dx,dx			;row 0 col 0
	mov	bp,si			;get location of message
	int	video			;print message
lupe:	jmp	lupe			;and hang
;
goodrd:
	mov	si,offset msg3+adjust	;point to no boot rec msg
	cmp	word ptr bootsig,0aa55h ;see if boot signature
	jne	wrmsg
;
	mov	si,bp			;restore partition table pointer
	mov	ax,offset bootloc	;where partition boot start
	push	ax
	ret
;
;
msg2	db	lmsg2,'Error loading operating system'
lmsg2	equ	($-msg2)-1
msg3	db	lmsg3,'Missing operating system'
lmsg3	equ	($-msg3)-1
msg4	db	lmsg4,'Enter X=Xenix, D=DOS '
lmsg4	equ	($-msg4)-1
msg5	db	lmsg5,'Cannot find '
msg5nm	db	'xxxxx'
lmsg5	equ	($-msg5)-1
dosnm	db	'DOS  '
xenixnm db	'XENIX'
parttbl equ	byte ptr bcode+1beh
p1	equ	bcode+1beh
;
p2	equ	p1+16
;
p3	equ	p2+16
;
p4	equ	p3+16
;
signat	equ	p4+16
bootsig equ	base+7dfeh
	org	bcode+512
bootsec endp
diskbuf db	512 dup(?)
helloms db	cr,lf
	db	'Bootwriter - This program will read the boot sector',cr,lf
	db	'from disk C: and merge the partition table in with',cr,lf
	db	'the boot program which follows and write it all back',cr,lf
	db	'out to disk C: overlaying what is there.  The resultant',cr,lf
	db	'boot program will prompt for the desired system when',cr,lf
	db	'booting, Xenix or Dos.',cr,lf
	db	cr,lf
	db	'The original boot program will be saved in a file named',cr,lf
	db	'IBMBOOT.SVE in the default directory.',cr,lf
	db	cr,lf
	db	'If you do not wish to do this, you should control-c out',cr,lf
	db	'at the prompt.',cr,lf
	db	'Reply with the enter key to continue, or control-c to stop $'
crlf	db	cr,lf,'$'
ibmboot db	'IBMBOOT.SVE',0
okmsg	db	'Boot sector updated',cr,lf,'$'
ermsg1	db	'Error reading boot sector',cr,lf,'$'
ermsg2	db	'Cannot open save file',cr,lf,'$'
ermsg3	db	'Cannot write save file',cr,lf,'$'
ermsg4	db	'Cannot close save file',cr,lf,'$'
ermsg5	db	'Cannot write boot sector, boot sector creamed',cr,lf,'$'
boothdl dw	0
;
start:
	mov	dx,offset helloms	;point to signon message
	mov	ah,9			;print string
	int	dos			;say print it
;
rdcns:	mov	ah,0ch			;clear kb buffer
	mov	al,1			;read keyboard input
	int	dos			;do it
	cmp	al,cr			;enter key?
	jne	rdcns			;wait till it is
;
;	well, we continue
;
	mov	dx,offset crlf		;echo the return
	mov	ah,9
	int	dos			;write to console
;
	mov	si,5			;set up for 5 retries
rddsk:
	push	si			;save retry counter
	mov	ah,2			;say read disk
	mov	al,1			;1 sector
	mov	bx,offset diskbuf	;point to buffer
	mov	ch,0			;say cylinder 0
	mov	cl,1			;say sector 1
	mov	dh,0			;say track 0
	mov	dl,80h			;say hard drive 0
	int	diskio			;do the io
	pop	si
	jnc	rdok			;good read
	dec	si			;any more tries?
	jnz	rddsk			;yes, try again
	mov	dx,offset ermsg1	;point to trouble message
	mov	ah,9			;say console write
	int	dos			;can't read boot sector
	mov	ah,4ch			;say terminate
	mov	al,1			;error return code
	int	dos			;does not return
;
rdok:
	mov	dx,offset ibmboot	;get file name
	mov	ah,3ch			;say create it
	sub	cx,cx			;zero attribute
	int	dos
	jnc	openok			;file opened
	mov	dx,offset ermsg2	;can't open save file
	mov	ah,9
	int	dos			;tell 'em
	mov	ah,4ch			;say terminate
	mov	al,2			;reason
	int	dos			;
;
openok:
	mov	boothdl,ax		;save handle
	mov	bx,ax			;and put in bx
	mov	ah,40h			;say write to file
	mov	dx,offset diskbuf	;get location
	mov	cx,512			;say 1 sector
	int	dos			;ask to have it done
	jnc	wrtok			;good write
	mov	dx,offset ermsg3	;can't write to save file
	mov	ah,9
	int	dos			;tell 'em
	mov	ah,4ch			;say terminate
	mov	al,3			;reason
	int	dos			;
;
wrtok:
	mov	ah,3eh			;say close file
	mov	bx,boothdl		;
	int	dos			;
	jnc	closok			;closed ok
	mov	dx,offset ermsg4	;can't close save file
	mov	ah,9
	int	dos			;tell 'em
	mov	ah,4ch			;say terminate
	mov	al,4			;reason
	int	dos			;
;
closok:
	push	si
	mov	si,offset diskbuf+1beh	;start of partition table
	mov	di,offset bootsec+1beh	;ditto for new sector
	cld				;make direction positive
	mov	cx,4*16+2		;how many bytes to move
	rep	movsb			;move em
	mov	si,5			;5 retries
wrtboot:
	push	si
	mov	ah,3			;say write to disk
	mov	al,1			;say 1 sector
	mov	bx,offset bootsec	;point to sector to write
	mov	cx,1			;say sector 1
	mov	dx,80h			;
	int	diskio			;do the io
	pop	si
	jnc	updok			;good write to boot sector
	dec	si			;count retries
	jnz	wrtboot 		;try again
;
	mov	dx,offset ermsg5	;can't write boot sector file
	mov	ah,9
	int	dos			;tell 'em
	mov	ah,4ch			;say terminate
	mov	al,5			;reason
	int	dos			;
;
updok:
	mov	dx,offset okmsg 	;say we did it
	mov	ah,9
	int	dos			;tell 'em
	mov	ah,4ch			;say terminate
	mov	al,0			;good return code
	int	dos			;
writboot endp
;
;	new boot code follows
;
code	ends
	end	writboot
