Make kernel and fat.bs use BPB struct

This commit is contained in:
Nero 2020-09-15 21:38:26 +02:00
parent 303b1756e0
commit 9cd4c04c42
3 changed files with 247 additions and 336 deletions

View File

@ -1,4 +1,4 @@
FLOPPY = 360 FLOPPY = 1440
PROGRAMS = hello.com PROGRAMS = hello.com
DISTFILES = $(PROGRAMS) kernel.bs DISTFILES = $(PROGRAMS) kernel.bs
@ -55,15 +55,6 @@ fat4.bs: boot/fat.asm
fat6.bs: boot/fat.asm fat6.bs: boot/fat.asm
$(NASM) $(NASM_ARGS) -DFAT16 -DCHS -DLARGE -o $@ $< $(NASM) $(NASM_ARGS) -DFAT16 -DCHS -DLARGE -o $@ $<
fatb.bs: boot/fat.asm
$(NASM) $(NASM_ARGS) -DFAT32 -DCHS -DLARGE -o $@ $<
fatc.bs: boot/fat.asm
$(NASM) $(NASM_ARGS) -DFAT32 -DLBA -DLARGE -o $@ $<
fate.bs: boot/fat.asm
$(NASM) $(NASM_ARGS) -DFAT16 -DLBA -DLARGE -o $@ $<
# BIOS option roms # BIOS option roms
%.rom: rom/%.asm utils/fix-rom %.rom: rom/%.asm utils/fix-rom
$(NASM) $(NASM_ARGS) -o $@ $< && utils/fix-rom $@ $(NASM) $(NASM_ARGS) -o $@ $< && utils/fix-rom $@

View File

@ -1,338 +1,270 @@
; Bootsector for FAT32 filesystems ; Bootsector for FAT12/FAT16 filesystems
; Takes defines: ; Takes defines:
; FAT12 FAT has 1.5 bytes per entry ; FAT12 FAT has 1.5 bytes per entry
; FAT16 FAT has WORD per entry ; FAT16 FAT has WORD per entry
; FAT32 FAT has DWORD per entry cpu 8086
; CHS uses int13h/AH=02h
; LARGE requires 32 bit sector numbers
; LBA uses int13h/AH=42h
cpu 8086
org 0x0800 org 0x0800
jmp short init jmp short init
nop nop
%include "inc/bpb.asm" %include "inc/bpb.asm"
bpb: equ 0x080B times ( 0x0B - ($-$$) ) db 0
; Area for BPB params: times bpb_size db 0
%ifdef FAT32
times ( 0x5A - ($-$$) ) db 0
%else
times ( 0x3E - ($-$$) ) db 0
%endif
init: xor ax, ax ; Area for BPB
mov ss, ax times ( 0x3E - ($-$$) ) db 0
mov sp, 0x7C00
; save potential partition table entry init: xor ax, ax
push ds mov ss, ax
push si mov sp, 0x7C00
mov ds, ax ; save potential partition table entry
mov es, ax push ds
push si
mov si, 0x7C00 mov ds, ax
mov di, 0x0800 mov es, ax
mov cx, 0x0100
rep movsw
jmp 0x0:main
%include "inc/booterr.asm" mov si, 0x7C00
mov di, 0x0800
mov cx, 0x0100
rep movsw
jmp 0x0:main
; offsets relative to FS %include "inc/booterr.asm"
readd: ; add offset of cluster data area to DX:AX
push cx
mov di, [bp+bpb_rde]
mov cl, 4
shr di, cl ; 32 bytes per entry
add ax, di
adc dx, 0
pop cx
readr: ; add offset to rootdir to DX:AX (FAT12/FAT16 only)
push cx
xor ch, ch
mov cl, byte [bp+bpb_fn]
fatlp:
%ifdef FAT32
add ax, [bp+bpb7_lsf]
adc dx, [bp+bpb7_lsf+2]
%else
add ax, [bp+bpb_sf]
adc dx, 0
%endif
loop fatlp
pop cx
readf: ; add offset to FAT table to DX:AX
add ax, word [bp+bpb_rsc]
adc dx, 0
readp: ; read sector DX:AX from partition
add ax, word [bp+bpb_po]
adc dx, word [bp+bpb_po+2]
jnc ($+5)
call errcll
%ifdef LBA ; offsets relative to FS
read_: ; read sector DX:AX from disk readd: ; add offset of cluster data area to DX:AX
; this uses the EBIOS extensions push cx
; qword sector number DX:AX mov di, [bp+bpb.direntries]
push cs mov cl, 4
push cs shr di, cl ; 32 bytes per entry
push dx add ax, di
push ax adc dx, 0
pop cx
readr: ; add offset to rootdir to DX:AX (FAT12/FAT16 only)
push cx
xor ch, ch
mov cl, byte [bp+bpb.fatnumber]
fatlp: add ax, [bp+bpb.fatsectors]
adc dx, 0
loop fatlp
pop cx
readf: ; add offset to FAT table to DX:AX
add ax, word [bp+bpb.reservedsects]
adc dx, 0
readp: ; read sector DX:AX from partition
add ax, word [bp+bpb.sectoroffset]
adc dx, word [bp+bpb.sectoroffset+2]
jnc ($+5)
call errcll
; dword target buffer: BX:0 read_: ; read sector DX:AX from disk
push bx ; uses basic CHS disk IO
push cs ; this cant reliable read over track boundaries
; so we read each single sector in loop over CX
chslp: push ax
push cx
push dx
push bx
; word sector number ; calculate CHS data
push cx div word [bp+bpb.tracksectors] ; ax:temp = (lba / spt)
inc dx ; dx:sector = (lba % spt) + 1
mov cl, dl ; sector number
xor dx, dx
div word [bp+bpb.heads] ; ax:cylinder = (tmp / heads)
; dx:head = (tmp % heads)
mov ch, al ; cylinder number
mov dh, dl ; head number
mov dl, [bp+bpb.drivenum] ; drive number
; size & passing ; set up read buffer
mov di, 0x10 mov es, bx
push di xor bx, bx
mov si, sp ; call bios
mov ah, 0x42 mov ax, 0x0201
mov dl, [bp+bpb7_dn] int 0x13
stc jnc ($+5)
int 0x13 call errcll
jnc ($+5)
call errcll
add sp, di pop bx
pop dx
pop cx
pop ax
ret ; increment sector num + write offset
%endif add ax, 1
adc dx, 0
add bx, 0x20
; loop on CX
loop chslp
ret
%ifdef CHS next: ; Advances DX:AX to next FAT entry
read_: ; read sector DX:AX from disk push ax
; uses basic CHS disk IO push bx
; this cant reliable read over track boundaries ; shift 2 left for dword-sized FAT entries
; so we read each single sector in loop over CX ; shift 9 right for sector size
chslp: push ax mov cl, 7
push cx shftl: clc
push dx rcr dx, 1
push bx rcr ax, 1
loop shftl
; calculate CHS data mov bx, 0xA0
div word [bp+bpb_spt] ; ax:temp = (lba / spt) %ifdef FAT12
inc dx ; dx:sector = (lba % spt) + 1 ; FAT item might span over two sectors
mov cl, dl ; sector number mov cx, 2
xor dx, dx %else
div word [bp+bpb_nos] ; ax:cylinder = (tmp / heads) mov cx, 1
; dx:head = (tmp % heads) %endif
mov ch, al ; cylinder number call readf
mov dh, dl ; head number
mov dl, [bp+bpb7_dn] ; drive number
; set up read buffer pop bx
mov es, bx
xor bx, bx
; call bios ; get address of cluster within sector
mov ax, 0x0201 pop si
int 0x13 %ifdef FAT12
jnc ($+5) push si
call errcll ; times 1.5
mov ax, si
shr ax, 1
add si, ax
add si, buf
lodsw
pop si
test si, 1
jz .odd
.even: mov cl, 4
shr ax, cl
jmp .done
.odd: and ax, 0x0FFF
.done: xor dx, dx
%endif
pop bx %ifdef FAT16
pop dx ; double
pop cx sal si, 1
pop ax ; make sure its within sector range
and si, 0x1FF
add si, buf
; load word
lodsw
xor dx, dx
%endif
; increment sector num + write offset ret
add ax, 1
adc dx, 0
add bx, 0x20
; loop on CX
loop chslp
ret
%endif
next: ; Advances DX:AX to next FAT entry ; reads current cluster into [dest]
push ax readc: ; load cluster number
push bx push ax
; shift 2 left for dword-sized FAT entries push dx
; shift 9 right for sector size
mov cl, 7
shftl: clc
rcr dx, 1
rcr ax, 1
loop shftl
mov bx, 0xA0 ; subtract the two dummy entries from FAT start
%ifdef FAT12 sub ax, 2
; FAT item might span over two sectors sbb dx, 0
mov cx, 2
%else
mov cx, 1
%endif
call readf
pop bx ; convert cluster number to sector number
; this is some cheapo multiplication with 2^n
; get address of cluster within sector mov cl, [bp+bpb.clustersects]
pop si l02: shr cl, 1
%ifdef FAT12 jz l02e
push si clc
; times 1.5 rcl ax, 1
mov ax, si rcl dx, 1
shr ax, 1 jmp l02
add si, ax
add si, buf
lodsw
pop si
test si, 1
jz .odd
.even: mov cl, 4
shr ax, cl
jmp .done
.odd: and ax, 0x0FFF
.done: xor dx, dx
%endif
%ifdef FAT16
; double
sal si, 1
; make sure its within sector range
and si, 0x1FF
add si, buf
; load word
lodsw
xor dx, dx
%endif
%ifdef FAT32
; multiply with 4
sal si, 1
sal si, 1
; make sure its within sector range
and si, 0x1FF
add si, buf
; load dword
lodsw
mov dx, [si]
%endif
ret
; reads current cluster into [dest]
readc: ; load cluster number
push ax
push dx
; subtract the two dummy entries from FAT start
sub ax, 2
sbb dx, 0
; convert cluster number to sector number
; this is some cheapo multiplication with 2^n
mov cl, [bp+bpb_sc]
l02: shr cl, 1
jz l02e
clc
rcl ax, 1
rcl dx, 1
jmp l02
l02e: l02e:
; dx:ax is now sector num in data area ; dx:ax is now sector num in data area
mov cx, [bp+bpb_sc] mov cx, [bp+bpb.clustersects]
xor ch, ch xor ch, ch
call readd call readd
xchg di, cx xchg di, cx
mov cl, 5 mov cl, 5
sal di, cl sal di, cl
add bx, di add bx, di
pop dx pop dx
pop ax pop ax
ret ret
; Load root directory ; Load root directory
loadr: loadr: mov ax, [bp+bpb.direntries]
%ifdef FAT32 mov cl, 4
mov ax, 2 shr ax, cl
xor dx, dx mov cx, ax
jmp load xor ax, ax
%else xor dx, dx
mov ax, [bp+bpb_rde] mov bx, 0x07C0
mov cl, 4 jmp readr
shr ax, cl
mov cx, ax
xor ax, ax
xor dx, dx
mov bx, 0x07C0
jmp readr
%endif
; Load file identified by fsattr ; Load file identified by fsattr
; Directory data is expected at 0x07C00 ; Directory data is expected at 0x07C00
loadf: mov si, (0x7C00-0x20) loadf: mov si, (0x7C00-0x20)
sloop: add si, 0x20 sloop: add si, 0x20
; check if entry is valid ; check if entry is valid
mov al, [si] mov al, [si]
; unallocated direntry ; unallocated direntry
test al, al test al, al
jnz ($+5) jnz ($+5)
call errcll call errcll
; deleted files ; deleted files
cmp al, 0xE2 cmp al, 0xE2
je sloop je sloop
; check attr ; check attr
mov al, [si+11] mov al, [si+11]
and al, 0x5C and al, 0x5C
cmp al, ah cmp al, ah
jne sloop jne sloop
mov ax, [si+0x1A] mov ax, [si+0x1A]
mov dx, [si+0x14] mov dx, [si+0x14]
; Load cluster chain DX:AX to 0x07C00 ; Load cluster chain DX:AX to 0x07C00
load: mov bx, 0x07C0 load: mov bx, 0x07C0
lloop: call readc lloop: call readc
call next call next
%ifdef FAT12 %ifdef FAT12
cmp word ax, 0x0FF8 cmp word ax, 0x0FF8
%endif %endif
%ifdef FAT16 %ifdef FAT16
cmp word ax, 0xFFF8 cmp word ax, 0xFFF8
%endif %endif
%ifdef FAT32 jc lloop
cmp word dx, 0x0FFF ret
%endif
jc lloop
ret
main: ; Set up BP to point to BPB main: ; Set up BP to point to BPB
; Relative addressing saves one instruction byte per access ; Relative addressing saves one instruction byte per access
mov bp, bpb mov bp, params
; Save DL contents ; Save DL contents
mov [bp+bpb7_dn], dl mov [bp+bpb.drivenum], dl
; load root directory ; load root directory
call loadr call loadr
; search for first system directory
mov ah, 0x14
call loadf
; search for first system file
mov ah, 0x04
call loadf
; restore drive number ; search for first system directory
mov dl, [bp+bpb7_dn] mov ah, 0x14
call loadf
; search for first system file
mov ah, 0x04
call loadf
; restore potential partition table ; restore drive number
pop si mov dl, [bp+bpb.drivenum]
pop ds
jmp 0x7C00 ; restore potential partition table
pop si
pop ds
; Padding and signature jmp 0x7C00
times (0x1FE - ($-$$)) db 0
dw 0xAA55 ; Padding and signature
times (0x1FE - ($-$$)) db 0
dw 0xAA55
buf: buf:

View File

@ -1,29 +1,17 @@
; DOS 3.31 Bios Parameter Block struc bpb
bpb_ss: equ 0x00 ; WORD sector size .sectorsize: resw 1 ; WORD sector size
bpb_sc: equ 0x02 ; BYTE sector / cluster .clustersects: resb 1 ; BYTE sector / cluster
bpb_rsc: equ 0x03 ; WORD reserved sector count .reservedsects: resw 1 ; WORD reserved sector count
bpb_fn: equ 0x05 ; BYTE fat number .fatnumber: resb 1 ; BYTE fat number
bpb_rde: equ 0x06 ; WORD root dir entries .direntries: resw 1 ; WORD root dir entries
bpb_ts: equ 0x08 ; WORD total sectors .total: resw 1 ; WORD total sectors
bpb_md: equ 0x0A ; BYTE media descriptor .mediadesc: resb 1 ; BYTE media descriptor
bpb_sf: equ 0x0B ; WORD sectors / fat .fatsectors: resw 1 ; WORD sectors / fat
bpb_spt: equ 0x0D ; WORD sectors per track .tracksectors: resw 1 ; WORD sectors per track
bpb_nos: equ 0x0F ; WORD number of sides .heads: resw 1 ; WORD number of sides
bpb_po: equ 0x11 ; DWORD partition offset .sectoroffset: resd 1 ; DWORD partition offset
bpb_lts: equ 0x15 ; DWORD large total sectors .longtotal: resd 1 ; DWORD large total sectors
.drivenum: resb 1 ; BYTE drive number
; DOS 4.0 Extended Bios Parameter Block .signature: resb 1 ; BYTE 28h
bpb4_dn: equ 0x19 ; BYTE drive number .serial: resd 1 ; DWORD serial
bpb4_sig: equ 0x1B ; BYTE 29h endstruc
bpb4_ser: equ 0x1C ; DWORD serial
; DOS 7.1 Extended Bios Parameter Block
bpb7_lsf: equ 0x19 ; DWORD large sectors / fat
bpb7_rdc: equ 0x21 ; DWORD root directory cluster
bpb7_fsc: equ 0x25 ; WORD fsinfo sector
bpb7_bsc: equ 0x27 ; WORD backup boot sector
bpb7_dn: equ 0x35 ; BYTE drive number
bpb7_sig: equ 0x37 ; BYTE 28h or 29h
bpb7_ser: equ 0x38 ; DWORD serial
bpb_len: equ 0x4F