From 9cd4c04c42224de3d0f7e4e9debe9a4716ea5c6d Mon Sep 17 00:00:00 2001 From: Ain <41307858+nero@users.noreply.github.com> Date: Tue, 15 Sep 2020 21:38:26 +0200 Subject: [PATCH] Make kernel and fat.bs use BPB struct --- Makefile | 11 +- boot/fat.asm | 526 ++++++++++++++++++++++----------------------------- inc/bpb.asm | 46 ++--- 3 files changed, 247 insertions(+), 336 deletions(-) diff --git a/Makefile b/Makefile index d83cba9..8acbb1d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -FLOPPY = 360 +FLOPPY = 1440 PROGRAMS = hello.com DISTFILES = $(PROGRAMS) kernel.bs @@ -55,15 +55,6 @@ fat4.bs: boot/fat.asm fat6.bs: boot/fat.asm $(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 %.rom: rom/%.asm utils/fix-rom $(NASM) $(NASM_ARGS) -o $@ $< && utils/fix-rom $@ diff --git a/boot/fat.asm b/boot/fat.asm index cdbe931..37228f4 100644 --- a/boot/fat.asm +++ b/boot/fat.asm @@ -1,338 +1,270 @@ - ; Bootsector for FAT32 filesystems - ; Takes defines: - ; FAT12 FAT has 1.5 bytes per entry - ; FAT16 FAT has WORD per entry - ; FAT32 FAT has DWORD per entry - ; CHS uses int13h/AH=02h - ; LARGE requires 32 bit sector numbers - ; LBA uses int13h/AH=42h - cpu 8086 + ; Bootsector for FAT12/FAT16 filesystems + ; Takes defines: + ; FAT12 FAT has 1.5 bytes per entry + ; FAT16 FAT has WORD per entry + cpu 8086 - org 0x0800 - jmp short init - nop + org 0x0800 + jmp short init + nop - %include "inc/bpb.asm" + %include "inc/bpb.asm" -bpb: equ 0x080B + times ( 0x0B - ($-$$) ) db 0 - ; Area for BPB - %ifdef FAT32 - times ( 0x5A - ($-$$) ) db 0 - %else - times ( 0x3E - ($-$$) ) db 0 - %endif +params: times bpb_size db 0 -init: xor ax, ax - mov ss, ax - mov sp, 0x7C00 + ; Area for BPB + times ( 0x3E - ($-$$) ) db 0 - ; save potential partition table entry - push ds - push si +init: xor ax, ax + mov ss, ax + mov sp, 0x7C00 - mov ds, ax - mov es, ax + ; save potential partition table entry + push ds + push si - mov si, 0x7C00 - mov di, 0x0800 - mov cx, 0x0100 - rep movsw - jmp 0x0:main + mov ds, ax + mov es, ax - %include "inc/booterr.asm" + mov si, 0x7C00 + mov di, 0x0800 + mov cx, 0x0100 + rep movsw + jmp 0x0:main - ; offsets relative to FS -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 + %include "inc/booterr.asm" - %ifdef LBA -read_: ; read sector DX:AX from disk - ; this uses the EBIOS extensions - ; qword sector number DX:AX - push cs - push cs - push dx - push ax + ; offsets relative to FS +readd: ; add offset of cluster data area to DX:AX + push cx + mov di, [bp+bpb.direntries] + 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.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 - push bx - push cs +read_: ; read sector DX:AX from disk + ; uses basic CHS disk IO + ; 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 - push cx + ; calculate CHS data + 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 - mov di, 0x10 - push di + ; set up read buffer + mov es, bx + xor bx, bx - mov si, sp - mov ah, 0x42 - mov dl, [bp+bpb7_dn] - stc - int 0x13 - jnc ($+5) - call errcll + ; call bios + mov ax, 0x0201 + int 0x13 + jnc ($+5) + call errcll - add sp, di + pop bx + pop dx + pop cx + pop ax - ret - %endif + ; increment sector num + write offset + add ax, 1 + adc dx, 0 + add bx, 0x20 + ; loop on CX + loop chslp + ret - %ifdef CHS -read_: ; read sector DX:AX from disk - ; uses basic CHS disk IO - ; 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 +next: ; Advances DX:AX to next FAT entry + push ax + push bx + ; shift 2 left for dword-sized FAT entries + ; shift 9 right for sector size + mov cl, 7 +shftl: clc + rcr dx, 1 + rcr ax, 1 + loop shftl - ; calculate CHS data - div word [bp+bpb_spt] ; ax:temp = (lba / spt) - inc dx ; dx:sector = (lba % spt) + 1 - mov cl, dl ; sector number - xor dx, dx - div word [bp+bpb_nos] ; ax:cylinder = (tmp / heads) - ; dx:head = (tmp % heads) - mov ch, al ; cylinder number - mov dh, dl ; head number - mov dl, [bp+bpb7_dn] ; drive number + mov bx, 0xA0 + %ifdef FAT12 + ; FAT item might span over two sectors + mov cx, 2 + %else + mov cx, 1 + %endif + call readf - ; set up read buffer - mov es, bx - xor bx, bx + pop bx - ; call bios - mov ax, 0x0201 - int 0x13 - jnc ($+5) - call errcll + ; get address of cluster within sector + pop si + %ifdef FAT12 + push si + ; 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 - pop dx - pop cx - pop ax + %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 - ; increment sector num + write offset - add ax, 1 - adc dx, 0 - add bx, 0x20 - ; loop on CX - loop chslp - ret - %endif + ret -next: ; Advances DX:AX to next FAT entry - push ax - push bx - ; shift 2 left for dword-sized FAT entries - ; shift 9 right for sector size - mov cl, 7 -shftl: clc - rcr dx, 1 - rcr ax, 1 - loop shftl + ; reads current cluster into [dest] +readc: ; load cluster number + push ax + push dx - mov bx, 0xA0 - %ifdef FAT12 - ; FAT item might span over two sectors - mov cx, 2 - %else - mov cx, 1 - %endif - call readf + ; subtract the two dummy entries from FAT start + sub ax, 2 + sbb dx, 0 - pop bx - - ; get address of cluster within sector - pop si - %ifdef FAT12 - push si - ; 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 - - %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 + ; convert cluster number to sector number + ; this is some cheapo multiplication with 2^n + mov cl, [bp+bpb.clustersects] +l02: shr cl, 1 + jz l02e + clc + rcl ax, 1 + rcl dx, 1 + jmp l02 l02e: - ; dx:ax is now sector num in data area - mov cx, [bp+bpb_sc] - xor ch, ch + ; dx:ax is now sector num in data area + mov cx, [bp+bpb.clustersects] + xor ch, ch - call readd + call readd - xchg di, cx - mov cl, 5 - sal di, cl - add bx, di + xchg di, cx + mov cl, 5 + sal di, cl + add bx, di - pop dx - pop ax + pop dx + pop ax - ret + ret - ; Load root directory -loadr: - %ifdef FAT32 - mov ax, 2 - xor dx, dx - jmp load - %else - mov ax, [bp+bpb_rde] - mov cl, 4 - shr ax, cl - mov cx, ax - xor ax, ax - xor dx, dx - mov bx, 0x07C0 - jmp readr - %endif + ; Load root directory +loadr: mov ax, [bp+bpb.direntries] + mov cl, 4 + shr ax, cl + mov cx, ax + xor ax, ax + xor dx, dx + mov bx, 0x07C0 + jmp readr - ; Load file identified by fsattr - ; Directory data is expected at 0x07C00 -loadf: mov si, (0x7C00-0x20) -sloop: add si, 0x20 - ; check if entry is valid - mov al, [si] - ; unallocated direntry - test al, al - jnz ($+5) - call errcll - ; deleted files - cmp al, 0xE2 - je sloop - ; check attr - mov al, [si+11] - and al, 0x5C - cmp al, ah - jne sloop - mov ax, [si+0x1A] - mov dx, [si+0x14] + ; Load file identified by fsattr + ; Directory data is expected at 0x07C00 +loadf: mov si, (0x7C00-0x20) +sloop: add si, 0x20 + ; check if entry is valid + mov al, [si] + ; unallocated direntry + test al, al + jnz ($+5) + call errcll + ; deleted files + cmp al, 0xE2 + je sloop + ; check attr + mov al, [si+11] + and al, 0x5C + cmp al, ah + jne sloop + mov ax, [si+0x1A] + mov dx, [si+0x14] - ; Load cluster chain DX:AX to 0x07C00 -load: mov bx, 0x07C0 -lloop: call readc - call next - %ifdef FAT12 - cmp word ax, 0x0FF8 - %endif - %ifdef FAT16 - cmp word ax, 0xFFF8 - %endif - %ifdef FAT32 - cmp word dx, 0x0FFF - %endif - jc lloop - ret + ; Load cluster chain DX:AX to 0x07C00 +load: mov bx, 0x07C0 +lloop: call readc + call next + %ifdef FAT12 + cmp word ax, 0x0FF8 + %endif + %ifdef FAT16 + cmp word ax, 0xFFF8 + %endif + jc lloop + ret -main: ; Set up BP to point to BPB - ; Relative addressing saves one instruction byte per access - mov bp, bpb - ; Save DL contents - mov [bp+bpb7_dn], dl +main: ; Set up BP to point to BPB + ; Relative addressing saves one instruction byte per access + mov bp, params + ; Save DL contents + mov [bp+bpb.drivenum], dl - ; load root directory - call loadr - ; search for first system directory - mov ah, 0x14 - call loadf - ; search for first system file - mov ah, 0x04 - call loadf + ; load root directory + call loadr - ; restore drive number - mov dl, [bp+bpb7_dn] + ; search for first system directory + mov ah, 0x14 + call loadf + ; search for first system file + mov ah, 0x04 + call loadf - ; restore potential partition table - pop si - pop ds + ; restore drive number + mov dl, [bp+bpb.drivenum] - jmp 0x7C00 + ; restore potential partition table + pop si + pop ds - ; Padding and signature - times (0x1FE - ($-$$)) db 0 - dw 0xAA55 + jmp 0x7C00 + + ; Padding and signature + times (0x1FE - ($-$$)) db 0 + dw 0xAA55 buf: diff --git a/inc/bpb.asm b/inc/bpb.asm index 01f2f51..62d8232 100644 --- a/inc/bpb.asm +++ b/inc/bpb.asm @@ -1,29 +1,17 @@ -; DOS 3.31 Bios Parameter Block -bpb_ss: equ 0x00 ; WORD sector size -bpb_sc: equ 0x02 ; BYTE sector / cluster -bpb_rsc: equ 0x03 ; WORD reserved sector count -bpb_fn: equ 0x05 ; BYTE fat number -bpb_rde: equ 0x06 ; WORD root dir entries -bpb_ts: equ 0x08 ; WORD total sectors -bpb_md: equ 0x0A ; BYTE media descriptor -bpb_sf: equ 0x0B ; WORD sectors / fat -bpb_spt: equ 0x0D ; WORD sectors per track -bpb_nos: equ 0x0F ; WORD number of sides -bpb_po: equ 0x11 ; DWORD partition offset -bpb_lts: equ 0x15 ; DWORD large total sectors - -; DOS 4.0 Extended Bios Parameter Block -bpb4_dn: equ 0x19 ; BYTE drive number -bpb4_sig: equ 0x1B ; BYTE 29h -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 +struc bpb +.sectorsize: resw 1 ; WORD sector size +.clustersects: resb 1 ; BYTE sector / cluster +.reservedsects: resw 1 ; WORD reserved sector count +.fatnumber: resb 1 ; BYTE fat number +.direntries: resw 1 ; WORD root dir entries +.total: resw 1 ; WORD total sectors +.mediadesc: resb 1 ; BYTE media descriptor +.fatsectors: resw 1 ; WORD sectors / fat +.tracksectors: resw 1 ; WORD sectors per track +.heads: resw 1 ; WORD number of sides +.sectoroffset: resd 1 ; DWORD partition offset +.longtotal: resd 1 ; DWORD large total sectors +.drivenum: resb 1 ; BYTE drive number +.signature: resb 1 ; BYTE 28h +.serial: resd 1 ; DWORD serial +endstruc