diff --git a/boot/kernel.asm b/boot/kernel.asm index 4fff9eb..0f205bc 100644 --- a/boot/kernel.asm +++ b/boot/kernel.asm @@ -3,6 +3,7 @@ jmp 0:(init+0x7C00-$$) %include "inc/bpb.asm" + %include "inc/mbr.asm" ; Far call via interrupt vector %macro intcall 1 @@ -195,7 +196,7 @@ fputc: push ax %include "kernel/diskio.asm" vects: dw int20h, int21h, retf, retf - dw retf, int25h, int26h, int20h + dw retf, retf, retf, int20h dw idle, fputc main: ; zero out first 64kb except our code @@ -222,12 +223,7 @@ intlp: movsw call dnconv mov al, dl - mov cx, 1 - mov dx, 0 - mov bx, buffer - int 3 - intcall 0x25 - int 3 + call select loop: int 0x28 jmp loop @@ -250,6 +246,3 @@ init: cli section .bss ; stack to be used during init and disk i/o stack: resw stacks - ; default int 25h/26h handler use a cache to keep geometry for - ; the first 4 drives -buffer: resb 512 diff --git a/inc/mbr.asm b/inc/mbr.asm new file mode 100644 index 0000000..b423d24 --- /dev/null +++ b/inc/mbr.asm @@ -0,0 +1,11 @@ +mbrtab: equ 0x1BE ; start of partition table +mbrsig: equ 0x1FE ; start of signature +mbrmn: equ 0x55AA ; signature value + +pardn: equ 0x00 ; byte: partition active flag +parchs: equ 0x01 ; 3 bytes: CHS for first sector +partyp: equ 0x04 ; byte: partition type +parend: equ 0x05 ; 3 bytes: CHS for last sector +paroff: equ 0x08 ; dword: partition offset in sectors +parlen: equ 0x0C ; dword: partition length in sectors +parsiz: equ 0x10 diff --git a/kernel/diskio.asm b/kernel/diskio.asm index a634e86..6e9440d 100644 --- a/kernel/diskio.asm +++ b/kernel/diskio.asm @@ -1,11 +1,23 @@ section .bss -chsspt: equ 0 ; word sectors per track -chsnos: equ 2 ; word number of sides -chspo: equ 4 ; dword partition offset -chssiz: equ 8 +disk_buffer: + resb 512 -chstab: resw (4*chssiz) +disk_current: + resb 1 + +lba_supported: + resb 1 + +disk_chs: ; DL, DH, CL, CH for int 13h CHS functions + resb 4 +disk_dap: ; disk access packet for int 13h EBIOS functions + resb 0x10 + +disk_tracks: ; heads * spt + resw 1 +disk_spt: + resb 1 ; Disk access packet for EBIOS extensions dapps: equ 0 ; byte packet size @@ -28,121 +40,77 @@ dncl: rcl dl, 1 xchg dh, dl ret -fndchs: ; find CHS table entry - ; IN dl DOS drive number (A=0, B=1, ...) - ; OUT cs:si ptr to chs table entry - push ax - mov ax, chssiz - mul dl - add ax, chstab - mov si, ax - pop ax - ret - - ; compare sector number in disk access packet with zero - ; sets zero flag accordingly -iszero: push ax - mov ax, [bx] - or ax, [bx+2] - pop ax - ret - - ; calculate CHS from dap and CHS table entry - ; IN ds:bx disk access packet - ; cs:si chstab table entry - ; OUT cx,dh chs data for int 13h -calchs: push ax - ; load linear sector number - mov dx, [bx+2] - mov ax, [bx] - ; if any word of it is non-zero, we need to do calculation - call iszero - jz .zero - ; ax is track number (lba / spt) - ; dx is sector (lba % spt) + 1 - div word [cs:si+chsspt] - inc dx - ; sector number - mov cl, dl - ; ax is cylinder (track / heads) - ; dx is head (track % heads) - xor dx, dx - div word [cs:si+chsnos] - ; set up cylinder and head number - mov ch, al - mov dh, dl - pop ax - ret - ; set up CHS data for int 13h for reading sector zero -.zero: mov cx, 1 ; C=0, S=1 - mov dh, 0 ; H=0 - pop ax - ret - - ; ABSOLUTE DISK READ / DISK WRITE -int25h: mov ah, 2 - jmp adisk -int26h: mov ah, 3 -adisk: push bp - push ds - push es - mov bp, sp - - push ax - - cmp cx, 0xFFFF - je .lrg - - ; build ebios DAP from registers supplied - ; qword sector number - push cs - push cs - push cs - push dx - ; dword target buffer - push ds - push bx - ; word number of sectors - push cx - jmp .psz - -.lrg: ; build ebios DAP from int 25h DAP - ; qword sector number - push cs - push cs - mov ax, [bx+2] - push ax - mov ax, [bx] - push ax - ; dword target buffer - mov ax, [bx+8] - push ax - mov ax, [bx+6] - push ax - ; word number of sectors - mov ax, [bx+4] - push ax -.psz: ; word packet size - mov ax, dapsiz - push ax - - ; DS:SI = SS:SP (ptr to dap) - push ss - pop ds - mov si, sp - - ; set up int 13h subfunction number - mov ax, [si+dapsiz] - add ah, 0x40 - - ; get BIOS drive number - mov dl, al + ; Select a drive for I/O + ; IN dl 0=A, 1=B, 2=C, 3=D +select: mov byte [disk_current], 0xFF + mov byte [lba_supported], 0 + cmp dl, 0x02 + jc select_floppy + ; detect EBIOS/LBA extensions call dnconv - + mov byte [disk_chs], dl + mov ah, 0x41 + mov bx, 0x55AA int 0x13 + test cx, 1 + jz .nolba + cmp bx, 0xAA55 + jnz .nolba + mov byte [lba_supported], 1 +.nolba: call seek_zero + ret -.ret: mov sp, bp +select_floppy: + xor dx, dx + xor ax, ax + call seek + call read + ret + + ; Set absolute sector number + ; IN dx:ax 32-bit sector number +seek: push ax + or ax, dx + pop ax + jz seek_zero + + ; dx:ax = lba + div word [disk_tracks] + xchg ax, dx + ; dx = cylinder, ax = head * spt + sector + div byte [disk_spt] + ; dx = cylinder, al = head, ah = sector + xchg dl, dh + ror dl, 1 + ror dl, 1 + or dl, ah + ;inc dx + ; dh bit 0-7: cylinder 0-7 + ; dl bit 0-5: sector number 0-5 + ; dl bit 6-7: cylinder 8-9 + ; store + mov byte [disk_chs+1], al + mov word [disk_chs+2], dx + int 3 + ret + +seek_zero: + mov byte [disk_chs+1], 0 + mov word [disk_chs+2], 1 + ret + + ; Read a sector into buffer +read: mov ax, 0x0201 + mov dx, [disk_chs] + mov cx, [disk_chs+2] + lea bx, [disk_buffer] + push cs pop es - pop ds - pop bp - retf + int 3 + int 0x13 + int 3 + ret + + ; Write a sector into buffer +write: + ret