summaryrefslogtreecommitdiff
path: root/bootblocks/msdos.s
blob: ddaa870dfff1c03aa09acdbf91086c3e6940d85e (plain)
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
!---------------------------------------------------------------------------
!! 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 or 16 bit. (known at install time)
! 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 sysboot16.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
  jmpi	$0,$FFFF	! Reboot.

!---------------------------------------------------------------------------
! 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:
  mov	bx,#7
  mov	ax,#$0E + ':
  int	$10		! Marker printed to say bootblock succeeded.

  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
  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.
  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

!---------------------------------------------------------------------------
! initilised data

fatsect:
  .word	0

error_msg:
  .asciz "\r\nError during initial boot\r\nPress a key:"

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.
!---------------------------------------------------------------------------