1 ; first stage boot loader
6 extern _stage2_start_seg
10 num_read_tries equ 7b06h ; 2 bytes
11 sect_pending equ 7b08h ; 2 bytes
12 sect_per_track equ 7b0ah ; 2 bytes
13 cur_head equ 7b0ch ; 2 bytes - current head
14 start_sect equ 7b0eh ; 2 bytes - start sector in track
15 destptr equ 7b10h ; 2 bytes - destination pointer
16 num_heads equ 7b12h ; 2 bytes - number of heads
17 cur_cyl equ 7b14h ; 2 bytes - current cylinder
19 %macro floppy_motor_off 0
22 jnz %%end ; skip if high bit is set (i.e. it's not a floppy)
31 BPB_DISK_SECTORS equ 720
32 BPB_TRACK_SECTORS equ 9
33 BPB_MEDIA_TYPE equ 0fdh
35 ;BPB_DISK_SECTORS equ 2880
36 ;BPB_TRACK_SECTORS equ 18
37 ;BPB_MEDIA_TYPE equ 0f0h
42 ; start of BPB at offset 3
43 db "86BOOT00" ; 03h: OEM ident, 8 bytes
44 dw 512 ; 0bh: bytes per sector
45 db 1 ; 0dh: sectors per cluster
46 dw 1 ; 0eh: reserved sectors (including boot record)
47 db 2 ; 10h: number of FATs
48 dw 224 ; 11h: number of dir entries
49 dw BPB_DISK_SECTORS ; 13h: number of sectors in volume
50 db BPB_MEDIA_TYPE ; 15h: media descriptor type (f0 = 3.5" HD floppy)
51 dw 9 ; 16h: number of sectors per FAT
52 dw BPB_TRACK_SECTORS ; 18h: number of sectors per track
53 dw 2 ; 1ah: number of heads
54 dd 0 ; 1ch: number of hidden sectors
55 dd 0 ; 20h: high bits of sector count
56 db 0 ; 24h: drive number
57 db 0 ; 25h: winnt flags
58 db 28h ; 26h: signature(?)
59 dd 0 ; 27h: volume serial number
60 db "80 SIX BOOT"; 2bh: volume label, 11 bytes
61 db "FAT12 " ; 36h: filesystem id, 8 bytes
74 mov [boot_driveno], dl
76 ; query sectors per track
77 mov ah, 8 ; get drive parameters call, dl already has the drive
82 mov [sect_per_track], cx
89 ; in case of failure, try 18 sectors per track, 2 heads
90 mov word [sect_per_track], 18
91 mov word [num_heads], 2
94 ; load the rest of the code high
100 mov [sect_pending], ax
101 mov ax, _stage2_start_seg
102 mov es, ax ; destination segment
103 mov word [destptr], 0
104 mov word [start_sect], 1 ; start from sector 1 to skip boot sector
105 mov word [cur_cyl], 0
106 mov word [cur_head], 0
110 mov ax, [sect_pending]
111 sub ax, cx ; num_sect = pending - start_sect
112 cmp ax, [sect_per_track]
114 mov ax, [sect_per_track] ; read max sect_per_track at a time
118 push ax ; save how many sectors we're reading
150 inc cl ; sector numbers start from 1
151 mov ah, 2 ; read sectors is call 2
152 mov dl, [boot_driveno]
155 ; track read sucessfully
156 mov word [start_sect], 0 ; all subsequent tracks are whole
167 sub [sect_pending], ax
170 shl ax, cl ; convert to bytes
175 ; loaded sucessfully, load segment registers and jump
176 .done: mov ax, _stage2_start_seg
185 .fail: add sp, 2 ; clear num_sect off the stack
186 dec word [num_read_tries]
189 ; reset controller and retry
191 mov dl, [boot_driveno]
195 ; failed to load second sector
198 floppy_motor_off ; turn off floppy motor (if dl is < 80h)
199 mov ax, str_load_fail
204 ; expects string ptr in ax
218 mov cx, 4 ; 4 digits to print
219 jmp print_n_hex_digits
222 mov cx, 2 ; 2 digits to print
223 mov ah, al ; move them in place
230 mov dx, ax ; save ax, print_hex_digit destroys it
234 jnz print_n_hex_digits
240 mov al, [bx + .hexdig_tab]
247 db "0123456789abcdef"
249 str_rdtrack2 db " from ",0
250 str_rdtrack3 db "/",0
251 str_load_fail db "Failed to load 2nd stage!",0
252 str_newline db 13,10,0
254 times 510-($-$$) db 0
257 ; vi:set ts=8 sts=8 sw=8 ft=nasm: