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
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
|
!---------------------------------------------------------------------------
!! This is a bootblock to load an execute a standalone program from an
!! MSDOS filesystem on a floppy disk.
!!
!! The file loaded is called 'BOOTFILE.SYS' and is loaded at address $7C00.
!---------------------------------------------------------------------------
! The filename can be changed at install time by following the label
! boot_name, because the file is loaded at address $7C00 it can be the
! image of a boot block (eg LILO). It's also checked for the magic number
! associated with a Linux-8086 standalone executable and this is used if
! it's found.
!
! There are a number of assumptions made by the code concerning the layout
! of the msdos files system:
!
! 1) All of the first 12 bit FAT must be on the first track.
! 2) The FAT must be 12 bit
! 3) The value of the hidden sectors field must be zero
!
! All these are true for mtools created floppies on normal PC drives.
!
! In addition this now has a compile time option for FAT16 partitions.
! TODO: Auto detect disk type
! FAT32
!
!---------------------------------------------------------------------------
ORGADDR=$0500
use16
! Some configuration values
LOADSEG= $7C0
export fatbits
fatbits=12 ! Set to 12 or 16 (16 for LS-120 disks)
export heads
heads=0 ! This can be 0,1 or 2. 0 is dynamic.
export harddisk
if fatbits=12
harddisk=0
else
harddisk=1 ! Allow for hard disks, but will only work with
endif ! disks formatted >= MSDOS 4.0
!---------------------------------------------------------------------------
! Absolute position macro, fails if code before it is too big.
macro locn
if *-start>?1
fail! *-start>?1
endif
.blkb ?1 + start-*
mend
org ORGADDR
start:
include sysboot.s
org dos_sysid
.ascii "DOSFS" ! System ID
!---------------------------------------------------------------------------
! Data into the temp area, 30 clear bytes
org floppy_temp
root_count: .blkw 1
!---------------------------------------------------------------------------
locn(codestart-start)
cld ! Assume _nothing_!
mov bx,#$7C00 ! Pointer to start of BB.
xor ax,ax ! Segs all to zero
mov ds,ax
mov es,ax
mov ss,ax
mov sp,bx ! SP Just below BB
mov cx,#$100 ! Move 256 words
mov si,bx ! From default BB
mov di,#ORGADDR ! To the correct address.
rep
movsw
jmpi cont,#0 ! Set CS:IP correct.
cont:
sti ! Let the interrupts back in.
! DONT Need to fix BPB for fd0 to correct sectors (Like linux bootblock does)
! as we only ever read one sector at a time.
! For each sector in root dir
! For each dir entry
! If entry name is == boot_name
! then load and run
! First dir = dos_fatlen*dos_nfat+dos_resv
mov ax,[dos_fatlen]
mov dl,[dos_nfat]
xor dh,dh
mul dx
add ax,[dos_resv]
mov di,ax
! DI is sector number of first root dir sector.
mov ax,[dos_nroot]
mov [root_count],ax
add ax,#15
mov cl,#4
shr ax,cl
add ax,di
mov bp,ax ! bp is first data sector.
nextsect:
call linsect
mov ax,#$0201
int $13
jc floppy_error
! ... foreach dir entry
mov si,bx
nextentry:
! TODO: Test attributes for !dir !label here ?
! test entry name
push si
push di
mov di,#boot_name
mov cx,#11
rep
cmpsb
pop di
pop si
jne bad_entry
mov ax,[si+26] ! Cluster number of start of file
test ax,ax ! Make sure we have a block.
jnz load_system
bad_entry:
add si,#32 ! skip to next entry
cmp si,#512
jnz nextentry
inc di ! Load next sector
sub [root_count],#16
jp nextsect
jmp no_system
!---------------------------------------------------------------------------
! Convert a cluster number in DI into a CHS in CX:DX
linclust:
mov ax,di
sub ax,#2
mov dl,[dos_clust]
xor dh,dh
mul dx
add ax,bp ! Add sector number of first data sector.
adc dx,#0
jmp linsect2
!
! This function converts a linear sector number in DI
! into a CHS representation in CX:DX
!
linsect:
mov ax,di
linsect1:
xor dx,dx
linsect2:
! Add partition offset in.
if fatbits =16
add ax,[dos_hidden]
adc dx,[dos_hidden+2]
endif
div [dos_spt]
inc dx
mov cl,dl ! Sector num
xor dx,dx ! Drive 0
if heads =2
shr ax,#1 ! Assume dos_heads == 2
adc dh,#0 ! Head num
endif
if heads =0
div [dos_heads]
xchg dh,dl
endif
mov ch,al ! Cylinder bits 0-7
if heads =0
sar ax,#1 ! Cylinder bits 8&9
sar ax,#1
and al,#$C0
or cl,al
endif
if harddisk
mov dl,[dos4_phy_drive]
endif
ret
!---------------------------------------------------------------------------
! Error processing.
no_system:
floppy_error:
mov si,#error_msg
no_boot: ! SI now has pointer to error message
lodsb
cmp al,#0
jz EOS
mov bx,#7
mov ah,#$E ! Can't use $13 cause that's AT+ only!
int $10
jmp no_boot
EOS:
xor ax,ax
int $16
int $19 ! This should be OK as we haven't touched anything.
jmpi $0,$FFFF ! Wam! Try or die!
!---------------------------------------------------------------------------
! This loads the boot program 1 sector at a time, funny thing is it actually
! loads at exactly the same speed as loading a track at a time, at least on
! my slow old 286/8Mhz. Oh well, we need the space so if you're worried just
! tell superformat to give you an interleave of 2 (-i 2).
!
load_system:
if fatbits =12
push ax ! Save cluster we're loading
! 1) Load FAT
! This assumes all of FAT1 is on the first track, this is normal
mov ax,[dos_fatlen]
mov ah,#2
mov bx,#fat_table
mov cx,[dos_resv] ! Fat starts past bootblock
inc cx
xor dx,dx ! Head zero
int $13
jc floppy_error
pop di ! Cluster to start load.
else
mov di,ax
endif
mov ax,#LOADSEG
mov es,ax
! load whole cluster
next_cluster:
mov si,[dos_clust] ! How big is a cluster
and si,#255
call linclust ! Find it's physical address
next:
mov ax,#$0201
xor bx,bx
int $13 ! Load 1 sector at a time
jc floppy_error
mov ax,es
add ax,#512/16
mov es,ax
cmp cl,[dos_spt] ! Does cluster straddle tracks ?
jnz sectok
mov cl,#0
if heads=2
inc dh
cmp dh,#2 ! Does cluster straddle cylinders ?
jnz sectok
xor dh,dh
endif
if heads=0
inc dh
cmp dh,[dos_heads] ! Nb low byte only.
jnz sectok
xor dh,dh
endif
inc ch
sectok:
inc cl
dec si
jnz next
call next_fat
jc next_cluster
jmp maincode
next_fat:
if fatbits =12
mov ax,di
shr ax,#1
pushf ! Save if odd number
add di,ax
mov di,fat_table[di]
popf
jnc noshift ! Odd in high nibbles.
mov cl,#4
shr di,cl
noshift:
and di,#$FFF
cmp di,#$FF0 ! FFF is EOF, clear carry flag.
! FF0+ are badblocks etc.
endif
if fatbits =16
mov ax,di
! load fat sector AH (if it's not already loaded)
xchg ah,al
xor ah,ah
add ax,[dos_resv]
cmp ax,[fatsect]
jz got_fsect
mov [fatsect],ax
call linsect1
push es
mov bx,#fat_table
xor ax,ax
mov es,ax
mov ax,#$0201
int $13
pop es
jnc got_fsect
br floppy_error
got_fsect:
! Load di with cluster number in di
and di,#$FF
shl di,#1
mov di,fat_table[di]
cmp di,#$FFF0
endif
ret
!---------------------------------------------------------------------------
! File is now loaded, execute it.
maincode:
if harddisk=0
mov bx,#7
mov ax,#$0E3E
int $10 ! Marker printed to say bootblock succeeded.
endif
xor dx,dx ! DX=0 => floppy drive
if harddisk
mov dl,[dos4_phy_drive]
endif
push dx ! CX=0 => partition offset = 0
mov si,[dos_spt] ! SI=Sectors per track
mov bx,#LOADSEG
mov ds,bx ! DS = loadaddress
inc bx
inc bx ! bx = initial CS
xor di,di ! Zero
mov ax,[di]
cmp ax,#0x0301 ! Right magic ?
jnz bad_magic ! Yuk ...
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.
add ax,bx
mov ss,ax
mov sp,[di+24] ! Chmem value
mov ds,ax
push bx ! jmpi 0,#LOADSEG+2
push di
! AX=ds, BX=cs, CX=X, DX=X, SI=X, DI=0, BP=X, ES=X, DS=*, SS=*, CS=*
retf
bad_magic:
pop cx
jmpi LOADSEG<<4,0 ! No magics, just go.
!---------------------------------------------------------------------------
! initilised data
fatsect:
.word 0
! if fatbits =16
error_msg:
.asciz "\r\nError during initial boot\r\nPress a key:"
! else
! error_msg:
! .asciz "\r\nBoot error:"
! endif
export boot_name
boot_name:
.ascii "BOOTFILESYS"
name_end:
! NNNNNNNNEEE
locn(510)
.word $AA55 ! This is a floppy so it should not need the magic _but_
! the debian MBR requires the magic even on floppies
fat_table: ! This is the location that the fat table is loaded.
! Note: The fat must be entirely on track zero if 12 bit.
!---------------------------------------------------------------------------
|