indigoos/src/bootloader/bios_disk.asm
2021-08-24 14:09:29 -05:00

150 lines
2.8 KiB
NASM

bios_disk:
.init:
mov [boot_device], dl
mov ah, 0x8
int 0x13
;TODO defaults
jc .init_use_defaults
mov [max_head], dh
mov [max_sector], cl
and WORD [max_sector], 0x3f
mov [max_cylinder], cl
shl WORD [max_cylinder], 8
or [max_cylinder], ch
and WORD [max_cylinder], 0x3ff
ret
.init_use_defaults:
mov BYTE [max_sector], 63
mov WORD [max_head], 15
mov BYTE [max_cylinder], 1023
ret
; Return:
; CH = low eight bits of maximum cylinder number
; CL = maximum sector number (bits 5-0), high two bits of maximum cylinder number (bits 7-6)
; DH = maximum head number
.load_sectors_v2:
;AH = 02h
;AL = number of sectors to read (must be nonzero)
;CH = low eight bits of cylinder number
;CL = sector number 1-63 (bits 0-5) high two bits of cylinder (bits 6-7)
;DH = head number
;DL = drive number (bit 7 set for hard disk)
;ES:BX -> data buffer
; I don't understand i8086. The base pointer needs to be above the stack pointer,
; yet the stack grows down,
; and we can't address using sp, or by subtraction.
; it's like it's forcing us to use the whole push/pop thing.
sub sp, 16
mov bp, sp
; sector: rbp + 0 (uint8_t)
; head: rbp + 1 (uint8_t)
; cylinder: rbp + 2 (uint16_t)
; sector_cnt: rbp + 4 (uint16_t)
; destination: rbp + 6 (uint32_t)
; set up variables ______________________________________________
;destination to stack
mov [bp + 6], edi
; find init chs ________________________________________________
; divide sector_start / max_sectors
; TODO test for overflow
mov ax, si
shr esi, 16
mov dx, si
;find sector
div DWORD [max_sector]
inc dx
mov [bp], edx ; remainder is sector variable
;find head and cylinder
mov dx, 0
div DWORD [max_head]
mov [bp + 1], dx ; head
mov [bp + 2], ax ; cylinder
.sector_for_loop:
mov [bp + 4], cx
; do bios call ___________________________________________________
mov ah, 2
mov al, 1
; sets up ch and cl
mov cx, [bp + 2]
xchg ch, cl
shl cl, 6
or cl, [bp]
mov dh, [bp + 1]
mov dl, [boot_device]
mov bx, 0x500 ; where we store the sector temporarily
int 0x13
jc .read_failed
; mempcy __________________________________________________________
; we move it to the place at edi, which I don't think changes
mov esi, 0x500
mov ecx, 512
a32 rep movsb
; recalc chs ______________________________________________________
; need to test for more overflows I think
inc WORD [bp]
mov al, [bp]; increase the sector we're on
cmp al, [max_sector]
jbe .continue_loop
mov WORD [bp], 1
inc WORD [bp + 1]
mov al, [bp + 1]
cmp al, [max_head]
jbe .continue_loop
mov WORD [bp + 1], 0
inc DWORD [bp + 2]
; loopin back ____________________________________________________
.continue_loop:
mov cx, [bp + 4]
loop .sector_for_loop
add bp, 16
mov sp, bp
ret
.read_failed:
mov bx, .loadsectors_error
call bios_print
cli
hlt
.loadsectors_error: db "Error loading required sector!", 0
boot_device: db 0
max_sector: db 0
max_cylinder: dw 0
max_head: db 0