1 ! masterboot
2.0 - Master boot block code Author
: Kees J. Bot
3 ! This code may
be placed in the first sector
(the boot sector
) of
a floppy
,
4 ! hard disk
or hard disk primary partition. There it will perform the
5 ! following actions at boot time
:
7 ! - If the booted device is
a hard disk
and one of the partitions is active
8 ! then the active partition is booted.
10 ! - Otherwise the next floppy
or hard disk device is booted
, trying them one
13 ! To make things
a little clearer
, the boot path might
be:
14 ! /dev
/fd0
- Floppy disk containing data
, tries fd1 then d0
15 ! [/dev
/fd1
] - Drive empty
16 ! /dev
/c0d0
- Master boot block
, selects active partition
2
17 ! /dev
/c0d0p2
- Submaster
, selects active subpartition
0
18 ! /dev
/c0d0p2s0
- Minix bootblock
, reads Boot Monitor
/boot
19 ! Minix
- Started by
/boot from
a kernel image in
/minix
21 LOADOFF
= 0x7C00 ! 0x0000:LOADOFF is where this code is loaded
22 BUFFER
= 0x0600 ! First free memory
23 PART_TABLE
= 446 ! Location of partition table within this code
24 PENTRYSIZE
= 16 ! Size of one partition table entry
25 MAGIC
= 510 ! Location of the AA55 magic number
35 ! Find active
(sub)partition
, load its first sector
, run it.
42 mov ss
, ax
! ds
= es
= ss
= Vector segment
46 ! Copy this code to safety
, then jump to it.
47 mov si
, sp
! si
= start of this code
48 push si
! Also where we
'll return to eventually
49 mov di, #BUFFER ! Buffer area
50 mov cx, #512/2 ! One sector
53 jmpf BUFFER+migrate, 0 ! To safety
56 ! Find the active partition
59 jns nextdisk ! No bootable partitions on floppies
60 mov si, #BUFFER+PART_TABLE
61 find: cmpb sysind(si), #0 ! Partition type, nonzero when in use
63 testb bootind(si), #0x80 ! Active partition flag in bit 7
64 jz nextpart ! It's
not active
66 call load
! Load partition bootstrap
67 jc error1
! Not supposed to fail
69 ret
! Jump to the master bootstrap
72 cmp si
, #BUFFER+PART_TABLE+4*PENTRYSIZE
74 ! No active partition
, tell
'em
76 .ascii "No active partition\0"
79 ! There are no active partitions on this drive, try the next drive.
81 incb dl ! Increment dl for the next drive
83 js nexthd ! Hard disk if negative
84 int 0x11 ! Get equipment configuration
85 shl ax, #1 ! Highest floppy drive # in bits 6-7
86 shl ax, #1 ! Now in bits 0-1 of ah
87 andb ah, #0x03 ! Extract bits
88 cmpb dl, ah ! Must be dl <= ah for drive to exist
89 ja nextdisk ! Otherwise try disk 0 eventually
90 call load0 ! Read the next floppy bootstrap
91 jc nextdisk ! It failed, next disk please
92 ret ! Jump to the next master bootstrap
93 nexthd: call load0 ! Read the hard disk bootstrap
94 error1: jc error ! No disk?
98 ! Load sector 0 from the current device. It's either
a floppy bootstrap
or
99 ! a hard disk master bootstrap.
101 mov si
, #BUFFER+zero-lowsec ! si = where lowsec(si) is zero
104 ! Load sector lowsec
(si
) from the current device. The obvious head
, sector
,
105 ! and cylinder numbers are ignored in favour of the more trustworthy absolute
106 ! start of partition.
108 mov di
, #3 ! Three retries for floppy spinup
109 retry
: push dx
! Save drive code
111 push di
! Next call destroys es
and di
112 movb ah
, #0x08 ! Code for drive parameters
116 andb cl
, #0x3F ! cl = max sector number (1-origin)
117 incb dh
! dh
= 1 + max head number
(0-origin
)
118 movb al
, cl
! al
= cl
= sectors per track
119 mulb dh
! dh
= heads
, ax
= heads
* sectors
120 mov bx
, ax
! bx
= sectors per cylinder
= heads
* sectors
122 mov dx
, lowsec+
2(si
)! dx
:ax
= sector within drive
123 cmp dx
, #[1024*255*63-255]>>16 ! Near 8G limit?
125 div bx
! ax
= cylinder
, dx
= sector within cylinder
126 xchg ax
, dx
! ax
= sector within cylinder
, dx
= cylinder
127 movb ch
, dl
! ch
= low
8 bits of cylinder
128 divb cl
! al
= head
, ah
= sector
(0-origin
)
129 xorb dl
, dl
! About to shift bits
8-9 of cylinder into dl
131 shr dx
, #1 ! dl[6..7] = high cylinder
132 orb dl
, ah
! dl
[0..5] = sector (0-origin)
133 movb cl
, dl
! cl
[0..5] = sector, cl[6..7] = high cyl
134 incb cl
! cl
[0..5] = sector (1-origin)
135 pop dx
! Restore drive code in dl
136 movb dh
, al
! dh
= al
= head
137 mov bx
, #LOADOFF ! es:bx = where sector is loaded
138 mov ax
, #0x0201 ! Code for read, just one sector
139 int
0x13 ! Call the BIOS for
a read
140 jmp rdeval
! Evaluate read result
142 mov bx
, dx
! bx
:ax
= dx
:ax
= sector to read
143 pop dx
! Restore drive code in dl
145 mov si
, #BUFFER+ext_rw ! si = extended read/write parameter packet
146 mov
8(si
), ax
! Starting block number
= bx
:ax
148 movb ah
, #0x42 ! Extended read
150 pop si
! Restore si to point to partition entry
153 jnc rdok
! Read succeeded
154 cmpb ah
, #0x80 ! Disk timed out? (Floppy drive empty)
157 jl rdbad
! Retry count expired
160 jnc retry
! Try again
161 rdbad
: stc
! Set carry flag
163 rdok
: cmp LOADOFF+MAGIC
, #0xAA55
164 jne nosig
! Error if signature wrong
165 ret
! Return with carry still clear
167 .ascii "Not bootable\0"
170 ! A read error occurred
, complain
and hang
172 mov si
, #LOADOFF+errno+1
173 prnum
: movb al
, ah
! Error number in ah
174 andb al
, #0x0F ! Low 4 bits
177 addb al
, #7 ! 'A' - ':'
178 digit
: addb
(si
), al
! Modify
'0' in string
180 movb cl
, #4 ! Next 4 bits
182 jnz prnum
! Again if digit
> 0
190 .ascii ". Hit any key to reboot.\0"
191 xorb ah
, ah
! Wait for keypress
198 print
: pop si
! si
= String following
'call print'
199 prnext
: lodsb
! al
= *si+
+ is char to
be printed
200 testb al
, al
! Null marks end
202 movb ah
, #0x0E ! Print character in teletype mode
203 mov bx
, #0x0001 ! Page 0, foreground color
206 prdone
: jmp
(si
) ! Continue after the string
210 ! Extended read
/write commands require
a parameter packet.
212 .data1 0x10 ! Length of extended r/w packet
214 .data2 1 ! Blocks to transfer (just one)
215 .data2 LOADOFF ! Buffer address offset
216 .data2 0 ! Buffer address segment
217 .data4 0 ! Starting block number low 32 bits (tbfi)
218 zero
: .data4 0 ! Starting block number high 32 bits