summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/fat.c82
-rw-r--r--src/kernel/fat.h37
-rw-r--r--src/kernel/fs.c106
-rw-r--r--src/kernel/fs.h7
-rw-r--r--src/kernel/main.c50
-rw-r--r--src/kernel/panic.c5
-rw-r--r--src/kernel/util.c11
-rw-r--r--src/kernel/util.h2
-rw-r--r--src/kernel/vga.inc11
9 files changed, 244 insertions, 67 deletions
diff --git a/src/kernel/fat.c b/src/kernel/fat.c
index 00fa61f..e574da5 100644
--- a/src/kernel/fat.c
+++ b/src/kernel/fat.c
@@ -1,21 +1,87 @@
#include "fat.h"
#include "ata.h"
#include "panic.h"
+#include "fs.h"
void load_fat() {
read_sectors(FAT_INFO->reserved_sectors, FAT_INFO->sectors_per_fat, FAT);
}
-uint16_t get_cluster(uint16_t n) {
- uint32_t t = *(uint32_t *)(FAT + (n / 2) * 3);
- return (n % 2 ? (t >> 12) : t) & 0xfff;
+bool check_fat_name(uint8_t *fname, uint8_t *sname) {
+ panic("Not implemented (check_fat_name)");
}
-void set_cluster(uint16_t n, uint16_t v) {
- uint32_t *t = (uint32_t *)(FAT + (n / 2) * 3);
- *t = (*t & (n % 2 ? 0xff000fff : 0xfffff000)) | (n % 2 ? v << 12 : v);
+bool check_fat_names(uint8_t *lname, uint8_t *rname) {
+ return (* (uint32_t *)lname == *(uint32_t *)rname) &&
+ (*((uint32_t *)lname + 1) == *((uint32_t *)rname + 1)) &&
+ (*((uint16_t *)lname + 4) == *((uint16_t *)rname + 4)) &&
+ (*( lname + 10) == *( rname + 10));
}
-uint16_t get_start_cluster(uint8_t *path) {
- panic("Not implemented (get_start_cluster).");
+struct directory_entry buffer[16];
+uint16_t dir_start, buffer_from;
+
+
+void load_root() {
+ dir_start = FAT_INFO->reserved_sectors + FAT_INFO->sectors_per_fat;
+}
+
+struct directory_entry *load_subentry(uint8_t *name) {
+ struct directory_entry *ptr = buffer;
+ uint16_t dir_current = dir_start;
+ do
+ if (((ptr == buffer + 16) && !read_sectors(buffer_from = dir_current++, 1, ptr = buffer)) || !ptr->name[0])
+ return 0;
+ while (!check_fat_name(ptr->name, name));
+ return ptr;
+}
+
+bool load_subdir(uint8_t *name) {
+ struct directory_entry *e = load_subentry(name);
+ if (!e)
+ return true;
+ dir_start = e->first_cluster;
+ return false;
+}
+
+struct directory_entry *load_entry(uint8_t *path) {
+ load_root();
+ for (uint8_t *ptr = path; ptr; ++ptr)
+ if (*ptr = '/') {
+ *ptr = 0;
+ if (load_subdir(path))
+ return 0;
+ path = ptr + 1;
+ }
+ return load_subentry(path);
+}
+
+bool get_entry(uint8_t *path, struct directory_entry *at) {
+ struct directory_entry *e = load_entry(path);
+ if (!e)
+ return true;
+ *at = *e;
+ return false;
+}
+
+bool update_entry(uint8_t *path, struct directory_entry *value) {
+ struct directory_entry *e = load_entry(path);
+ if (!e)
+ return true;
+ *e = *value;
+ write_sectors(buffer_from, 1, buffer);
+ return false;
+}
+
+bool create_entry(uint8_t *dir_path, struct directory_entry *value) {
+ fs_handle h = fs_open(dir_path);
+ struct directory_entry *check;
+ while (fs_read(h, 32, check))
+ if (check_fat_names(check->name, value->name)) {
+ fs_close(h);
+ return true;
+ }
+ fs_write(h, 32, value);
+ fs_close(h);
+ return false;
} \ No newline at end of file
diff --git a/src/kernel/fat.h b/src/kernel/fat.h
index 0fbf59f..73eaaae 100644
--- a/src/kernel/fat.h
+++ b/src/kernel/fat.h
@@ -1,4 +1,5 @@
#include <stdint.h>
+#include <stdbool.h>
#define FAT_INFO ((struct fat_info *)0x7c03)
@@ -24,9 +25,37 @@ struct fat_info {
uint8_t fs_type[8];
} __attribute__ ((packed));
-#define FAT ((void *)0x00026000)
+enum {
+ FA_READ_ONLY = 0x01,
+ FA_HIDDEN = 0x02,
+ FA_SYSTEM = 0x04,
+ FA_LABEL = 0x08,
+ FA_DIRECTORY = 0x10,
+ FA_ARCHIVE = 0x20,
+
+ FA_LFN = 0x0f
+};
+
+struct directory_entry {
+ uint8_t name[11];
+ uint8_t attrib;
+ uint8_t name_case;
+ uint8_t created_decimal;
+ uint16_t created_time;
+ uint16_t created_date;
+ uint16_t accessed_date;
+ uint16_t ignore;
+ uint16_t modified_time;
+ uint16_t modified_date;
+ uint16_t first_cluster;
+ uint32_t length;
+} __attribute__ ((packed));
+
+#define FAT ((uint16_t *)0x00020000)
void load_fat();
-uint16_t get_cluster(uint16_t n);
-void set_cluster(uint16_t n, uint16_t v);
-uint16_t get_start_cluster(uint8_t *path); \ No newline at end of file
+#define CTOS(c) (FAT_INFO->reserved_sectors + FAT_INFO->sectors_per_fat + (FAT_INFO->root_entries >> 4) + (c) - 2)
+
+bool get_entry(uint8_t *path, struct directory_entry *at);
+bool update_entry(uint8_t *path, struct directory_entry *value);
+bool create_entry(uint8_t *path, struct directory_entry *value); \ No newline at end of file
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
diff --git a/src/kernel/fs.h b/src/kernel/fs.h
index 821d810..e2b14c0 100644
--- a/src/kernel/fs.h
+++ b/src/kernel/fs.h
@@ -4,7 +4,8 @@ void clear_fs_handles();
typedef uint8_t fs_handle;
fs_handle fs_open(uint8_t *path);
-int16_t fs_seek(fs_handle handle, int16_t by);
-uint16_t fs_read(fs_handle handle, uint16_t max, void *buffer);
-uint16_t fs_write(fs_handle handle, uint16_t max, void *buffer);
+fs_handle fs_open_root();
+int32_t fs_seek(fs_handle handle, int32_t by);
+uint32_t fs_read(fs_handle handle, uint32_t max, void *buffer);
+uint32_t fs_write(fs_handle handle, uint32_t max, void *buffer);
void fs_close(fs_handle handle); \ No newline at end of file
diff --git a/src/kernel/main.c b/src/kernel/main.c
index 877a276..194ce93 100644
--- a/src/kernel/main.c
+++ b/src/kernel/main.c
@@ -16,21 +16,43 @@ void main() {
vga_printsz("\n Serial ready.");
load_fat();
clear_fs_handles();
- vga_printsz("\n File system ready.\n\nDisk label: ");
+ vga_printsz("\n File system ready.\n\nDisk info:\n Disk label: ");
vga_printsn(FAT_INFO->label, 11);
- vga_printsz("\nDisk size: ");
- u32_dec(FAT_INFO->sectors >> 1, nbuf);
+ vga_printsz("\n Disk size: ");
+ u16_dec(FAT_INFO->sectors >> 1, nbuf);
vga_printsz(nbuf);
- vga_printsz("k\n\nFAT start:\n");
- nbuf[3] = 0;
- for (uint8_t r = 0; r < 192; r += 24) {
- for (uint8_t c = 0; c < 24; ++c) {
- u8_hex(*(uint8_t *)(FAT + r + c), nbuf);
- nbuf[2] = ' ';
- vga_printsz(nbuf);
- }
- vga_printch('\n');
+ vga_printsz("k\n FAT size: ");
+ u16_dec(FAT_INFO->sectors_per_fat >> 1, nbuf);
+ vga_printsz(nbuf);
+ vga_printsz("k\n Root size: ");
+ u16_dec(FAT_INFO->root_entries >> 5, nbuf);
+ vga_printsz(nbuf);
+ vga_printsz("k\n\nRoot directory:");
+ fs_handle root = fs_open_root();
+ struct directory_entry e;
+ while(1) {
+ fs_read(root, 32, &e);
+ if (!e.name[0])
+ break;
+ if (e.attrib == FA_LFN)
+ continue;
+ uint8_t *p = (uint8_t *)&e;
+ nbuf[3] = 0;
+ vga_printsz("\n ");
+ vga_printsn((uint8_t *)&e.name, 11);
+ vga_printsz(" | 0x");
+ u8_hex(e.attrib, nbuf);
+ vga_printsz(nbuf);
+ vga_printch(' ');
+ vga_printch(e.attrib & FA_READ_ONLY ? 'R' : '_');
+ vga_printch(e.attrib & FA_HIDDEN ? 'H' : '_');
+ vga_printch(e.attrib & FA_SYSTEM ? 'S' : '_');
+ vga_printch(e.attrib & FA_LABEL ? 'L' : '_');
+ vga_printch(e.attrib & FA_DIRECTORY ? 'D' : '_');
+ vga_printch(e.attrib & FA_ARCHIVE ? 'A' : '_');
+ vga_printsz(" | ");
+ u32_dec(e.length, nbuf);
+ vga_printsz(nbuf);
}
- while (1)
- asm ("hlt");
+ halt();
} \ No newline at end of file
diff --git a/src/kernel/panic.c b/src/kernel/panic.c
index 49d4a27..a463a2a 100644
--- a/src/kernel/panic.c
+++ b/src/kernel/panic.c
@@ -4,6 +4,7 @@
#include "util.h"
void halt() {
+ vga_printsz("\n\nHalting...");
while (1)
asm volatile ("hlt");
}
@@ -20,12 +21,12 @@ void panic(uint8_t *message) {
vga_printsz("\n\nStack trace:");
uint8_t stb[6];
while (1) {
- uint32_t ip = *(uint32_t *)(0x38000 + frame + 4);
+ uint32_t ip = *((uint32_t *)frame + 1);
if (!ip)
halt();
vga_printsz("\n 0x");
u16_hex(ip - 0x30000 - 5, stb);//assumes would return to just after a call instruction
vga_printsz(stb);
- frame = *(uint32_t *)(0x38000 + frame);
+ frame = *(uint32_t *)frame;
}
} \ No newline at end of file
diff --git a/src/kernel/util.c b/src/kernel/util.c
index df6e7d8..c7a5035 100644
--- a/src/kernel/util.c
+++ b/src/kernel/util.c
@@ -2,8 +2,15 @@
#include "panic.h"
#include <stdbool.h>
-void memcpy(void *from, void *to, uint32_t n) {
- panic("Not implemented (memcpy).");
+void memcpy(void *to, void *from, uint32_t n) {
+ uint32_t *tp = to, *fp = from;
+ while (n >= 4) {
+ *(tp++) = *(fp++);
+ n -= 4;
+ }
+ uint8_t *tpp = (uint8_t *)tp, *fpp = (uint8_t *)fp;
+ while (n--)
+ *(tpp++) = *(fpp++);
}
void u32_dec(uint32_t n, uint8_t *b) {
diff --git a/src/kernel/util.h b/src/kernel/util.h
index 08b3e4a..e02c819 100644
--- a/src/kernel/util.h
+++ b/src/kernel/util.h
@@ -1,6 +1,6 @@
#include <stdint.h>
-void memcpy(void *from, void *to, uint32_t n);
+void memcpy(void *to, void *from, uint32_t n);
void outb(uint16_t port, uint8_t value);
uint8_t inb(uint16_t port);
void outw(uint16_t port, uint16_t value);
diff --git a/src/kernel/vga.inc b/src/kernel/vga.inc
deleted file mode 100644
index c7244e1..0000000
--- a/src/kernel/vga.inc
+++ /dev/null
@@ -1,11 +0,0 @@
-extern vga_set_color
-extern vga_blank
-extern vga_scroll
-extern vga_printch
-extern vga_printsz
-extern vga_printsn
-extern vga_printu32
-extern vga_printu16
-extern vga_printu8
-extern vga_printu32h
-extern vga_printu8h \ No newline at end of file