X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=kern%2Fsrc%2Fboot.asm;fp=kern%2Fsrc%2Fboot.asm;h=96506de177878426b08c7da880baebfe4cde1719;hb=426ed1c5006c82261fee2eea3feafe3282b2b862;hp=0000000000000000000000000000000000000000;hpb=a7e2224fbb33e0662d6fd3fe21e91f5fe185fd4b;p=eightysix diff --git a/kern/src/boot.asm b/kern/src/boot.asm new file mode 100644 index 0000000..96506de --- /dev/null +++ b/kern/src/boot.asm @@ -0,0 +1,257 @@ +; first stage boot loader + cpu 8086 + bits 16 + section .bootsect + +extern _stage2_start_seg +extern _stage2_size + +boot_driveno equ 7b00h +num_read_tries equ 7b06h ; 2 bytes +sect_pending equ 7b08h ; 2 bytes +sect_per_track equ 7b0ah ; 2 bytes +cur_head equ 7b0ch ; 2 bytes - current head +start_sect equ 7b0eh ; 2 bytes - start sector in track +destptr equ 7b10h ; 2 bytes - destination pointer +num_heads equ 7b12h ; 2 bytes - number of heads +cur_cyl equ 7b14h ; 2 bytes - current cylinder + +%macro floppy_motor_off 0 + pushf + and dl, 80h + jnz %%end ; skip if high bit is set (i.e. it's not a floppy) + mov dx, 3f2h + in al, dx + and al, 0fh + out dx, al +%%end: popf +%endmacro + +; 5.25" 360K floppy +BPB_DISK_SECTORS equ 720 +BPB_TRACK_SECTORS equ 9 +BPB_MEDIA_TYPE equ 0fdh +; 3.5" 1.44M floppy +;BPB_DISK_SECTORS equ 2880 +;BPB_TRACK_SECTORS equ 18 +;BPB_MEDIA_TYPE equ 0f0h + +bios_param_block: + jmp start ; 2 bytes + nop ; 1 byte + ; start of BPB at offset 3 + db "86BOOT00" ; 03h: OEM ident, 8 bytes + dw 512 ; 0bh: bytes per sector + db 1 ; 0dh: sectors per cluster + dw 1 ; 0eh: reserved sectors (including boot record) + db 2 ; 10h: number of FATs + dw 224 ; 11h: number of dir entries + dw BPB_DISK_SECTORS ; 13h: number of sectors in volume + db BPB_MEDIA_TYPE ; 15h: media descriptor type (f0 = 3.5" HD floppy) + dw 9 ; 16h: number of sectors per FAT + dw BPB_TRACK_SECTORS ; 18h: number of sectors per track + dw 2 ; 1ah: number of heads + dd 0 ; 1ch: number of hidden sectors + dd 0 ; 20h: high bits of sector count + db 0 ; 24h: drive number + db 0 ; 25h: winnt flags + db 28h ; 26h: signature(?) + dd 0 ; 27h: volume serial number + db "80 SIX BOOT"; 2bh: volume label, 11 bytes + db "FAT12 " ; 36h: filesystem id, 8 bytes + +start: + cld + xor ax, ax + mov ds, ax + mov es, ax + jmp 00:.setcs +.setcs: + ; put the stack high + mov ax, 0x7f00 + mov ss, ax + xor sp, sp + mov [boot_driveno], dl + + ; query sectors per track + mov ah, 8 ; get drive parameters call, dl already has the drive + xor di, di + int 13h + jc .queryfail + and cx, 3fh + mov [sect_per_track], cx + mov cl, 8 + shr dx, cl + inc dx + mov [num_heads], dx + jmp .querydone +.queryfail: + ; in case of failure, try 18 sectors per track, 2 heads + mov word [sect_per_track], 18 + mov word [num_heads], 2 +.querydone: + + ; load the rest of the code high + mov ax, _stage2_size + add ax, 511 + mov cl, 9 + shr ax, cl + inc ax + mov [sect_pending], ax + mov ax, _stage2_start_seg + mov es, ax ; destination segment + mov word [destptr], 0 + mov word [start_sect], 1 ; start from sector 1 to skip boot sector + mov word [cur_cyl], 0 + mov word [cur_head], 0 + +.rdloop: + mov cx, [start_sect] + mov ax, [sect_pending] + sub ax, cx ; num_sect = pending - start_sect + cmp ax, [sect_per_track] + jbe .noadj + mov ax, [sect_per_track] ; read max sect_per_track at a time + sub ax, cx +.noadj: test ax, ax + jz .done + push ax ; save how many sectors we're reading + + push ax + push bx + push cx + push dx + push si + call print_hex_word + mov ax, str_rdtrack2 + call printstr + mov ax, [cur_cyl] + call print_hex_byte + mov ax, str_rdtrack3 + call printstr + mov ax, [cur_head] + call print_hex_byte + mov ax, str_rdtrack3 + call printstr + mov ax, [start_sect] + call print_hex_byte + mov ax, str_newline + call printstr + pop si + pop dx + pop cx + pop bx + pop ax + + mov ch, [cur_cyl] + mov dh, [cur_head] + mov bx, [destptr] + + inc cl ; sector numbers start from 1 + mov ah, 2 ; read sectors is call 2 + mov dl, [boot_driveno] + int 13h + jc .fail + ; track read sucessfully + mov word [start_sect], 0 ; all subsequent tracks are whole + mov ax, [cur_head] + inc ax + cmp ax, [num_heads] + jnz .skip_cyl_adv + xor ax, ax + inc byte [cur_cyl] +.skip_cyl_adv: + mov [cur_head], ax + + pop ax ; num_sect + sub [sect_pending], ax + push cx + mov cl, 9 + shl ax, cl ; convert to bytes + pop cx + add [destptr], ax + jnz .rdloop + + ; loaded sucessfully, load segment registers and jump +.done: mov ax, _stage2_start_seg + mov ds, ax + mov es, ax + push ax + xor ax, ax + push ax + retf + + +.fail: add sp, 2 ; clear num_sect off the stack + dec word [num_read_tries] + jz .abort + + ; reset controller and retry + xor ax, ax + mov dl, [boot_driveno] + int 13h + jmp .rdloop + + ; failed to load second sector +.abort: xor ax, ax + mov es, ax + floppy_motor_off ; turn off floppy motor (if dl is < 80h) + mov ax, str_load_fail + call printstr +.hang: hlt + jmp .hang + + ; expects string ptr in ax +printstr: + mov si, ax +.loop: mov al, [si] + inc si + test al, al + jz .done + mov ah, 0eh + mov bx, 7 + int 10h + jmp .loop +.done: ret + +print_hex_word: + mov cx, 4 ; 4 digits to print + jmp print_n_hex_digits + +print_hex_byte: + mov cx, 2 ; 2 digits to print + mov ah, al ; move them in place + +print_n_hex_digits: + rol ax, 1 + rol ax, 1 + rol ax, 1 + rol ax, 1 + mov dx, ax ; save ax, print_hex_digit destroys it + call print_hex_digit + mov ax, dx + dec cx + jnz print_n_hex_digits + ret + +print_hex_digit: + mov bl, al + and bx, 0fh + mov al, [bx + .hexdig_tab] + mov ah, 0eh + mov bx, 7 + int 10h + ret + +.hexdig_tab: + db "0123456789abcdef" + +str_rdtrack2 db " from ",0 +str_rdtrack3 db "/",0 +str_load_fail db "Failed to load 2nd stage!",0 +str_newline db 13,10,0 + + times 510-($-$$) db 0 +bootsig dw 0xaa55 + +; vi:set ts=8 sts=8 sw=8 ft=nasm: