1!--------------------------------------------------------------------------- 2!! This is a bootblock to load an execute a standalone program from an 3!! MSDOS filesystem on a floppy disk. 4!! 5!! The file loaded is called 'BOOTFILE.SYS' and is loaded at address $7C00. 6!--------------------------------------------------------------------------- 7! The filename can be changed at install time by following the label 8! boot_name, because the file is loaded at address $7C00 it can be the 9! image of a boot block (eg LILO). It's also checked for the magic number 10! associated with a Linux-8086 standalone executable and this is used if 11! it's found. 12! 13! There are a number of assumptions made by the code concerning the layout 14! of the msdos files system: 15! 16! 1) All of the first 12 bit FAT must be on the first track. 17! 2) The FAT must be 12 bit or 16 bit. (known at install time) 18! 3) The value of the hidden sectors field must be zero 19! 20! All these are true for mtools created floppies on normal PC drives. 21! 22! In addition this now has a compile time option for FAT16 partitions. 23! TODO: Auto detect disk type 24! FAT32 25! 26!--------------------------------------------------------------------------- 27ORGADDR=$0500 28 29use16 30 31! Some configuration values 32LOADSEG= $7C0 33export fatbits 34fatbits=12 ! Set to 12 or 16 (16 for LS-120 disks) 35 36export heads 37heads=0 ! This can be 0,1 or 2. 0 is dynamic. 38 39export harddisk 40 if fatbits=12 41harddisk=0 42 else 43harddisk=1 ! Allow for hard disks, but will only work with 44 endif ! disks formatted >= MSDOS 4.0 45 46!--------------------------------------------------------------------------- 47! Absolute position macro, fails if code before it is too big. 48macro locn 49 if *-start>?1 50 fail! *-start>?1 51 endif 52 .blkb ?1 + start-* 53mend 54 55org ORGADDR 56start: 57include sysboot16.s 58 59org dos_sysid 60 .ascii "DOSFS" ! System ID 61 62!--------------------------------------------------------------------------- 63! Data into the temp area, 30 clear bytes 64org floppy_temp 65root_count: .blkw 1 66 67!--------------------------------------------------------------------------- 68 locn(codestart-start) 69 70 cld ! Assume _nothing_! 71 mov bx,#$7C00 ! Pointer to start of BB. 72 xor ax,ax ! Segs all to zero 73 mov ds,ax 74 mov es,ax 75 mov ss,ax 76 mov sp,bx ! SP Just below BB 77 mov cx,#$100 ! Move 256 words 78 mov si,bx ! From default BB 79 mov di,#ORGADDR ! To the correct address. 80 rep 81 movsw 82 jmpi cont,#0 ! Set CS:IP correct. 83cont: 84 sti ! Let the interrupts back in. 85 86! DONT Need to fix BPB for fd0 to correct sectors (Like linux bootblock does) 87! as we only ever read one sector at a time. 88 89! For each sector in root dir 90! For each dir entry 91! If entry name is == boot_name 92! then load and run 93 94 ! First dir = dos_fatlen*dos_nfat+dos_resv 95 mov ax,[dos_fatlen] 96 mov dl,[dos_nfat] 97 xor dh,dh 98 mul dx 99 add ax,[dos_resv] 100 mov di,ax 101 ! DI is sector number of first root dir sector. 102 103 mov ax,[dos_nroot] 104 mov [root_count],ax 105 add ax,#15 106 mov cl,#4 107 shr ax,cl 108 add ax,di 109 mov bp,ax ! bp is first data sector. 110 111nextsect: 112 call linsect 113 mov ax,#$0201 114 int $13 115 jc floppy_error 116 117! ... foreach dir entry 118 mov si,bx 119nextentry: 120 121 ! TODO: Test attributes for !dir !label here ? 122 123! test entry name 124 push si 125 push di 126 mov di,#boot_name 127 mov cx,#11 128 rep 129 cmpsb 130 pop di 131 pop si 132 jne bad_entry 133 134 mov ax,[si+26] ! Cluster number of start of file 135 test ax,ax ! Make sure we have a block. 136 jnz load_system 137 138bad_entry: 139 add si,#32 ! skip to next entry 140 cmp si,#512 141 jnz nextentry 142 143 inc di ! Load next sector 144 sub [root_count],#16 145 jp nextsect 146 jmp no_system 147 148!--------------------------------------------------------------------------- 149! Convert a cluster number in DI into a CHS in CX:DX 150linclust: 151 mov ax,di 152 sub ax,#2 153 mov dl,[dos_clust] 154 xor dh,dh 155 mul dx 156 add ax,bp ! Add sector number of first data sector. 157 adc dx,#0 158 jmp linsect2 159 160! 161! This function converts a linear sector number in DI 162! into a CHS representation in CX:DX 163! 164linsect: 165 mov ax,di 166linsect1: 167 xor dx,dx 168linsect2: 169 ! Add partition offset in. 170 if fatbits =16 171 add ax,[dos_hidden] 172 adc dx,[dos_hidden+2] 173 endif 174 175 div [dos_spt] 176 inc dx 177 mov cl,dl ! Sector num 178 xor dx,dx ! Drive 0 179 if heads =2 180 shr ax,#1 ! Assume dos_heads == 2 181 adc dh,#0 ! Head num 182 endif 183 if heads =0 184 div [dos_heads] 185 xchg dh,dl 186 endif 187 mov ch,al ! Cylinder bits 0-7 188 if heads =0 189 sar ax,#1 ! Cylinder bits 8&9 190 sar ax,#1 191 and al,#$C0 192 or cl,al 193 endif 194 if harddisk 195 mov dl,[dos4_phy_drive] 196 endif 197 ret 198 199!--------------------------------------------------------------------------- 200! Error processing. 201no_system: 202floppy_error: 203 204 mov si,#error_msg 205no_boot: ! SI now has pointer to error message 206 lodsb 207 cmp al,#0 208 jz EOS 209 mov bx,#7 210 mov ah,#$E ! Can't use $13 cause that's AT+ only! 211 int $10 212 jmp no_boot 213EOS: 214 xor ax,ax 215 int $16 216 jmpi $0,$FFFF ! Reboot. 217 218!--------------------------------------------------------------------------- 219! This loads the boot program 1 sector at a time, funny thing is it actually 220! loads at exactly the same speed as loading a track at a time, at least on 221! my slow old 286/8Mhz. Oh well, we need the space so if you're worried just 222! tell superformat to give you an interleave of 2 (-i 2). 223! 224 225load_system: 226 if fatbits =12 227 push ax ! Save cluster we're loading 228 229! 1) Load FAT 230 ! This assumes all of FAT1 is on the first track, this is normal 231 mov ax,[dos_fatlen] 232 mov ah,#2 233 mov bx,#fat_table 234 mov cx,[dos_resv] ! Fat starts past bootblock 235 inc cx 236 xor dx,dx ! Head zero 237 int $13 238 jc floppy_error 239 pop di ! Cluster to start load. 240 else 241 mov di,ax 242 endif 243 244 mov ax,#LOADSEG 245 mov es,ax 246 247 ! load whole cluster 248next_cluster: 249 250 mov si,[dos_clust] ! How big is a cluster 251 and si,#255 252 call linclust ! Find it's physical address 253 254next: 255 mov ax,#$0201 256 xor bx,bx 257 int $13 ! Load 1 sector at a time 258 jc floppy_error 259 260 mov ax,es 261 add ax,#512/16 262 mov es,ax 263 264 cmp cl,[dos_spt] ! Does cluster straddle tracks ? 265 jnz sectok 266 mov cl,#0 267 if heads=2 268 inc dh 269 cmp dh,#2 ! Does cluster straddle cylinders ? 270 jnz sectok 271 xor dh,dh 272 endif 273 if heads=0 274 inc dh 275 cmp dh,[dos_heads] ! Nb low byte only. 276 jnz sectok 277 xor dh,dh 278 endif 279 inc ch 280sectok: 281 inc cl 282 dec si 283 jnz next 284 285 call next_fat 286 jc next_cluster 287 jmp maincode 288 289next_fat: 290 if fatbits =12 291 mov ax,di 292 shr ax,#1 293 pushf ! Save if odd number 294 add di,ax 295 mov di,fat_table[di] 296 popf 297 jnc noshift ! Odd in high nibbles. 298 mov cl,#4 299 shr di,cl 300noshift: 301 and di,#$FFF 302 cmp di,#$FF0 ! FFF is EOF, clear carry flag. 303 ! FF0+ are badblocks etc. 304 endif 305 306 if fatbits =16 307 mov ax,di 308 ! load fat sector AH (if it's not already loaded) 309 310 xchg ah,al 311 xor ah,ah 312 add ax,[dos_resv] 313 314 cmp ax,[fatsect] 315 jz got_fsect 316 mov [fatsect],ax 317 318 call linsect1 319 320 push es 321 mov bx,#fat_table 322 xor ax,ax 323 mov es,ax 324 mov ax,#$0201 325 int $13 326 pop es 327 jnc got_fsect 328 br floppy_error 329 330got_fsect: 331 ! Load di with cluster number in di 332 and di,#$FF 333 shl di,#1 334 mov di,fat_table[di] 335 cmp di,#$FFF0 336 endif 337 338 ret 339 340!--------------------------------------------------------------------------- 341! File is now loaded, execute it. 342maincode: 343 mov bx,#7 344 mov ax,#$0E + ': 345 int $10 ! Marker printed to say bootblock succeeded. 346 347 xor dx,dx ! DX=0 => floppy drive 348 if harddisk 349 mov dl,[dos4_phy_drive] 350 endif 351 push dx ! CX=0 => partition offset = 0 352 mov si,[dos_spt] ! SI=Sectors per track 353 354 mov bx,#LOADSEG 355 mov ds,bx ! DS = loadaddress 356 xor di,di ! Zero 357 mov ax,[di] 358 cmp ax,#0x0301 ! Right magic ? 359 jnz bad_magic ! Yuk ... 360 mov ax,[di+2] 361 and ax,#$20 ! Is it split I/D ? 362 jz impure ! No ... 363 mov cl,#4 364 mov ax,[di+8] 365 shr ax,cl 366impure: 367 pop cx ! Partition offset. 368 inc bx 369 inc bx ! bx = initial CS 370 add ax,bx 371 mov ss,ax 372 mov sp,[di+24] ! Chmem value 373 mov ds,ax 374 375 ! AX=ds, BX=cs, CX=X, DX=X, SI=X, DI=0, BP=X, ES=X, DS=*, SS=*, CS=* 376 377bad_magic: 378 push bx ! jmpi 0,#LOADSEG+2 379 push di 380 retf 381 382!--------------------------------------------------------------------------- 383! initilised data 384 385fatsect: 386 .word 0 387 388error_msg: 389 .asciz "\r\nError during initial boot\r\nPress a key:" 390 391export boot_name 392boot_name: 393 .ascii "BOOTFILESYS" 394name_end: 395! NNNNNNNNEEE 396 397locn(510) 398 .word $AA55 ! This is a floppy so it should not need the magic _but_ 399 ! the debian MBR requires the magic even on floppies 400 401fat_table: ! This is the location that the fat table is loaded. 402 ! Note: The fat must be entirely on track zero if 12 bit. 403!--------------------------------------------------------------------------- 404