a131085a5b
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.
256 lines
8.4 KiB
ArmAsm
256 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.
|