#include #include "fs.h" #include "ata.h" #include "fat.h" #include #include "panic.h" #include "util.h" #define MAX_HANDLES 32 #define FILE_BUFFER(h) ((void *)(0x0002be00 + (h << 9))) #define HANDLE(h) ((handles - 1)[h]) #define HEAD(h) (FILE_BUFFER(h) + HANDLE(h).seek % 512) enum { FH_DIRTY = 0x01, FH_NO_WRITE = 0x02, FH_NO_EXPAND = 0x04, FH_ROOT = 0x08 }; struct handle_info { uint16_t first_cluster; uint16_t loaded_cluster; uint32_t seek; uint32_t length; uint8_t flags; }; struct handle_info handles[MAX_HANDLES]; void clear_fs_handles() { struct handle_info *f = handles; while (f < handles + MAX_HANDLES) (f++)->first_cluster = 0; } fs_handle next_handle() { fs_handle r = 0; while (HANDLE(++r).first_cluster) if (r == MAX_HANDLES) return 0; return r; } void write_buffer(fs_handle handle) { HANDLE(handle).flags &= ~FH_DIRTY; if (HANDLE(handle).flags & FH_ROOT) write_sectors(HANDLE(handle).loaded_cluster, 1, FILE_BUFFER(handle)); else write_sectors(CTOS(HANDLE(handle).loaded_cluster), 1, FILE_BUFFER(handle)); } void read_buffer(fs_handle handle) { if (HANDLE(handle).flags & FH_DIRTY) write_buffer(handle); uint16_t s = HANDLE(handle).seek >> 9; if (HANDLE(handle).flags & FH_ROOT) { HANDLE(handle).loaded_cluster = HANDLE(handle).first_cluster + s; read_sectors(HANDLE(handle).first_cluster + s, 1, FILE_BUFFER(handle)); } else { uint16_t c = HANDLE(handle).first_cluster; while (s--) c = FAT[c]; HANDLE(handle).loaded_cluster = c; read_sectors(CTOS(c), 1, FILE_BUFFER(handle)); } } fs_handle fs_open(uint8_t *path) { fs_handle next = next_handle(); if (!next) return 0; struct directory_entry e; if (get_entry(path, &e)) return 0; HANDLE(next).first_cluster = e.first_cluster; HANDLE(next).seek = 0; HANDLE(next).length = e.length; HANDLE(next).flags = (e.attrib & FA_READ_ONLY ? FH_NO_WRITE : 0) | (e.attrib & FA_SYSTEM ? FH_NO_EXPAND : 0); read_buffer(next); return next; } fs_handle fs_open_root() { fs_handle next = next_handle(); if (!next) return 0; HANDLE(next).first_cluster = FAT_INFO->reserved_sectors + FAT_INFO->sectors_per_fat; HANDLE(next).seek = 0; HANDLE(next).length = FAT_INFO->root_entries * 32; HANDLE(next).flags = FH_NO_EXPAND | FH_ROOT; read_buffer(next); return next; } int32_t fs_seek(fs_handle handle, int32_t by) { uint32_t old = HANDLE(handle).seek; uint32_t to = -by > old ? 0 : old + by > HANDLE(handle).length ? HANDLE(handle).length : old + by; HANDLE(handle).seek = to; if ((to ^ old) & 0xfe00) read_buffer(handle); return to - old; } uint32_t fs_read(fs_handle handle, uint32_t max, void *buffer) { max = HANDLE(handle).seek + max > HANDLE(handle).length ? HANDLE(handle).length - HANDLE(handle).seek : max; uint32_t left = max, eos = 512 - (HANDLE(handle).seek & 0x1ff); if (left < eos) { memcpy(buffer, FILE_BUFFER(handle) + (HANDLE(handle).seek & 0x1ff), left); HANDLE(handle).seek += left; return max; } memcpy(buffer, FILE_BUFFER(handle) + (HANDLE(handle).seek & 0x1ff), eos); left -= eos; buffer += eos; HANDLE(handle).seek += eos; while (left >= 512) { read_buffer(handle); memcpy(buffer, FILE_BUFFER(handle), 512); left -= 512; buffer += 512; HANDLE(handle).seek += 512; } if (left) { read_buffer(handle); memcpy(buffer, FILE_BUFFER(handle), left); HANDLE(handle).seek += left; } return max; } uint32_t fs_write(fs_handle handle, uint32_t max, void *buffer) { if (HANDLE(handle).flags & FH_NO_WRITE) return 0; panic("Not implemented (fs_write)."); } void fs_close(fs_handle handle) { if (HANDLE(handle).flags & FH_DIRTY) write_buffer(handle); HANDLE(handle).first_cluster = 0; }