1 ; first stage boot loader
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 "86BOOT "; 2bh: volume label, 11 bytes
61 db "FAT12 " ; 36h: filesystem id, 8 bytes
71 mov sp, 0x7b00 ; temp stack below our vars
72 mov [boot_driveno], dl
74 ; query sectors per track
75 mov ah, 8 ; get drive parameters call, dl already has the drive
80 mov [sect_per_track], cx
87 ; in case of failure, try 18 sectors per track, 2 heads
88 mov word [sect_per_track], 18
89 mov word [num_heads], 2
92 ; load the rest of the code high
98 mov [sect_pending], ax
99 mov ax, _kern_start_seg
100 mov es, ax ; destination segment
101 mov word [destptr], 0
102 mov word [start_sect], 1 ; start from sector 1 to skip boot sector
103 mov word [cur_cyl], 0
104 mov word [cur_head], 0
108 mov ax, [sect_pending]
109 sub ax, cx ; num_sect = pending - start_sect
110 cmp ax, [sect_per_track]
112 mov ax, [sect_per_track] ; read max sect_per_track at a time
116 push ax ; save how many sectors we're reading
148 inc cl ; sector numbers start from 1
149 mov ah, 2 ; read sectors is call 2
150 mov dl, [boot_driveno]
153 ; track read sucessfully
154 mov word [start_sect], 0 ; all subsequent tracks are whole
165 sub [sect_pending], ax
168 shl ax, cl ; convert to bytes
173 ; loaded sucessfully, load segment registers and jump
174 .done: mov ax, _kern_start_seg
183 .fail: add sp, 2 ; clear num_sect off the stack
184 dec word [num_read_tries]
187 ; reset controller and retry
189 mov dl, [boot_driveno]
193 ; failed to load second sector
196 floppy_motor_off ; turn off floppy motor (if dl is < 80h)
197 mov ax, str_load_fail
202 ; expects string ptr in ax
216 mov cx, 4 ; 4 digits to print
217 jmp print_n_hex_digits
220 mov cx, 2 ; 2 digits to print
221 mov ah, al ; move them in place
228 mov dx, ax ; save ax, print_hex_digit destroys it
232 jnz print_n_hex_digits
238 mov al, [bx + .hexdig_tab]
245 db "0123456789abcdef"
247 str_rdtrack2 db " from ",0
248 str_rdtrack3 db "/",0
249 str_load_fail db "Failed to load kernel!",0
250 str_newline db 13,10,0
252 times 510-($-$$) db 0
255 ; vi:set ts=8 sts=8 sw=8 ft=nasm: