Add externs to avoid multiple definitions, and then add missing definitions.
[rrq/maintain_lilo.git] / diagnose / sector.S
1 ; sector.S -- boot program named:  HIPBOOT.SYS
2 ;             from any MSDOS floppy diskette
3 ;
4 ; Copyright 2001-2005 John Coffman.
5 ; All rights reserved.
6 ;
7 ; Licensed under the terms contained in the file 'COPYING' in the LILO
8 ; source directory.
9 ;
10 #define DEBUG 0         /* enables loading .EXE for codeview debugging */
11 #define OPTION 1        /* enables fast directory search exit */
12 #define LARGE 0         /* enables loading code >32K */
13 #define TESTFAT 0       /* enables testing for FAT12/FAT16 */
14 #define SYSSEG 0x1000   /* load at a fixed address SYSSEG:0000 */
15
16 ;;directory_entry         
17                         block   0
18
19 dir_filename:           .blkb   8
20 dir_filename_ext:       .blkb   3
21 dir_attribute:          .blkb   1
22 dir_Reserved:           .blkb   10
23 dir_time_updated:       .blkw   1
24 dir_date_updated:       .blkw   1
25 dir_cluster:            .blkw   1
26 dir_file_size:          .blkw   2
27
28 dir_entry_size:
29                         endb
30
31 base    equ     0x7C00
32 buffer  equ     0x0500          ;scratch disk buffer
33
34
35
36
37
38 ;contAddr  equ   SS:[bp-4]      ;dword     DO NOT MOVE
39 ;dataBase  equ   SS:[bp-8]       ;dword    DO NOT MOVE
40 ;FATshift  equ   SS:[bp-9]      ; byte 
41 ;diskNumber  equ SS:[bp-10]      ; byte    DO NOT MOVE
42 ;dirBase equ     SS:[bp-14]       ;dword
43 ;nDirSec equ     SS:[bp-16]      ;word
44 ;FATsector equ   SS:[bp-18]      ;word
45 ;FATnibbles  equ SS:[bp-20]      ;word
46
47
48 stacksize       equ     20
49
50
51                         block   -stacksize
52
53 FATnibbles:     .blkw   1
54 FATsector:      .blkw   1
55 nDirSec:        .blkw   1
56 dirBase:        .blkw   2
57 diskNumber:     .blkb   1       ; DO NOT MOVE
58 FATshift:       .blkb   1
59 dataBase:       .blkw   2       ; DO NOT MOVE
60 contAddr:       .blkw   2       ; DO NOT MOVE
61
62 stack:  /* this had better be zero */
63
64                 .blkb   3       ; jump instruction
65                 .blkb   8       ; system ID string
66 secSiz:         .blkw   1       ; bytes_per_sector
67 secPerCl:       .blkb   1       ; sectors_per_cluster
68 FATbase:        .blkw   1       ; reserved_sectors
69 nFATs:          .blkb   1       ; FAT_copies
70 nDirEnt:        .blkw   1       ; directory_entries
71 totSec:         .blkw   1       ; total_sectors
72 media:          .blkb   1       ; media_descriptor
73 secPerFAT:      .blkw   1       ; sectors_per_FAT
74 nSEC:           .blkw   1       ; sectors_per_track
75 nSides:         .blkw   1       ; heads_per_cylinder
76 hidSec:         .blkw   2       ; hidden_sectors
77                 .blkb   22
78 fs_id:          .blkb   8       ; filesystem_id
79
80                         endb
81
82 .globl _main
83                         org     0
84 ; jump instruction
85 _main:                  jmp     beginning
86                         nop
87
88 system_id_string:       .ascii  "DISKBOOT"      ; 8 chars
89
90 msdos_boot_data:
91
92 bytes_per_sector:       dw      512
93 sectors_per_cluster:    db      1
94 reserved_sectors:       dw      1
95 FAT_copies:             db      2
96 directory_entries:      dw      224       ; 112 & 224 are typical
97 total_sectors:          dw      2880
98 media_descriptor:       db      0xf0      ; 0f9H, 0f0h, 0fAh, etc.
99 sectors_per_FAT:        dw      9
100 sectors_per_track:      dw      18
101 heads_per_cylinder:     dw      2
102 hidden_sectors:         dd      0       ; always zero for floppies
103 total_sectors_2:        dd      0       ; actual value if 'total_sectors' is zero
104 BPB_rsvd:               dw      0       ; reserved
105 vol_id_marker:          db      0x29    ; marker? for volume ID
106 serial_number:          dd      0       ; volume unique ID number
107
108 volume_label:           .ascii  "NO NAME    "   ; 11 chars
109 filesystem_id:          .ascii  "FAT12   "      ;  8 chars
110
111
112
113 beginning:
114         xor     ax,ax
115         mov     bp,#base         ;origin at 7C00
116 #if DEBUG
117         xor     dl,dl
118         mov     ax,ss
119 #endif
120         cli
121         mov     ss,ax
122         lea     sp,(bp-stacksize)
123         sti
124
125         cld
126         mov     es,ax           ;both at zero
127         mov     ds,ax
128 #if DEBUG
129         xor     ax,ax
130 #endif
131         mov     diskNumber(bp),dl   ;save disk number
132         int     0x13             ;reset the disk system
133         jc      error
134 noError:
135         mov     ax,#0x0403        ;shift=4, nibbles=3 -- FAT12
136 fat12   equ     *-2
137 #if TESTFAT
138         cmp     byte ptr fs_id+4(bp),#$36       ; '6'
139         jne     isFAT12
140         mov     ax,#0004        ;shift=0, nibbles=4 -- FAT16
141 isFAT12:
142 #endif
143         mov     FATshift(bp),ah     ;set shift count
144         cbw
145         mov     FATnibbles(bp),ax   ;set number of nibbles per FAT index entry
146
147         mov     al,nFATs(bp)        ;number of FATs
148 ;       cbw
149         mul     word ptr secPerFAT(bp)       ;* sectors per FAT
150         add     ax,FATbase(bp)      ;+ FAT base
151         adc     dx,#0            ; SI = 0
152         mov     dirBase(bp),ax
153         mov     dirBase+2(bp),dx    ;save directory base
154
155         mov     dataBase(bp),ax
156         mov     dataBase+2(bp),dx   ;still forming Data base 
157
158         mov     ax,#dir_entry_size
159         mul     word ptr nDirEnt(bp)
160         mov     bx,secSiz(bp)
161         add     ax,bx           
162         dec     ax
163         div     bx              ;get base of data
164 #if DEBUG
165         add     bx,bx
166 #endif
167 #if SYSSEG
168         mov     contAddr(bp),ss            ; SS = 0
169         mov     word ptr contAddr+2(bp),#SYSSEG      ; begin at SYSSEG:0000
170 #else
171         add     bx,#base
172         mov     contAddr(bp),bx     ;save continuation address
173         mov     contAddr+2(bp),es
174 #endif
175         mov     nDirSec(bp),ax      ;save no. of Directory sectors
176         add     dataBase(bp),ax
177         adc     word ptr dataBase+2(bp),#0           ; SI = 0
178
179 ; scan the directory for the required bootstrap file
180
181         mov     ax,dirBase(bp)      ; starting disk block in DX:AX
182         mov     dx,dirBase+2(bp)
183 dirscan:
184         mov     bx,#buffer        ; ES:BX points to buffer
185         call    ReadSector
186         mov     di,bx
187         mov     bx,secSiz(bp)
188 dirscan1:
189         
190         call    S21
191 tofind: .ascii  "HIPBOOT SYS"
192
193 error:
194         call    write
195         db      13,10,10
196         .ascii  'Non-SYSTEM disk or disk error'
197         db      13,10
198         .ascii  'Press any key to re-boot ...'
199         db      0
200 done:
201         xor     ax,ax
202         int     0x16             ;wait for keypress
203         int     0x19             ;re-boot
204
205
206 S21:    pop     si
207         push    di
208         mov     cx,#11           ;name length
209         rep     
210          seg cs
211           cmpsb    ;byte ptr CS:[si],ES:[di]
212         pop     di
213         je      hipboot
214 #if OPTION
215         cmp     byte ptr (di),#0
216         je      endOfDirectory
217 #endif
218         lea     di,dir_entry_size(di)
219         sub     bx,#dir_entry_size
220         jg      dirscan1
221
222         inc     ax
223         dec     word ptr nDirSec(bp)
224         jnz     dirscan
225 endOfDirectory:
226 error2:
227         jmp     error
228
229 ReadSector:
230         push    dx              ;save registers
231         push    cx
232         push    ax
233         
234         add     ax,hidSec(bp)       ;+ Hidden Sectors
235         adc     dx,hidSec+2(bp)     ;
236         xchg    ax,dx
237         push    dx              ;AX=dividend-hi, DX=dividend-low
238         cwd
239         div     word ptr nSEC(bp)            ;DX=remainder, AX=quo-hi
240         
241         pop     cx
242         xchg    ax,cx           ;CX=quo-hi, DX:AX=dividend-low
243         div     word ptr nSEC(bp)            ;remainder is sector number, zero based
244         inc     dx              ;DX=sector#, CX:AX=quotient
245         push    dx              ;save sector number
246
247         mov     dx,cx           ;DX:AX=quotient
248         div     word ptr nSides(bp)          ;DX = side, AX = Cyl No.
249         mov     cl,#6
250         shl     ah,cl           ;AH is hi-bits of cyl no.
251         pop     cx              ;restore sector number
252         or      cl,ah
253         mov     ch,al
254         mov     dh,dl
255         mov     dl,diskNumber(bp)
256 retry:
257         mov     ax,#0x0201        ;BIOS read 1 sector
258         int     0x13
259 #if DEBUG
260         jnc     readcont
261         xor     ax,ax
262         int     0x13
263         jmp     retry
264 readcont:
265 #endif
266 error3:
267         jc      error2
268         pop     ax
269         pop     cx
270         pop     dx
271         ret
272
273 hipboot:
274         mov     cx,dir_cluster(di)
275         mov     word ptr FATsector(bp),#-1    ;no FAT sector present
276         les     bx,contAddr(bp)     ;get continue address
277 nextCluster:
278         call    readCluster
279         push    es
280         push    bx
281         mov     ax,FATnibbles(bp)   ;get number of nibbles in a FAT entry
282         mul     cx              ;DX:AX is nibble index
283         shr     dx,1
284         rcr     ax,1            ;DX:AX is byte index, CF=odd/even
285         pushf                   ;save CF
286         mov     si,secSiz(bp)       ;sector size to SI
287         div     si              ;AX is rel. sector, DX is byte offset
288         mov     di,dx           ;DI is byte offset
289         push    ds
290         pop     es
291         mov     bx,#buffer
292         call    ForceFatSector  ;AX is rel. FATsector to force
293         mov     dl,(bx+di)   ;get low byte
294         dec     si
295         inc     di
296         and     di,si           ;mask DI byte offset
297         jnz     sameFATsec
298         inc     ax
299         call    ForceFatSector
300 sameFATsec:
301         mov     dh,(bx+di)
302         popf                    ;restore shift flag
303         mov     cl,FATshift(bp)
304         jc      shiftIt
305         shl     dx,cl
306 shiftIt:
307         shr     dx,cl
308         mov     si,#-1
309         shr     si,cl           ;si is EOF
310         and     si,#-8          ;0xFFF8
311         mov     cx,dx           ;CX is next cluster
312         pop     bx
313         pop     es
314
315         cmp     cx,si
316         jb      nextCluster
317
318         mov     ch,media(bp)        ;pass on media descriptor
319         lea     sp,diskNumber(bp)
320         pop     dx
321         pop     bx              ;low order start of data
322         pop     ax              ;high order start of data
323 #if DEBUG
324         jmp     done
325 #endif
326         retf
327
328
329 readCluster:
330         push    cx
331         mov     al,secPerCl(bp)     ;sectors per cluster
332         cbw
333         xchg    ax,cx           ;AX=cluster #,  CX=# sectors per cluster
334         dec     ax
335         dec     ax              ;base it at 0, instead of 2
336         mul     cx
337         add     ax,dataBase(bp)     ;offset onto disk
338         adc     dx,dataBase+2(bp)
339 readClus1:
340         call    ReadSector      ;read a sector
341         add     bx,secSiz(bp)       ;update address
342 #if LARGE
343         jnc     readClus2
344         mov     si,es           ;get segment register
345         add     si,#0x1000        ;REAL mode increment
346         mov     es,si           ;update segment register
347 #else
348         jc      error3          ;segment overflow
349 #endif
350 readClus2:
351         inc     ax              ;update sector number
352         jnz     readClus3
353         inc     dx
354 readClus3:
355         loop    readClus1
356
357         pop     cx
358         ret
359
360
361 ForceFatSector:
362         push    dx
363         cmp     ax,FATsector(bp)
364         je      gotFATsector
365         mov     FATsector(bp),ax
366         add     ax,FATbase(bp)
367         xor     dx,dx
368         call    ReadSector
369 gotFATsector:
370         pop     dx
371         ret
372
373
374
375 write:
376         pop     si              ;get character string pointer
377 write1:
378         seg cs
379         lodsb   ;byte ptr CS:[si]
380         test    al,al
381         jz      return
382         mov     ah,#0x0e
383         mov     bx,#7
384         int     0x10
385         jmp     write1
386 return:
387         jmp     si
388
389         org     510
390         dw      0xAA55          ; BOOT_SIGNATURE
391
392 endup:
393 theend:
394
395