diff options
Diffstat (limited to 'src/kernel/fs.c')
-rw-r--r-- | src/kernel/fs.c | 106 |
1 files changed, 84 insertions, 22 deletions
diff --git a/src/kernel/fs.c b/src/kernel/fs.c index 129e631..0d51c22 100644 --- a/src/kernel/fs.c +++ b/src/kernel/fs.c @@ -4,17 +4,26 @@ #include "fat.h" #include <stdbool.h> #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 start_cluster; - uint16_t seek; + uint16_t first_cluster; uint16_t loaded_cluster; - bool dirty; + uint32_t seek; + uint32_t length; + uint8_t flags; }; struct handle_info handles[MAX_HANDLES]; @@ -22,61 +31,114 @@ struct handle_info handles[MAX_HANDLES]; void clear_fs_handles() { struct handle_info *f = handles; while (f < handles + MAX_HANDLES) - (f++)->start_cluster = 0; + (f++)->first_cluster = 0; } fs_handle next_handle() { fs_handle r = 0; - while (HANDLE(++r).start_cluster) + while (HANDLE(++r).first_cluster) if (r == MAX_HANDLES) return 0; return r; } void write_buffer(fs_handle handle) { - HANDLE(handle).dirty = false; - panic("Not implemented (write_buffer)."); + 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).dirty) + if (HANDLE(handle).flags & FH_DIRTY) write_buffer(handle); - HANDLE(handle).loaded_cluster = HANDLE(handle).seek >> 9; - panic("Not implemented (read_buffer)."); + 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; - uint16_t s = get_start_cluster(path); - if (!s) + struct directory_entry e; + if (get_entry(path, &e)) return 0; - HANDLE(next).start_cluster = s; + HANDLE(next).first_cluster = e.first_cluster; HANDLE(next).seek = 0; - HANDLE(next).dirty = false; + 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; } -int16_t fs_seek(fs_handle handle, int16_t by) { - uint16_t old = HANDLE(handle).seek; - uint16_t to = -by > old ? 0 : old + by; +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; } -uint16_t fs_read(fs_handle handle, uint16_t max, void *buffer) { - panic("Not implemented (fs_read)."); +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; } -uint16_t fs_write(fs_handle handle, uint16_t max, void *buffer) { +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).dirty) + if (HANDLE(handle).flags & FH_DIRTY) write_buffer(handle); - HANDLE(handle).start_cluster = 0; + HANDLE(handle).first_cluster = 0; }
\ No newline at end of file |