implement bpb parsing

This commit is contained in:
Nero 2021-12-20 20:08:37 +00:00
parent e26adff688
commit f1c414bb26

View File

@ -6,24 +6,11 @@ cseg equ 0x0
%include "farptr.inc" %include "farptr.inc"
; dflags bitfields ; dflags bitfields
DRVLOG equ 0x01 ; bit 0 (1) - drive logged in (see drvnum) DRVLOG equ 0x01 ; bit 0 - drive logged in (see drvnum)
DRVRST equ 0x02 ; bit 1 (2) - controller configured DRVCTL equ 0x02 ; bit 1 - controller configured
DRVEXT equ 0x04 ; bit 2 (4) - EBIOS supported DRVEXT equ 0x04 ; bit 2 - EBIOS supported
DIRTY equ 0x08 ; bit 3 (8) - dskbuf dirty DIRTY equ 0x08 ; bit 3 - dskbuf dirty
DRVCHS equ 0x10 ; bit 4 - CHS geometry known
; initial setup for disk i/o
; copy previously set DPT to our data area
dinit xor ax, ax
mov es, ax
les bx, [es:4*0x1E]
mov dx, dpt
mov cx, 11
call lodfar
; set interrupt vector
mov es, cx
mov word [es:4*0x1E], dpt
mov word [es:4*0x1E+2], ds
ret
align 16 align 16
; IBM Interrupt Sharing Protocol structure ; IBM Interrupt Sharing Protocol structure
@ -52,8 +39,11 @@ int13 pushf
; read BIOS int13h/AH=8 values ; read BIOS int13h/AH=8 values
; DPT data gets copied over our dpt ; DPT data gets copied over our dpt
; CHS data gets inserted into our bpb ; CHS data gets inserted into our bpb
getprm test byte [dskflag], 4 getprm test byte [dflags], DRVEXT
jnz .ret jnz .ret
; fallback non-zero values (5 1/4", 160kB)
mov word [drvspt], 8
mov word [drvspc], 8
; do the query ; do the query
mov ah, 8 mov ah, 8
mov dl, [biosnum] mov dl, [biosnum]
@ -65,12 +55,16 @@ getprm test byte [dskflag], 4
jz .nochs jz .nochs
; get and store sector number ; get and store sector number
and cx, 0x3F and cx, 0x3F
mov word [bpb+BPBSPT], cx mov word [drvspt], cx
; get and store number of heads ; get and store number heads
xchg dl, dh xchg dl, dh
and dx, 0xFF and dx, 0xFF
inc dx inc dx
mov [bpb+BPBNOS], dx ; multiply with sectors per track
mov ax, dx
mul cx
; store sectors per cylinder
mov [drvspc], ax
; test if DPT ptr is non-zero ; test if DPT ptr is non-zero
.nochs mov ax, es .nochs mov ax, es
or ax, di or ax, di
@ -87,98 +81,128 @@ getprm test byte [dskflag], 4
; IN dl drive number ; IN dl drive number
; dont do anything if drive already selected ; dont do anything if drive already selected
select cmp dl, [drvnum] select cmp dl, [drvnum]
je logfdd.ret je getprm.ret
; clear out current contents ; clear out current contents
push dx push dx
call flush call flush
mov ax, 0xFFFF mov ax, 0xFFFF
mov [dskseek], ax mov [drvseek], ax
mov [dskseek+2], ax mov [drvseek+2], ax
mov byte [dskflag], 0 and word [dflags], ~(DRVLOG|DRVCTL|DRVEXT|DIRTY|DRVCHS)
pop dx pop dx
; set current drive number ; set current drive number
mov [dsknum], dl mov [drvnum], dl
; fork off if hdd ; fork off if hdd
cmp dl, 2 cmp dl, 2
jnc loghdd jnc loghdd
logfdd mov [biosnum], dl logfdd mov [biosnum], dl
; assume some default values and dx, 0x0D
xor ax, ax ; query bios for geometry and DPT
mov word [bpb+BPBHS], ax
mov word [bpb+BPBHS+2], ax
mov word [bpb+BPBNOS], 2 ; 5 1/4" 360kB
mov word [bpb+BPBSPT], 9
; reset dpt to defaults
call getprm call getprm
; load boot sector ; assume 512 bytes per sector
; TODO: read this from DPT
mov byte [drvss], 2
; fill partition offset with zeroes
xor ax, ax xor ax, ax
xor dx, dx mov di, drvoff
call mapabs stosw
; copy bios parameter block stosw
; TODO: guess from first byte of FAT if BPB invalid ; fill partition end with 1's
call rstseg not ax
mov si, dskbuf+BPBOFF stosw
mov di, bpb stosw
mov cx, BPBSIZ ; shared code with loghdd
rep movsb jmp rdbpb
; copy SPT to DPT
mov al, [bpb+BPBSPT]
mov [dpt+4], al
.ret ret
loghdd sub dl, 2 ; Log in a drive on a hard disk
cmp dl, 4 ; IN dl bits 0-1: partition number
jnc logerr ; bits 2-7: drive number
push dx ; Partition offset is read from MBR
mov dl, 0x80 ; split drive & partition number
loghdd mov dh, dl
and ah, 0x3
shr dl, 1
shl dl, 1
add dl, 0x80
; partition number in DH
mov byte [biosnum], dl mov byte [biosnum], dl
; test for ebios extensions push dx
; test for EBIOS extensions
mov ah, 0x41 mov ah, 0x41
mov bx, 0x55AA mov bx, 0x55AA
call int13 call int13
sbb bx, 0xAA55 sbb bx, 0xAA55
jnz .chs jnz .noeb
; enable ebios and assume controller is configured ; enable EBIOS and assume controller is configured
or byte [dflags], DRVCTL | DRVEXT or word [dflags], DRVCTL | DRVEXT
; get chs data (needed or we cant load vbr) ; hard disks are always assumed to be 512 bytes / sector
.chs call getprm .noeb mov byte [drvss], 2
; read mbr ; query BIOS for geometry
call getprm
or word [dflags], DRVCHS
; read MBR
xor ax, ax xor ax, ax
xor dx, dx xor dx, dx
call mapabs call map
; get partition number ; get partition number
pop bx pop bx
xor bh, bh xor bh, bh
mov cl, 4 mov cl, 4
sal bx, cl sal bx, cl
; bail out if no partition ; bail out if partition undef
cmp byte [dskbuf+0x1be+bx+4], 0 cmp byte [dskbuf+0x1be+bx+4], 0
je logerr je .ret
; load partition offset ; load partition offset
mov ax, [dskbuf+0x1be+bx+8] mov ax, [dskbuf+0x1be+bx+8]
mov dx, [dskbuf+0x1be+bx+8+2] mov dx, [dskbuf+0x1be+bx+8+2]
; save to to stack ; store partition offset
push dx mov [drvoff], ax
push ax mov [drvoff+2], dx
; load vbr ; add partition length
call mapabs add ax, [dskbuf+0x1be+bx+12]
; copy bpb adc dx, [dskbuf+0x1be+bx+12+2]
mov si, dskbuf+BPBOFF ; partitions after 4 TB mark not allowed
mov di, bpb jc .ret
mov cx, BPBSIZ ; store partition end
rep movsb mov [drvend], ax
; fix CHS data mov [drvend+2], dx
call getprm .ret ret
; fix partition offset
pop word [bpb+BPBHS]
pop word [bpb+BPBHS+2]
;pop [bpb+BPBNOS]
;pop [bpb+BPBSPT]
ret
logerr stc ; parse bios parameter block from drvoff
ret ; drvoff and biosnum need to be set up
rdbpb mov ax, [drvoff]
mov dx, [drvoff+2]
call map
; read partition start
mov ax, [drvoff]
mov dx, [drvoff+2]
; add reserved sectors
add ax, [dskbuf+BPBOFF+BPBRSC]
adc dx, 0
jc .ret
; save offset of fat table
mov [drvfat], ax
mov [drvfat+2], dx
; calculate length of all fat tables
mov ah, 0
mov al, [dskbuf+BPBOFF+BPBFN]
mov dx, [dskbuf+BPBOFF+BPBFS]
mov [drvfn], dx
mul dx
add ax, [drvfat]
adc dx, [drvfat+2]
; save offset of root directory
mov [drvrd], ax
mov [drvrd+2], dx
; calculate length of root directory
mov ax, [dskbuf+BPBOFF+BPBRDE]
mov cl, [drvss]
add cl, 2
shr ax, cl
; read offset to cluster area
; read cluster size
.ret ret
; map sector into dskbuf ; map sector into dskbuf
; skip doing a read if sector number matches ; skip doing a read if sector number matches
@ -227,13 +251,13 @@ diskio mov cl, 1 ; read len
mov si, dap mov si, dap
jmp .do jmp .do
; check if we can skip controller reset ; check if we can skip controller reset
.noext test word [dflags], DRVRST .noext test word [dflags], DRVCTL
jnz .norst jnz .norst
; do controller reset ; do controller reset
mov dl, [biosnum] mov dl, [biosnum]
mov ah, 0 mov ah, 0
call int13 call int13
or word [dflags], DRVRST or word [dflags], DRVCTL
; put linear sector num into dx:ax ; put linear sector num into dx:ax
.norst mov ax, [drvseek] .norst mov ax, [drvseek]
mov dx, [drvseek+2] mov dx, [drvseek+2]
@ -272,16 +296,58 @@ diskio mov cl, 1 ; read len
clc clc
ret ret
; assume controller is misconfigured ; assume controller is misconfigured
.err and word [dflags], ~DRVRST .err and word [dflags], ~DRVCTL
; exit with carry flag set ; exit with carry flag set
stc stc
ret ret
; Get interrupt vector
; IN al interrupt number
; OUT es:bx vector
getint mov bl, al
mov bh, 0
; multiply with 4
add bx, bx
add bx, bx
les bx, [cs:bx]
ret
; Set interrupt vector
; IN al interrupt number
; ds:dx vector
setint mov bl, al
mov bh, 0
; multiply with 4
add bx, bx
add bx, bx
mov [cs:bx], dx
mov [cs:bx+2], ds
ret
init mov ax, cs init mov ax, cs
; boot failure if loaded wrong ; boot failure if loaded wrong
cmp ax, cseg cmp ax, cseg
je $+4 je $+4
int 0x18 int 0x18
call rstseg
; fetch current DPT
les bx, [4*0x1E]
mov dx, dpt
mov cx, 11
call lodfar
; set interrupt vector
mov word [4*0x1E], dpt
mov word [4*0x1E+2], ds
; save int 13 handler
les bx, [4*0x13]
mov [i13isp+2], bx
mov [i13isp+4], es
; install ours
mov word [4*0x13], int13i
mov [4*0x13+2], cs
mov ax, 0x0e37
int 0x10
halt hlt halt hlt
jmp halt jmp halt