1 ; sector.S -- boot program named: HIPBOOT.SYS
2 ; from any MSDOS floppy diskette
4 ; Copyright 2001-2005 John Coffman.
7 ; Licensed under the terms contained in the file 'COPYING' in the LILO
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 */
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
26 dir_file_size: .blkw 2
32 buffer equ 0x0500 ;scratch disk buffer
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
57 diskNumber: .blkb 1 ; DO NOT MOVE
59 dataBase: .blkw 2 ; DO NOT MOVE
60 contAddr: .blkw 2 ; DO NOT MOVE
62 stack: /* this had better be zero */
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
78 fs_id: .blkb 8 ; filesystem_id
88 system_id_string: .ascii "DISKBOOT" ; 8 chars
92 bytes_per_sector: dw 512
93 sectors_per_cluster: db 1
94 reserved_sectors: dw 1
96 directory_entries: dw 224 ; 112 & 224 are typical
97 total_sectors: dw 2880
98 media_descriptor: db 0xf0 ; 0f9H, 0f0h, 0fAh, etc.
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
108 volume_label: .ascii "NO NAME " ; 11 chars
109 filesystem_id: .ascii "FAT12 " ; 8 chars
115 mov bp,#base ;origin at 7C00
122 lea sp,(bp-stacksize)
126 mov es,ax ;both at zero
131 mov diskNumber(bp),dl ;save disk number
132 int 0x13 ;reset the disk system
135 mov ax,#0x0403 ;shift=4, nibbles=3 -- FAT12
138 cmp byte ptr fs_id+4(bp),#$36 ; '6'
140 mov ax,#0004 ;shift=0, nibbles=4 -- FAT16
143 mov FATshift(bp),ah ;set shift count
145 mov FATnibbles(bp),ax ;set number of nibbles per FAT index entry
147 mov al,nFATs(bp) ;number of FATs
149 mul word ptr secPerFAT(bp) ;* sectors per FAT
150 add ax,FATbase(bp) ;+ FAT base
153 mov dirBase+2(bp),dx ;save directory base
156 mov dataBase+2(bp),dx ;still forming Data base
158 mov ax,#dir_entry_size
159 mul word ptr nDirEnt(bp)
163 div bx ;get base of data
168 mov contAddr(bp),ss ; SS = 0
169 mov word ptr contAddr+2(bp),#SYSSEG ; begin at SYSSEG:0000
172 mov contAddr(bp),bx ;save continuation address
173 mov contAddr+2(bp),es
175 mov nDirSec(bp),ax ;save no. of Directory sectors
177 adc word ptr dataBase+2(bp),#0 ; SI = 0
179 ; scan the directory for the required bootstrap file
181 mov ax,dirBase(bp) ; starting disk block in DX:AX
184 mov bx,#buffer ; ES:BX points to buffer
191 tofind: .ascii "HIPBOOT SYS"
196 .ascii 'Non-SYSTEM disk or disk error'
198 .ascii 'Press any key to re-boot ...'
202 int 0x16 ;wait for keypress
208 mov cx,#11 ;name length
211 cmpsb ;byte ptr CS:[si],ES:[di]
218 lea di,dir_entry_size(di)
219 sub bx,#dir_entry_size
223 dec word ptr nDirSec(bp)
230 push dx ;save registers
234 add ax,hidSec(bp) ;+ Hidden Sectors
235 adc dx,hidSec+2(bp) ;
237 push dx ;AX=dividend-hi, DX=dividend-low
239 div word ptr nSEC(bp) ;DX=remainder, AX=quo-hi
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
247 mov dx,cx ;DX:AX=quotient
248 div word ptr nSides(bp) ;DX = side, AX = Cyl No.
250 shl ah,cl ;AH is hi-bits of cyl no.
251 pop cx ;restore sector number
255 mov dl,diskNumber(bp)
257 mov ax,#0x0201 ;BIOS read 1 sector
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
281 mov ax,FATnibbles(bp) ;get number of nibbles in a FAT entry
282 mul cx ;DX:AX is nibble index
284 rcr ax,1 ;DX:AX is byte index, CF=odd/even
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
292 call ForceFatSector ;AX is rel. FATsector to force
293 mov dl,(bx+di) ;get low byte
296 and di,si ;mask DI byte offset
302 popf ;restore shift flag
311 mov cx,dx ;CX is next cluster
318 mov ch,media(bp) ;pass on media descriptor
319 lea sp,diskNumber(bp)
321 pop bx ;low order start of data
322 pop ax ;high order start of data
331 mov al,secPerCl(bp) ;sectors per cluster
333 xchg ax,cx ;AX=cluster #, CX=# sectors per cluster
335 dec ax ;base it at 0, instead of 2
337 add ax,dataBase(bp) ;offset onto disk
338 adc dx,dataBase+2(bp)
340 call ReadSector ;read a sector
341 add bx,secSiz(bp) ;update address
344 mov si,es ;get segment register
345 add si,#0x1000 ;REAL mode increment
346 mov es,si ;update segment register
348 jc error3 ;segment overflow
351 inc ax ;update sector number
376 pop si ;get character string pointer
379 lodsb ;byte ptr CS:[si]
390 dw 0xAA55 ; BOOT_SIGNATURE