+++ /dev/null
-; 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: