1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
|
! This binary is for loading a dev86 a.out file from a floppy without
! a filesystem; to make a bootable disk just do:
!
! cat boot_fpy.bin monitor.out > /dev/fd0
!
ORGADDR=0x0600
EXEADDR=0x0800 ! This must be up to 0x7E0 or 0x0800
LOADSEG=0x0080 ! Must be 512b aligned for DMA
! Padding so you can join with 'cat'.
.org EXEADDR-1
.byte 0
! This marker is needed by many boot managers (and bochs) but the BIOS does
! NOT require it on a floppy.
if EXEADDR=0x0800
.org ORGADDR+0x1FE
.word 0xAA55
endif
.org ORGADDR
entry start
public start
start:
xor ax,ax
mov si,#$7C00
mov di,#ORGADDR
mov ss,ax
mov sp,di ! Or si or ax
push ax
pop ds
push ax
pop es
mov cx,#256
cld
rep
movsw
jmpi go,#0
go:
! Grrr, have to load sector 1 in by hand.
if EXEADDR=0x0800
Loopi:
mov ax,#$0201 ! Read 1 sector
mov bx,#EXEADDR ! Into EXEADDR
mov cx,#$0002 ! From sector 2
xor dx,dx ! Of the floppy drive head zero
int $13
jc Loopi
endif
mov si,#Boot_message
call puts
mov ax,[a_text] ! How many sectors to load
mov cl,#4
shr ax,cl
mov bx,ax
mov ax,[a_data]
mov cl,#4
shr ax,cl
add ax,bx
add ax,#$1F
mov cl,#5
shr ax,cl ! ax = sectors to read
! This routine starts by loading one sector at a time, with most
! modern PCs the processor is fast enough to keep up with single
! sector reads, in reality an 8Mhz 286 can keep up!
! But occasionally some older machines have really poor BIOSes
! (Some modern ones too) so once we know how many sectors to read
! we switch to reading a track at a time. But we only try it once
! for each track. Normally, as long as the load address is sector
! aligned, this will work every time but with some BIOSes we can't
! read a track without messing with the BPB so if the track read
! fails it's one try we fall back to sector reads.
!
! Overall this usually gives good performance, and with a BIOS that
! isn't completely broken and correctly formatted floppies will run
! at about 2.5 rotations per cylinder (1.25 per track). If you find
! your BIOS is one of the bad ones you'll have to format your disks
! to a 2:1 interleave.
!
! BTW: It's very easy to make superformat incorrectly calculate the
! inter-sector gaps so it ends up squeezing the sectors to the start
! of the track. This means that only a full track read is fast enough.
! I suggest you use fdformat as it always uses 'safe' parameters for
! a 1440k floppy.
! AX = count of sectors
mov cx,#2 ! CX = First sector
mov bx,#LOADSEG ! ES:BX = Where to load
mov es,bx
xor bx,bx ! Initial offset
xor dx,dx ! DX = Drive 0
! ax=cnt, dl=drv, ch=*, dh=*, cl=sec, es:bx=buffer.
read_data:
mov si,ax ! Save big count.
xor ch,ch
xor dh,dh
mov maxsect,cl ! Save first sector.
load_loop:
mov di,#5 ! Error retry.
sect_retry:
mov ax,#$0201
! ah=2, al=1, dl=drv, ch=cyl, dh=head, cl=sec, es:bx=buffer.
int $13
jnc next_sect
dec di ! Retry counter
jz sect_error
cmp cl,maxsect ! If this is first sector or previously ok sector
jle sect_retry ! number then retry.
mov maxsect,cl
j inc_trk
next_sect:
mov ax,es ! Inc load address.
add ax,#32
mov es,ax
dec si ! Had enough ?
jz all_loaded
inc_sect:
inc cl
cmp cl,maxsect
jnz load_loop
inc_trk: ! Reached end of track, seek to next.
mov cl,#1
xor dh,cl
jnz load_track
inc ch
load_track:
cmp si,maxsect ! Is the whole track needed ?
jb load_loop ! no, goto load_loop for 1 by 1
! Try to load the track _once_ only, if it fails go 1 by 1 again.
mov ax,maxsect
dec ax
mov ah,#$02
! ah=2, al=*, dl=drv, ch=cyl, dh=head, cl=sec, es:bx=buffer.
int $13
jc load_loop
mov ax,maxsect ! Ok that worked, update the pointers
dec ax
mov cl,#5
shl ax,cl
mov di,es
add ax,di
mov es,ax
inc si
sub si,maxsect
jnz inc_trk
all_loaded:
! Now it's loaded turn off the floppy motor.
mov dx,#0x3f2
xor al, al
outb
! And start up the program.
xor dx,dx ! DX=0 => floppy drive
push dx ! CX=0 => partition offset = 0
mov si,dx ! Sect/track = 0
mov bx,#EXEADDR>>4
mov ds,bx ! DS = loadaddress
xor di,di ! Zero
mov ax,[di+2]
and ax,#$20 ! Is it split I/D ?
jz impure ! No ...
mov cl,#4
mov ax,[di+8]
shr ax,cl
impure:
pop cx ! Partition offset.
inc bx
inc bx ! bx = initial CS
add ax,bx
mov ss,ax
mov sp,[di+24] ! Chmem value
mov ds,ax
! AX=ds, BX=cs, CX=X, DX=X, SI=X, DI=0, BP=X, ES=X, DS=*, SS=*, CS=*
bad_magic:
push bx ! jmpi 0,#LOADSEG+2
push di
retf
sect_error:
! Disk error, wait then reboot.
mov si,#reboot_msg
call puts
xor ax,ax ! Wait for the user.
int $16
jmpi $0,$FFFF
puts:
lodsb
cmp al,#0
jz EOS
push bx
mov bx,#7
mov ah,#$E ! Can't use $13 cause that's AT+ only!
int $10
pop bx
jmp puts
EOS:
ret
maxsect:
.word 0
reboot_msg:
.asciz "Disk error, press a key to reboot:"
Boot_message:
.asciz "Boot sector loaded.\r\n"
! Check for overlap
end_of_code:
if end_of_code>hitme
fail! Overlap at end_of_code
endif
.org EXEADDR
hitme:
magic: .space 2 ! A.out header
btype: .space 2
headerlen: .space 4
a_text: .space 4
a_data: .space 4
a_bss: .space 4
a_entry: .space 4
a_total: .space 4
a_syms: .space 4
|