diff options
-rw-r--r-- | doc/internal/gdt.txt | 3 | ||||
-rw-r--r-- | doc/internal/mem.txt | 9 | ||||
-rw-r--r-- | makefile | 2 | ||||
-rw-r--r-- | src/boot.asm | 4 | ||||
-rw-r--r-- | src/kernel/fat.c | 82 | ||||
-rw-r--r-- | src/kernel/fat.h | 37 | ||||
-rw-r--r-- | src/kernel/fs.c | 106 | ||||
-rw-r--r-- | src/kernel/fs.h | 7 | ||||
-rw-r--r-- | src/kernel/main.c | 50 | ||||
-rw-r--r-- | src/kernel/panic.c | 5 | ||||
-rw-r--r-- | src/kernel/util.c | 11 | ||||
-rw-r--r-- | src/kernel/util.h | 2 | ||||
-rw-r--r-- | src/kernel/vga.inc | 11 |
13 files changed, 251 insertions, 78 deletions
diff --git a/doc/internal/gdt.txt b/doc/internal/gdt.txt index 6f5e1f4..0a8b5ea 100644 --- a/doc/internal/gdt.txt +++ b/doc/internal/gdt.txt @@ -1,3 +1,2 @@ 0x08: 0x0000.0000 - 0x0007.ffff (code) -0x10: 0x0000.0000 - 0x000f.ffff (data) -0x18: 0x0003.8000 - 0x0003.ffff (stack)
\ No newline at end of file +0x10: 0x0000.0000 - 0x000f.ffff (data)
\ No newline at end of file diff --git a/doc/internal/mem.txt b/doc/internal/mem.txt index cc5d301..ea96d13 100644 --- a/doc/internal/mem.txt +++ b/doc/internal/mem.txt @@ -1,8 +1,7 @@ -0x0001.0000 - 0x0002.5fff: unused -0x0002.6000 - 0x0002.bfff: fat +0x0001.0000 - 0x0001.ffff: unused +0x0002.0000 - 0x0002.7fff: fat +0x0002.8000 - 0x0002.bfff: unused 0x0002.c000 - 0x0002.ffff: file buffers 0x0003.0000 - 0x0003.7fff: kernel 0x0003.8000 - 0x0003.ffff: stack -0x0004.0000 - 0x0007.ffff: unused -0x0008.0000 - 0x000d.9fff: ramd -0x000d.a000 - 0xffff.ffff: unused
\ No newline at end of file +0x0004.0000 - 0x000f.ffff: unused
\ No newline at end of file @@ -1,6 +1,6 @@ disk: kernel boot mkdir -p obj out - /sbin/mkfs.fat -C -f 1 -F 12 -n "PORTLAND OS" -R 17 obj/shadow.img 8192 + /sbin/mkfs.fat -C -f 1 -F 16 -n "PORTLAND OS" -R 17 -s 1 -S 512 obj/shadow.img 8192 echo -n -e '\xeb\x3c' > obj/jmp.bin dd if=obj/jmp.bin of=obj/shadow.img obs=2 conv=notrunc dd if=out/boot.bin of=obj/shadow.img obs=1 seek=62 conv=notrunc diff --git a/src/boot.asm b/src/boot.asm index f8ff1c8..8e463be 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -39,9 +39,8 @@ bits 32 pmode: mov ax, 0x10 mov ds, ax - mov ax, 0x18 mov ss, ax - mov esp, 0x00008000 + mov esp, 0x00040000 xor ebp, ebp call kernel_segment * 16 @@ -57,7 +56,6 @@ gdt: dq 0x0000_0000_0000_0000 dq 0x00c0_9a00_0000_007f dq 0x00c0_9200_0000_00ff - dq 0x0040_9203_8000_7fff .e: times $$ + 448 - $ db 0 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 |