diff --git a/include/fat32/FAT32_SYS.nasm b/include/fat32/FAT32_SYS.nasm new file mode 100644 index 0000000..ed4e503 --- /dev/null +++ b/include/fat32/FAT32_SYS.nasm @@ -0,0 +1,160 @@ +; Copyright (C) 2025 Elaina Claus +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see . + +%ifndef __INC_FAT32_SYS + +%include "partition_table.inc" +%include "fat32/bpb_offset_bx.inc" +%include "fat32/fat32_structures.inc" + +; Prototyping for now... + +; TODO: +; - bio_read_sectors (BIOS int13h LBA or CHS) + tiny sector cache. +; - mount: parse BPB, derive fat0_lba, data_lba, cluster0_lba. +; - FAT read: fat32_read_fat, fat32_next_clus. +; - dir iterator (SFN only) + path lookup. +; - file reader (fopen/fread) with cluster crossing. +; - contiguity probe for speed (optional). +; - (later) LFN support & code page handling. + + +; keep count <= 127 +; int bio_read_sectors(uint64_t lba, uint16_t count, void* dst); +; will also need a bio_bios_int13h() (refactor ext_disk_read?) +; to abstract the backend 'sector getter' + +; Error codes + +; FS_OK 0 +; FS_E_IO 1 (bio read failed) +; FS_E_FMT 2 (not FAT32 or bad BPB) +; FS_E_RANGE 3 (bad cluster or out of range) +; FS_E_END 4 (iterator end) +; FS_E_NOSUCH 5 (file/dir not found) +; FS_E_ISDIR 6 (opened dir as file) +; FS_E_TOOLONG 7 (path segment too long for 8.3) +; FS_E_UNSUPPORTED 8 (LFN present but disabled) +; FS_E_UNIMPLEMENTED 0xffff (procedure call unimplmented) + +; +; Cache methods +; +; TODO: make a cache for ~4-8 disk sectors +; TODO: make a cache for FATs to avoid having to re-read the FAT +; +; // uses bio_read_sectors + cache +; int cache_read_sector(uint64_t lba, void* dst); +; int cache_invalidate_all(void); + +; what a 'mount' should probably do at this point... +; - read VBR at partition_lba +; - validate FAT32 signatures +; - fill fat32_bpb_t and compute derived fields +; - read FSInfo (free count/next free) +; - ??? +; int fat32_mount(uint32_t partition_lba, fat32_bpb_t* out); + + +; +; Accessors +; + +; // Convert cluster -> LBA of first sector of that cluster +; uint64_t clus_to_lba(const fat32_bpb_t* v, uint32_t clus) { +; return v->data_lba + (uint64_t)(clus - 2) * v->secs_per_clus; +; } + +; FAT32 entry is 32-bits; only low 28 bits are meaningful. +; EOC if (val & 0x0FFFFFFF) >= 0x0FFFFFF8. +; bad if == 0x0FFFFFF7. +; free if == 0x00000000. + +; // Read 32-bit FAT entry for cluster n +; int fat32_read_fat(const fat32_bpb_t* v, uint32_t clus, uint32_t* out); + +; // Walk to next cluster in chain (validates EOC/bad) +; int fat32_next_clus(const fat32_bpb_t* v, uint32_t clus, uint32_t* out_next); + +; +; SFN directories +; + +; typedef struct { +; char name83[12]; // "FILENAMEEXT" (no dot), NUL-terminated +; uint8_t attr; // ATTR_DIRECTORY=0x10, ATTR_VOLUME=0x08 +; uint32_t first_clus; // (hi<<16)|lo +; uint32_t size; // bytes +; } fat32_dirent_sfn_t; + +; typedef struct { // iterator +; fat32_bpb_t* v; +; uint32_t cur_clus; +; uint32_t offs_in_clus; // byte offset +; } fat32_dir_iter_t; + +;int fat32_dir_iter_open_root(fat32_bpb_t* v, fat32_dir_iter_t* it); +;int fat32_dir_iter_open(fat32_bpb_t* v, uint32_t first_clus, fat32_dir_iter_t* it); +;int fat32_dir_iter_next(fat32_dir_iter_t* it, fat32_dirent_sfn_t* out); // FS_OK or FS_E_END + + +; typedef struct { +; uint32_t first_clus; +; uint32_t size; +; uint8_t attr; // dir or file +; } fat32_node_t; + +; split by / or \. +; start at root (v->root_clus). +; for each component: +; iterate directory with dir_iter_* to find case-insensitive 8.3 match (fold to upper and space-pad during compare). +; if final component: return file’s cluster & size. +; if intermediate: ensure ATTR_DIRECTORY and descend. +; +; int fat32_path_lookup(fat32_bpb_t* v, const char* path, fat32_node_t* out); + +; an example 'do the thing' proc to load a file to a location +; +; // loads file at path into dst, up to max_bytes; returns size read. +; int fat32_load_file(fat32_bpb_t* v, const char* path, void* dst, +; uint32_t max_bytes, uint32_t* out_size); + +; streamed reads +; +; typedef struct { +; fat32_bpb_t* v; +; uint32_t first_clus; +; uint32_t cur_clus; +; uint32_t cur_clus_index; // which cluster within file we’re on +; uint32_t size; // total bytes +; uint32_t pos; // current byte position +; } fat32_file_t; +; +; +; int fat32_fopen(fat32_bpb_t* v, const char* path, fat32_file_t* f); +; int fat32_fread(fat32_file_t* f, void* dst, uint32_t nbytes, uint32_t* out_read); +; int fat32_fseek(fat32_file_t* f, uint32_t new_pos); // forward seeks only is fine +; int fat32_fclose(fat32_file_t* f); + + +; an example 'do the thing' proc to load a file to a location +; +; // loads file at path into dst, up to max_bytes; returns size read. +; int fat32_load_file(fat32_bpb_t* v, const char* path, void* dst, +; uint32_t max_bytes, uint32_t* out_size); + + +%endif +%define __INC_FAT32_SYS \ No newline at end of file