diff --git a/bin/os b/bin/os index 7f55763..20c9734 100755 Binary files a/bin/os and b/bin/os differ diff --git a/image.hdd b/image.hdd index 83dddff..bc8add9 100644 Binary files a/image.hdd and b/image.hdd differ diff --git "a/image.hdd\r" "b/image.hdd\r" new file mode 100644 index 0000000..b33a060 Binary files /dev/null and "b/image.hdd\r" differ diff --git a/limine b/limine index e0e61c9..eecf8d6 160000 --- a/limine +++ b/limine @@ -1 +1 @@ -Subproject commit e0e61c946933696453f591da525ab1f8a66a553d +Subproject commit eecf8d682a749701691e31b89f66f330f525c611 diff --git a/obj/src/int.c.o b/obj/src/int.c.o index cb5e576..e9b0d98 100644 Binary files a/obj/src/int.c.o and b/obj/src/int.c.o differ diff --git a/obj/src/main.c.d b/obj/src/main.c.d index 5b08ec0..1a81cb1 100644 --- a/obj/src/main.c.d +++ b/obj/src/main.c.d @@ -1,19 +1,20 @@ obj/src/main.c.o: src/main.c src/../include/limine.h src/prompt/lex.h \ - src/prompt/file.h src/acpi.h src/common.h src/ahci.h src/alloc.h \ - src/apic.h src/fat32.h src/lib/stdio.h src/lib/malloc.h \ - src/lib/../common.h src/lib/../kbd.h src/lib/../print.h src/print.h + src/prompt/file.h src/prompt/file.h src/acpi.h src/common.h src/ahci.h \ + src/alloc.h src/apic.h src/fat32.h src/lib/ctype.h src/lib/string.h \ + src/lib/stdio.h src/lib/malloc.h src/lib/../kbd.h src/lib/../print.h src/../include/limine.h: src/prompt/lex.h: src/prompt/file.h: +src/prompt/file.h: src/acpi.h: src/common.h: src/ahci.h: src/alloc.h: src/apic.h: src/fat32.h: +src/lib/ctype.h: +src/lib/string.h: src/lib/stdio.h: src/lib/malloc.h: -src/lib/../common.h: src/lib/../kbd.h: src/lib/../print.h: -src/print.h: diff --git a/obj/src/main.c.o b/obj/src/main.c.o index 5767244..4ca8dc8 100644 Binary files a/obj/src/main.c.o and b/obj/src/main.c.o differ diff --git a/run.sh b/run.sh index d71d485..b3049a2 100644 --- a/run.sh +++ b/run.sh @@ -1,6 +1,6 @@ -qemu-system-x86_64 \ +# qemu-system-x86_64 \ +/mnt/c/'Program Files'/qemu/qemu-system-x86_64.exe \ -drive id=disk0,file=image.hdd,format=raw,if=none \ -device ich9-ahci,id=ahci0 \ -device ide-hd,drive=disk0,bus=ahci0.0 -#/mnt/c/'Program Files'/qemu/qemu-system-x86_64.exe image.hdd diff --git a/src/fat32.h b/src/fat32.h index ba75555..69d3b43 100644 --- a/src/fat32.h +++ b/src/fat32.h @@ -3,6 +3,8 @@ #include "ahci.h" #include "alloc.h" #include "common.h" +#include "lib/ctype.h" +#include "lib/string.h" #include "lib/stdio.h" // FAT32 BPB (BIOS Parameter Block) sits at the start of sector 0 @@ -141,3 +143,110 @@ enum fat32_attr { static u32 fat32_dirent_cluster(fat32_dirent_t* dirent) { return ((u32)dirent->cluster_high << 16) | dirent->cluster_low; } + +static void fat32_to_name83(const char* name, u8* out) { + memset(out, ' ', 11); + + const char* dot = NULL; + for (const char* p = name; *p; p++) { + if (*p == '.') dot = p; + } + + // copy base name (up to 8 chars) + int base_len = dot ? (int)(dot - name) : (int)strlen(name); + if (base_len > 8) base_len = 8; + for (int i = 0; i < base_len; i++) + out[i] = (u8) toupper((unsigned char)name[i]); + + // copy extension (up to 3 chars) + if (dot && dot[1]) { + const char* ext = dot + 1; + int ext_len = (int)strlen(ext); + if (ext_len > 3) ext_len = 3; + for (int i = 0; i < ext_len; i++) + out[8 + i] = (u8) toupper((unsigned char)ext[i]); + } +} + +static fat32_dirent_t* fat32_find(int port, fat32_vol_t* vol, u32 dir_cluster, const u8* name83) { + u32 cluster_size = vol->sectors_per_cluster * TODO_MAKE_ME_DYNAMIC_BLOCK_SIZE; + u8* buff = (u8*) alloc(cluster_size); + u32 cluster = dir_cluster; + + while (!fat32_is_eof(cluster)) { + if (fat32_read_cluster(port, vol, cluster, buff) < 0) { + printf("fat32_find: read failed at cluster=%u\n", cluster); + break; + } + + u32 entries_per_cluster = cluster_size / sizeof(fat32_dirent_t); + fat32_dirent_t* dir = (fat32_dirent_t*) buff; + + for (u32 i = 0; i < entries_per_cluster; i++) { + fat32_dirent_t* e = &dir[i]; + + if (e->name[0] == 0x00) goto not_found; + if (e->name[0] == 0xE5) continue; + if ((e->attr & ATTR_LFN) == ATTR_LFN) continue; + if (e->attr & ATTR_VOL_ID) continue; + + if (memcmp(e->name, name83, 8) == 0 && memcmp(e->ext, name83 + 8, 3) == 0) { + fat32_dirent_t* result = (fat32_dirent_t*) alloc(sizeof(fat32_dirent_t)); + *result = *e; + return result; + } + } + + cluster = fat32_next(port, vol, cluster); + } + +not_found: + return NULL; +} + + +// fat32_find_path: resolve a full path like "/dir/subdir/file.txt" +// leading slash is optional, "" or "/" both refer to root +static fat32_dirent_t* fat32_find_path(int port, fat32_vol_t* vol, const char* path) { + u32 cluster = vol->root_cluster; + + // skip leading slash + if (*path == '/') path++; + + // root itself + if (*path == '\0') return NULL; + + char part[12]; + while (*path) { + // extract next path component + int len = 0; + while (path[len] && path[len] != '/') len++; + if (len > 11) return NULL; // can't possibly be valid 8.3 + printn(path, len); + + memcpy(part, path, len); + part[len] = '\0'; + path += len; + if (*path == '/') path++; + + put('\n'); + // convert component to 8.3 + u8 name83[11]; + + fat32_dirent_t* e = fat32_find(port, vol, cluster, name83); + if (!e) return NULL; + + // if there's more path to walk, this must be a directory + if (*path != '\0') { + if (!(e->attr & ATTR_DIR)) return NULL; + cluster = fat32_dirent_cluster(e); + // free(e); // if you're tracking allocs + continue; + } + + // last component — return it whether file or dir + return e; + } + + return NULL; +} \ No newline at end of file diff --git a/src/lib/ctype.h b/src/lib/ctype.h new file mode 100644 index 0000000..daafc74 --- /dev/null +++ b/src/lib/ctype.h @@ -0,0 +1,35 @@ +#pragma once + +static bool isdigit(int ch) { + return (ch <= '9' && ch >= '0'); +} + +static bool isalpha(int ch) { + return (ch <= 'z' && ch >= 'a') + || (ch <= 'Z' && ch >= 'A'); +} + +static bool isalnum(int ch) { + return isdigit(ch) || isalpha(ch); +} + +static int toupper(int ch) { + if(ch >= 'a' && ch <= 'z') + ch += 'A'-'a'; + return ch; +} + +static int tolower(int ch) { + if(ch >= 'A' && ch <= 'Z') + ch += 'a'-'A'; + return ch; +} + +static bool isxdigit(int ch) { + return isdigit(ch) || (isalpha(ch) && tolower(ch) <= 'f'); +} + +// cribbed from musl +static bool isspace(int ch) { + return ch == ' ' || (unsigned)ch-'\t' < 5; +} \ No newline at end of file diff --git a/src/lib/stdio.h b/src/lib/stdio.h index 1339fb2..39d7467 100644 --- a/src/lib/stdio.h +++ b/src/lib/stdio.h @@ -143,49 +143,46 @@ static inline char *_fmt_uint(char *end, u64 val, int base, bool upper) { static inline int vprintf(const char *fmt, va_list ap) { int written = 0; - #define _EMIT(c) do { put(c); written++; } while(0) #define _EMITS(s) do { const char *_p=(s); while(*_p){_EMIT(*_p);_p++;} } while(0) - while (*fmt) { if (*fmt != '%') { _EMIT(*fmt++); continue; } fmt++; /* skip '%' */ - /* flags */ bool left_align = false; bool zero_pad = false; if (*fmt == '-') { left_align = true; fmt++; } if (*fmt == '0') { zero_pad = true; fmt++; } - /* width */ int width = 0; while (*fmt >= '0' && *fmt <= '9') width = width*10 + (*fmt++ - '0'); - + /* precision: %.N */ + int precision = -1; /* -1 = no precision specified */ + if (*fmt == '.') { + fmt++; + precision = 0; + while (*fmt >= '0' && *fmt <= '9') precision = precision*10 + (*fmt++ - '0'); + } /* length modifier */ int lng = 0; /* 0=int, 1=long, 2=long long */ if (*fmt == 'l') { lng=1; fmt++; } if (*fmt == 'l') { lng=2; fmt++; } - char tmp[66]; char *s = NULL; char cbuf[2] = {0,0}; bool neg = false; - switch (*fmt++) { case '%': _EMIT('%'); continue; - case 'c': cbuf[0] = (char)va_arg(ap, int); s = cbuf; break; - case 's': s = va_arg(ap, char *); if (!s) s = "(null)"; break; - case 'd': case 'i': { i64 v = (lng==2) ? va_arg(ap,long long) : (lng==1) ? va_arg(ap,long) : @@ -194,7 +191,6 @@ static inline int vprintf(const char *fmt, va_list ap) { s = _fmt_uint(tmp+65, (u64)v, 10, false); break; } - case 'u': { u64 v = (lng==2) ? va_arg(ap,unsigned long long) : (lng==1) ? va_arg(ap,unsigned long) : @@ -202,7 +198,6 @@ static inline int vprintf(const char *fmt, va_list ap) { s = _fmt_uint(tmp+65, v, 10, false); break; } - case 'o': { u64 v = (lng==2) ? va_arg(ap,unsigned long long) : (lng==1) ? va_arg(ap,unsigned long) : @@ -210,7 +205,6 @@ static inline int vprintf(const char *fmt, va_list ap) { s = _fmt_uint(tmp+65, v, 8, false); break; } - case 'x': { u64 v = (lng==2) ? va_arg(ap,unsigned long long) : (lng==1) ? va_arg(ap,unsigned long) : @@ -218,7 +212,6 @@ static inline int vprintf(const char *fmt, va_list ap) { s = _fmt_uint(tmp+65, v, 16, false); break; } - case 'X': { u64 v = (lng==2) ? va_arg(ap,unsigned long long) : (lng==1) ? va_arg(ap,unsigned long) : @@ -226,7 +219,6 @@ static inline int vprintf(const char *fmt, va_list ap) { s = _fmt_uint(tmp+65, v, 16, true); break; } - case 'p': { u64 v = (u64)(uintptr_t)va_arg(ap, void *); print("0x"); @@ -234,30 +226,33 @@ static inline int vprintf(const char *fmt, va_list ap) { s = _fmt_uint(tmp+65, v, 16, false); break; } - default: _EMIT('?'); continue; } - - /* padding / output */ + /* apply precision to string length (%.8s style) */ int slen = 0; - for (const char *p = s; *p; p++) slen++; + if (precision >= 0) { + /* count up to precision chars, stop at null */ + const char *p = s; + while (slen < precision && *p) { slen++; p++; } + } else { + for (const char *p = s; *p; p++) slen++; + } if (neg) slen++; /* for '-' */ - int pad = width - slen; - if (!left_align && pad > 0) { char pc = zero_pad ? '0' : ' '; if (neg && zero_pad) { _EMIT('-'); neg=false; written++; } while (pad-- > 0) { _EMIT(pc); written++; } } if (neg) { _EMIT('-'); written++; } - while (*s) { _EMIT(*s++); written++; } + /* emit exactly slen chars (respects precision cutoff) */ + int emit = neg ? slen - 1 : slen; + for (int i = 0; i < emit && *s; i++) { _EMIT(*s++); written++; } if (left_align && pad > 0) while (pad-- > 0) { _EMIT(' '); written++; } } - #undef _EMIT #undef _EMITS return written; diff --git a/src/lib/string.h b/src/lib/string.h new file mode 100644 index 0000000..3b1dc01 --- /dev/null +++ b/src/lib/string.h @@ -0,0 +1,8 @@ +#pragma once + +static size_t strlen(const char* str) { + size_t len = 0; + while(*(str++)) + len++; + return len; +} \ No newline at end of file diff --git a/src/main.c b/src/main.c index c7445a3..f947916 100644 --- a/src/main.c +++ b/src/main.c @@ -329,44 +329,11 @@ void kmain() { ls(port, 0, &vol, vol.root_cluster); - //dealloc((void*) bpb, 1<<12); + print("Attempting to find FORTU.NE\n"); + fat32_dirent_t* fortune = fat32_find_path(port, &vol, "fort/fortu.ne"); -// #define LINES 40 -// size_t max_len = MAX_LINE_LEN; -// char* lines[LINES]; -// size_t n_lines = 0; -// for(n_lines = 0; n_lines < LINES; n_lines++) { -// char* line = getline_alloc(max_len); -// if(!line) -// break; -// if(line[0] == 'F' && line[1] == 'I' && line[2] == '\n') -// break; -// lines[n_lines] = line; -// } - -// const char* name = "stdin"; -// struct file input = { -// .row = 0, -// .col = 0, -// .rows = n_lines, -// .lines = (char**)lines, -// .name = name, -// .tokens = NULL, -// .tail = &input.tokens, -// }; - -// int res = lex(&input); - -// print("Number of Errors: "); -// print8(res); - -// printf("\n# of Tokens: %d\n", input.tokens->len); -// struct token* token = input.tokens; - -// for(;token; token = token->next) { -// print_tok(token); -// } + printf("Fortune size: %d\n", fortune->file_size); hang(); } diff --git a/src/prompt/iden.c b/src/prompt/iden.c index 477d7a9..42f7a3e 100644 --- a/src/prompt/iden.c +++ b/src/prompt/iden.c @@ -23,7 +23,7 @@ size_t register_iden(const char* data, size_t len, uint64_t hash) { for(i = 0; i < identbl_len; i++) { if(hash == identbl[i].hash && identbl[i].len == len && - strneq(data, identbl[i].data, len)) { + strneq(data, (const char*)identbl[i].data, len)) { return i; } } diff --git a/src/prompt/lex.c b/src/prompt/lex.c index 707d103..ac0647a 100644 --- a/src/prompt/lex.c +++ b/src/prompt/lex.c @@ -3,19 +3,14 @@ #include "iden.h" #include "lex.h" #include "../lib/stdio.h" +#include "../lib/ctype.h" +#include "../lib/string.h" static int lex_error(struct file* state, const char* err) { printf("%s:%d:%d: %s\n", state->name, state->row+1, state->col+1, err); return 1; } -static size_t strlen(const char* str) { - size_t len = 0; - while(*(str++)) - len++; - return len; -} - static bool strneq(const char* l, const char* r, size_t n) { for(size_t i = 0; i < n; i++) { if(r[i] != l[i]) @@ -71,41 +66,6 @@ static struct token* tok(enum tokentype type, struct file* state, int col, void* } - -static bool isdigit(int ch) { - return (ch <= '9' && ch >= '0'); -} - -static bool isalpha(int ch) { - return (ch <= 'z' && ch >= 'a') - || (ch <= 'Z' && ch >= 'A'); -} - -static bool isalnum(int ch) { - return isdigit(ch) || isalpha(ch); -} - -static int toupper(int ch) { - if(ch >= 'a' && ch <= 'z') - ch += 'A'-'a'; - return ch; -} - -static int tolower(int ch) { - if(ch >= 'A' && ch <= 'Z') - ch += 'a'-'A'; - return ch; -} - -static bool isxdigit(int ch) { - return isdigit(ch) || (isalpha(ch) && tolower(ch) <= 'f'); -} - -// cribbed from musl -static bool isspace(int ch) { - return ch == ' ' || (unsigned)ch-'\t' < 5; -} - static int parse_num(struct file* state, int save, int sign) { int64_t num = 0; int ch = state->lines[state->row][state->col]; diff --git a/src/prompt/print.c b/src/prompt/print.c index b3aea6c..31e0977 100644 --- a/src/prompt/print.c +++ b/src/prompt/print.c @@ -1,5 +1,6 @@ #include "iden.h" #include "lex.h" +#include "../lib/stdio.h" #include "../print.h" #include "../common.h" @@ -48,16 +49,7 @@ void print_tok(struct token* tok) { case TOK_IDEN: { color = 0x137FFF; struct iden* id = &identbl[tok->iden]; - print("iden: { .hash = 0x"); - print32(id->hash); - print(", .data = \""); - print(id->data); - print("\" ("); - /* print pointer value as hex */ - print("ptr"); /* pointer printing omitted; add if needed */ - print("), .len = "); - print32((int)id->len); - print(" }:\n"); + printf("iden: { .hash = 0x%x, .data = \"%s\"\" (%d)\n", id->hash, *id->data, (int)id->len); break; } case TOK_OP: {