262 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			262 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
		
			Executable File
		
	
	
	
	
!	jumpboot 1.0 - Jump to another bootstrap	Author: Kees J. Bot
 | 
						|
!								14 Apr 1999
 | 
						|
!
 | 
						|
! This code may be placed into any free boot sector, like the first sector
 | 
						|
! of an extended partition, a file system partition other than the root,
 | 
						|
! or even the master bootstrap.  It will load and run another bootstrap whose
 | 
						|
! disk, partition, and slice number (not necessarily all three) are patched
 | 
						|
! into this code by installboot.  If the ALT key is held down when this code
 | 
						|
! is booted then you can type the disk, partition, and slice numbers manually.
 | 
						|
! The manual interface is default if no numbers are patched in by installboot.
 | 
						|
!
 | 
						|
 | 
						|
	o32	   =	  0x66	! This assembler doesn't know 386 extensions
 | 
						|
	LOADOFF	   =	0x7C00	! 0x0000:LOADOFF is where this code is loaded
 | 
						|
	BUFFER	   =	0x0600	! First free memory
 | 
						|
	PART_TABLE =	   446	! Location of partition table within master
 | 
						|
	PENTRYSIZE =	    16	! Size of one partition table entry
 | 
						|
	MAGIC	   =	   510	! Location of the AA55 magic number
 | 
						|
 | 
						|
	! <ibm/partition.h>:
 | 
						|
	MINIX_PART =	  0x81
 | 
						|
	sysind	   =	     4
 | 
						|
	lowsec	   =	     8
 | 
						|
 | 
						|
 | 
						|
.text
 | 
						|
 | 
						|
! Find and load another bootstrap and jump to it.
 | 
						|
jumpboot:
 | 
						|
	xor	ax, ax
 | 
						|
	mov	ds, ax
 | 
						|
	mov	es, ax
 | 
						|
	cli
 | 
						|
	mov	ss, ax			! ds = es = ss = Vector segment
 | 
						|
	mov	sp, #LOADOFF
 | 
						|
	sti
 | 
						|
 | 
						|
! Move this code to safety, then jump to it.
 | 
						|
	mov	si, sp			! si = start of this code
 | 
						|
	mov	di, #BUFFER		! di = Buffer area
 | 
						|
	mov	cx, #512/2		! One sector
 | 
						|
	cld
 | 
						|
  rep	movs
 | 
						|
	jmpf	BUFFER+migrate, 0	! To safety
 | 
						|
migrate:
 | 
						|
 | 
						|
	mov	bp, #BUFFER+guide	! Patched guiding characters
 | 
						|
altkey:
 | 
						|
	movb	ah, #0x02		! Keyboard shift status
 | 
						|
	int	0x16
 | 
						|
	testb	al, #0x08		! Bit 3 = ALT key
 | 
						|
	jz	noalt			! ALT key pressed?
 | 
						|
again:
 | 
						|
	mov	bp, #zero		! Ignore patched stuff
 | 
						|
noalt:
 | 
						|
 | 
						|
! Follow guide characters to find the boot partition.
 | 
						|
	call	print
 | 
						|
	.ascii	"d?\b\0"		! Initial greeting
 | 
						|
 | 
						|
! Disk number?
 | 
						|
disk:
 | 
						|
	movb	dl, #0x80 - 0x30	! Prepare to add an ASCII digit
 | 
						|
	call	getch			! Get number to tell which disk
 | 
						|
	addb	dl, al			! dl = 0x80 + (al - '0')
 | 
						|
	jns	n0nboot			! Result should be >= 0x80
 | 
						|
	mov	si, #BUFFER+zero-lowsec	! si = where lowsec(si) is zero
 | 
						|
	cmpb	(bp), #0x23		! Next guide character is '#'?
 | 
						|
	jne	notlogical
 | 
						|
	lea	si, 1-lowsec(bp)	! Logical sector offset follows '#'
 | 
						|
notlogical:
 | 
						|
	call	load			! Load chosen sector of chosen disk
 | 
						|
	cmpb	(bp), #0x23
 | 
						|
	je	boot			! Run bootstrap if a logical is chosen
 | 
						|
 | 
						|
	call	print			! Intro to partition number
 | 
						|
	.ascii	"p?\b\0"
 | 
						|
 | 
						|
part:
 | 
						|
	call	getch			! Get character to tell partition
 | 
						|
	call	gettable		! Get partition table
 | 
						|
	call	sort			! Sort partition table
 | 
						|
	call	choose_load		! Compute chosen entry and load
 | 
						|
 | 
						|
	cmpb	sysind(si), #MINIX_PART	! Minix subpartition table possible?
 | 
						|
	jne	waitboot
 | 
						|
 | 
						|
	call	print			! Intro to slice number
 | 
						|
	.ascii	"s?\b\0"
 | 
						|
 | 
						|
slice:
 | 
						|
	call	getch			! Get character to tell slice
 | 
						|
	call	gettable		! Get partition table
 | 
						|
	call	choose_load		! Compute chosen entry and load
 | 
						|
 | 
						|
waitboot:
 | 
						|
	call	print			! Intro to nothing
 | 
						|
	.ascii	" ?\b\0"
 | 
						|
	call	getch			! Supposed to type RETURN now
 | 
						|
n0nboot:jmp	nonboot			! Sorry, can't go further
 | 
						|
 | 
						|
! Get a character, either the patched-in, or one from the keyboard.
 | 
						|
getch:
 | 
						|
	movb	al, (bp)	! Get patched-in character
 | 
						|
	testb	al, al
 | 
						|
	jz	getkey
 | 
						|
	inc	bp
 | 
						|
	jmp	gotkey
 | 
						|
getkey:	xorb	ah, ah		! Wait for keypress
 | 
						|
	int	0x16
 | 
						|
gotkey:	testb	dl, dl		! Ignore CR if disk number not yet set
 | 
						|
	jns	putch
 | 
						|
	cmpb	al, #0x0D	! Carriage return?
 | 
						|
	je	boot
 | 
						|
	!jmp	putch
 | 
						|
 | 
						|
! Print a character
 | 
						|
putch:	movb	ah, #0x0E	! Print character in teletype mode
 | 
						|
	mov	bx, #0x0001	! Page 0, foreground color
 | 
						|
	int	0x10
 | 
						|
	ret
 | 
						|
 | 
						|
! Print a message.
 | 
						|
print:	mov	cx, si		! Save si
 | 
						|
	pop	si		! si = String following 'call print'
 | 
						|
prnext:	lodsb			! al = *si++ is char to be printed
 | 
						|
	testb	al, al		! Null marks end
 | 
						|
	jz	prdone
 | 
						|
	call	putch
 | 
						|
	jmp	prnext
 | 
						|
prdone:	xchg	si, cx		! Restore si
 | 
						|
	jmp	(cx)		! Continue after the string
 | 
						|
 | 
						|
! Return typed (or in patched data) means to run the bootstrap now in core!
 | 
						|
boot:
 | 
						|
	call	print		! Make line on screen look proper
 | 
						|
	.ascii	"\b  \r\n\0"
 | 
						|
	jmp	LOADOFF-BUFFER	! Jump to LOADOFF
 | 
						|
 | 
						|
! Compute address of chosen partition entry from choice al into si, then
 | 
						|
! continue to load the boot sector of that partition.
 | 
						|
choose_load:
 | 
						|
	subb	al, #0x30		! al -= '0'
 | 
						|
	cmpb	al, #4			! Only four partitions
 | 
						|
	ja	n0nboot
 | 
						|
	movb	ah, #PENTRYSIZE
 | 
						|
	mulb	ah			! al *= PENTRYSIZE
 | 
						|
	add	ax, #BUFFER+PART_TABLE
 | 
						|
	mov	si, ax			! si = &part_table[al - '0']
 | 
						|
	movb	al, sysind(si)		! System indicator
 | 
						|
	testb	al, al			! Unused partition?
 | 
						|
	jz	n0nboot
 | 
						|
	!jmp	load			! Continue to load boot sector
 | 
						|
 | 
						|
! Load boot sector of the current partition.
 | 
						|
load:
 | 
						|
	push	dx		! Save drive code
 | 
						|
	push	es		! Next call sets es
 | 
						|
	movb	ah, #0x08	! Code for drive parameters
 | 
						|
	int	0x13
 | 
						|
	pop	es
 | 
						|
	andb	cl, #0x3F	! cl = max sector number (1-origin)
 | 
						|
	incb	dh		! dh = 1 + max head number (0-origin)
 | 
						|
	movb	al, cl		! al = cl = sectors per track
 | 
						|
	mulb	dh		! dh = heads, ax = heads * sectors
 | 
						|
	mov	bx, ax		! bx = sectors per cylinder = heads * sectors
 | 
						|
	mov	ax, lowsec+0(si)
 | 
						|
	mov	dx, lowsec+2(si) ! dx:ax = sector within drive
 | 
						|
	cmp	dx, #[1024*255*63-255]>>16  ! Near 8G limit?
 | 
						|
	jae	bigdisk
 | 
						|
	div	bx		! ax = cylinder, dx = sector within cylinder
 | 
						|
	xchg	ax, dx		! ax = sector within cylinder, dx = cylinder
 | 
						|
	movb	ch, dl		! ch = low 8 bits of cylinder
 | 
						|
	divb	cl		! al = head, ah = sector (0-origin)
 | 
						|
	xorb	dl, dl		! About to shift bits 8-9 of cylinder into dl
 | 
						|
	shr	dx, #1
 | 
						|
	shr	dx, #1		! dl[6..7] = high cylinder
 | 
						|
	orb	dl, ah		! dl[0..5] = sector (0-origin)
 | 
						|
	movb	cl, dl		! cl[0..5] = sector, cl[6..7] = high cyl
 | 
						|
	incb	cl		! cl[0..5] = sector (1-origin)
 | 
						|
	pop	dx		! Restore drive code in dl
 | 
						|
	movb	dh, al		! dh = al = head
 | 
						|
	mov	bx, #LOADOFF	! es:bx = where sector is loaded
 | 
						|
	mov	ax, #0x0201	! ah = Code for read / al = one sector
 | 
						|
	int	0x13
 | 
						|
	jmp	rdeval		! Evaluate read result
 | 
						|
bigdisk:
 | 
						|
	mov	bx, dx		! bx:ax = dx:ax = sector to read
 | 
						|
	pop	dx		! Restore drive code in dl
 | 
						|
	push	si		! Save si
 | 
						|
	mov	si, #BUFFER+ext_rw ! si = extended read/write parameter packet
 | 
						|
	mov	8(si), ax	! Starting block number = bx:ax
 | 
						|
	mov	10(si), bx
 | 
						|
	movb	ah, #0x42	! Extended read
 | 
						|
	int	0x13
 | 
						|
	pop	si		! Restore si to point to partition entry
 | 
						|
	!jmp	rdeval
 | 
						|
rdeval:
 | 
						|
	jnc	rdok
 | 
						|
rderr:
 | 
						|
	call	print
 | 
						|
	.ascii	"\r\nRead error\r\n\0"
 | 
						|
	jmp	again
 | 
						|
rdok:
 | 
						|
	cmp	LOADOFF+MAGIC, #0xAA55
 | 
						|
	je	sigok		! Signature ok?
 | 
						|
nonboot:
 | 
						|
	call	print
 | 
						|
	.ascii	"\r\nNot bootable\r\n\0"
 | 
						|
	jmp	again
 | 
						|
sigok:
 | 
						|
	ret
 | 
						|
 | 
						|
! Get the partition table into my space.
 | 
						|
gettable:
 | 
						|
	mov	si, #LOADOFF+PART_TABLE
 | 
						|
	mov	di, #BUFFER+PART_TABLE
 | 
						|
	mov	cx, #4*PENTRYSIZE/2
 | 
						|
  rep	movs
 | 
						|
	ret
 | 
						|
 | 
						|
! Sort the partition table.
 | 
						|
sort:
 | 
						|
	mov	cx, #4			! Four times is enough to sort
 | 
						|
bubble:	mov	si, #BUFFER+PART_TABLE	! First table entry
 | 
						|
bubble1:lea	di, PENTRYSIZE(si)	! Next entry
 | 
						|
	cmpb	sysind(si), ch		! Partition type, nonzero when in use
 | 
						|
	jz	exchg			! Unused entries sort to the end
 | 
						|
inuse:	mov	bx, lowsec+0(di)
 | 
						|
	sub	bx, lowsec+0(si)	! Compute di->lowsec - si->lowsec
 | 
						|
	mov	bx, lowsec+2(di)
 | 
						|
	sbb	bx, lowsec+2(si)
 | 
						|
	jae	order			! In order if si->lowsec <= di->lowsec
 | 
						|
exchg:	movb	bl, (si)
 | 
						|
	xchgb	bl, PENTRYSIZE(si)	! Exchange entries byte by byte
 | 
						|
	movb	(si), bl
 | 
						|
	inc	si
 | 
						|
	cmp	si, di
 | 
						|
	jb	exchg
 | 
						|
order:	mov	si, di
 | 
						|
	cmp	si, #BUFFER+PART_TABLE+3*PENTRYSIZE
 | 
						|
	jb	bubble1
 | 
						|
	loop	bubble
 | 
						|
	ret
 | 
						|
 | 
						|
.data
 | 
						|
 | 
						|
! Extended read/write commands require a parameter packet.
 | 
						|
ext_rw:
 | 
						|
	.data1	0x10		! Length of extended r/w packet
 | 
						|
	.data1	0		! Reserved
 | 
						|
	.data2	1		! Blocks to transfer (just one)
 | 
						|
	.data2	LOADOFF		! Buffer address offset
 | 
						|
	.data2	0		! Buffer address segment
 | 
						|
	.data4	0		! Starting block number low 32 bits (tbfi)
 | 
						|
zero:	.data4	0		! Starting block number high 32 bits
 | 
						|
 | 
						|
	.align	2
 | 
						|
guide:
 | 
						|
! Guide characters and possibly a logical partition number patched here by
 | 
						|
! installboot, up to 6 bytes maximum.
 |