From f1c414bb26f39bb802295f24dd4a6dae4fbb12df Mon Sep 17 00:00:00 2001 From: Nero <41307858+nero@users.noreply.github.com> Date: Mon, 20 Dec 2021 20:08:37 +0000 Subject: [PATCH] implement bpb parsing --- src/@rdos.asm | 238 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 152 insertions(+), 86 deletions(-) diff --git a/src/@rdos.asm b/src/@rdos.asm index ccd2e3c..4d3c5de 100644 --- a/src/@rdos.asm +++ b/src/@rdos.asm @@ -6,24 +6,11 @@ cseg equ 0x0 %include "farptr.inc" ; dflags bitfields -DRVLOG equ 0x01 ; bit 0 (1) - drive logged in (see drvnum) -DRVRST equ 0x02 ; bit 1 (2) - controller configured -DRVEXT equ 0x04 ; bit 2 (4) - EBIOS supported -DIRTY equ 0x08 ; bit 3 (8) - dskbuf dirty - - ; 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 +DRVLOG equ 0x01 ; bit 0 - drive logged in (see drvnum) +DRVCTL equ 0x02 ; bit 1 - controller configured +DRVEXT equ 0x04 ; bit 2 - EBIOS supported +DIRTY equ 0x08 ; bit 3 - dskbuf dirty +DRVCHS equ 0x10 ; bit 4 - CHS geometry known align 16 ; IBM Interrupt Sharing Protocol structure @@ -52,8 +39,11 @@ int13 pushf ; read BIOS int13h/AH=8 values ; DPT data gets copied over our dpt ; CHS data gets inserted into our bpb -getprm test byte [dskflag], 4 +getprm test byte [dflags], DRVEXT jnz .ret + ; fallback non-zero values (5 1/4", 160kB) + mov word [drvspt], 8 + mov word [drvspc], 8 ; do the query mov ah, 8 mov dl, [biosnum] @@ -65,12 +55,16 @@ getprm test byte [dskflag], 4 jz .nochs ; get and store sector number and cx, 0x3F - mov word [bpb+BPBSPT], cx - ; get and store number of heads + mov word [drvspt], cx + ; get and store number heads xchg dl, dh and dx, 0xFF 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 .nochs mov ax, es or ax, di @@ -87,98 +81,128 @@ getprm test byte [dskflag], 4 ; IN dl drive number ; dont do anything if drive already selected select cmp dl, [drvnum] - je logfdd.ret + je getprm.ret ; clear out current contents push dx call flush mov ax, 0xFFFF - mov [dskseek], ax - mov [dskseek+2], ax - mov byte [dskflag], 0 + mov [drvseek], ax + mov [drvseek+2], ax + and word [dflags], ~(DRVLOG|DRVCTL|DRVEXT|DIRTY|DRVCHS) pop dx ; set current drive number - mov [dsknum], dl + mov [drvnum], dl ; fork off if hdd cmp dl, 2 jnc loghdd logfdd mov [biosnum], dl - ; assume some default values - xor ax, ax - 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 + and dx, 0x0D + ; query bios for geometry and DPT 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 dx, dx - call mapabs - ; copy bios parameter block - ; TODO: guess from first byte of FAT if BPB invalid - call rstseg - mov si, dskbuf+BPBOFF - mov di, bpb - mov cx, BPBSIZ - rep movsb - ; copy SPT to DPT - mov al, [bpb+BPBSPT] - mov [dpt+4], al -.ret ret + mov di, drvoff + stosw + stosw + ; fill partition end with 1's + not ax + stosw + stosw + ; shared code with loghdd + jmp rdbpb -loghdd sub dl, 2 - cmp dl, 4 - jnc logerr - push dx - mov dl, 0x80 + ; Log in a drive on a hard disk + ; IN dl bits 0-1: partition number + ; bits 2-7: drive number + ; Partition offset is read from MBR + ; 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 - ; test for ebios extensions + push dx + ; test for EBIOS extensions mov ah, 0x41 mov bx, 0x55AA call int13 sbb bx, 0xAA55 - jnz .chs - ; enable ebios and assume controller is configured - or byte [dflags], DRVCTL | DRVEXT - ; get chs data (needed or we cant load vbr) -.chs call getprm - ; read mbr + jnz .noeb + ; enable EBIOS and assume controller is configured + or word [dflags], DRVCTL | DRVEXT + ; hard disks are always assumed to be 512 bytes / sector +.noeb mov byte [drvss], 2 + ; query BIOS for geometry + call getprm + or word [dflags], DRVCHS + ; read MBR xor ax, ax xor dx, dx - call mapabs + call map ; get partition number pop bx xor bh, bh mov cl, 4 sal bx, cl - ; bail out if no partition + ; bail out if partition undef cmp byte [dskbuf+0x1be+bx+4], 0 - je logerr + je .ret ; load partition offset mov ax, [dskbuf+0x1be+bx+8] mov dx, [dskbuf+0x1be+bx+8+2] - ; save to to stack - push dx - push ax - ; load vbr - call mapabs - ; copy bpb - mov si, dskbuf+BPBOFF - mov di, bpb - mov cx, BPBSIZ - rep movsb - ; fix CHS data - call getprm - ; fix partition offset - pop word [bpb+BPBHS] - pop word [bpb+BPBHS+2] - ;pop [bpb+BPBNOS] - ;pop [bpb+BPBSPT] - ret + ; store partition offset + mov [drvoff], ax + mov [drvoff+2], dx + ; add partition length + add ax, [dskbuf+0x1be+bx+12] + adc dx, [dskbuf+0x1be+bx+12+2] + ; partitions after 4 TB mark not allowed + jc .ret + ; store partition end + mov [drvend], ax + mov [drvend+2], dx +.ret ret -logerr stc - ret + ; parse bios parameter block from drvoff + ; 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 ; skip doing a read if sector number matches @@ -227,13 +251,13 @@ diskio mov cl, 1 ; read len mov si, dap jmp .do ; check if we can skip controller reset -.noext test word [dflags], DRVRST +.noext test word [dflags], DRVCTL jnz .norst ; do controller reset mov dl, [biosnum] mov ah, 0 call int13 - or word [dflags], DRVRST + or word [dflags], DRVCTL ; put linear sector num into dx:ax .norst mov ax, [drvseek] mov dx, [drvseek+2] @@ -272,16 +296,58 @@ diskio mov cl, 1 ; read len clc ret ; assume controller is misconfigured -.err and word [dflags], ~DRVRST +.err and word [dflags], ~DRVCTL ; exit with carry flag set stc 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 ; boot failure if loaded wrong cmp ax, cseg je $+4 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 jmp halt