summaryrefslogtreecommitdiff
path: root/src/kernel/fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/fs.c')
-rw-r--r--src/kernel/fs.c106
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