1 ; first stage boot loader
10 boot_driveno equ 0500h
11 num_read_tries equ 0506h ; 2 bytes
12 sect_pending equ 0508h ; 2 bytes
13 sect_per_track equ 050ah ; 2 bytes
14 cur_head equ 050ch ; 2 bytes - current head
15 start_sect equ 050eh ; 2 bytes - start sector in track
16 destptr equ 0510h ; 2 bytes - destination pointer
17 num_heads equ 0512h ; 2 bytes - number of heads
18 cur_cyl equ 0514h ; 2 bytes - current cylinder
20 %macro floppy_motor_off 0
23 jnz %%end ; skip if high bit is set (i.e. it's not a floppy)
32 BPB_DISK_SECTORS equ 720
33 BPB_TRACK_SECTORS equ 9
34 BPB_MEDIA_TYPE equ 0fdh
36 ;BPB_DISK_SECTORS equ 2880
37 ;BPB_TRACK_SECTORS equ 18
38 ;BPB_MEDIA_TYPE equ 0f0h
43 ; start of BPB at offset 3
44 db "86BOOT00" ; 03h: OEM ident, 8 bytes
45 dw 512 ; 0bh: bytes per sector
46 db 1 ; 0dh: sectors per cluster
47 dw 1 ; 0eh: reserved sectors (including boot record)
48 db 2 ; 10h: number of FATs
49 dw 224 ; 11h: number of dir entries
50 dw BPB_DISK_SECTORS ; 13h: number of sectors in volume
51 db BPB_MEDIA_TYPE ; 15h: media descriptor type (f0 = 3.5" HD floppy)
52 dw 9 ; 16h: number of sectors per FAT
53 dw BPB_TRACK_SECTORS ; 18h: number of sectors per track
54 dw 2 ; 1ah: number of heads
55 dd 0 ; 1ch: number of hidden sectors
56 dd 0 ; 20h: high bits of sector count
57 db 0 ; 24h: drive number
58 db 0 ; 25h: winnt flags
59 db 28h ; 26h: signature(?)
60 dd 0 ; 27h: volume serial number
61 db "86BOOT "; 2bh: volume label, 11 bytes
62 db "FAT12 " ; 36h: filesystem id, 8 bytes
70 mov [boot_driveno], dl ; save boot drive number
72 ; relocate boot sector to 600h
74 mov di, _bootsect_start
80 mov sp, _bootsect_start ; temp stack below our relocated address
82 ; query sectors per track
83 mov ah, 8 ; get drive parameters call, dl already has the drive
88 mov [sect_per_track], cx
95 ; in case of failure, try 18 sectors per track, 2 heads
96 mov word [sect_per_track], 18
97 mov word [num_heads], 2
100 ; load the rest of the code high
106 mov [sect_pending], ax
107 mov ax, _kern_start_seg
108 mov es, ax ; destination segment
109 mov word [destptr], 0
110 mov word [start_sect], 1 ; start from sector 1 to skip boot sector
111 mov word [cur_cyl], 0
112 mov word [cur_head], 0
116 mov ax, [sect_pending]
117 sub ax, cx ; num_sect = pending - start_sect
118 cmp ax, [sect_per_track]
120 mov ax, [sect_per_track] ; read max sect_per_track at a time
124 push ax ; save how many sectors we're reading
156 inc cl ; sector numbers start from 1
157 mov ah, 2 ; read sectors is call 2
158 mov dl, [boot_driveno]
161 ; track read sucessfully
162 mov word [start_sect], 0 ; all subsequent tracks are whole
173 sub [sect_pending], ax
176 shl ax, cl ; convert to bytes
181 ; loaded sucessfully, load segment registers and jump
182 .done: mov ax, _kern_start_seg
191 .fail: add sp, 2 ; clear num_sect off the stack
192 dec word [num_read_tries]
195 ; reset controller and retry
197 mov dl, [boot_driveno]
201 ; failed to load second sector
204 floppy_motor_off ; turn off floppy motor (if dl is < 80h)
205 mov ax, str_load_fail
210 ; expects string ptr in ax
224 mov cx, 4 ; 4 digits to print
225 jmp print_n_hex_digits
228 mov cx, 2 ; 2 digits to print
229 mov ah, al ; move them in place
236 mov dx, ax ; save ax, print_hex_digit destroys it
240 jnz print_n_hex_digits
246 mov al, [bx + .hexdig_tab]
253 db "0123456789abcdef"
255 str_rdtrack2 db " from ",0
256 str_rdtrack3 db "/",0
257 str_load_fail db "Failed to load kernel!",0
258 str_newline db 13,10,0
260 times 510-($-$$) db 0
263 ; vi:set ts=8 sts=8 sw=8 ft=nasm: