minix/boot/bootblock.s
Ben Gras a131085a5b cd boot workaround for bioses that didn't want to boot >4 image sectors.
boot is a normal binary with a.out again. use 'cdbootblock,' a CDBOOT
variant of bootblock, both from bootblock.s, as the first boot image
that then loads boot, exactly like the bootblock loads boot when booting
from harddisk. the sector numbers (2048 byte iso sectors) are patched in
by writeisofs, like installboot does for bootblock. bootblock unchanged.
2010-04-26 22:07:21 +00:00

257 lines
8.4 KiB
ArmAsm

#
! Bootblock 1.5 - Minix boot block. Author: Kees J. Bot
! 21 Dec 1991
!
! When the PC is powered on, it will try to read the first sector of floppy
! disk 0 at address 0x7C00. If this fails due to the absence of flexible
! magnetic media, it will read the master boot record from the first sector
! of the hard disk. This sector not only contains executable code, but also
! the partition table of the hard disk. When executed, it will select the
! active partition and load the first sector of that at address 0x7C00.
! This file contains the code that is eventually read from either the floppy
! disk, or the hard disk partition. It is just smart enough to load /boot
! from the boot device into memory at address 0x10000 and execute that. The
! disk addresses for /boot are patched into this code by installboot as 24-bit
! sector numbers and 8-bit sector counts above enddata upwards. /boot is in
! turn smart enough to load the different parts of the Minix kernel into
! memory and execute them to finally get Minix started.
!
LOADOFF = 0x7C00 ! 0x0000:LOADOFF is where this code is loaded
BOOTSEG = 0x1000 ! Secondary boot code segment.
#ifdef CDBOOT
BOOTOFF = 0x0050 ! Offset into /boot above header
#else
BOOTOFF = 0x0030 ! Offset into /boot above header
#endif
BUFFER = 0x0600 ! First free memory
#ifndef CDBOOT /* just constants, but make no sense for CDs */
LOWSEC = 8 ! Offset of logical first sector in partition
! table
! Variables addressed using bp register
lowsec = 2 ! Offset of boot partition within drive
secpcyl = 6 ! Sectors per cylinder = heads * sectors
#endif
device = 0 ! The boot device
.text
! Start boot procedure.
boot:
xor ax, ax ! ax = 0x0000, the vector segment
mov ds, ax
cli ! Ignore interrupts while setting stack
mov ss, ax ! ss = ds = vector segment
mov sp, #LOADOFF ! Usual place for a bootstrap stack
sti
push ax
push ax ! Push a zero lowsec(bp)
push dx ! Boot device in dl will be device(bp)
mov bp, sp ! Using var(bp) is one byte cheaper then var.
push es
push si ! es:si = partition table entry if hard disk
mov di, #LOADOFF+sectors ! char *di = sectors;
#ifndef CDBOOT
testb dl, dl ! Winchester disks if dl >= 0x80
jge floppy
#endif
winchester:
#ifndef CDBOOT
! Get the offset of the first sector of the boot partition from the partition
! table. The table is found at es:si, the lowsec parameter at offset LOWSEC.
eseg
les ax, LOWSEC(si) ! es:ax = LOWSEC+2(si):LOWSEC(si)
mov lowsec+0(bp), ax ! Low 16 bits of partitions first sector
mov lowsec+2(bp), es ! High 16 bits of partitions first sector
! Get the drive parameters, the number of sectors is bluntly written into the
! floppy disk sectors/track array.
movb ah, #0x08 ! Code for drive parameters
int 0x13 ! dl still contains drive
andb cl, #0x3F ! cl = max sector number (1-origin)
movb (di), cl ! Number of sectors per track
incb dh ! dh = 1 + max head number (0-origin)
#endif
jmp loadboot
#ifndef CDBOOT
! Floppy:
! Execute three read tests to determine the drive type. Test for each floppy
! type by reading the last sector on the first track. If it fails, try a type
! that has less sectors. Therefore we start with 1.44M (18 sectors) then 1.2M
! (15 sectors) ending with 720K/360K (both 9 sectors).
next: inc di ! Next number of sectors per track
floppy: xorb ah, ah ! Reset drive
int 0x13
movb cl, (di) ! cl = number of last sector on track
cmpb cl, #9 ! No need to do the last 720K/360K test
je success
! Try to read the last sector on track 0
mov es, lowsec(bp) ! es = vector segment (lowsec = 0)
mov bx, #BUFFER ! es:bx buffer = 0x0000:0x0600
mov ax, #0x0201 ! Read sector, #sectors = 1
xorb ch, ch ! Track 0, last sector
xorb dh, dh ! Drive dl, head 0
int 0x13
jc next ! Error, try the next floppy type
success:movb dh, #2 ! Load number of heads for multiply
#endif
loadboot:
! Load /boot from the boot device
#ifndef CDBOOT
movb al, (di) ! al = (di) = sectors per track
mulb dh ! dh = heads, ax = heads * sectors
mov secpcyl(bp), ax ! Sectors per cylinder = heads * sectors
#endif
mov ax, #BOOTSEG ! Segment to load /boot into
mov es, ax
xor bx, bx ! Load first sector at es:bx = BOOTSEG:0x0000
mov si, #LOADOFF+addresses ! Start of the boot code addresses
load:
mov ax, 1(si) ! Get next sector number: low 16 bits
movb dl, 3(si) ! Bits 16-23 for your up to 8GB partition
xorb dh, dh ! dx:ax = sector within partition
#ifndef CDBOOT
add ax, lowsec+0(bp)
adc dx, lowsec+2(bp)! dx:ax = sector within drive
cmp dx, #[1024*255*63-255]>>16 ! Near 8G limit?
jae bigdisk
div secpcyl(bp) ! 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 (di) ! 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)
movb dh, al ! dh = al = head
movb dl, device(bp) ! dl = device to read
movb al, (di) ! Sectors per track - Sector number (0-origin)
subb al, ah ! = Sectors left on this track
cmpb al, (si) ! Compare with # sectors to read
jbe read ! Cant read past the end of a cylinder?
movb al, (si) ! (si) < sectors left on this track
read: push ax ! Save al = sectors to read
movb ah, #0x02 ! Code for disk read (all registers in use now!)
int 0x13 ! Call the BIOS for a read
pop cx ! Restore al in cl
jmp rdeval
#endif
bigdisk:
movb cl, (si) ! Number of sectors to read
push si ! Save si
mov si, #LOADOFF+ext_rw ! si = extended read/write parameter packet
movb 2(si), cl ! Fill in # blocks to transfer
mov 4(si), bx ! Buffer address
mov 8(si), ax ! Starting block number = dx:ax
mov 10(si), dx
movb dl, device(bp) ! dl = device to read
movb ah, #0x42 ! Extended read
int 0x13
pop si ! Restore si to point to the addresses array
!jmp rdeval
rdeval:
jc error ! Jump on disk read error
movb al, cl ! Restore al = sectors read
addb bh, al ! bx += 2 * al * 256 (add bytes read)
addb bh, al ! es:bx = where next sector must be read
#ifdef CDBOOT
addb bh, al ! For CDs, a sector is 2048 bytes, so
addb bh, al ! do this 6 more times to get byte count.
addb bh, al
addb bh, al
addb bh, al
addb bh, al
#endif
add 1(si), ax ! Update address by sectors read
adcb 3(si), ah ! Don't forget bits 16-23 (add ah = 0)
subb (si), al ! Decrement sector count by sectors read
jnz load ! Not all sectors have been read
add si, #4 ! Next (address, count) pair
cmpb ah, (si) ! Done when no sectors to read
jnz load ! Read next chunk of /boot
done:
! Call /boot, assuming a long a.out header (48 bytes). The a.out header is
! usually short (32 bytes), but to be sure /boot has two entry points:
! One at offset 0 for the long, and one at offset 16 for the short header.
! Parameters passed in registers are:
!
! dl = Boot-device.
! es:si = Partition table entry if hard disk.
!
pop si ! Restore es:si = partition table entry
pop es ! dl is still loaded
jmpf BOOTOFF, BOOTSEG ! jmp to sec. boot (skipping header).
! Read error: print message, hang forever
error:
mov si, #LOADOFF+errno+1
prnum: movb al, ah ! Error number in ah
andb al, #0x0F ! Low 4 bits
cmpb al, #10 ! A-F?
jb digit ! 0-9!
addb al, #7 ! 'A' - ':'
digit: addb (si), al ! Modify '0' in string
dec si
movb cl, #4 ! Next 4 bits
shrb ah, cl
jnz prnum ! Again if digit > 0
mov si, #LOADOFF+rderr ! String to print
print: lodsb ! al = *si++ is char to be printed
testb al, al ! Null byte marks end
hang: jz hang ! Hang forever waiting for CTRL-ALT-DEL
movb ah, #0x0E ! Print character in teletype mode
mov bx, #0x0001 ! Page 0, foreground color
int 0x10 ! Call BIOS VIDEO_IO
jmp print
.data
rderr: .ascii "Read error "
errno: .ascii "00 \0"
errend:
! Floppy disk sectors per track for the 1.44M, 1.2M and 360K/720K types:
sectors:
.data1 18, 15, 9
! Extended read/write commands require a parameter packet.
ext_rw:
.data1 0x10 ! Length of extended r/w packet
.data1 0 ! Reserved
.data2 0 ! Blocks to transfer (to be filled in)
.data2 0 ! Buffer address offset (tbfi)
.data2 BOOTSEG ! Buffer address segment
.data4 0 ! Starting block number low 32 bits (tbfi)
.data4 0 ! Starting block number high 32 bits
.align 2
addresses:
! The space below this is for disk addresses for a 38K /boot program (worst
! case, i.e. file is completely fragmented). It should be enough.