262 lines
7.4 KiB
ArmAsm
262 lines
7.4 KiB
ArmAsm
|
! 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.
|