diff --git a/.DS_Store b/.DS_Store index 3e18b3a..facdf2f 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 664f775..f07671c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,7 @@ boredos.dump qemu-debug.log build/ iso_root/ -limine +limine/ +src/kernel/userland/bin/ +boredos.iso +disk.img diff --git a/Makefile b/Makefile index 8e16f76..c25c1e7 100644 --- a/Makefile +++ b/Makefile @@ -15,16 +15,15 @@ KERNEL_ELF = $(BUILD_DIR)/boredos.elf ISO_IMAGE = boredos.iso C_SOURCES = $(wildcard $(SRC_DIR)/*.c) -CLI_APP_SOURCES = $(wildcard $(SRC_DIR)/cli_apps/*.c) + ASM_SOURCES = $(wildcard $(SRC_DIR)/*.asm) OBJ_FILES = $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(C_SOURCES)) \ - $(patsubst $(SRC_DIR)/cli_apps/%.c, $(BUILD_DIR)/cli_apps/%.o, $(CLI_APP_SOURCES)) \ $(patsubst $(SRC_DIR)/%.asm, $(BUILD_DIR)/%.o, $(ASM_SOURCES)) CFLAGS = -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding \ -fno-stack-protector -fno-stack-check -fno-lto -fPIE \ -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone \ - -I$(SRC_DIR) -I$(SRC_DIR)/cli_apps + -I$(SRC_DIR) LDFLAGS = -m elf_x86_64 -nostdlib -static -pie --no-dynamic-linker \ -z text -z max-page-size=0x1000 -T linker.ld @@ -42,7 +41,7 @@ all: $(ISO_IMAGE) # Ensure build directories exist $(BUILD_DIR): mkdir -p $(BUILD_DIR) - mkdir -p $(BUILD_DIR)/cli_apps + mkdir -p $(BUILD_DIR) # Download Limine Binaries via Git limine-setup: @@ -62,9 +61,7 @@ limine-setup: $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR) limine-setup $(CC) $(CFLAGS) -c $< -o $@ -# Compile CLI Apps C Sources -$(BUILD_DIR)/cli_apps/%.o: $(SRC_DIR)/cli_apps/%.c | $(BUILD_DIR) limine-setup - $(CC) $(CFLAGS) -c $< -o $@ + # Assemble ASM Sources $(BUILD_DIR)/%.o: $(SRC_DIR)/%.asm | $(BUILD_DIR) @@ -96,7 +93,7 @@ $(ISO_IMAGE): $(KERNEL_ELF) limine.cfg limine-setup # Build ISO limine.cfg natively with modules cp limine.cfg $(ISO_DIR)/ mkdir -p $(ISO_DIR)/bin - @for f in $(SRC_DIR)/userland/*.elf; do \ + @for f in $(SRC_DIR)/userland/bin/*.elf; do \ if [ -f "$$f" ]; then \ basename=$$(basename "$$f"); \ cp "$$f" $(ISO_DIR)/bin/; \ @@ -138,4 +135,4 @@ run: $(ISO_IMAGE) -audiodev coreaudio,id=audio0 -machine pcspk-audiodev=audio0 \ -netdev user,id=net0,hostfwd=udp::12345-:12345 -device e1000,netdev=net0 \ -vga std -global VGA.xres=1920 -global VGA.yres=1080 \ - + -drive file=disk.img,format=raw,file.locking=off \ No newline at end of file diff --git a/boredos.iso b/boredos.iso index b0d0f6f..ebfe321 100644 Binary files a/boredos.iso and b/boredos.iso differ diff --git a/build/cmd.o b/build/cmd.o index d5ebab8..82fb549 100644 Binary files a/build/cmd.o and b/build/cmd.o differ diff --git a/build/explorer.o b/build/explorer.o index ebbe0e4..ba52500 100644 Binary files a/build/explorer.o and b/build/explorer.o differ diff --git a/build/idt.o b/build/idt.o index 2f38f96..8372391 100644 Binary files a/build/idt.o and b/build/idt.o differ diff --git a/build/main.o b/build/main.o index 45433a6..cac14f0 100644 Binary files a/build/main.o and b/build/main.o differ diff --git a/build/ps2.o b/build/ps2.o index 93366b3..c9bd481 100644 Binary files a/build/ps2.o and b/build/ps2.o differ diff --git a/build_error.log b/build_error.log new file mode 100644 index 0000000..8263bca --- /dev/null +++ b/build_error.log @@ -0,0 +1,33 @@ +src/kernel/wm.c: In function 'wm_handle_click': +src/kernel/wm.c:1491:29: warning: this 'if' clause does not guard... [-Wmisleading-indentation] + 1491 | if (col < 0) col = 0; if (row < 0) row = 0; + | ^~ +src/kernel/wm.c:1491:51: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if' + 1491 | if (col < 0) col = 0; if (row < 0) row = 0; + | ^~ +src/kernel/wm.c: In function 'wm_handle_mouse': +src/kernel/wm.c:1884:17: error: implicit declaration of function 'cli_cmd_shutdown' [-Wimplicit-function-declaration] + 1884 | cli_cmd_shutdown(NULL); + | ^~~~~~~~~~~~~~~~ +src/kernel/wm.c:1886:17: error: implicit declaration of function 'cli_cmd_reboot' [-Wimplicit-function-declaration] + 1886 | cli_cmd_reboot(NULL); + | ^~~~~~~~~~~~~~ +src/kernel/wm.c:2083:41: warning: this 'if' clause does not guard... [-Wmisleading-indentation] + 2083 | if (col < 0) col = 0; if (row < 0) row = 0; + | ^~ +src/kernel/wm.c:2083:63: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if' + 2083 | if (col < 0) col = 0; if (row < 0) row = 0; + | ^~ +src/kernel/wm.c: At top level: +src/kernel/wm.c:1057:13: warning: 'erase_cursor' defined but not used [-Wunused-function] + 1057 | static void erase_cursor(int x, int y) { + | ^~~~~~~~~~~~ +src/kernel/wm.c:976:13: warning: 'draw_dock_editor' defined but not used [-Wunused-function] + 976 | static void draw_dock_editor(int x, int y) { + | ^~~~~~~~~~~~~~~~ +src/kernel/wm.c:82:13: warning: 'cursor_visible' defined but not used [-Wunused-variable] + 82 | static bool cursor_visible = true; + | ^~~~~~~~~~~~~~ +src/kernel/wm.c:79:12: warning: 'desktop_refresh_timer' defined but not used [-Wunused-variable] + 79 | static int desktop_refresh_timer = 0; + | ^~~~~~~~~~~~~~~~~~~~~ diff --git a/disk.img b/disk.img index c63159a..1f924f8 100644 Binary files a/disk.img and b/disk.img differ diff --git a/src/kernel/cli_apps/beep.c b/src/kernel/cli_apps/beep.c deleted file mode 100644 index e3d5641..0000000 --- a/src/kernel/cli_apps/beep.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "cli_utils.h" -#include "io.h" - -void cli_cmd_beep(char *args) { - (void)args; - cli_write("BEEP!\n"); - outb(0x43, 0xB6); - int freq = 1000; - int div = 1193180 / freq; - outb(0x42, div & 0xFF); - outb(0x42, (div >> 8) & 0xFF); - - outb(0x61, inb(0x61) | 0x03); - cli_sleep(100); - outb(0x61, inb(0x61) & 0xFC); -} diff --git a/src/kernel/cli_apps/blind.c b/src/kernel/cli_apps/blind.c deleted file mode 100644 index d1fe69b..0000000 --- a/src/kernel/cli_apps/blind.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "cli_utils.h" - -void cli_cmd_blind(char *args) { - (void)args; - cli_write("Woah.. is this heaven?\n"); - cli_write("no.\n"); - cli_write("This isn't TempleOS you fucking retard.\n"); -} diff --git a/src/kernel/cli_apps/boredver.c b/src/kernel/cli_apps/boredver.c deleted file mode 100644 index 744978b..0000000 --- a/src/kernel/cli_apps/boredver.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "cli_utils.h" - -void cli_cmd_boredver(char *args) { - (void)args; - cli_write("BoredOS v1.64\n"); - cli_write("BoredOS Kernel V3.0.0\n"); -} diff --git a/src/kernel/cli_apps/cc.c b/src/kernel/cli_apps/cc.c deleted file mode 100644 index 2cbcf31..0000000 --- a/src/kernel/cli_apps/cc.c +++ /dev/null @@ -1,738 +0,0 @@ -#include "cli_apps.h" -#include "cli_utils.h" -#include "../vm.h" -#include "../fat32.h" -#include "../memory_manager.h" -#include "../cmd.h" - -// --- Compiler Limits --- -#define MAX_SOURCE 65536 -#define MAX_TOKENS 16384 -#define MAX_VARS 512 -#define CODE_SIZE 32768 -#define STR_POOL_SIZE 16384 - -static int compile_error = 0; - -// --- Lexer --- -typedef enum { - TOK_EOF, - TOK_INT, // 123, 0xFF - TOK_STRING, // "hello" - TOK_ID, // abc - TOK_PLUS, // + - TOK_MINUS, // - - TOK_MUL, // * - TOK_DIV, // / - TOK_ASSIGN, // = - TOK_LPAREN, // ( - TOK_RPAREN, // ) - TOK_LBRACKET, // [ - TOK_RBRACKET, // ] - TOK_LBRACE, // { - TOK_RBRACE, // } - TOK_SEMI, // ; - TOK_COMMA, // , - TOK_EQ, // == - TOK_NEQ, // != - TOK_LT, // < - TOK_GT, // > - TOK_LE, // <= - TOK_GE, // >= - TOK_IF, // if - TOK_ELSE, // else - TOK_WHILE, // while - TOK_INT_TYPE, // int - TOK_CHAR_TYPE,// char - TOK_VOID_TYPE,// void - TOK_MAIN // main -} TokenType; - -typedef struct { - TokenType type; - int int_val; - char str_val[64]; // Identifier or String Content -} Token; - -static char *source_ptr; -static Token tokens[MAX_TOKENS]; -static int token_count = 0; - -static void lex_error(const char *msg) { - cmd_write("Compiler Error: "); - cmd_write(msg); - cmd_write("\n"); - compile_error = 1; -} - -static void lexer(const char *source) { - source_ptr = (char*)source; - token_count = 0; - compile_error = 0; - - while (*source_ptr) { - // Skip whitespace - while (*source_ptr == ' ' || *source_ptr == '\n' || *source_ptr == '\t' || *source_ptr == '\r') source_ptr++; - if (!*source_ptr) break; - - // Skip comments // - if (*source_ptr == '/' && *(source_ptr+1) == '/') { - while (*source_ptr && *source_ptr != '\n') source_ptr++; - continue; - } - - Token *t = &tokens[token_count++]; - - // Hex Literals 0x... - if (*source_ptr == '0' && (*(source_ptr+1) == 'x' || *(source_ptr+1) == 'X')) { - source_ptr += 2; // Skip 0x - t->type = TOK_INT; - t->int_val = 0; - int has_digits = 0; - while ((*source_ptr >= '0' && *source_ptr <= '9') || - (*source_ptr >= 'a' && *source_ptr <= 'f') || - (*source_ptr >= 'A' && *source_ptr <= 'F')) { - int digit = 0; - if (*source_ptr >= '0' && *source_ptr <= '9') digit = *source_ptr - '0'; - else if (*source_ptr >= 'a' && *source_ptr <= 'f') digit = *source_ptr - 'a' + 10; - else if (*source_ptr >= 'A' && *source_ptr <= 'F') digit = *source_ptr - 'A' + 10; - - t->int_val = (t->int_val << 4) | digit; - source_ptr++; - has_digits = 1; - } - if (!has_digits) { - lex_error("Invalid hex literal"); - return; - } - } - // Decimal Integers - else if (*source_ptr >= '0' && *source_ptr <= '9') { - t->type = TOK_INT; - t->int_val = 0; - while (*source_ptr >= '0' && *source_ptr <= '9') { - t->int_val = t->int_val * 10 + (*source_ptr - '0'); - source_ptr++; - } - } - // Strings - else if (*source_ptr == '"') { - t->type = TOK_STRING; - source_ptr++; // Skip " - int len = 0; - while (*source_ptr && *source_ptr != '"') { - if (*source_ptr == '\\' && *(source_ptr+1) == 'n') { - if (len < 63) t->str_val[len++] = '\n'; - source_ptr += 2; - } else { - if (len < 63) t->str_val[len++] = *source_ptr; - source_ptr++; - } - } - t->str_val[len] = 0; - if (*source_ptr == '"') source_ptr++; - } - // Character Literals - else if (*source_ptr == '\'') { - t->type = TOK_INT; - source_ptr++; // Skip ' - char c = 0; - if (*source_ptr == '\\') { - source_ptr++; - if (*source_ptr == 'n') c = '\n'; - else if (*source_ptr == 't') c = '\t'; - else if (*source_ptr == '0') c = '\0'; - else if (*source_ptr == '\\') c = '\\'; - else if (*source_ptr == '\'') c = '\''; - else c = *source_ptr; - source_ptr++; - } else { - c = *source_ptr; - source_ptr++; - } - if (*source_ptr == '\'') source_ptr++; - else { lex_error("Expected closing '"); return; } - t->int_val = (int)c; - } - // Identifiers - else if ((*source_ptr >= 'a' && *source_ptr <= 'z') || (*source_ptr >= 'A' && *source_ptr <= 'Z') || *source_ptr == '_') { - int len = 0; - while ((*source_ptr >= 'a' && *source_ptr <= 'z') || (*source_ptr >= 'A' && *source_ptr <= 'Z') || (*source_ptr >= '0' && *source_ptr <= '9') || *source_ptr == '_') { - if (len < 63) t->str_val[len++] = *source_ptr; - source_ptr++; - } - t->str_val[len] = 0; - - if (cli_strcmp(t->str_val, "if") == 0) t->type = TOK_IF; - else if (cli_strcmp(t->str_val, "else") == 0) t->type = TOK_ELSE; - else if (cli_strcmp(t->str_val, "while") == 0) t->type = TOK_WHILE; - else if (cli_strcmp(t->str_val, "int") == 0) t->type = TOK_INT_TYPE; - else if (cli_strcmp(t->str_val, "char") == 0) t->type = TOK_CHAR_TYPE; - else if (cli_strcmp(t->str_val, "void") == 0) t->type = TOK_VOID_TYPE; - else if (cli_strcmp(t->str_val, "main") == 0) t->type = TOK_MAIN; - else t->type = TOK_ID; - } else { - switch (*source_ptr) { - case '+': t->type = TOK_PLUS; break; - case '-': t->type = TOK_MINUS; break; - case '*': t->type = TOK_MUL; break; - case '/': t->type = TOK_DIV; break; - case '(': t->type = TOK_LPAREN; break; - case ')': t->type = TOK_RPAREN; break; - case '[': t->type = TOK_LBRACKET; break; - case ']': t->type = TOK_RBRACKET; break; - case '{': t->type = TOK_LBRACE; break; - case '}': t->type = TOK_RBRACE; break; - case ';': t->type = TOK_SEMI; break; - case ',': t->type = TOK_COMMA; break; - case '=': - if (*(source_ptr+1) == '=') { t->type = TOK_EQ; source_ptr++; } - else t->type = TOK_ASSIGN; - break; - case '!': - if (*(source_ptr+1) == '=') { t->type = TOK_NEQ; source_ptr++; } - else { lex_error("Unexpected !"); return; } - break; - case '<': - if (*(source_ptr+1) == '=') { t->type = TOK_LE; source_ptr++; } - else t->type = TOK_LT; - break; - case '>': - if (*(source_ptr+1) == '=') { t->type = TOK_GE; source_ptr++; } - else t->type = TOK_GT; - break; - default: - lex_error("Unknown char"); - return; - } - source_ptr++; - } - } - tokens[token_count].type = TOK_EOF; -} - -// --- Builtins --- - -typedef struct { - const char *name; - int syscall_id; -} Builtin; - -static const Builtin builtins[] = { - {"exit", SYS_EXIT}, - {"print_int", SYS_PRINT_INT}, - {"print_char", SYS_PRINT_CHAR}, - {"print_str", SYS_PRINT_STR}, // puts - {"print", SYS_PRINT_INT}, // Alias - {"pritc", SYS_PRINT_CHAR}, // Alias - {"puts", SYS_PRINT_STR}, // Alias - {"nl", SYS_NL}, - {"cls", SYS_CLS}, - {"getchar", SYS_GETCHAR}, - {"strlen", SYS_STRLEN}, - {"strcmp", SYS_STRCMP}, - {"strcpy", SYS_STRCPY}, - {"strcat", SYS_STRCAT}, - {"memset", SYS_MEMSET}, - {"memcpy", SYS_MEMCPY}, - {"malloc", SYS_MALLOC}, - {"free", SYS_FREE}, - {"rand", SYS_RAND}, - {"srand", SYS_SRAND}, - {"abs", SYS_ABS}, - {"min", SYS_MIN}, - {"max", SYS_MAX}, - {"pow", SYS_POW}, - {"sqrt", SYS_SQRT}, - {"sleep", SYS_SLEEP}, - {"fopen", SYS_FOPEN}, - {"fclose", SYS_FCLOSE}, - {"fread", SYS_FREAD}, - {"fwrite", SYS_FWRITE}, - {"fseek", SYS_FSEEK}, - {"remove", SYS_REMOVE}, - {"draw_pixel", SYS_DRAW_PIXEL}, - {"draw_rect", SYS_DRAW_RECT}, - {"draw_line", SYS_DRAW_LINE}, - {"draw_text", SYS_DRAW_TEXT}, - {"get_width", SYS_GET_WIDTH}, - {"get_height", SYS_GET_HEIGHT}, - {"get_time", SYS_GET_TIME}, - {"kb_hit", SYS_KB_HIT}, - {"mouse_x", SYS_MOUSE_X}, - {"mouse_y", SYS_MOUSE_Y}, - {"mouse_state", SYS_MOUSE_STATE}, - {"play_sound", SYS_PLAY_SOUND}, - {"atoi", SYS_ATOI}, - {"itoa", SYS_ITOA}, - {"peek", SYS_PEEK}, - {"poke", SYS_POKE}, - {"exec", SYS_EXEC}, - {"system", SYS_SYSTEM}, - {"strchr", SYS_STRCHR}, - {"memcmp", SYS_MEMCMP}, - {"isalnum", SYS_ISALNUM}, - {"isalpha", SYS_ISALPHA}, - {"isdigit", SYS_ISDIGIT}, - {"tolower", SYS_TOLOWER}, - {"toupper", SYS_TOUPPER}, - {"strncpy", SYS_STRNCPY}, - {"strncat", SYS_STRNCAT}, - {"strncmp", SYS_STRNCMP}, - {"strstr", SYS_STRSTR}, - {"strrchr", SYS_STRRCHR}, - {"memmove", SYS_MEMMOVE}, - {NULL, 0} -}; - -static int find_builtin(const char *name) { - for (int i = 0; builtins[i].name != NULL; i++) { - if (cli_strcmp(builtins[i].name, name) == 0) { - return builtins[i].syscall_id; - } - } - return -1; -} - -// --- Parser & CodeGen --- - -static uint8_t code[CODE_SIZE]; -static int code_pos = 0; -static int cur_token = 0; - -static uint8_t str_pool[STR_POOL_SIZE]; -static int str_pool_pos = 0; - -// Variables -typedef struct { - char name[32]; - int addr; // Address in VM memory -} Symbol; - -static Symbol symbols[MAX_VARS]; -static int symbol_count = 0; - -static int next_var_addr = 32768; - -static int find_symbol(const char *name) { - for (int i = 0; i < symbol_count; i++) { - if (cli_strcmp(symbols[i].name, name) == 0) return symbols[i].addr; - } - return -1; -} - -static int add_symbol(const char *name) { - if (find_symbol(name) != -1) return find_symbol(name); - if (symbol_count >= MAX_VARS) return -1; - cli_strcpy(symbols[symbol_count].name, name); - symbols[symbol_count].addr = next_var_addr; - next_var_addr += 4; // 32-bit int - return symbol_count++; -} - -static void emit(uint8_t b) { - if (code_pos < CODE_SIZE) code[code_pos++] = b; - else { - cmd_write("Error: Code buffer overflow\n"); - compile_error = 1; - } -} - -static void emit32(int v) { - emit(v & 0xFF); - emit((v >> 8) & 0xFF); - emit((v >> 16) & 0xFF); - emit((v >> 24) & 0xFF); -} - -static int add_string(const char *str) { - int start = str_pool_pos; - int len = cli_strlen(str); - if (str_pool_pos + len + 1 >= STR_POOL_SIZE) { - cmd_write("Error: String pool overflow\n"); - compile_error = 1; - return 0; - } - for(int i=0; i= TOK_EQ && tokens[cur_token].type <= TOK_GE) { - TokenType op = tokens[cur_token].type; - cur_token++; - additive(); - switch (op) { - case TOK_EQ: emit(OP_EQ); break; - case TOK_NEQ: emit(OP_NEQ); break; - case TOK_LT: emit(OP_LT); break; - case TOK_GT: emit(OP_GT); break; - case TOK_LE: emit(OP_LE); break; - case TOK_GE: emit(OP_GE); break; - default: break; - } - } -} - -static void expression() { - if (compile_error) return; - relation(); -} - -static void statement() { - if (compile_error) return; - if (tokens[cur_token].type == TOK_INT_TYPE || tokens[cur_token].type == TOK_CHAR_TYPE) { - // Declaration - cur_token++; - while (tokens[cur_token].type == TOK_MUL) cur_token++; // Skip pointers * - - if (tokens[cur_token].type == TOK_ID) { - add_symbol(tokens[cur_token].str_val); - cur_token++; - - // Skip array size [INT] - if (tokens[cur_token].type == TOK_LBRACKET) { - cur_token++; - if (tokens[cur_token].type == TOK_INT) cur_token++; - if (tokens[cur_token].type == TOK_RBRACKET) cur_token++; - else cmd_write("Error: Expected ]\n"); - } - - if (tokens[cur_token].type == TOK_ASSIGN) { int addr = find_symbol(tokens[cur_token-1].str_val); - cur_token++; - expression(); - emit(OP_STORE); - emit32(addr); - } - match(TOK_SEMI); - } else { - cmd_write("Syntax Error: Expected identifier\n"); - compile_error = 1; - } - } else if (tokens[cur_token].type == TOK_ID) { - int syscall = find_builtin(tokens[cur_token].str_val); - if (syscall != -1 && tokens[cur_token+1].type == TOK_LPAREN) { - function_call(syscall); - match(TOK_SEMI); - // Drop return value (primitive) - emit(OP_POP); - } else { - // Assignment: x = expr; - int addr = find_symbol(tokens[cur_token].str_val); - if (addr == -1) { - cmd_write("Error: Undefined variable assignment: "); - cmd_write(tokens[cur_token].str_val); - cmd_write("\n"); - compile_error = 1; - return; - } - cur_token++; - match(TOK_ASSIGN); - expression(); - match(TOK_SEMI); - emit(OP_STORE); - emit32(addr); - } - } else if (tokens[cur_token].type == TOK_IF) { - cur_token++; - match(TOK_LPAREN); - expression(); - match(TOK_RPAREN); - - emit(OP_JZ); - int jz_addr_pos = code_pos; - emit32(0); - - block(); - - if (tokens[cur_token].type == TOK_ELSE) { - emit(OP_JMP); - int jmp_addr_pos = code_pos; - emit32(0); - - int else_start = code_pos; - code[jz_addr_pos] = else_start & 0xFF; - code[jz_addr_pos+1] = (else_start >> 8) & 0xFF; - code[jz_addr_pos+2] = (else_start >> 16) & 0xFF; - code[jz_addr_pos+3] = (else_start >> 24) & 0xFF; - - cur_token++; - block(); - - int end_addr = code_pos; - code[jmp_addr_pos] = end_addr & 0xFF; - code[jmp_addr_pos+1] = (end_addr >> 8) & 0xFF; - code[jmp_addr_pos+2] = (end_addr >> 16) & 0xFF; - code[jmp_addr_pos+3] = (end_addr >> 24) & 0xFF; - } else { - int end_addr = code_pos; - code[jz_addr_pos] = end_addr & 0xFF; - code[jz_addr_pos+1] = (end_addr >> 8) & 0xFF; - code[jz_addr_pos+2] = (end_addr >> 16) & 0xFF; - code[jz_addr_pos+3] = (end_addr >> 24) & 0xFF; - } - } else if (tokens[cur_token].type == TOK_WHILE) { - int start_addr = code_pos; - cur_token++; - match(TOK_LPAREN); - expression(); - match(TOK_RPAREN); - - emit(OP_JZ); - int jz_addr_pos = code_pos; - emit32(0); - - block(); - - emit(OP_JMP); - emit32(start_addr); - - int end_addr = code_pos; - code[jz_addr_pos] = end_addr & 0xFF; - code[jz_addr_pos+1] = (end_addr >> 8) & 0xFF; - code[jz_addr_pos+2] = (end_addr >> 16) & 0xFF; - code[jz_addr_pos+3] = (end_addr >> 24) & 0xFF; - } else { - cur_token++; - } -} - -static void block() { - if (compile_error) return; - match(TOK_LBRACE); - while (tokens[cur_token].type != TOK_RBRACE && tokens[cur_token].type != TOK_EOF && !compile_error) { - statement(); - } - match(TOK_RBRACE); -} - -static void program() { - if (tokens[cur_token].type == TOK_INT_TYPE || tokens[cur_token].type == TOK_VOID_TYPE) cur_token++; - if (tokens[cur_token].type == TOK_MAIN) cur_token++; - match(TOK_LPAREN); - match(TOK_RPAREN); - block(); - emit(OP_HALT); -} - -void cli_cmd_cc(char *args) { - if (!args || !*args) { - cmd_write("Usage: cc \n"); - return; - } - - FAT32_FileHandle *fh = fat32_open(args, "r"); - if (!fh) { - cmd_write("Error: Cannot open source file.\n"); - return; - } - - char *source = (char*)kmalloc(MAX_SOURCE); - if (!source) { - cmd_write("Error: Out of memory for source buffer.\n"); - fat32_close(fh); - return; - } - - int len = fat32_read(fh, source, MAX_SOURCE - 1); - source[len] = 0; - fat32_close(fh); - - lexer(source); - kfree(source); - - if (compile_error) return; - - code_pos = 0; - symbol_count = 0; - cur_token = 0; - str_pool_pos = 0; - next_var_addr = 32768; - - const char* magic = VM_MAGIC; - for(int i=0; i<7; i++) emit(magic[i]); - emit(1); - - program(); - - if (compile_error) { - cmd_write("Compilation Failed.\n"); - return; - } - - // Finalize Code - int pool_start_addr = code_pos; - for(int i=0; i> 8) & 0xFF; - code[pc+2] = (abs_addr >> 16) & 0xFF; - code[pc+3] = (abs_addr >> 24) & 0xFF; - - pc += 4; - code[pc-5] = OP_IMM; - break; - } - default: break; - } - } - - char out_name[64]; - int i = 0; - while(args[i] && args[i] != '.') { - out_name[i] = args[i]; - i++; - } - out_name[i] = 0; - - FAT32_FileHandle *out_fh = fat32_open(out_name, "w"); - if (out_fh) { - fat32_write(out_fh, code, code_pos); - fat32_close(out_fh); - cmd_write("Compilation successful. Output: "); - cmd_write(out_name); - cmd_write("\n"); - } else { - cmd_write("Error: Cannot write output file.\n"); - } -} \ No newline at end of file diff --git a/src/kernel/cli_apps/clear.c b/src/kernel/cli_apps/clear.c deleted file mode 100644 index 32e17b6..0000000 --- a/src/kernel/cli_apps/clear.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "cli_utils.h" - -// Public declaration from cmd.c -extern void cmd_screen_clear(void); - -void cli_cmd_clear(char *args) { - (void)args; - cmd_screen_clear(); -} diff --git a/src/kernel/cli_apps/cli_apps.h b/src/kernel/cli_apps/cli_apps.h deleted file mode 100644 index 6d349fd..0000000 --- a/src/kernel/cli_apps/cli_apps.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef CLI_APPS_H -#define CLI_APPS_H - -// All CLI command function declarations -void cli_cmd_help(char *args); -void cli_cmd_date(char *args); -void cli_cmd_math(char *args); -void cli_cmd_beep(char *args); -void cli_cmd_cowsay(char *args); -void cli_cmd_reboot(char *args); -void cli_cmd_shutdown(char *args); -void cli_cmd_uptime(char *args); -void cli_cmd_man(char *args); -void cli_cmd_txtedit(char *args); -void cli_cmd_blind(char *args); -void cli_cmd_readtheman(char *args); -void cli_cmd_boredver(char *args); -void cli_cmd_clear(char *args); -void cli_cmd_exit(char *args); - - -// Filesystem commands -void cli_cmd_cd(char *args); -void cli_cmd_pwd(char *args); -void cli_cmd_ls(char *args); -void cli_cmd_mkdir(char *args); -void cli_cmd_rm(char *args); -void cli_cmd_echo(char *args); -void cli_cmd_cat(char *args); -void cli_cmd_touch(char *args); -void cli_cmd_cp(char *args); -void cli_cmd_mv(char *args); - -// Memory management commands -void cli_cmd_meminfo(char *args); -void cli_cmd_malloc(char *args); -void cli_cmd_free_mem(char *args); -void cli_cmd_memblock(char *args); -void cli_cmd_memvalid(char *args); -void cli_cmd_memtest(char *args); - -// Network commands -void cli_cmd_netinit(char *args); -void cli_cmd_netinfo(char *args); -void cli_cmd_ipset(char *args); -void cli_cmd_udpsend(char *args); -void cli_cmd_udptest(char *args); -void cli_cmd_msgrc(char *args); - -// PCI commands -void cli_cmd_pcilist(char *args); - -// Compiler -void cli_cmd_cc(char *args); - -// Music -void cli_cmd_minecraft(char *args); - -#endif diff --git a/src/kernel/cli_apps/cli_command.h b/src/kernel/cli_apps/cli_command.h deleted file mode 100644 index 7174c01..0000000 --- a/src/kernel/cli_apps/cli_command.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef CLI_COMMAND_H -#define CLI_COMMAND_H - -#include - -// Standard interface for CLI command output -// Commands should call these functions to write to the terminal -extern void cli_write(const char *str); -extern void cli_write_int(int n); -extern void cli_putchar(char c); - -// Callback function type for command execution -typedef void (*cmd_callback_t)(char *args); - -// Command entry in dispatch table -typedef struct { - const char *name; - cmd_callback_t callback; - const char *help_text; -} CLI_Command; - -#endif diff --git a/src/kernel/cli_apps/cli_utils.h b/src/kernel/cli_apps/cli_utils.h deleted file mode 100644 index c238e38..0000000 --- a/src/kernel/cli_apps/cli_utils.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef CLI_UTILS_H -#define CLI_UTILS_H - -#include -#include - -// String utilities -void cli_memset(void *dest, int val, size_t len); -size_t cli_strlen(const char *str); -int cli_strcmp(const char *s1, const char *s2); -void cli_strcpy(char *dest, const char *src); -int cli_atoi(const char *str); -void cli_itoa(int n, char *buf); - -// IO utilities -void cli_write(const char *str); -void cli_write_int(int n); -void cli_putchar(char c); - -// Timing utility -void cli_delay(int iterations); -void cli_sleep(int ms); - -// CLI Command declarations -void cli_cmd_shutdown(char *args); -void cli_cmd_reboot(char *args); - -#endif diff --git a/src/kernel/cli_apps/cowsay.c b/src/kernel/cli_apps/cowsay.c deleted file mode 100644 index d85bc6d..0000000 --- a/src/kernel/cli_apps/cowsay.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "cli_utils.h" - -void cli_cmd_cowsay(char *args) { - if (!args || !*args) args = (char*)"Bored!"; - size_t len = cli_strlen(args); - - cli_write(" "); - for(size_t i=0; i\n "); - for(size_t i=0; i\n"); - return; - } - - char dirname[256]; - int i = 0; - while (args[i] && args[i] != ' ' && args[i] != '\t') { - dirname[i] = args[i]; - i++; - } - dirname[i] = 0; - - if (fat32_mkdir(dirname)) { - cli_write("Created directory: "); - cli_write(dirname); - cli_write("\n"); - } else { - cli_write("Error: Cannot create directory\n"); - } -} - -// Helper for recursive deletion -static bool rm_recursive(const char *path) { - if (fat32_exists(path) && !fat32_is_directory(path)) { - return fat32_delete(path); - } - - if (!fat32_exists(path)) { - return false; - } - - // It's a directory: delete contents first - while (1) { - FAT32_FileInfo entries[10]; - int count = fat32_list_directory(path, entries, 10); - if (count <= 0) break; - - for (int i = 0; i < count; i++) { - // Construct child path - char child_path[256]; - cli_strcpy(child_path, path); - int len = cli_strlen(child_path); - if (len > 0 && child_path[len-1] != '/') { - child_path[len++] = '/'; - child_path[len] = 0; - } - - // Append name - const char *name = entries[i].name; - int j = 0; - while (name[j] && len < 255) { - child_path[len++] = name[j++]; - } - child_path[len] = 0; - - // Recurse - if (!rm_recursive(child_path)) { - cli_write("Error: Failed to delete "); - cli_write(child_path); - cli_write("\n"); - } - } - } - - return fat32_rmdir(path); -} - -void cli_cmd_rm(char *args) { - if (!args || args[0] == 0) { - cli_write("Usage: rm [-r] \n"); - return; - } - - bool recursive = false; - - // Check for -r flag - int i = 0; - while (args[i] == ' ' || args[i] == '\t') i++; - - if (args[i] == '-' && args[i+1] == 'r' && (args[i+2] == ' ' || args[i+2] == '\t' || args[i+2] == 0)) { - recursive = true; - i += 2; - while (args[i] == ' ' || args[i] == '\t') i++; - } - - char *path_start = args + i; - if (path_start[0] == 0) { - cli_write("Usage: rm [-r] \n"); - return; - } - - char filename[256]; - int j = 0; - while (path_start[j] && path_start[j] != ' ' && path_start[j] != '\t') { - filename[j] = path_start[j]; - j++; - } - filename[j] = 0; - - if (recursive) { - if (rm_recursive(filename)) { - cli_write("Deleted recursively: "); - cli_write(filename); - cli_write("\n"); - } else { - cli_write("Error: Cannot delete "); - cli_write(filename); - cli_write("\n"); - } - } else { - if (fat32_is_directory(filename)) { - cli_write("Error: Is a directory. Use -r to delete.\n"); - } else { - if (fat32_delete(filename)) { - cli_write("Deleted: "); - cli_write(filename); - cli_write("\n"); - } else { - cli_write("Error: Cannot delete file\n"); - } - } - } -} - -void cli_cmd_echo(char *args) { - if (!args || args[0] == 0) { - cli_write("\n"); - return; - } - - // Check for redirection operators - char *redirect_ptr = NULL; - char redirect_mode = 0; // '>' for write, 'a' for append - char output_file[256] = {0}; - char echo_text[512] = {0}; - - // Find > or >> - for (int i = 0; args[i]; i++) { - if (args[i] == '>' && args[i+1] == '>') { - redirect_ptr = args + i + 2; - redirect_mode = 'a'; // append - // Copy text before redirection - for (int j = 0; j < i; j++) { - echo_text[j] = args[j]; - } - echo_text[i] = 0; - break; - } else if (args[i] == '>') { - redirect_ptr = args + i + 1; - redirect_mode = '>'; // write - // Copy text before redirection - for (int j = 0; j < i; j++) { - echo_text[j] = args[j]; - } - echo_text[i] = 0; - break; - } - } - - // If no redirection, just print the text - if (!redirect_ptr) { - cli_write(args); - cli_write("\n"); - return; - } - - // Parse output filename - int i = 0; - while (redirect_ptr[i] && (redirect_ptr[i] == ' ' || redirect_ptr[i] == '\t')) { - i++; - } - - int j = 0; - while (redirect_ptr[i] && redirect_ptr[i] != ' ' && redirect_ptr[i] != '\t') { - output_file[j++] = redirect_ptr[i++]; - } - output_file[j] = 0; - - if (!output_file[0]) { - cli_write("Error: No output file specified\n"); - return; - } - - // Open file - const char *mode = (redirect_mode == 'a') ? "a" : "w"; - FAT32_FileHandle *fh = fat32_open(output_file, mode); - if (!fh) { - cli_write("Error: Cannot open file for writing\n"); - return; - } - - // Write text - int text_len = 0; - while (echo_text[text_len]) text_len++; - - fat32_write(fh, echo_text, text_len); - fat32_write(fh, "\n", 1); - fat32_close(fh); - - cli_write("Wrote to: "); - cli_write(output_file); - cli_write("\n"); -} - -void cli_cmd_cat(char *args) { - if (!args || args[0] == 0) { - cli_write("Usage: cat \n"); - return; - } - - char filename[256]; - int i = 0; - while (args[i] && args[i] != ' ' && args[i] != '\t') { - filename[i] = args[i]; - i++; - } - filename[i] = 0; - - if (cli_strcmp(filename, "messages") == 0) { - cmd_reset_msg_count(); - } - - FAT32_FileHandle *fh = fat32_open(filename, "r"); - if (!fh) { - cli_write("Error: Cannot open file\n"); - return; - } - - // Read and display file - char buffer[4096]; - int bytes_read; - while ((bytes_read = fat32_read(fh, buffer, sizeof(buffer))) > 0) { - for (int j = 0; j < bytes_read; j++) { - cli_putchar(buffer[j]); - } - } - - fat32_close(fh); -} - -void cli_cmd_touch(char *args) { - if (!args || args[0] == 0) { - cli_write("Usage: touch \n"); - return; - } - - char filename[256]; - int i = 0; - while (args[i] && args[i] != ' ' && args[i] != '\t') { - filename[i] = args[i]; - i++; - } - filename[i] = 0; - - // Check if file already exists - if (fat32_exists(filename)) { - cli_write("File already exists: "); - cli_write(filename); - cli_write("\n"); - return; - } - - // Open file in write mode to create it - FAT32_FileHandle *fh = fat32_open(filename, "w"); - if (!fh) { - cli_write("Error: Cannot create file\n"); - return; - } - - fat32_close(fh); - - cli_write("Created: "); - cli_write(filename); - cli_write("\n"); -} - -void cli_cmd_cp(char *args) { - char *src = args; - while (*src == ' ') src++; - - char *dest = src; - while (*dest && *dest != ' ') dest++; - - if (*dest) { - *dest = 0; - dest++; - while (*dest == ' ') dest++; - } - - if (!*src || !*dest) { - cli_write("Usage: cp \n"); - return; - } - - // Check if dest is a directory - char final_dest[256]; - cli_strcpy(final_dest, dest); - - if (fat32_is_directory(dest)) { - // Append filename from src to dest - int len = cli_strlen(final_dest); - if (len > 0 && final_dest[len-1] != '/') { - final_dest[len++] = '/'; - final_dest[len] = 0; - } - - // Extract filename from src - const char *fname = src; - const char *p = src; - while (*p) { - if (*p == '/') fname = p + 1; - p++; - } - - // Append - int j = 0; - while (fname[j]) { - final_dest[len++] = fname[j++]; - } - final_dest[len] = 0; - } - - FAT32_FileHandle *fh_in = fat32_open(src, "r"); - if (!fh_in) { - cli_write("Error: Cannot open source file: "); - cli_write(src); - cli_write("\n"); - return; - } - - FAT32_FileHandle *fh_out = fat32_open(final_dest, "w"); - if (!fh_out) { - cli_write("Error: Cannot create destination file: "); - cli_write(final_dest); - cli_write("\n"); - fat32_close(fh_in); - return; - } - - char buffer[4096]; - int bytes; - while ((bytes = fat32_read(fh_in, buffer, sizeof(buffer))) > 0) { - fat32_write(fh_out, buffer, bytes); - } - - fat32_close(fh_in); - fat32_close(fh_out); - - cli_write("Copied "); - cli_write(src); - cli_write(" to "); - cli_write(final_dest); - cli_write("\n"); -} - -void cli_cmd_mv(char *args) { - // Parse args similar to cp - char *src = args; - while (*src == ' ') src++; - - char *dest = src; - while (*dest && *dest != ' ') dest++; - - if (*dest) { - *dest = 0; - dest++; - while (*dest == ' ') dest++; - } - - if (!*src || !*dest) { - cli_write("Usage: mv \n"); - return; - } - - - char cp_args[512]; - int i = 0; - const char *s = src; - while (*s) cp_args[i++] = *s++; - cp_args[i++] = ' '; - const char *d = dest; - while (*d) cp_args[i++] = *d++; - cp_args[i] = 0; - - cli_cmd_cp(cp_args); - - fat32_delete(src); -} diff --git a/src/kernel/cli_apps/help.c b/src/kernel/cli_apps/help.c deleted file mode 100644 index ee80669..0000000 --- a/src/kernel/cli_apps/help.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "cli_utils.h" - -void cli_cmd_help(char *args) { - (void)args; - cli_write("Available commands:\n"); - cli_write(" HELP - Display this help message\n"); - cli_write(" DATE - Display current date and time\n"); - cli_write(" CLEAR - Clear the screen\n"); - cli_write(" BOREDVER - Gives version info\n"); - cli_write(" MATH - math (e.g. math + 1 2)\n"); - cli_write(" MAN - Show user manual (interactive)\n"); - cli_write(" LICENSE - Show license (interactive)\n"); - cli_write(" UPTIME - System uptime\n"); - cli_write(" BEEP - Make a sound\n"); - cli_write(" COWSAY - cowsay \n"); - cli_write(" REBOOT - Reboot system\n"); - cli_write(" SHUTDOWN - Shutdown system\n"); - cli_write(" MEMINFO - Gives memory info\n"); - cli_write(" CC - C compiler\n"); -} diff --git a/src/kernel/cli_apps/man.c b/src/kernel/cli_apps/man.c deleted file mode 100644 index 57f1c9d..0000000 --- a/src/kernel/cli_apps/man.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "cli_utils.h" - -// Forward declaration from cmd.c -extern void pager_wrap_content(const char **lines, int count); -extern void pager_set_mode(void); - -const char* manual_pages[] = { - "No manual round here pal", - -}; -const int manual_num_lines = sizeof(manual_pages) / sizeof(char*); - -void cli_cmd_man(char *args) { - (void)args; - pager_wrap_content(manual_pages, manual_num_lines); - pager_set_mode(); -} diff --git a/src/kernel/cli_apps/math.c b/src/kernel/cli_apps/math.c deleted file mode 100644 index 258c145..0000000 --- a/src/kernel/cli_apps/math.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "cli_utils.h" - -void cli_cmd_math(char *args) { - while (*args == ' ') args++; - if (!*args) { - cli_write("Usage: math \n"); - return; - } - char op = *args; - args++; - while (*args == ' ') args++; - - char *end = args; - while (*end && *end != ' ') end++; - int saved = *end; - *end = 0; - int n1 = cli_atoi(args); - if (saved) *end = saved; - - args = end; - while (*args == ' ') args++; - - int n2 = cli_atoi(args); - - int res = 0; - switch(op) { - case '+': res = n1 + n2; break; - case '-': res = n1 - n2; break; - case '*': res = n1 * n2; break; - case '/': if(n2!=0) res = n1/n2; else { cli_write("Div by zero\n"); return; } break; - default: cli_write("Invalid op.\n"); return; - } - cli_write("Result: "); cli_write_int(res); cli_write("\n"); -} diff --git a/src/kernel/cli_apps/memcmd.c b/src/kernel/cli_apps/memcmd.c deleted file mode 100644 index b357b14..0000000 --- a/src/kernel/cli_apps/memcmd.c +++ /dev/null @@ -1,143 +0,0 @@ -#include "cli_utils.h" -#include "../memory_manager.h" - -#define MAX_TEST_ALLOCS 64 -static void *test_allocs[MAX_TEST_ALLOCS]; -static int test_alloc_count = 0; - -void cli_cmd_malloc(char *args) { - if (!args || !args[0]) { - cli_write("Usage: malloc \n"); - cli_write("Example: malloc 10\n"); - return; - } - - // Parse size in KB - int size_kb = cli_atoi(args); - if (size_kb <= 0 || size_kb > 1024) { - cli_write("Invalid size. Use 1-1024 KB\n"); - return; - } - - size_t size = size_kb * 1024; - void *ptr = kmalloc(size); - - if (ptr == NULL) { - cli_write("Allocation failed!\n"); - return; - } - - // Track allocation for later freeing - if (test_alloc_count < MAX_TEST_ALLOCS) { - test_allocs[test_alloc_count++] = ptr; - } - - cli_write("Allocated "); - cli_write_int(size_kb); - cli_write("KB at address 0x"); - cli_write_int((uintptr_t)ptr / 1024); - cli_write("\n"); - cli_write("Test allocation index: "); - cli_write_int(test_alloc_count - 1); - cli_write("\n"); - - memory_print_stats(); -} - -void cli_cmd_free_mem(char *args) { - if (!args || !args[0]) { - cli_write("Usage: freemem \n"); - cli_write("Specify the allocation index from malloc output\n"); - return; - } - - int idx = cli_atoi(args); - if (idx < 0 || idx >= test_alloc_count) { - cli_write("Invalid index. Must be 0-"); - cli_write_int(test_alloc_count - 1); - cli_write("\n"); - return; - } - - void *ptr = test_allocs[idx]; - if (ptr == NULL) { - cli_write("Allocation at index "); - cli_write_int(idx); - cli_write(" is NULL\n"); - return; - } - - kfree(ptr); - test_allocs[idx] = NULL; - - cli_write("Freed allocation at index "); - cli_write_int(idx); - cli_write("\n"); - - memory_print_stats(); -} - -void cli_cmd_memblock(char *args) { - (void)args; - - cli_write("Detailed block information:\n"); - memory_print_detailed(); -} - -void cli_cmd_memvalid(char *args) { - (void)args; - - cli_write("Validating memory integrity...\n"); - memory_validate(); -} - -void cli_cmd_memtest(char *args) { - (void)args; - - cli_write("\n=== MEMORY STRESS TEST ===\n"); - - // Allocate multiple blocks - cli_write("Allocating 10 blocks of 256KB each...\n"); - void *test_ptrs[10]; - - for (int i = 0; i < 10; i++) { - test_ptrs[i] = kmalloc(256 * 1024); - if (test_ptrs[i] == NULL) { - cli_write("Allocation "); - cli_write_int(i); - cli_write(" failed\n"); - - // Free previous allocations - for (int j = 0; j < i; j++) { - kfree(test_ptrs[j]); - } - return; - } - cli_write("Allocated block "); - cli_write_int(i); - cli_write("\n"); - } - - memory_print_stats(); - - // Free every other block (create fragmentation) - cli_write("\nFreeing alternate blocks to create fragmentation...\n"); - for (int i = 0; i < 10; i += 2) { - kfree(test_ptrs[i]); - cli_write("Freed block "); - cli_write_int(i); - cli_write("\n"); - } - - memory_print_stats(); - - // Free remaining blocks - cli_write("\nFreeing remaining blocks...\n"); - for (int i = 1; i < 10; i += 2) { - kfree(test_ptrs[i]); - } - - memory_print_stats(); - - cli_write("=== TEST COMPLETE ===\n\n"); -} diff --git a/src/kernel/cli_apps/meminfo.c b/src/kernel/cli_apps/meminfo.c deleted file mode 100644 index ab81ecd..0000000 --- a/src/kernel/cli_apps/meminfo.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "cli_utils.h" -#include "../memory_manager.h" - -void cli_cmd_meminfo(char *args) { - (void)args; - - // Print memory statistics - memory_print_stats(); -} diff --git a/src/kernel/cli_apps/net.c b/src/kernel/cli_apps/net.c deleted file mode 100644 index 4c6ab26..0000000 --- a/src/kernel/cli_apps/net.c +++ /dev/null @@ -1,189 +0,0 @@ -#include "cli_utils.h" -#include "network.h" -#include "fat32.h" -#include "cmd.h" -#include "memory_manager.h" - -static void print_mac(const mac_address_t* mac){ - char buf[64]; - int p=0; - for(int i=0;i<6;i++){ - int v=mac->bytes[i]; - int hi=(v>>4)&0xF, lo=v&0xF; - buf[p++]= (hi<10)?('0'+hi):('A'+(hi-10)); - buf[p++]= (lo<10)?('0'+lo):('A'+(lo-10)); - if(i<5) buf[p++]=':'; - } - buf[p]=0; - cli_write(buf); -} - -void cli_cmd_netinit(char *args){ - (void)args; - int r=network_init(); - if(r==0){ - cli_write("Network initialized\n"); - int d=network_dhcp_acquire(); - if(d==0){ - cli_write("DHCP acquired\n"); - } else { - cli_write("DHCP failed\n"); - } - } else { - cli_write("Network init failed\n"); - } -} - -void cli_cmd_netinfo(char *args){ - (void)args; - mac_address_t mac; - ipv4_address_t ip; - if(network_get_mac_address(&mac)==0){ - cli_write("MAC: "); print_mac(&mac); cli_write("\n"); - } - if(network_get_ipv4_address(&ip)==0){ - cli_write("IP: "); - for(int i=0;i<4;i++){ cli_write_int(ip.bytes[i]); if(i<3) cli_write("."); } - cli_write("\n"); - } - cli_write("Frames: "); cli_write_int(network_get_frames_received()); cli_write("\n"); - cli_write("UDP packets: "); cli_write_int(network_get_udp_packets_received()); cli_write("\n"); - cli_write("UDP callbacks: "); cli_write_int(network_get_udp_callbacks_called()); cli_write("\n"); - cli_write("E1000 receive calls: "); cli_write_int(network_get_e1000_receive_calls()); cli_write("\n"); - cli_write("E1000 receive empty: "); cli_write_int(network_get_e1000_receive_empty()); cli_write("\n"); - cli_write("Process calls: "); cli_write_int(network_get_process_calls()); cli_write("\n"); -} - -void cli_cmd_ipset(char *args){ - if(!args||!*args){ cli_write("Usage: IPSET a.b.c.d\n"); return; } - ipv4_address_t ip={{0,0,0,0}}; - int part=0; int val=0; int i=0; - while(args[i]){ - char ch=args[i++]; - if(ch>='0'&&ch<='9'){ val=val*10+(ch-'0'); if(val>255){ cli_write("Invalid IP\n"); return; } } - else if(ch=='.'){ if(part>3){ cli_write("Invalid IP\n"); return; } ip.bytes[part++]=(uint8_t)val; val=0; } - else { cli_write("Invalid IP\n"); return; } - } - if(part!=3){ cli_write("Invalid IP\n"); return; } - ip.bytes[3]=(uint8_t)val; - if(network_set_ipv4_address(&ip)==0){ cli_write("IP set\n"); } else { cli_write("IP set failed\n"); } -} - -void cli_cmd_udpsend(char *args){ - if(!args||!*args){ cli_write("Usage: UDPSEND ip port data\n"); return; } - char ipstr[32]; int pos=0; - while(args[pos] && args[pos]!=' '){ ipstr[pos]=args[pos]; pos++; } - ipstr[pos]=0; - while(args[pos]==' ') pos++; - char portstr[16]; int p=0; - while(args[pos] && args[pos]!=' '){ portstr[p++]=args[pos++]; } - portstr[p]=0; - while(args[pos]==' ') pos++; - char* datastr = args+pos; - ipv4_address_t ip={{0,0,0,0}}; - int idx=0; int val=0; int j=0; - while(ipstr[j]){ - char ch=ipstr[j++]; - if(ch>='0'&&ch<='9'){ val=val*10+(ch-'0'); if(val>255){ cli_write("Invalid IP\n"); return; } } - else if(ch=='.'){ if(idx>3){ cli_write("Invalid IP\n"); return; } ip.bytes[idx++]=(uint8_t)val; val=0; } - else { cli_write("Invalid IP\n"); return; } - } - if(idx!=3){ cli_write("Invalid IP\n"); return; } - ip.bytes[3]=(uint8_t)val; - int port=0; int k=0; while(portstr[k]){ char ch=portstr[k++]; if(ch<'0'||ch>'9'){ cli_write("Invalid port\n"); return; } port=port*10+(ch-'0'); } - if(port<=0||port>65535){ cli_write("Invalid port\n"); return; } - int len=(int)cli_strlen(datastr); - if(len<=0){ cli_write("No data\n"); return; } - int r=udp_send_packet(&ip,(uint16_t)port,12345,datastr,(size_t)len); - if(r==0) cli_write("Sent\n"); else cli_write("Send failed\n"); -} - -static void udp_print_callback(const ipv4_address_t* src_ip,uint16_t src_port,const mac_address_t* src_mac,const void* data,size_t length){ - (void)src_mac; - - FAT32_FileHandle *fh = fat32_open("messages", "a"); - if (fh) { - char buf[32]; - fat32_write(fh, "UDP from ", 9); - - // Write IP - for(int i=0;i<4;i++){ - cli_itoa(src_ip->bytes[i], buf); - fat32_write(fh, buf, cli_strlen(buf)); - if(i<3) fat32_write(fh, ".", 1); - } - - fat32_write(fh, ":", 1); - - // Write Port - cli_itoa(src_port, buf); - fat32_write(fh, buf, cli_strlen(buf)); - - fat32_write(fh, " ", 1); - - // Write Message - fat32_write(fh, data, length); - fat32_write(fh, "\n", 1); - - fat32_close(fh); - - cmd_increment_msg_count(); - } -} - -void cli_cmd_udptest(char *args){ - if(!args||!*args){ cli_write("Usage: UDPTEST port\n"); return; } - int port=cli_atoi(args); - if(port<=0||port>65535){ cli_write("Invalid port\n"); return; } - if(udp_register_callback((uint16_t)port,udp_print_callback)==0) cli_write("UDP callback registered\n"); else cli_write("Register failed\n"); -} - -void cli_cmd_msgrc(char *args) { - (void)args; - cmd_reset_msg_count(); - - FAT32_FileHandle *fh = fat32_open("messages", "r"); - if (!fh) { - cli_write("No messages.\n"); - return; - } - - uint32_t size = fh->size; - if (size == 0) { - fat32_close(fh); - cli_write("No messages.\n"); - return; - } - - char *buffer = (char*)kmalloc(size + 1); - if (!buffer) { - fat32_close(fh); - cli_write("Error: Out of memory\n"); - return; - } - - fat32_read(fh, buffer, size); - buffer[size] = 0; - fat32_close(fh); - - int count = 0; - int pos = size - 1; - - while (count < 10 && pos >= 0) { - // Skip trailing newlines/whitespace - while (pos >= 0 && (buffer[pos] == '\n' || buffer[pos] == '\r')) { - buffer[pos] = 0; - pos--; - } - if (pos < 0) break; - - // Find start of line - while (pos >= 0 && buffer[pos] != '\n' && buffer[pos] != '\r') pos--; - - cli_write(&buffer[pos + 1]); - cli_write("\n"); - count++; - } - - kfree(buffer); -} diff --git a/src/kernel/cli_apps/pci_list.c b/src/kernel/cli_apps/pci_list.c deleted file mode 100644 index 783f42d..0000000 --- a/src/kernel/cli_apps/pci_list.c +++ /dev/null @@ -1,44 +0,0 @@ -#include "cli_utils.h" -#include "pci.h" - -static void print_hex16(uint16_t v){ - char buf[7]; buf[0]='0'; buf[1]='x'; - for(int i=0;i<4;i++){ - int nyb=(v >> ((3-i)*4)) & 0xF; - buf[2+i]= nyb<10?('0'+nyb):('A'+(nyb-10)); - } - buf[6]=0; - cli_write(buf); -} - -static void print_hex8(uint8_t v){ - char buf[5]; buf[0]='0'; buf[1]='x'; - int hi=(v>>4)&0xF, lo=v&0xF; - buf[2]= hi<10?('0'+hi):('A'+(hi-10)); - buf[3]= lo<10?('0'+lo):('A'+(lo-10)); - buf[4]=0; - cli_write(buf); -} - -void cli_cmd_pcilist(char *args){ - (void)args; - pci_device_t devs[64]; - int n=pci_enumerate_devices(devs,64); - cli_write("PCI devices:\n"); - for(int i=0;i> 8) & 0xFF); - outb(0x61, inb(0x61) | 0x03); - } - - - cli_sleep(duration_ms); - - outb(0x61, inb(0x61) & 0xFC); - cli_sleep(20); -} - -void cli_cmd_minecraft(char *args) { - (void)args; - cli_write("Playing: Sweden - C418 (What a masterpiece)\n"); - - int melody[] = { - 196, 330, 294, 0, // G3, E4, D4, rest - 196, 262, 247, 220, 196, 0, // G3, C4, B3, A3, G3, rest - - 196, 330, 294, 392, 330, 0, // G3, E4, D4, G4, E4, rest - - 440, 330, 294, 0, // A4, E4, D4, rest - 262, 247, 220, 196, 147, 0, // C4, B3, A3, G3, D3, rest - - 196, 330, 294, 0, // Return to G3, E4, D4 - 196, 262, 247, 220, 196 // Final resolution - }; - - int rhythm[] = { - 1000, 1000, 2000, 500, - 1000, 1000, 1000, 1000, 2000, 500, - - 1000, 1000, 1000, 1000, 2000, 500, - - 1000, 1000, 2000, 500, - 1000, 1000, 1000, 1000, 2000, 500, - - 1000, 1000, 2000, 500, - 1000, 1000, 1000, 1000, 3000 - }; - - int song_length = sizeof(melody) / sizeof(melody[0]); - - for (int i = 0; i < song_length; i++) { - play_note(melody[i], rhythm[i]); - } - - outb(0x61, inb(0x61) & 0xFC); - cli_write("Composition finished.\n"); -} \ No newline at end of file diff --git a/src/kernel/cli_apps/uptime.c b/src/kernel/cli_apps/uptime.c deleted file mode 100644 index c2dd133..0000000 --- a/src/kernel/cli_apps/uptime.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "cli_utils.h" - -// Forward declarations from cmd.c -extern void rtc_get_datetime(int *y, int *m, int *d, int *h, int *min, int *s); -extern int boot_time_init; -extern int boot_year, boot_month, boot_day, boot_hour, boot_min, boot_sec; - -void cli_cmd_uptime(char *args) { - (void)args; - int y, m, d, h, min, s; - rtc_get_datetime(&y, &m, &d, &h, &min, &s); - - int start_sec = boot_hour * 3600 + boot_min * 60 + boot_sec; - int curr_sec = h * 3600 + min * 60 + s; - if (curr_sec < start_sec) curr_sec += 24 * 3600; - - int diff = curr_sec - start_sec; - int up_h = diff / 3600; - int up_m = (diff % 3600) / 60; - int up_s = diff % 60; - - cli_write("Uptime: "); - cli_write_int(up_h); cli_write("h "); - cli_write_int(up_m); cli_write("m "); - cli_write_int(up_s); cli_write("s\n"); -} diff --git a/src/kernel/cmd.c b/src/kernel/cmd.c index fa8d84d..d85152b 100644 --- a/src/kernel/cmd.c +++ b/src/kernel/cmd.c @@ -6,7 +6,7 @@ #include "fat32.h" #include "disk.h" -#include "cli_apps/cli_apps.h" +#include "kutils.h" #include "licensewr.h" #include #include "memory_manager.h" @@ -17,6 +17,7 @@ #include "network.h" #include "vm.h" #include "net_defs.h" +#include "man_entries.h" #define CMD_COLS 116 #define CMD_ROWS 41 @@ -376,22 +377,7 @@ void pager_set_mode(void) { // Internal LS command to avoid stack overflow in external module static void cmd_update_dir(const char *path); // Forward declaration -static void internal_cmd_pwd(char *args) { - (void)args; - if (cmd_state) { - char drive_str[3]; - drive_str[0] = cmd_state->current_drive; - drive_str[1] = ':'; - drive_str[2] = 0; - cmd_write(drive_str); - cmd_write(cmd_state->current_dir); - } else { - char cwd[256]; - fat32_get_current_dir(cwd, sizeof(cwd)); - cmd_write(cwd); - } - cmd_write("\n"); -} + static void internal_cmd_cd(char *args) { // Handle cd with proper cmd_state context @@ -533,46 +519,14 @@ static void internal_cmd_txtedit(char *args) { cmd_write("\n"); cmd_is_waiting_for_process = true; - process_create_elf("A:/bin/txtedit.elf", normalized_path); + process_t *proc = process_create_elf("A:/bin/txtedit.elf", normalized_path); + if (proc) { + proc->is_terminal_proc = true; + proc->ui_window = &win_cmd; + } } -static void internal_cmd_ls(char *args) { - char path[256]; - if (args && *args) { - int i=0; - while(args[i] && i < 255) { path[i] = args[i]; i++; } - path[i] = 0; - } else { - path[0] = '.'; path[1] = 0; - } - int max_files = 64; - FAT32_FileInfo *files = (FAT32_FileInfo*)kmalloc(max_files * sizeof(FAT32_FileInfo)); - if (!files) { - cmd_write("Error: Out of memory\n"); - return; - } - - int count = fat32_list_directory(path, files, max_files); - - for (int i = 0; i < count; i++) { - if (files[i].is_directory) { - cmd_write("[DIR] "); - } else { - cmd_write("[FILE] "); - } - - cmd_write(files[i].name); - if (!files[i].is_directory) { - cmd_write(" "); - cmd_write_int(files[i].size); - cmd_write("b"); - } - cmd_write("\n"); - } - - kfree(files); -} void cmd_exec_elf(char *args) { @@ -611,7 +565,11 @@ void cmd_exec_elf(char *args) { } cmd_is_waiting_for_process = true; - process_create_elf(full_exec_path, args); + process_t *proc = process_create_elf(full_exec_path, args); + if (proc) { + proc->is_terminal_proc = true; + proc->ui_window = &win_cmd; + } } // Public API for syscall exit @@ -628,6 +586,11 @@ void cmd_process_finished(void) { } } +static void internal_cmd_exit(char *args) { + (void)args; + cmd_window_exit(); +} + // Command dispatch table typedef struct { const char *name; @@ -637,101 +600,18 @@ typedef struct { static const CommandEntry commands[] = { {"EXEC", cmd_exec_elf}, {"exec", cmd_exec_elf}, - {"HELP", cli_cmd_help}, - {"help", cli_cmd_help}, - {"DATE", cli_cmd_date}, - {"date", cli_cmd_date}, - {"CLEAR", cli_cmd_clear}, - {"clear", cli_cmd_clear}, - {"BOREDVER", cli_cmd_boredver}, - {"boredver", cli_cmd_boredver}, - {"MATH", cli_cmd_math}, - {"math", cli_cmd_math}, - {"MAN", cli_cmd_man}, - {"man", cli_cmd_man}, {"TXTEDIT", internal_cmd_txtedit}, {"txtedit", internal_cmd_txtedit}, - {"UPTIME", cli_cmd_uptime}, - {"uptime", cli_cmd_uptime}, - {"BEEP", cli_cmd_beep}, - {"beep", cli_cmd_beep}, - {"COWSAY", cli_cmd_cowsay}, - {"cowsay", cli_cmd_cowsay}, - {"REBOOT", cli_cmd_reboot}, - {"reboot", cli_cmd_reboot}, - {"SHUTDOWN", cli_cmd_shutdown}, - {"shutdown", cli_cmd_shutdown}, - {"IREADTHEMANUAL", cli_cmd_readtheman}, - {"ireadthemanual", cli_cmd_readtheman}, - {"BLIND", cli_cmd_blind}, - {"blind", cli_cmd_blind}, - {"EXIT", cli_cmd_exit}, - {"exit", cli_cmd_exit}, - // Filesystem Commands + {"EXIT", internal_cmd_exit}, + {"exit", internal_cmd_exit}, {"CD", internal_cmd_cd}, {"cd", internal_cmd_cd}, - {"PWD", internal_cmd_pwd}, - {"pwd", internal_cmd_pwd}, - {"LS", internal_cmd_ls}, - {"ls", internal_cmd_ls}, - {"MKDIR", cli_cmd_mkdir}, - {"mkdir", cli_cmd_mkdir}, - {"RM", cli_cmd_rm}, - {"rm", cli_cmd_rm}, - {"ECHO", cli_cmd_echo}, - {"echo", cli_cmd_echo}, - {"CAT", cli_cmd_cat}, - {"cat", cli_cmd_cat}, - {"TOUCH", cli_cmd_touch}, - {"touch", cli_cmd_touch}, - {"CP", cli_cmd_cp}, - {"cp", cli_cmd_cp}, - {"MV", cli_cmd_mv}, - {"mv", cli_cmd_mv}, - // Memory Management Commands - {"MEMINFO", cli_cmd_meminfo}, - {"meminfo", cli_cmd_meminfo}, - {"MALLOC", cli_cmd_malloc}, - {"malloc", cli_cmd_malloc}, - {"FREEMEM", cli_cmd_free_mem}, - {"freemem", cli_cmd_free_mem}, - {"MEMBLOCK", cli_cmd_memblock}, - {"memblock", cli_cmd_memblock}, - {"MEMVALID", cli_cmd_memvalid}, - {"memvalid", cli_cmd_memvalid}, - {"MEMTEST", cli_cmd_memtest}, - {"memtest", cli_cmd_memtest}, - // Network Commands - {"NETINIT", cli_cmd_netinit}, - {"netinit", cli_cmd_netinit}, - {"NETINFO", cli_cmd_netinfo}, - {"netinfo", cli_cmd_netinfo}, - {"IPSET", cli_cmd_ipset}, - {"ipset", cli_cmd_ipset}, - {"UDPSEND", cli_cmd_udpsend}, - {"udpsend", cli_cmd_udpsend}, - {"UDPTEST", cli_cmd_udptest}, - {"udptest", cli_cmd_udptest}, - {"PING", cli_cmd_ping}, - {"ping", cli_cmd_ping}, - {"DNS", cli_cmd_dns}, - {"dns", cli_cmd_dns}, - {"HTTPGET", cli_cmd_httpget}, - {"httpget", cli_cmd_httpget}, - {"PCILIST", cli_cmd_pcilist}, - {"pcilist", cli_cmd_pcilist}, - {"MSGRC", cli_cmd_msgrc}, - {"msgrc", cli_cmd_msgrc}, - {"COMPC", cli_cmd_cc}, - {"compc", cli_cmd_cc}, - {"CC", cli_cmd_cc}, - {"cc", cli_cmd_cc}, - {"sweden", cli_cmd_minecraft}, - {"SWEDEN", cli_cmd_minecraft}, {NULL, NULL} }; + + // Helper to sync cmd window directory after cd static void cmd_update_dir(const char *path) { if (!cmd_state || !path) return; @@ -932,6 +812,7 @@ static void cmd_exec_single(char *cmd) { temp_args[j++] = args[i++]; } } + (void)in_redirect; temp_args[j] = 0; cmd_strcpy(full_path_arg, temp_args); args = full_path_arg; @@ -1095,7 +976,11 @@ static void cmd_exec_single(char *cmd) { if (fh) { fat32_close(fh); cmd_is_waiting_for_process = true; - process_create_elf(search_path, args); + process_t *proc = process_create_elf(search_path, args); + if (proc) { + proc->is_terminal_proc = true; + proc->ui_window = &win_cmd; + } return; } } @@ -1116,7 +1001,11 @@ static void cmd_exec_single(char *cmd) { if (fh) { fat32_close(fh); cmd_is_waiting_for_process = true; - process_create_elf(search_path, args); + process_t *proc = process_create_elf(search_path, args); + if (proc) { + proc->is_terminal_proc = true; + proc->ui_window = &win_cmd; + } return; } } @@ -1705,6 +1594,7 @@ static void create_test_files(void) { void cmd_init(void) { create_test_files(); + create_man_entries(); win_cmd.title = "Command Prompt"; win_cmd.x = 50; diff --git a/src/kernel/explorer.c b/src/kernel/explorer.c index f243594..baa1ae0 100644 --- a/src/kernel/explorer.c +++ b/src/kernel/explorer.c @@ -724,8 +724,8 @@ static void explorer_load_directory(Window *win, const char *path) { int count = fat32_list_directory(path, entries, EXPLORER_MAX_FILES); - state->item_count = 0; - for (int i = 0; i < count && state->item_count < EXPLORER_MAX_FILES; i++) { + int temp_count = 0; + for (int i = 0; i < count && temp_count < EXPLORER_MAX_FILES; i++) { // Skip .color files if (explorer_strcmp(entries[i].name, ".color") == 0) { continue; @@ -736,24 +736,26 @@ static void explorer_load_directory(Window *win, const char *path) { continue; } - explorer_strcpy(state->items[state->item_count].name, entries[i].name); - state->items[state->item_count].is_directory = entries[i].is_directory; - state->items[state->item_count].size = entries[i].size; + explorer_strcpy(state->items[temp_count].name, entries[i].name); + state->items[temp_count].is_directory = entries[i].is_directory; + state->items[temp_count].size = entries[i].size; - if (state->items[state->item_count].is_directory) { + if (state->items[temp_count].is_directory) { char subfolder_path[FAT32_MAX_PATH]; explorer_strcpy(subfolder_path, path); if (subfolder_path[explorer_strlen(subfolder_path) - 1] != '/') { explorer_strcat(subfolder_path, "/"); } - explorer_strcat(subfolder_path, state->items[state->item_count].name); - state->items[state->item_count].color = explorer_get_folder_color(subfolder_path); + explorer_strcat(subfolder_path, state->items[temp_count].name); + state->items[temp_count].color = explorer_get_folder_color(subfolder_path); } else { - state->items[state->item_count].color = COLOR_APPLE_YELLOW; + state->items[temp_count].color = COLOR_APPLE_YELLOW; } - state->item_count++; + temp_count++; } + state->item_count = temp_count; + kfree(entries); if (path_changed) { state->selected_item = -1; diff --git a/src/kernel/cli_apps/cli_utils.c b/src/kernel/kutils.c similarity index 62% rename from src/kernel/cli_apps/cli_utils.c rename to src/kernel/kutils.c index e5f6088..6d99e6c 100644 --- a/src/kernel/cli_apps/cli_utils.c +++ b/src/kernel/kutils.c @@ -1,23 +1,25 @@ -#include "cli_utils.h" +#include "kutils.h" #include "wm.h" +#include "io.h" -// Forward declarations - these will be provided by cmd.c -extern void cmd_putchar(char c); -extern void cmd_write(const char *str); -extern void cmd_write_int(int n); - -void cli_memset(void *dest, int val, size_t len) { - unsigned char *ptr = dest; - while (len-- > 0) *ptr++ = val; +void k_memset(void *dest, int val, size_t len) { + unsigned char *ptr = (unsigned char *)dest; + while (len-- > 0) *ptr++ = (unsigned char)val; } -size_t cli_strlen(const char *str) { +void k_memcpy(void *dest, const void *src, size_t len) { + unsigned char *d = (unsigned char *)dest; + const unsigned char *s = (const unsigned char *)src; + while (len-- > 0) *d++ = *s++; +} + +size_t k_strlen(const char *str) { size_t len = 0; while (str[len]) len++; return len; } -int cli_strcmp(const char *s1, const char *s2) { +int k_strcmp(const char *s1, const char *s2) { while (*s1 && (*s1 == *s2)) { s1++; s2++; @@ -25,12 +27,12 @@ int cli_strcmp(const char *s1, const char *s2) { return *(const unsigned char*)s1 - *(const unsigned char*)s2; } -void cli_strcpy(char *dest, const char *src) { +void k_strcpy(char *dest, const char *src) { while (*src) *dest++ = *src++; *dest = 0; } -int cli_atoi(const char *str) { +int k_atoi(const char *str) { int res = 0; int sign = 1; if (*str == '-') { sign = -1; str++; } @@ -41,7 +43,7 @@ int cli_atoi(const char *str) { return res * sign; } -void cli_itoa(int n, char *buf) { +void k_itoa(int n, char *buf) { if (n == 0) { buf[0] = '0'; buf[1] = 0; return; } @@ -54,7 +56,6 @@ void cli_itoa(int n, char *buf) { } if (sign) buf[i++] = '-'; buf[i] = 0; - // Reverse for (int j = 0; j < i / 2; j++) { char t = buf[j]; buf[j] = buf[i - 1 - j]; @@ -62,25 +63,13 @@ void cli_itoa(int n, char *buf) { } } -void cli_write(const char *str) { - cmd_write(str); -} - -void cli_write_int(int n) { - cmd_write_int(n); -} - -void cli_putchar(char c) { - cmd_putchar(c); -} - -void cli_delay(int iterations) { +void k_delay(int iterations) { for (volatile int i = 0; i < iterations; i++) { __asm__ __volatile__("nop"); } } -void cli_sleep(int ms) { +void k_sleep(int ms) { // Timer is ~60Hz, so 1 tick = 16.66ms uint32_t ticks = ms / 16; if (ticks == 0 && ms > 0) ticks = 1; @@ -90,3 +79,11 @@ void cli_sleep(int ms) { __asm__ __volatile__("hlt"); } } + +void k_reboot(void) { + outb(0x64, 0xFE); +} + +void k_shutdown(void) { + outw(0x604, 0x2000); +} diff --git a/src/kernel/kutils.h b/src/kernel/kutils.h new file mode 100644 index 0000000..b4e20d4 --- /dev/null +++ b/src/kernel/kutils.h @@ -0,0 +1,22 @@ +#ifndef KUTILS_H +#define KUTILS_H + +#include +#include + +// Kernel string utilities +void k_memset(void *dest, int val, size_t len); +void k_memcpy(void *dest, const void *src, size_t len); +size_t k_strlen(const char *str); +int k_strcmp(const char *s1, const char *s2); +void k_strcpy(char *dest, const char *src); +int k_atoi(const char *str); +void k_itoa(int n, char *buf); + +// Kernel timing utilities +void k_delay(int iterations); +void k_sleep(int ms); +void k_reboot(void); +void k_shutdown(void); + +#endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 362aa76..613b9fe 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -46,6 +46,13 @@ static volatile struct limine_request *const requests_start_marker[] = { NULL }; +__attribute__((used, section(".requests"))) +static volatile struct limine_stack_size_request stack_size_request = { + .id = LIMINE_STACK_SIZE_REQUEST, + .revision = 0, + .stack_size = 1024 * 1024 // 1MB stack +}; + __attribute__((used, section(".requests_end"))) static volatile struct limine_request *const requests_end_marker[] = { NULL diff --git a/src/kernel/man_entries.h b/src/kernel/man_entries.h new file mode 100644 index 0000000..8c359d8 --- /dev/null +++ b/src/kernel/man_entries.h @@ -0,0 +1,69 @@ +#ifndef MAN_ENTRIES_H +#define MAN_ENTRIES_H + +#include "fat32.h" +#include + +static size_t man_strlen(const char *str) { + size_t len = 0; + while (str[len]) len++; + return len; +} + +static void write_man_file(const char *name, const char *content) { + char path[128] = "A:/Library/man/"; + int i = 15; + while (*name) path[i++] = *name++; + path[i++] = '.'; + path[i++] = 't'; + path[i++] = 'x'; + path[i++] = 't'; + path[i] = 0; + + FAT32_FileHandle *fh = fat32_open(path, "w"); + if (fh) { + fat32_write(fh, (void *)content, man_strlen(content)); + fat32_close(fh); + } +} + +void create_man_entries(void) { + fat32_mkdir("A:/Library"); + fat32_mkdir("A:/Library/man"); + + write_man_file("ls", "LS - List directory contents\n\nUsage: ls [path]\n\nLists files and directories in the current or specified directory."); + write_man_file("cat", "CAT - Concatenate and display file contents\n\nUsage: cat \n\nDisplays the text content of the specified file."); + write_man_file("man", "MAN - Display manual pages\n\nUsage: man \n\nDisplays help information for the specified command."); + write_man_file("beep", "BEEP - Play system beep\n\nUsage: beep\n\nPlays a short tone through the PC speaker."); + write_man_file("sweden", "SWEDEN - Play Swedish melody\n\nUsage: sweden\n\nPlays the Swedish national anthem through the PC speaker."); + write_man_file("clear", "CLEAR - Clear terminal screen\n\nUsage: clear\n\nClears all text from the current terminal window."); + write_man_file("date", "DATE - Show current date and time\n\nUsage: date\n\nDisplays the current system date and time from the RTC."); + write_man_file("echo", "ECHO - Print text\n\nUsage: echo [text]\n\nPrints the specified text to the terminal."); + write_man_file("hello", "HELLO - Hello World demo\n\nUsage: hello\n\nA simple demonstration program that prints a greeting."); + write_man_file("help", "HELP - List available commands\n\nUsage: help\n\nLists all internal and external commands available in the shell."); + write_man_file("uptime", "UPTIME - Show system uptime\n\nUsage: uptime\n\nDisplays how long BoredOS has been running since boot."); + write_man_file("pwd", "PWD - Print working directory\n\nUsage: pwd\n\nDisplays the absolute path of the current working directory."); + write_man_file("mkdir", "MKDIR - Create directory\n\nUsage: mkdir \n\nCreates a new directory with the specified name."); + write_man_file("rm", "RM - Remove file\n\nUsage: rm \n\nDeletes the specified file from the filesystem."); + write_man_file("mv", "MV - Move or rename file\n\nUsage: mv \n\nMoves or renames a file or directory."); + write_man_file("cp", "CP - Copy file\n\nUsage: cp \n\nCopies a file from the source path to the destination path."); + write_man_file("touch", "TOUCH - Create empty file\n\nUsage: touch \n\nCreates a new empty file if it doesn't exist."); + write_man_file("cc", "CC - C Compiler\n\nUsage: cc \n\nThe BoredOS C Compiler. Compiles C source files into ELF executables."); + write_man_file("crash", "CRASH - Trigger kernel exception\n\nUsage: crash\n\nIntentionally triggers a null pointer dereference to test handlers."); + write_man_file("boredver", "BOREDVER - Show OS version\n\nUsage: boredver\n\nDisplays current BoredOS version and kernel build information."); + write_man_file("meminfo", "MEMINFO - Memory usage stats\n\nUsage: meminfo\n\nDisplays current physical and virtual memory allocation statistics."); + write_man_file("pci_list", "PCI_LIST - Scan PCI bus\n\nUsage: pci_list\n\nScans the PCI bus and lists all detected hardware devices."); + write_man_file("reboot", "REBOOT - Restart system\n\nUsage: reboot\n\nRestarts the computer immediately."); + write_man_file("shutdown", "SHUTDOWN - Power off\n\nUsage: shutdown\n\nPowers off the machine (requires ACPI support)."); + write_man_file("calculator", "CALCULATOR - Graphical calculator\n\nUsage: calculator\n\nOpens a simple calculator with a mouse interface."); + write_man_file("notepad", "NOTEPAD - Desktop text editor\n\nUsage: notepad\n\nOpens a graphical text editor for the BoredOS desktop."); + write_man_file("paint", "PAINT - Drawing application\n\nUsage: paint\n\nOpens a simple drawing program with various colors."); + write_man_file("minesweeper", "MINESWEEPER - Classic game\n\nUsage: minesweeper\n\nPlays the classic minesweeper puzzle game."); + write_man_file("markdown", "MARKDOWN - MD file viewer\n\nUsage: markdown \n\nOpens a graphical viewer for formatted markdown files."); + write_man_file("txtedit", "TXTEDIT - Terminal text editor\n\nUsage: txtedit \n\nOpens a CLI-based text editor within the terminal."); + write_man_file("math", "MATH - Expression evaluator\n\nUsage: math \n\nEvaluates simple arithmetic expressions from the command line."); + write_man_file("viewer", "VIEWER - Image viewer\n\nUsage: viewer \n\nA graphical application for viewing image files."); + write_man_file("settings", "SETTINGS - System settings\n\nUsage: settings\n\nOpens the graphical system configuration tool."); +} + +#endif diff --git a/src/kernel/process.c b/src/kernel/process.c index 5224220..b5cb47c 100644 --- a/src/kernel/process.c +++ b/src/kernel/process.c @@ -51,8 +51,8 @@ void process_create(void* entry_point, bool is_user) { if (!new_proc->pml4_phys) return; // 2. Allocate aligned stack - void* stack = kmalloc_aligned(4096, 4096); - void* kernel_stack = kmalloc_aligned(16384, 16384); // Needed for when user interrupts to Ring 0 + void* stack = kmalloc_aligned(524288, 4096); // 512KB for kernel threads + void* kernel_stack = kmalloc_aligned(126976, 16384); // 128KB for ringswitch if (is_user) { // Map user stack to 0x800000 @@ -66,7 +66,7 @@ void process_create(void* entry_point, bool is_user) { // Build initial stack frame for iretq // Stack grows down, start at top - uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 16384); + uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 126976); *(--stack_ptr) = 0x1B; // SS (User Data) *(--stack_ptr) = 0x800000 + 4096; // RSP @@ -79,11 +79,11 @@ void process_create(void* entry_point, bool is_user) { // Push 15 zeros for general purpose registers (r15 -> rax) for (int i = 0; i < 15; i++) *(--stack_ptr) = 0; - new_proc->kernel_stack = (uint64_t)kernel_stack + 16384; + new_proc->kernel_stack = (uint64_t)kernel_stack + 126976; new_proc->rsp = (uint64_t)stack_ptr; } else { // Kernel thread - uint64_t* stack_ptr = (uint64_t*)((uint64_t)stack + 4096); + uint64_t* stack_ptr = (uint64_t*)((uint64_t)stack + 524288); *(--stack_ptr) = 0x10; // SS (Kernel Data) stack_ptr--; *stack_ptr = (uint64_t)stack_ptr; // RSP @@ -104,8 +104,8 @@ void process_create(void* entry_point, bool is_user) { current_process->next = new_proc; } -void process_create_elf(const char* filepath, const char* args_str) { - if (process_count >= MAX_PROCESSES) return; +process_t* process_create_elf(const char* filepath, const char* args_str) { + if (process_count >= MAX_PROCESSES) return NULL; process_t *new_proc = &processes[process_count]; new_proc->pid = next_pid++; @@ -113,7 +113,7 @@ void process_create_elf(const char* filepath, const char* args_str) { // 1. Setup Page Table new_proc->pml4_phys = paging_create_user_pml4_phys(); - if (!new_proc->pml4_phys) return; + if (!new_proc->pml4_phys) return NULL; for (int i = 0; i < MAX_PROCESS_FDS; i++) new_proc->fds[i] = NULL; new_proc->gui_event_head = 0; @@ -121,6 +121,7 @@ void process_create_elf(const char* filepath, const char* args_str) { new_proc->ui_window = NULL; new_proc->heap_start = 0x20000000; // 512MB mark new_proc->heap_end = 0x20000000; + new_proc->is_terminal_proc = false; // 2. Load ELF executable uint64_t entry_point = elf_load(filepath, new_proc->pml4_phys); @@ -129,21 +130,23 @@ void process_create_elf(const char* filepath, const char* args_str) { serial_write(filepath); serial_write("\n"); // We technically leak the page table here, but let's ignore cleanup for now - return; + return NULL; } // 3. Allocate generic User stack and Kernel stack for interrupts - void* stack = kmalloc_aligned(4096, 4096); - void* kernel_stack = kmalloc_aligned(16384, 16384); + void* stack = kmalloc_aligned(2097152, 4096); // 2MB for user apps + void* kernel_stack = kmalloc_aligned(126976, 16384); // 128KB for interrupts - // Map User stack to 0x800000 - paging_map_page(new_proc->pml4_phys, 0x800000, v2p((uint64_t)stack), PT_PRESENT | PT_RW | PT_USER); + // Map User stack to 0x800000 (starting from 0x600000 for 2MB) + for (uint64_t i = 0; i < 512; i++) { + paging_map_page(new_proc->pml4_phys, 0x800000 - 2097152 + (i * 4096), v2p((uint64_t)stack + (i * 4096)), PT_PRESENT | PT_RW | PT_USER); + } // Parse arguments and push them to the user stack // We'll place the strings at the very high end of the user stack int argc = 1; - char *args_buf = (char *)stack + 4096; - uint64_t user_args_buf = 0x800000 + 4096; + char *args_buf = (char *)stack + 2097152; + uint64_t user_args_buf = 0x800000; // Copy filepath as argv[0] int path_len = 0; @@ -194,7 +197,7 @@ void process_create_elf(const char* filepath, const char* args_str) { // Align stack to 8 bytes before pushing argv array uint64_t current_user_sp = user_args_buf; current_user_sp &= ~7ULL; - args_buf = (char *)((uint64_t)stack + (current_user_sp - 0x800000)); + args_buf = (char *)((uint64_t)stack + (current_user_sp - (0x800000 - 2097152))); // Push argv array int argv_size = (argc + 1) * sizeof(uint64_t); @@ -212,7 +215,7 @@ void process_create_elf(const char* filepath, const char* args_str) { current_user_sp &= ~15ULL; // 4. Build Stack Frame for context switch via IRETQ - uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 16384); + uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 126976); *(--stack_ptr) = 0x1B; // SS (User Mode Data) *(--stack_ptr) = current_user_sp; // RSP (Updated user stack pointer) *(--stack_ptr) = 0x202; // RFLAGS (Interrupts Enabled) @@ -253,6 +256,7 @@ void process_create_elf(const char* filepath, const char* args_str) { serial_write("[PROCESS] Spawned ELF Executable: "); serial_write(filepath); serial_write("\n"); + return new_proc; } process_t* process_get_current(void) { @@ -288,7 +292,7 @@ uint64_t process_terminate_current(void) { if (!current_process) return 0; // 1. Cleanup side effects - if (current_process->ui_window) { + if (current_process->ui_window && !current_process->is_terminal_proc) { extern void serial_write(const char *str); serial_write("PROC: Terminating proc with window\n"); wm_remove_window((Window *)current_process->ui_window); diff --git a/src/kernel/process.h b/src/kernel/process.h index 710e541..ee965f8 100644 --- a/src/kernel/process.h +++ b/src/kernel/process.h @@ -38,12 +38,14 @@ typedef struct process { void *kernel_stack_alloc; // Original pointer from kmalloc for freeing void *user_stack_alloc; // Original pointer from kmalloc for freeing + bool is_terminal_proc; // Was this process started from the shell? + struct process *next; } process_t; void process_init(void); void process_create(void* entry_point, bool is_user); -void process_create_elf(const char* filepath, const char* args_str); +process_t* process_create_elf(const char* filepath, const char* args_str); process_t* process_get_current(void); uint64_t process_schedule(uint64_t current_rsp); uint64_t process_terminate_current(void); diff --git a/src/kernel/ps2.c b/src/kernel/ps2.c index 409ec84..72524bb 100644 --- a/src/kernel/ps2.c +++ b/src/kernel/ps2.c @@ -22,6 +22,7 @@ uint64_t timer_handler(registers_t *regs) { // --- Keyboard --- static bool shift_pressed = false; +static bool ctrl_pressed = false; static bool extended_scancode = false; // Simple US QWERTY Scan Code Set 1 Map @@ -50,6 +51,27 @@ uint64_t keyboard_handler(registers_t *regs) { return (uint64_t)regs; } + if (scancode == 0x1D) { + ctrl_pressed = true; + extended_scancode = false; // Reset if Ctrl is pressed (prevents E0 1D bug) + } else if (scancode == 0x9D) { + ctrl_pressed = false; + extended_scancode = false; + } + + if (ctrl_pressed && scancode == 0x2E) { + extern process_t* process_get_current(void); + process_t* proc = process_get_current(); + if (proc && proc->is_user && proc->is_terminal_proc && proc->ui_window) { + // Only kill if the associated terminal window is focused + if (((Window*)proc->ui_window)->focused) { + extern uint64_t process_terminate_current(void); + outb(0x20, 0x20); // EOI before context switch + return process_terminate_current(); + } + } + } + if (scancode == 0x2A || scancode == 0x36) { // Shift Down shift_pressed = true; } else if (scancode == 0xAA || scancode == 0xB6) { // Shift Up diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 0da7767..b5ce626 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -7,6 +7,9 @@ #include "fat32.h" #include "paging.h" #include "platform.h" +#include "io.h" +#include "pci.h" +#include "kutils.h" // Read MSR static inline uint64_t rdmsr(uint32_t msr) { @@ -130,7 +133,6 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u if (syscall_num == 1) { // SYS_WRITE // arg2 is the buffer based on our user_test logic cmd_write((const char*)arg2); - serial_write((const char*)arg2); } else if (syscall_num == 0 || syscall_num == 60) { // SYS_EXIT serial_write("Kernel: SYS_EXIT called\n"); uint64_t next_rsp = process_terminate_current(); @@ -478,12 +480,28 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u const char *path = (const char *)arg2; if (!path) return 0; return fat32_exists(path) ? 1 : 0; + } else if (cmd == FS_CMD_GETCWD) { + char *buf = (char *)arg2; + int size = (int)arg3; + if (!buf) return -1; + fat32_get_current_dir(buf, size); + return 0; + } else if (cmd == FS_CMD_CHDIR) { + const char *path = (const char *)arg2; + if (!path) return -1; + return fat32_chdir(path) ? 0 : -1; } return 0; } else if (syscall_num == 8) { // DEBUG_SERIAL_WRITE extern void serial_write(const char *str); serial_write((const char *)arg2); return 0; + } else if (syscall_num == 10) { // SYS_KILL + // Simplified kill: just terminate current for now + uint64_t next_rsp = process_terminate_current(); + extern void context_switch_to(uint64_t rsp); + context_switch_to(next_rsp); + while(1); } else if (syscall_num == 9) { // SYS_SBRK int incr = (int)arg1; process_t *proc = process_get_current(); @@ -591,6 +609,68 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u if (!thumb) return -1; for (int i=0; i<100*60; i++) dest[i] = thumb[i]; return 0; + } else if (cmd == 10) { // SYSTEM_CMD_CLEAR_SCREEN + extern void cmd_screen_clear(void); + cmd_screen_clear(); + return 0; + } else if (cmd == 11) { // SYSTEM_CMD_RTC_GET + int *dt = (int *)arg2; + if (!dt) return -1; + extern void rtc_get_datetime(int *y, int *m, int *d, int *h, int *min, int *s); + rtc_get_datetime(&dt[0], &dt[1], &dt[2], &dt[3], &dt[4], &dt[5]); + return 0; + } else if (cmd == 12) { // SYSTEM_CMD_REBOOT + k_reboot(); + return 0; + } else if (cmd == 13) { // SYSTEM_CMD_SHUTDOWN + k_shutdown(); + return 0; + } else if (cmd == 14) { // SYSTEM_CMD_BEEP + int freq = (int)arg2; + int ms = (int)arg3; + if (freq > 0) { + int div = 1193180 / freq; + outb(0x43, 0xB6); + outb(0x42, div & 0xFF); + outb(0x42, (div >> 8) & 0xFF); + outb(0x61, inb(0x61) | 0x03); + } + // Sleep - kernel side + k_sleep(ms); + outb(0x61, inb(0x61) & 0xFC); + return 0; + } else if (cmd == 15) { // SYSTEM_CMD_MEMINFO + uint64_t *out = (uint64_t *)arg2; + if (!out) return -1; + MemStats stats = memory_get_stats(); + out[0] = stats.total_memory; + out[1] = stats.used_memory; + return 0; + } else if (cmd == 16) { // SYSTEM_CMD_UPTIME + return wm_get_ticks(); + } else if (cmd == 17) { // SYSTEM_CMD_PCI_LIST + typedef struct { + uint16_t vendor; + uint16_t device; + uint8_t class_code; + uint8_t subclass; + } pci_info_t; + pci_info_t *info = (pci_info_t *)arg2; + int idx = (int)arg3; + if (!info) { + pci_device_t pci_devs[128]; + return pci_enumerate_devices(pci_devs, 128); + } + pci_device_t pci_devs[128]; + int count = pci_enumerate_devices(pci_devs, 128); + if (idx >= 0 && idx < count) { + info->vendor = pci_devs[idx].vendor_id; + info->device = pci_devs[idx].device_id; + info->class_code = pci_devs[idx].class_code; + info->subclass = pci_devs[idx].subclass; + return 0; + } + return -1; } return -1; } diff --git a/src/kernel/syscall.h b/src/kernel/syscall.h index faa54bf..0a7d7c2 100644 --- a/src/kernel/syscall.h +++ b/src/kernel/syscall.h @@ -31,6 +31,8 @@ typedef struct Window Window; #define FS_CMD_SIZE 9 #define FS_CMD_MKDIR 10 #define FS_CMD_EXISTS 11 +#define FS_CMD_GETCWD 12 +#define FS_CMD_CHDIR 13 void syscall_init(void); uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5); diff --git a/src/kernel/syscalls.asm b/src/kernel/syscalls.asm index 7a7ab9a..62cd266 100644 --- a/src/kernel/syscalls.asm +++ b/src/kernel/syscalls.asm @@ -48,7 +48,9 @@ syscall_entry: mov rdi, rax ; syscall_num ; 5. Call C handler + sti call syscall_handler_c + cli ; 6. Restore RCX and R11 pop r11 diff --git a/src/kernel/userland/Makefile b/src/kernel/userland/Makefile index e13afcd..2fcef83 100644 --- a/src/kernel/userland/Makefile +++ b/src/kernel/userland/Makefile @@ -5,29 +5,36 @@ LD = x86_64-elf-ld CFLAGS = -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc LDFLAGS = -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start +BIN_DIR = bin + LIBC_SOURCES = $(wildcard libc/*.c) -LIBC_OBJS = $(LIBC_SOURCES:.c=.o) crt0.o +LIBC_OBJS = $(patsubst libc/%.c, $(BIN_DIR)/%.o, $(LIBC_SOURCES)) $(BIN_DIR)/crt0.o APP_SOURCES = $(filter-out nanojpeg.c, $(wildcard *.c)) -APP_OBJS = $(APP_SOURCES:.c=.o) -APP_ELFS = $(APP_SOURCES:.c=.elf) +APP_ELFS = $(patsubst %.c, $(BIN_DIR)/%.elf, $(APP_SOURCES)) -all: $(APP_ELFS) +all: $(BIN_DIR) $(APP_ELFS) -crt0.o: crt0.asm +$(BIN_DIR): + mkdir -p $(BIN_DIR) + +$(BIN_DIR)/crt0.o: crt0.asm $(AS) -f elf64 $< -o $@ -libc/%.o: libc/%.c +$(BIN_DIR)/%.o: libc/%.c $(CC) $(CFLAGS) -c $< -o $@ -%.o: %.c +$(BIN_DIR)/nanojpeg.o: nanojpeg.c $(CC) $(CFLAGS) -c $< -o $@ -viewer.elf: $(LIBC_OBJS) viewer.o nanojpeg.o +$(BIN_DIR)/%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(BIN_DIR)/viewer.elf: $(LIBC_OBJS) $(BIN_DIR)/viewer.o $(BIN_DIR)/nanojpeg.o $(LD) $(LDFLAGS) $^ -o $@ -%.elf: $(LIBC_OBJS) %.o +$(BIN_DIR)/%.elf: $(LIBC_OBJS) $(BIN_DIR)/%.o $(LD) $(LDFLAGS) $^ -o $@ clean: - rm -f *.o libc/*.o *.elf + rm -rf $(BIN_DIR) diff --git a/src/kernel/userland/beep.c b/src/kernel/userland/beep.c new file mode 100644 index 0000000..97df1c7 --- /dev/null +++ b/src/kernel/userland/beep.c @@ -0,0 +1,9 @@ +#include +#include + +int main(int argc, char **argv) { + (void)argc; (void)argv; + printf("BEEP!\n"); + sys_system(14, 1000, 100, 0, 0); // SYSTEM_CMD_BEEP (freq, ms) + return 0; +} diff --git a/src/kernel/userland/boredver.c b/src/kernel/userland/boredver.c new file mode 100644 index 0000000..34ac26d --- /dev/null +++ b/src/kernel/userland/boredver.c @@ -0,0 +1,9 @@ +#include +#include + +int main(int argc, char **argv) { + (void)argc; (void)argv; + printf("BoredOS v1.64\n"); + printf("BoredOS Kernel V3.0.0\n"); + return 0; +} diff --git a/src/kernel/userland/calculator.elf b/src/kernel/userland/calculator.elf deleted file mode 100755 index 69b143c..0000000 Binary files a/src/kernel/userland/calculator.elf and /dev/null differ diff --git a/src/kernel/userland/cat.c b/src/kernel/userland/cat.c new file mode 100644 index 0000000..f6169dc --- /dev/null +++ b/src/kernel/userland/cat.c @@ -0,0 +1,24 @@ +#include +#include + +int main(int argc, char **argv) { + if (argc < 2) { + printf("Usage: cat \n"); + return 1; + } + + int fd = sys_open(argv[1], "r"); + if (fd < 0) { + printf("Error: Cannot open %s\n", argv[1]); + return 1; + } + + char buffer[4096]; + int bytes; + while ((bytes = sys_read(fd, buffer, sizeof(buffer))) > 0) { + sys_write(1, buffer, bytes); + } + + sys_close(fd); + return 0; +} diff --git a/src/kernel/userland/cc.c b/src/kernel/userland/cc.c new file mode 100644 index 0000000..9b093b8 --- /dev/null +++ b/src/kernel/userland/cc.c @@ -0,0 +1,519 @@ +#include +#include +#include "../vm.h" + +// --- Compiler Limits --- +#define MAX_SOURCE 65536 +#define MAX_TOKENS 16384 +#define MAX_VARS 512 +#define CODE_SIZE 32768 +#define STR_POOL_SIZE 16384 + +static int compile_error = 0; + +// --- Lexer --- +typedef enum { + TOK_EOF, + TOK_INT, // 123, 0xFF + TOK_STRING, // "hello" + TOK_ID, // abc + TOK_PLUS, // + + TOK_MINUS, // - + TOK_MUL, // * + TOK_DIV, // / + TOK_ASSIGN, // = + TOK_LPAREN, // ( + TOK_RPAREN, // ) + TOK_LBRACKET, // [ + TOK_RBRACKET, // ] + TOK_LBRACE, // { + TOK_RBRACE, // } + TOK_SEMI, // ; + TOK_COMMA, // , + TOK_EQ, // == + TOK_NEQ, // != + TOK_LT, // < + TOK_GT, // > + TOK_LE, // <= + TOK_GE, // >= + TOK_IF, // if + TOK_ELSE, // else + TOK_WHILE, // while + TOK_INT_TYPE, // int + TOK_CHAR_TYPE,// char + TOK_VOID_TYPE,// void + TOK_MAIN // main +} TokenType; + +typedef struct { + TokenType type; + int int_val; + char str_val[64]; // Identifier or String Content +} Token; + +static char *source_ptr; +static Token tokens[MAX_TOKENS]; +static int token_count = 0; + +static void lex_error(const char *msg) { + printf("Compiler Error: %s\n", msg); + compile_error = 1; +} + +static void lexer(const char *source) { + source_ptr = (char*)source; + token_count = 0; + compile_error = 0; + + while (*source_ptr) { + while (*source_ptr == ' ' || *source_ptr == '\n' || *source_ptr == '\t' || *source_ptr == '\r') source_ptr++; + if (!*source_ptr) break; + + if (*source_ptr == '/' && *(source_ptr+1) == '/') { + while (*source_ptr && *source_ptr != '\n') source_ptr++; + continue; + } + + Token *t = &tokens[token_count++]; + + if (*source_ptr == '0' && (*(source_ptr+1) == 'x' || *(source_ptr+1) == 'X')) { + source_ptr += 2; + t->type = TOK_INT; + t->int_val = 0; + int has_digits = 0; + while ((*source_ptr >= '0' && *source_ptr <= '9') || + (*source_ptr >= 'a' && *source_ptr <= 'f') || + (*source_ptr >= 'A' && *source_ptr <= 'F')) { + int digit = 0; + if (*source_ptr >= '0' && *source_ptr <= '9') digit = *source_ptr - '0'; + else if (*source_ptr >= 'a' && *source_ptr <= 'f') digit = *source_ptr - 'a' + 10; + else if (*source_ptr >= 'A' && *source_ptr <= 'F') digit = *source_ptr - 'A' + 10; + t->int_val = (t->int_val << 4) | digit; + source_ptr++; + has_digits = 1; + } + if (!has_digits) { lex_error("Invalid hex literal"); return; } + } else if (*source_ptr >= '0' && *source_ptr <= '9') { + t->type = TOK_INT; + t->int_val = 0; + while (*source_ptr >= '0' && *source_ptr <= '9') { + t->int_val = t->int_val * 10 + (*source_ptr - '0'); + source_ptr++; + } + } else if (*source_ptr == '"') { + t->type = TOK_STRING; + source_ptr++; + int len = 0; + while (*source_ptr && *source_ptr != '"') { + if (*source_ptr == '\\' && *(source_ptr+1) == 'n') { + if (len < 63) t->str_val[len++] = '\n'; + source_ptr += 2; + } else { + if (len < 63) t->str_val[len++] = *source_ptr; + source_ptr++; + } + } + t->str_val[len] = 0; + if (*source_ptr == '"') source_ptr++; + } else if (*source_ptr == '\'') { + t->type = TOK_INT; + source_ptr++; + char c = 0; + if (*source_ptr == '\\') { + source_ptr++; + if (*source_ptr == 'n') c = '\n'; + else if (*source_ptr == 't') c = '\t'; + else if (*source_ptr == '0') c = '\0'; + else if (*source_ptr == '\\') c = '\\'; + else if (*source_ptr == '\'') c = '\''; + else c = *source_ptr; + source_ptr++; + } else { + c = *source_ptr; + source_ptr++; + } + if (*source_ptr == '\'') source_ptr++; + else { lex_error("Expected closing '"); return; } + t->int_val = (int)c; + } else if ((*source_ptr >= 'a' && *source_ptr <= 'z') || (*source_ptr >= 'A' && *source_ptr <= 'Z') || *source_ptr == '_') { + int len = 0; + while ((*source_ptr >= 'a' && *source_ptr <= 'z') || (*source_ptr >= 'A' && *source_ptr <= 'Z') || (*source_ptr >= '0' && *source_ptr <= '9') || *source_ptr == '_') { + if (len < 63) t->str_val[len++] = *source_ptr; + source_ptr++; + } + t->str_val[len] = 0; + if (strcmp(t->str_val, "if") == 0) t->type = TOK_IF; + else if (strcmp(t->str_val, "else") == 0) t->type = TOK_ELSE; + else if (strcmp(t->str_val, "while") == 0) t->type = TOK_WHILE; + else if (strcmp(t->str_val, "int") == 0) t->type = TOK_INT_TYPE; + else if (strcmp(t->str_val, "char") == 0) t->type = TOK_CHAR_TYPE; + else if (strcmp(t->str_val, "void") == 0) t->type = TOK_VOID_TYPE; + else if (strcmp(t->str_val, "main") == 0) t->type = TOK_MAIN; + else t->type = TOK_ID; + } else { + switch (*source_ptr) { + case '+': t->type = TOK_PLUS; break; + case '-': t->type = TOK_MINUS; break; + case '*': t->type = TOK_MUL; break; + case '/': t->type = TOK_DIV; break; + case '(': t->type = TOK_LPAREN; break; + case ')': t->type = TOK_RPAREN; break; + case '[': t->type = TOK_LBRACKET; break; + case ']': t->type = TOK_RBRACKET; break; + case '{': t->type = TOK_LBRACE; break; + case '}': t->type = TOK_RBRACE; break; + case ';': t->type = TOK_SEMI; break; + case ',': t->type = TOK_COMMA; break; + case '=': + if (*(source_ptr+1) == '=') { t->type = TOK_EQ; source_ptr++; } + else t->type = TOK_ASSIGN; + break; + case '!': + if (*(source_ptr+1) == '=') { t->type = TOK_NEQ; source_ptr++; } + else { lex_error("Unexpected !"); return; } + break; + case '<': + if (*(source_ptr+1) == '=') { t->type = TOK_LE; source_ptr++; } + else t->type = TOK_LT; + break; + case '>': + if (*(source_ptr+1) == '=') { t->type = TOK_GE; source_ptr++; } + else t->type = TOK_GT; + break; + default: lex_error("Unknown char"); return; + } + source_ptr++; + } + } + tokens[token_count].type = TOK_EOF; +} + +typedef struct { + const char *name; + int syscall_id; +} Builtin; + +static const Builtin builtins[] = { + {"exit", VM_SYS_EXIT}, + {"print_int", VM_SYS_PRINT_INT}, + {"print_char", VM_SYS_PRINT_CHAR}, + {"print_str", VM_SYS_PRINT_STR}, + {"print", VM_SYS_PRINT_INT}, + {"pritc", VM_SYS_PRINT_CHAR}, + {"puts", VM_SYS_PRINT_STR}, + {"nl", VM_SYS_NL}, + {"cls", VM_SYS_CLS}, + {"getchar", VM_SYS_GETCHAR}, + {"strlen", VM_SYS_STRLEN}, + {"strcmp", VM_SYS_STRCMP}, + {"strcpy", VM_SYS_STRCPY}, + {"strcat", VM_SYS_STRCAT}, + {"memset", VM_SYS_MEMSET}, + {"memcpy", VM_SYS_MEMCPY}, + {"malloc", VM_SYS_MALLOC}, + {"free", VM_SYS_FREE}, + {"rand", VM_SYS_RAND}, + {"srand", VM_SYS_SRAND}, + {"abs", VM_SYS_ABS}, + {"min", VM_SYS_MIN}, + {"max", VM_SYS_MAX}, + {"pow", VM_SYS_POW}, + {"sqrt", VM_SYS_SQRT}, + {"sleep", VM_SYS_SLEEP}, + {"fopen", VM_SYS_FOPEN}, + {"fclose", VM_SYS_FCLOSE}, + {"fread", VM_SYS_FREAD}, + {"fwrite", VM_SYS_FWRITE}, + {"fseek", VM_SYS_FSEEK}, + {"remove", VM_SYS_REMOVE}, + {"draw_pixel", VM_SYS_DRAW_PIXEL}, + {"draw_rect", VM_SYS_DRAW_RECT}, + {"draw_line", VM_SYS_DRAW_LINE}, + {"draw_text", VM_SYS_DRAW_TEXT}, + {"get_width", VM_SYS_GET_WIDTH}, + {"get_height", VM_SYS_GET_HEIGHT}, + {"get_time", VM_SYS_GET_TIME}, + {"kb_hit", VM_SYS_KB_HIT}, + {"mouse_x", VM_SYS_MOUSE_X}, + {"mouse_y", VM_SYS_MOUSE_Y}, + {"mouse_state", VM_SYS_MOUSE_STATE}, + {"play_sound", VM_SYS_PLAY_SOUND}, + {"atoi", VM_SYS_ATOI}, + {"itoa", VM_SYS_ITOA}, + {"peek", VM_SYS_PEEK}, + {"poke", VM_SYS_POKE}, + {"exec", VM_SYS_EXEC}, + {"system", VM_SYS_SYSTEM}, + {"strchr", VM_SYS_STRCHR}, + {"memcmp", VM_SYS_MEMCMP}, + {"isalnum", VM_SYS_ISALNUM}, + {"isalpha", VM_SYS_ISALPHA}, + {"isdigit", VM_SYS_ISDIGIT}, + {"tolower", VM_SYS_TOLOWER}, + {"toupper", VM_SYS_TOUPPER}, + {"strncpy", VM_SYS_STRNCPY}, + {"strncat", VM_SYS_STRNCAT}, + {"strncmp", VM_SYS_STRNCMP}, + {"strstr", VM_SYS_STRSTR}, + {"strrchr", VM_SYS_STRRCHR}, + {"memmove", VM_SYS_MEMMOVE}, + {NULL, 0} +}; + +static int find_builtin(const char *name) { + for (int i = 0; builtins[i].name != NULL; i++) { + if (strcmp(builtins[i].name, name) == 0) return builtins[i].syscall_id; + } + return -1; +} + +static uint8_t code[CODE_SIZE]; +static int code_pos = 0; +static int cur_token = 0; +static uint8_t str_pool[STR_POOL_SIZE]; +static int str_pool_pos = 0; + +typedef struct { + char name[32]; + int addr; +} Symbol; + +static Symbol symbols[MAX_VARS]; +static int symbol_count = 0; +static int next_var_addr = 32768; + +static int find_symbol(const char *name) { + for (int i = 0; i < symbol_count; i++) { + if (strcmp(symbols[i].name, name) == 0) return symbols[i].addr; + } + return -1; +} + +static int add_symbol(const char *name) { + int existing = find_symbol(name); + if (existing != -1) return existing; + if (symbol_count >= MAX_VARS) return -1; + strcpy(symbols[symbol_count].name, name); + symbols[symbol_count].addr = next_var_addr; + next_var_addr += 4; + return symbol_count++; +} + +static void emit(uint8_t b) { + if (code_pos < CODE_SIZE) code[code_pos++] = b; + else { printf("Error: Code buffer overflow\n"); compile_error = 1; } +} + +static void emit32(int v) { + emit(v & 0xFF); emit((v >> 8) & 0xFF); emit((v >> 16) & 0xFF); emit((v >> 24) & 0xFF); +} + +static int add_string(const char *str) { + int start = str_pool_pos; + int len = strlen(str); + if (str_pool_pos + len + 1 >= STR_POOL_SIZE) { printf("Error: String pool overflow\n"); compile_error = 1; return 0; } + for(int i=0; i= TOK_EQ && tokens[cur_token].type <= TOK_GE) { + TokenType op = tokens[cur_token].type; cur_token++; additive(); + switch (op) { + case TOK_EQ: emit(OP_EQ); break; + case TOK_NEQ: emit(OP_NEQ); break; + case TOK_LT: emit(OP_LT); break; + case TOK_GT: emit(OP_GT); break; + case TOK_LE: emit(OP_LE); break; + case TOK_GE: emit(OP_GE); break; + default: break; + } + } +} + +static void expression() { if (compile_error) return; relation(); } + +static void statement() { + if (compile_error) return; + if (tokens[cur_token].type == TOK_INT_TYPE || tokens[cur_token].type == TOK_CHAR_TYPE) { + cur_token++; + while (tokens[cur_token].type == TOK_MUL) cur_token++; + if (tokens[cur_token].type == TOK_ID) { + add_symbol(tokens[cur_token].str_val); + cur_token++; + if (tokens[cur_token].type == TOK_LBRACKET) { + cur_token++; if (tokens[cur_token].type == TOK_INT) cur_token++; + if (tokens[cur_token].type == TOK_RBRACKET) cur_token++; + else printf("Error: Expected ]\n"); + } + if (tokens[cur_token].type == TOK_ASSIGN) { + int addr = find_symbol(tokens[cur_token-1].str_val); + cur_token++; expression(); emit(OP_STORE); emit32(addr); + } + match(TOK_SEMI); + } else { printf("Syntax Error: Expected identifier\n"); compile_error = 1; } + } else if (tokens[cur_token].type == TOK_ID) { + int syscall = find_builtin(tokens[cur_token].str_val); + if (syscall != -1 && tokens[cur_token+1].type == TOK_LPAREN) { + function_call(syscall); match(TOK_SEMI); emit(OP_POP); + } else { + int addr = find_symbol(tokens[cur_token].str_val); + if (addr == -1) { printf("Error: Undefined variable assignment: %s\n", tokens[cur_token].str_val); compile_error = 1; return; } + cur_token++; match(TOK_ASSIGN); expression(); match(TOK_SEMI); emit(OP_STORE); emit32(addr); + } + } else if (tokens[cur_token].type == TOK_IF) { + cur_token++; match(TOK_LPAREN); expression(); match(TOK_RPAREN); + emit(OP_JZ); int jz_addr_pos = code_pos; emit32(0); block(); + if (tokens[cur_token].type == TOK_ELSE) { + emit(OP_JMP); int jmp_addr_pos = code_pos; emit32(0); + int else_start = code_pos; + code[jz_addr_pos] = else_start & 0xFF; code[jz_addr_pos+1] = (else_start >> 8) & 0xFF; code[jz_addr_pos+2] = (else_start >> 16) & 0xFF; code[jz_addr_pos+3] = (else_start >> 24) & 0xFF; + cur_token++; block(); + int end_addr = code_pos; + code[jmp_addr_pos] = end_addr & 0xFF; code[jmp_addr_pos+1] = (end_addr >> 8) & 0xFF; code[jmp_addr_pos+2] = (end_addr >> 16) & 0xFF; code[jmp_addr_pos+3] = (end_addr >> 24) & 0xFF; + } else { + int end_addr = code_pos; + code[jz_addr_pos] = end_addr & 0xFF; code[jz_addr_pos+1] = (end_addr >> 8) & 0xFF; code[jz_addr_pos+2] = (end_addr >> 16) & 0xFF; code[jz_addr_pos+3] = (end_addr >> 24) & 0xFF; + } + } else if (tokens[cur_token].type == TOK_WHILE) { + int start_addr = code_pos; cur_token++; match(TOK_LPAREN); expression(); match(TOK_RPAREN); + emit(OP_JZ); int jz_addr_pos = code_pos; emit32(0); block(); + emit(OP_JMP); emit32(start_addr); + int end_addr = code_pos; + code[jz_addr_pos] = end_addr & 0xFF; code[jz_addr_pos+1] = (end_addr >> 8) & 0xFF; code[jz_addr_pos+2] = (end_addr >> 16) & 0xFF; code[jz_addr_pos+3] = (end_addr >> 24) & 0xFF; + } else cur_token++; +} + +static void block() { + if (compile_error) return; + match(TOK_LBRACE); + while (tokens[cur_token].type != TOK_RBRACE && tokens[cur_token].type != TOK_EOF && !compile_error) statement(); + match(TOK_RBRACE); +} + +static void program() { + if (tokens[cur_token].type == TOK_INT_TYPE || tokens[cur_token].type == TOK_VOID_TYPE) cur_token++; + if (tokens[cur_token].type == TOK_MAIN) cur_token++; + match(TOK_LPAREN); match(TOK_RPAREN); block(); emit(OP_HALT); +} + +int main(int argc, char **argv) { + if (argc < 2) { printf("Usage: cc \n"); return 1; } + + int fh = sys_open(argv[1], "r"); + if (fh < 0) { printf("Error: Cannot open source file.\n"); return 1; } + + char *source = (char*)malloc(MAX_SOURCE); + if (!source) { printf("Error: Out of memory for source buffer.\n"); sys_close(fh); return 1; } + + int len = sys_read(fh, source, MAX_SOURCE - 1); + source[len] = 0; + sys_close(fh); + + lexer(source); + free(source); + + if (compile_error) return 1; + + code_pos = 0; symbol_count = 0; cur_token = 0; str_pool_pos = 0; next_var_addr = 32768; + + const char* magic = VM_MAGIC; + for(int i=0; i<7; i++) emit(magic[i]); + emit(1); + program(); + + if (compile_error) { printf("Compilation Failed.\n"); return 1; } + + int pool_start_addr = code_pos; + for(int i=0; i> 8) & 0xFF; code[pc+2] = (abs_addr >> 16) & 0xFF; code[pc+3] = (abs_addr >> 24) & 0xFF; + pc += 4; code[pc-5] = OP_IMM; break; + } + default: break; + } + } + + char out_name[64]; int i = 0; + while(argv[1][i] && argv[1][i] != '.') { out_name[i] = argv[1][i]; i++; } + out_name[i] = 0; + + int out_fh = sys_open(out_name, "w"); + if (out_fh >= 0) { + sys_write_fs(out_fh, code, code_pos); + sys_close(out_fh); + printf("Compilation successful. Output: %s\n", out_name); + } else { printf("Error: Cannot write output file.\n"); } + + return 0; +} diff --git a/src/kernel/userland/clear.c b/src/kernel/userland/clear.c new file mode 100644 index 0000000..3219fee --- /dev/null +++ b/src/kernel/userland/clear.c @@ -0,0 +1,8 @@ +#include +#include + +int main(int argc, char **argv) { + (void)argc; (void)argv; + sys_system(10, 0, 0, 0, 0); // SYSTEM_CMD_CLEAR_SCREEN + return 0; +} diff --git a/src/kernel/userland/cowsay.c b/src/kernel/userland/cowsay.c new file mode 100644 index 0000000..9cffca3 --- /dev/null +++ b/src/kernel/userland/cowsay.c @@ -0,0 +1,26 @@ +#include +#include + +int main(int argc, char **argv) { + char *msg = (char*)"Bored!"; + if (argc > 1) { + // Simple concatenation of args for now + // For simplicity in this demo, just use the first arg + msg = argv[1]; + } + + size_t len = strlen(msg); + + printf(" "); + for(size_t i=0; i\n ", msg); + for(size_t i=0; i +#include + +int main(int argc, char **argv) { + if (argc < 3) { + printf("Usage: cp \n"); + return 1; + } + + int fd_in = sys_open(argv[1], "r"); + if (fd_in < 0) { + printf("Error: Cannot open source %s\n", argv[1]); + return 1; + } + + int fd_out = sys_open(argv[2], "w"); + if (fd_out < 0) { + printf("Error: Cannot create destination %s\n", argv[2]); + sys_close(fd_in); + return 1; + } + + char buffer[4096]; + int bytes; + while ((bytes = sys_read(fd_in, buffer, sizeof(buffer))) > 0) { + sys_write_fs(fd_out, buffer, bytes); + } + + sys_close(fd_in); + sys_close(fd_out); + + return 0; +} diff --git a/src/kernel/userland/crash.elf b/src/kernel/userland/crash.elf deleted file mode 100755 index b4c2d1c..0000000 Binary files a/src/kernel/userland/crash.elf and /dev/null differ diff --git a/src/kernel/userland/crt0.o b/src/kernel/userland/crt0.o deleted file mode 100644 index 3f46cdb..0000000 Binary files a/src/kernel/userland/crt0.o and /dev/null differ diff --git a/src/kernel/userland/date.c b/src/kernel/userland/date.c new file mode 100644 index 0000000..39eea87 --- /dev/null +++ b/src/kernel/userland/date.c @@ -0,0 +1,13 @@ +#include +#include + +int main(int argc, char **argv) { + (void)argc; (void)argv; + int dt[6]; + if (sys_system(11, (uint64_t)dt, 0, 0, 0) == 0) { + printf("Current Date: %d-%d-%d %d:%d:%d\n", dt[0], dt[1], dt[2], dt[3], dt[4], dt[5]); + } else { + printf("Error: Could not retrieve date.\n"); + } + return 0; +} diff --git a/src/kernel/userland/echo.c b/src/kernel/userland/echo.c new file mode 100644 index 0000000..0b4f26f --- /dev/null +++ b/src/kernel/userland/echo.c @@ -0,0 +1,10 @@ +#include +#include + +int main(int argc, char **argv) { + for (int i = 1; i < argc; i++) { + printf("%s%s", argv[i], (i == argc - 1) ? "" : " "); + } + printf("\n"); + return 0; +} diff --git a/src/kernel/userland/hello.c b/src/kernel/userland/hello.c index fa8e8b5..0f89df8 100644 --- a/src/kernel/userland/hello.c +++ b/src/kernel/userland/hello.c @@ -1,41 +1,13 @@ -#include "syscall.h" - -int strlen(const char* str) { - int len = 0; - while(str[len]) len++; - return len; -} - -void print_int(int n) { - char buf[16]; - if (n == 0) { - sys_write(1, "0", 1); - return; - } - int i = 0; - while(n > 0) { - buf[i++] = (n % 10) + '0'; - n /= 10; - } - for(int j = i - 1; j >= 0; j--) { - sys_write(1, &buf[j], 1); - } -} +#include +#include int main(int argc, char** argv) { - const char* msg = "Hello from Userland ELF!\n"; - sys_write(1, msg, 25); + printf("Hello from Userland ELF!\n"); - sys_write(1, "argc: ", 6); - print_int(argc); - sys_write(1, "\n", 1); + printf("argc: %d\n", argc); for (int i = 0; i < argc; i++) { - sys_write(1, "argv[", 5); - print_int(i); - sys_write(1, "]: ", 3); - sys_write(1, argv[i], strlen(argv[i])); - sys_write(1, "\n", 1); + printf("argv[%d]: %s\n", i, argv[i]); } return 0; diff --git a/src/kernel/userland/hello.elf b/src/kernel/userland/hello.elf deleted file mode 100755 index 3a28dda..0000000 Binary files a/src/kernel/userland/hello.elf and /dev/null differ diff --git a/src/kernel/userland/hello.o b/src/kernel/userland/hello.o deleted file mode 100644 index 7ff9077..0000000 Binary files a/src/kernel/userland/hello.o and /dev/null differ diff --git a/src/kernel/userland/help.c b/src/kernel/userland/help.c new file mode 100644 index 0000000..3d19068 --- /dev/null +++ b/src/kernel/userland/help.c @@ -0,0 +1,32 @@ +#include +#include + +int main(int argc, char **argv) { + (void)argc; (void)argv; + printf("BoredOS CLI Help (Userspace)\n"); + printf("---------------------------\n"); + printf("ls [path] - List directory contents\n"); + printf("cd - Change current directory (built-in)\n"); + printf("pwd - Print current directory\n"); + printf("mkdir - Create directory\n"); + printf("rm - Remove file or directory\n"); + printf("cat - Print file contents\n"); + printf("echo [text] - Print text\n"); + printf("touch - Create empty file\n"); + printf("cp - Copy file\n"); + printf("mv - Move file\n"); + printf("date - Print current date and time\n"); + printf("uptime - Print system uptime\n"); + printf("meminfo - Print memory information\n"); + printf("cowsay [msg] - Fun cow says something\n"); + printf("beep - Make a beep sound\n"); + printf("reboot - Reboot the system\n"); + printf("shutdown - Shutdown the system\n"); + printf("boredver - Show BoredOS version\n"); + printf("cc - C Compiler\n"); + printf("man - Show manual page\n"); + printf("clear - Clear the screen\n"); + printf("exit - Exit the terminal\n"); + printf("\nHint: Use Ctrl+C to force quit any running .elf app.\n"); + return 0; +} diff --git a/src/kernel/userland/libc/libui.o b/src/kernel/userland/libc/libui.o deleted file mode 100644 index 22ab036..0000000 Binary files a/src/kernel/userland/libc/libui.o and /dev/null differ diff --git a/src/kernel/userland/libc/stdlib.c b/src/kernel/userland/libc/stdlib.c index 82c381a..c47098a 100644 --- a/src/kernel/userland/libc/stdlib.c +++ b/src/kernel/userland/libc/stdlib.c @@ -123,14 +123,142 @@ void *realloc(void *ptr, size_t size) { } void *memset(void *s, int c, size_t n) { - unsigned char *p = s; + unsigned char *p = (unsigned char *)s; while (n--) *p++ = (unsigned char)c; return s; } void *memcpy(void *dest, const void *src, size_t n) { - unsigned char *d = dest; - const unsigned char *s = src; + unsigned char *d = (unsigned char *)dest; + const unsigned char *s = (const unsigned char *)src; while (n--) *d++ = *s++; return dest; } + +// String functions +size_t strlen(const char *s) { + size_t len = 0; + while (s[len]) len++; + return len; +} + +int strcmp(const char *s1, const char *s2) { + while (*s1 && (*s1 == *s2)) { + s1++; + s2++; + } + return *(const unsigned char*)s1 - *(const unsigned char*)s2; +} + +char* strcpy(char *dest, const char *src) { + char *ret = dest; + while (*src) *dest++ = *src++; + *dest = 0; + return ret; +} + +char* strcat(char *dest, const char *src) { + char *ret = dest; + while (*dest) dest++; + while (*src) *dest++ = *src++; + *dest = 0; + return ret; +} + +int atoi(const char *nptr) { + int res = 0; + int sign = 1; + if (*nptr == '-') { + sign = -1; + nptr++; + } + while (*nptr >= '0' && *nptr <= '9') { + res = res * 10 + (*nptr - '0'); + nptr++; + } + return sign * res; +} + +void itoa(int n, char *buf) { + if (n == 0) { + buf[0] = '0'; buf[1] = 0; return; + } + int i = 0; + int sign = n < 0; + if (sign) n = -n; + while (n > 0) { + buf[i++] = (n % 10) + '0'; + n /= 10; + } + if (sign) buf[i++] = '-'; + buf[i] = 0; + // Reverse + for (int j = 0; j < i / 2; j++) { + char t = buf[j]; + buf[j] = buf[i - 1 - j]; + buf[i - 1 - j] = t; + } +} + +// IO functions +void puts(const char *s) { + sys_write(1, s, strlen(s)); + sys_write(1, "\n", 1); +} + +void printf(const char *fmt, ...) { + // Simple printf implementation + __builtin_va_list args; + __builtin_va_start(args, fmt); + char buf[1024]; + int buf_idx = 0; + + while (*fmt) { + if (*fmt == '%') { + fmt++; + if (*fmt == 's') { + char *s = __builtin_va_arg(args, char *); + while (*s) buf[buf_idx++] = *s++; + } else if (*fmt == 'd') { + int d = __builtin_va_arg(args, int); + char ibuf[32]; + itoa(d, ibuf); + char *s = ibuf; + while (*s) buf[buf_idx++] = *s++; + } else if (*fmt == 'c') { + char c = (char)__builtin_va_arg(args, int); + buf[buf_idx++] = c; + } else if (*fmt == '%') { + buf[buf_idx++] = '%'; + } + } else { + buf[buf_idx++] = *fmt; + } + fmt++; + if (buf_idx >= 1022) break; // Simple overflow protection + } + buf[buf_idx] = 0; + sys_write(1, buf, buf_idx); + __builtin_va_end(args); +} + +// System/Process functions +int chdir(const char *path) { + return sys_chdir(path); +} + +char* getcwd(char *buf, int size) { + if (sys_getcwd(buf, size) == 0) return buf; + return NULL; +} + +void sleep(int ms) { + // We don't have a sleep syscall yet, so we'll just busy wait for now or skip + // Actually, BoredOS doesn't seem to have a sleep syscall. + // I'll add one if needed, but for now I'll just skip. + (void)ms; +} + +void exit(int status) { + sys_exit(status); +} diff --git a/src/kernel/userland/libc/stdlib.h b/src/kernel/userland/libc/stdlib.h index ef71f64..af64385 100644 --- a/src/kernel/userland/libc/stdlib.h +++ b/src/kernel/userland/libc/stdlib.h @@ -11,4 +11,22 @@ void* realloc(void* ptr, size_t size); void *memset(void *s, int c, size_t n); void *memcpy(void *dest, const void *src, size_t n); +// String functions +size_t strlen(const char *s); +int strcmp(const char *s1, const char *s2); +char* strcpy(char *dest, const char *src); +char* strcat(char *dest, const char *src); +int atoi(const char *nptr); +void itoa(int n, char *buf); + +// IO functions +void puts(const char *s); +void printf(const char *fmt, ...); + +// System/Process functions +int chdir(const char *path); +char* getcwd(char *buf, int size); +void sleep(int ms); +void exit(int status); + #endif diff --git a/src/kernel/userland/libc/stdlib.o b/src/kernel/userland/libc/stdlib.o deleted file mode 100644 index 22e6ecd..0000000 Binary files a/src/kernel/userland/libc/stdlib.o and /dev/null differ diff --git a/src/kernel/userland/libc/syscall.c b/src/kernel/userland/libc/syscall.c index 236e4f5..abba093 100644 --- a/src/kernel/userland/libc/syscall.c +++ b/src/kernel/userland/libc/syscall.c @@ -121,3 +121,15 @@ int sys_exists(const char *path) { return (int)syscall2(SYS_FS, FS_CMD_EXISTS, (uint64_t)path); } +int sys_getcwd(char *buf, int size) { + return (int)syscall3(SYS_FS, FS_CMD_GETCWD, (uint64_t)buf, (uint64_t)size); +} + +int sys_chdir(const char *path) { + return (int)syscall2(SYS_FS, FS_CMD_CHDIR, (uint64_t)path); +} + +void sys_kill(int pid) { + syscall1(SYS_KILL, (uint64_t)pid); +} + diff --git a/src/kernel/userland/libc/syscall.h b/src/kernel/userland/libc/syscall.h index 478122b..dd9fc06 100644 --- a/src/kernel/userland/libc/syscall.h +++ b/src/kernel/userland/libc/syscall.h @@ -9,6 +9,7 @@ #define SYS_GUI 3 #define SYS_FS 4 #define SYS_SYSTEM 5 +#define SYS_KILL 10 #define SYS_SBRK 9 // FS Commands @@ -23,6 +24,8 @@ #define FS_CMD_SIZE 9 #define FS_CMD_MKDIR 10 #define FS_CMD_EXISTS 11 +#define FS_CMD_GETCWD 12 +#define FS_CMD_CHDIR 13 // Internal assembly entry into Ring 0 extern uint64_t syscall0(uint64_t sys_num); @@ -36,6 +39,7 @@ extern uint64_t syscall5(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_ void sys_exit(int status); int sys_write(int fd, const char *buf, int len); void *sys_sbrk(int incr); +void sys_kill(int pid); int sys_system(int cmd, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4); // FS API @@ -49,8 +53,18 @@ uint32_t sys_size(int fd); int sys_delete(const char *path); int sys_mkdir(const char *path); int sys_exists(const char *path); +int sys_getcwd(char *buf, int size); +int sys_chdir(const char *path); -struct FAT32_FileInfo; -int sys_list(const char *path, struct FAT32_FileInfo *entries, int max_entries); +typedef struct { + char name[256]; + uint32_t size; + uint8_t is_directory; + uint32_t start_cluster; + uint16_t write_date; + uint16_t write_time; +} FAT32_FileInfo; + +int sys_list(const char *path, FAT32_FileInfo *entries, int max_entries); #endif diff --git a/src/kernel/userland/libc/syscall.o b/src/kernel/userland/libc/syscall.o deleted file mode 100644 index 141329b..0000000 Binary files a/src/kernel/userland/libc/syscall.o and /dev/null differ diff --git a/src/kernel/userland/ls.c b/src/kernel/userland/ls.c new file mode 100644 index 0000000..9cf0729 --- /dev/null +++ b/src/kernel/userland/ls.c @@ -0,0 +1,32 @@ +#include +#include + +int main(int argc, char **argv) { + char path[256]; + if (argc > 1) { + strcpy(path, argv[1]); + } else { + if (!getcwd(path, sizeof(path))) { + strcpy(path, "."); + } + } + + FAT32_FileInfo entries[128]; + int count = sys_list(path, entries, 128); + + if (count < 0) { + printf("Error: Cannot list directory %s\n", path); + return 1; + } + + for (int i = 0; i < count; i++) { + if (entries[i].is_directory) { + printf("[DIR] %s\n", entries[i].name); + } else { + printf("[FILE] %s (%d bytes)\n", entries[i].name, entries[i].size); + } + } + + printf("\nTotal: %d items\n", count); + return 0; +} diff --git a/src/kernel/userland/man.c b/src/kernel/userland/man.c new file mode 100644 index 0000000..cae6db0 --- /dev/null +++ b/src/kernel/userland/man.c @@ -0,0 +1,33 @@ +#include +#include + +int main(int argc, char **argv) { + if (argc < 2) { + printf("What manual page do you want?\nExample: man ls\n"); + return 0; + } + + char path[128]; + printf("Manual for: %s\n", argv[1]); + printf("---------------------------\n"); + + strcpy(path, "A:/Library/man/"); + strcat(path, argv[1]); + strcat(path, ".txt"); + + int fd = sys_open(path, "r"); + if (fd < 0) { + printf("No manual entry for %s\n", argv[1]); + return 1; + } + + char buffer[4096]; + int bytes; + while ((bytes = sys_read(fd, buffer, sizeof(buffer))) > 0) { + sys_write(1, buffer, bytes); + } + + sys_close(fd); + printf("\n"); + return 0; +} diff --git a/src/kernel/userland/markdown.elf b/src/kernel/userland/markdown.elf deleted file mode 100755 index 541c80b..0000000 Binary files a/src/kernel/userland/markdown.elf and /dev/null differ diff --git a/src/kernel/userland/math.c b/src/kernel/userland/math.c new file mode 100644 index 0000000..6fc59d4 --- /dev/null +++ b/src/kernel/userland/math.c @@ -0,0 +1,27 @@ +#include +#include + +int main(int argc, char **argv) { + if (argc < 4) { + printf("Usage: math \n"); + printf("Ops: + - * /\n"); + return 0; + } + + int n1 = atoi(argv[1]); + int n2 = atoi(argv[3]); + char op = argv[2][0]; + int res = 0; + + if (op == '+') res = n1 + n2; + else if (op == '-') res = n1 - n2; + else if (op == '*') res = n1 * n2; + else if (op == '/') { + if (n2 == 0) { printf("Error: Div by zero\n"); return 1; } + res = n1 / n2; + } + else { printf("Error: Unknown op %c\n", op); return 1; } + + printf("%d %c %d = %d\n", n1, op, n2, res); + return 0; +} diff --git a/src/kernel/userland/meminfo.c b/src/kernel/userland/meminfo.c new file mode 100644 index 0000000..3134700 --- /dev/null +++ b/src/kernel/userland/meminfo.c @@ -0,0 +1,16 @@ +#include +#include + +int main(int argc, char **argv) { + (void)argc; (void)argv; + uint64_t mem[2]; + if (sys_system(15, (uint64_t)mem, 0, 0, 0) == 0) { + printf("Memory Info:\n"); + printf("Total: %d MB\n", (int)(mem[0] / 1024 / 1024)); + printf("Used: %d MB\n", (int)(mem[1] / 1024 / 1024)); + printf("Free: %d MB\n", (int)((mem[0] - mem[1]) / 1024 / 1024)); + } else { + printf("Error: Could not retrieve memory info.\n"); + } + return 0; +} diff --git a/src/kernel/userland/minesweeper.elf b/src/kernel/userland/minesweeper.elf deleted file mode 100755 index def1804..0000000 Binary files a/src/kernel/userland/minesweeper.elf and /dev/null differ diff --git a/src/kernel/userland/mkdir.c b/src/kernel/userland/mkdir.c new file mode 100644 index 0000000..6a3e29e --- /dev/null +++ b/src/kernel/userland/mkdir.c @@ -0,0 +1,17 @@ +#include +#include + +int main(int argc, char **argv) { + if (argc < 2) { + printf("Usage: mkdir \n"); + return 1; + } + + if (sys_mkdir(argv[1]) == 0) { + printf("Created directory: %s\n", argv[1]); + } else { + printf("Error: Cannot create directory %s\n", argv[1]); + return 1; + } + return 0; +} diff --git a/src/kernel/userland/mv.c b/src/kernel/userland/mv.c new file mode 100644 index 0000000..f5346c3 --- /dev/null +++ b/src/kernel/userland/mv.c @@ -0,0 +1,38 @@ +#include +#include + +int main(int argc, char **argv) { + if (argc < 3) { + printf("Usage: mv \n"); + return 1; + } + + // Simplification: use cp then rm + int fd_in = sys_open(argv[1], "r"); + if (fd_in < 0) { + printf("Error: Cannot open source %s\n", argv[1]); + return 1; + } + + int fd_out = sys_open(argv[2], "w"); + if (fd_out < 0) { + printf("Error: Cannot create destination %s\n", argv[2]); + sys_close(fd_in); + return 1; + } + + char buffer[4096]; + int bytes; + while ((bytes = sys_read(fd_in, buffer, sizeof(buffer))) > 0) { + sys_write_fs(fd_out, buffer, bytes); + } + + sys_close(fd_in); + sys_close(fd_out); + + if (sys_delete(argv[1]) != 0) { + printf("Warning: Failed to delete source %s after copy\n", argv[1]); + } + + return 0; +} diff --git a/src/kernel/userland/nanojpeg.o b/src/kernel/userland/nanojpeg.o deleted file mode 100644 index b9c0a23..0000000 Binary files a/src/kernel/userland/nanojpeg.o and /dev/null differ diff --git a/src/kernel/userland/notepad.elf b/src/kernel/userland/notepad.elf deleted file mode 100755 index 7779ace..0000000 Binary files a/src/kernel/userland/notepad.elf and /dev/null differ diff --git a/src/kernel/userland/paint.elf b/src/kernel/userland/paint.elf deleted file mode 100755 index df2ef8e..0000000 Binary files a/src/kernel/userland/paint.elf and /dev/null differ diff --git a/src/kernel/userland/pci_list.c b/src/kernel/userland/pci_list.c new file mode 100644 index 0000000..564d56b --- /dev/null +++ b/src/kernel/userland/pci_list.c @@ -0,0 +1,30 @@ +#include +#include + +typedef struct { + uint16_t vendor; + uint16_t device; + uint8_t class_code; + uint8_t subclass; +} pci_info_t; + +int main(int argc, char **argv) { + (void)argc; (void)argv; + int count = sys_system(17, 0, 0, 0, 0); // Get count + if (count < 0) { + printf("Error: Could not retrieve PCI device count.\n"); + return 1; + } + + printf("PCI Devices (%d found):\n", count); + printf("---------------------------\n"); + for (int i = 0; i < count; i++) { + pci_info_t info; + if (sys_system(17, (uint64_t)&info, i, 0, 0) == 0) { + printf("[%d] Vendor:%04x Device:%04x Class:%02x Sub:%02x\n", + i, info.vendor, info.device, info.class_code, info.subclass); + } + } + + return 0; +} diff --git a/src/kernel/userland/pwd.c b/src/kernel/userland/pwd.c new file mode 100644 index 0000000..9e3c9c4 --- /dev/null +++ b/src/kernel/userland/pwd.c @@ -0,0 +1,14 @@ +#include +#include + +int main(int argc, char **argv) { + (void)argc; (void)argv; + char path[256]; + if (getcwd(path, sizeof(path))) { + printf("%s\n", path); + } else { + printf("Error: Could not get current directory\n"); + return 1; + } + return 0; +} diff --git a/src/kernel/userland/reboot.c b/src/kernel/userland/reboot.c new file mode 100644 index 0000000..b6b9405 --- /dev/null +++ b/src/kernel/userland/reboot.c @@ -0,0 +1,9 @@ +#include +#include + +int main(int argc, char **argv) { + (void)argc; (void)argv; + printf("Rebooting...\n"); + sys_system(12, 0, 0, 0, 0); // SYSTEM_CMD_REBOOT + return 0; +} diff --git a/src/kernel/userland/rm.c b/src/kernel/userland/rm.c new file mode 100644 index 0000000..ff4f528 --- /dev/null +++ b/src/kernel/userland/rm.c @@ -0,0 +1,18 @@ +#include +#include + +int main(int argc, char **argv) { + if (argc < 2) { + printf("Usage: rm \n"); + return 1; + } + + // Simple rm (no recursive support yet for simplicity, but can be added) + if (sys_delete(argv[1]) == 0) { + printf("Deleted: %s\n", argv[1]); + } else { + printf("Error: Cannot delete %s\n", argv[1]); + return 1; + } + return 0; +} diff --git a/src/kernel/userland/settings.elf b/src/kernel/userland/settings.elf deleted file mode 100755 index 3bcf1ee..0000000 Binary files a/src/kernel/userland/settings.elf and /dev/null differ diff --git a/src/kernel/userland/shutdown.c b/src/kernel/userland/shutdown.c new file mode 100644 index 0000000..3ae38d4 --- /dev/null +++ b/src/kernel/userland/shutdown.c @@ -0,0 +1,9 @@ +#include +#include + +int main(int argc, char **argv) { + (void)argc; (void)argv; + printf("Shutting down...\n"); + sys_system(13, 0, 0, 0, 0); // SYSTEM_CMD_SHUTDOWN + return 0; +} diff --git a/src/kernel/userland/sweden.c b/src/kernel/userland/sweden.c new file mode 100644 index 0000000..a9e9b20 --- /dev/null +++ b/src/kernel/userland/sweden.c @@ -0,0 +1,30 @@ +#include +#include + +static void beep(int freq, int ms) { + sys_system(14, freq, ms, 0, 0); +} + +int main(int argc, char **argv) { + (void)argc; (void)argv; + printf("Playing Sweden - C418 (Minecraft)...\n"); + + // Main melody (simplified pattern) + beep(392, 400); // G4 + beep(440, 400); // A4 + beep(493, 800); // B4 + + beep(440, 400); // A4 + beep(392, 800); // G4 + beep(329, 800); // E4 + + beep(392, 400); // G4 + beep(440, 400); // A4 + beep(493, 800); // B4 + + beep(440, 400); // A4 + beep(392, 1200); // G4 + + printf("Done.\n"); + return 0; +} diff --git a/src/kernel/userland/touch.c b/src/kernel/userland/touch.c new file mode 100644 index 0000000..f4165b2 --- /dev/null +++ b/src/kernel/userland/touch.c @@ -0,0 +1,24 @@ +#include +#include + +int main(int argc, char **argv) { + if (argc < 2) { + printf("Usage: touch \n"); + return 1; + } + + // Check if file already exists + if (sys_exists(argv[1])) { + // Just return success if it exists (simplification) + return 0; + } + + int fd = sys_open(argv[1], "w"); + if (fd < 0) { + printf("Error: Cannot create %s\n", argv[1]); + return 1; + } + + sys_close(fd); + return 0; +} diff --git a/src/kernel/userland/txtedit.elf b/src/kernel/userland/txtedit.elf deleted file mode 100755 index cdc1834..0000000 Binary files a/src/kernel/userland/txtedit.elf and /dev/null differ diff --git a/src/kernel/userland/uptime.c b/src/kernel/userland/uptime.c new file mode 100644 index 0000000..d4daf7a --- /dev/null +++ b/src/kernel/userland/uptime.c @@ -0,0 +1,16 @@ +#include +#include + +int main(int argc, char **argv) { + (void)argc; (void)argv; + uint64_t ticks = sys_system(16, 0, 0, 0, 0); // SYSTEM_CMD_UPTIME + uint64_t seconds = ticks / 100; // 100Hz timer assumed + uint64_t minutes = seconds / 60; + uint64_t hours = minutes / 60; + uint64_t days = hours / 24; + + printf("Uptime: %d days, %d hours, %d minutes, %d seconds\n", + (int)days, (int)(hours % 24), (int)(minutes % 60), (int)(seconds % 60)); + + return 0; +} diff --git a/src/kernel/userland/viewer.elf b/src/kernel/userland/viewer.elf deleted file mode 100755 index 8589e4d..0000000 Binary files a/src/kernel/userland/viewer.elf and /dev/null differ diff --git a/src/kernel/userland/viewer.o b/src/kernel/userland/viewer.o deleted file mode 100644 index d6a263e..0000000 Binary files a/src/kernel/userland/viewer.o and /dev/null differ diff --git a/src/kernel/vm.c b/src/kernel/vm.c index d83f8f6..0e7b1dd 100644 --- a/src/kernel/vm.c +++ b/src/kernel/vm.c @@ -6,7 +6,7 @@ #include "fat32.h" #include "rtc.h" #include "ps2.h" -#include "cli_apps/cli_utils.h" +#include "kutils.h" #include "io.h" // --- Scancode Map (Set 1) --- @@ -62,7 +62,7 @@ static void mem_write32(int addr, int val) { static void vm_reset(void) { sp = 0; - cli_memset(memory, 0, VM_MEMORY_SIZE); + k_memset(memory, 0, VM_MEMORY_SIZE); vm_heap_ptr = 8192; } @@ -85,22 +85,22 @@ static int pop(void) { // Syscall Implementations static void vm_syscall(int id) { switch (id) { - case SYS_EXIT: + case VM_SYS_EXIT: // Handled by return code in main loop usually, but here just do nothing or treat as halt push(0); break; - case SYS_PRINT_INT: + case VM_SYS_PRINT_INT: cmd_write_int(pop()); push(0); break; - case SYS_PRINT_CHAR: { + case VM_SYS_PRINT_CHAR: { char c = (char)pop(); char s[2] = {c, 0}; cmd_write(s); push(0); break; } - case SYS_PRINT_STR: { + case VM_SYS_PRINT_STR: { int addr = pop(); if (addr >= 0 && addr < VM_MEMORY_SIZE) { cmd_write((char*)&memory[addr]); @@ -108,15 +108,15 @@ static void vm_syscall(int id) { push(0); break; } - case SYS_NL: + case VM_SYS_NL: cmd_write("\n"); push(0); break; - case SYS_CLS: + case VM_SYS_CLS: cmd_screen_clear(); push(0); break; - case SYS_GETCHAR: { + case VM_SYS_GETCHAR: { int c = 0; // Blocking read for a valid key press while (1) { @@ -133,50 +133,50 @@ static void vm_syscall(int id) { push(c); break; } - case SYS_KB_HIT: + case VM_SYS_KB_HIT: // Simple check if data is waiting in keyboard controller push((inb(0x64) & 1) ? 1 : 0); break; - case SYS_STRLEN: { + case VM_SYS_STRLEN: { int addr = pop(); if (addr >= 0 && addr < VM_MEMORY_SIZE) { - push(cli_strlen((char*)&memory[addr])); + push(k_strlen((char*)&memory[addr])); } else push(0); break; } - case SYS_STRCMP: { + case VM_SYS_STRCMP: { int a2 = pop(); int a1 = pop(); if (a1 >= 0 && a1 < VM_MEMORY_SIZE && a2 >= 0 && a2 < VM_MEMORY_SIZE) { - push(cli_strcmp((char*)&memory[a1], (char*)&memory[a2])); + push(k_strcmp((char*)&memory[a1], (char*)&memory[a2])); } else push(0); break; } - case SYS_STRCPY: { + case VM_SYS_STRCPY: { int src = pop(); int dest = pop(); - if (dest >= 0 && dest < VM_MEMORY_SIZE && src >= 0 && src < VM_MEMORY_SIZE) { - cli_strcpy((char*)&memory[dest], (char*)&memory[src]); + if (dest >= 0 && dest < VM_MEMORY_SIZE && src >= 0 && src < VM_MEMORY_SIZE) { + k_strcpy((char*)&memory[dest], (char*)&memory[src]); push(dest); - } else push(0); + } else push(0); break; } - case SYS_STRCAT: { + case VM_SYS_STRCAT: { // Not implemented in cli_utils pop(); pop(); push(0); break; } - case SYS_MEMSET: { + case VM_SYS_MEMSET: { int n = pop(); int val = pop(); int ptr = pop(); if (ptr >= 0 && ptr + n <= VM_MEMORY_SIZE) { - cli_memset(&memory[ptr], val, n); + k_memset(&memory[ptr], val, n); push(ptr); } else push(0); break; } - case SYS_MEMCPY: { + case VM_SYS_MEMCPY: { int n = pop(); int src = pop(); int dest = pop(); @@ -189,7 +189,7 @@ static void vm_syscall(int id) { // Simplified Heap (using top of memory growing down?) // For now, static allocation or mapped. // Dummy malloc that returns an index into memory starting at 1024 - case SYS_MALLOC: { + case VM_SYS_MALLOC: { int size = pop(); int res = vm_heap_ptr; vm_heap_ptr += size; @@ -200,38 +200,38 @@ static void vm_syscall(int id) { } break; } - case SYS_FREE: + case VM_SYS_FREE: pop(); // No-op push(0); break; - case SYS_RAND: { + case VM_SYS_RAND: { rand_next = rand_next * 1103515245 + 12345; push((unsigned int)(rand_next/65536) % 32768); break; } - case SYS_SRAND: { + case VM_SYS_SRAND: { rand_next = pop(); push(0); break; } - case SYS_ABS: { + case VM_SYS_ABS: { int x = pop(); push(x < 0 ? -x : x); break; } - case SYS_MIN: { + case VM_SYS_MIN: { int b = pop(); int a = pop(); push(a < b ? a : b); break; } - case SYS_MAX: { + case VM_SYS_MAX: { int b = pop(); int a = pop(); push(a > b ? a : b); break; } - case SYS_POW: { + case VM_SYS_POW: { int exp = pop(); int base = pop(); int res = 1; @@ -239,26 +239,26 @@ static void vm_syscall(int id) { push(res); break; } - case SYS_SQRT: { + case VM_SYS_SQRT: { int n = pop(); int res = 0; while ((res*res) <= n) res++; push(res - 1); break; } - case SYS_SLEEP: - cli_sleep(pop()); + case VM_SYS_SLEEP: + k_sleep(pop()); push(0); break; // File IO - Not supported yet as FILE* cannot be easily passed to VM - case SYS_FOPEN: pop(); pop(); push(0); break; - case SYS_FCLOSE: pop(); push(0); break; - case SYS_FREAD: pop(); pop(); pop(); pop(); push(0); break; - case SYS_FWRITE: pop(); pop(); pop(); pop(); push(0); break; - case SYS_FSEEK: pop(); pop(); pop(); push(0); break; - case SYS_REMOVE: pop(); push(0); break; + case VM_SYS_FOPEN: pop(); pop(); push(0); break; + case VM_SYS_FCLOSE: pop(); push(0); break; + case VM_SYS_FREAD: pop(); pop(); pop(); pop(); push(0); break; + case VM_SYS_FWRITE: pop(); pop(); pop(); pop(); push(0); break; + case VM_SYS_FSEEK: pop(); pop(); pop(); push(0); break; + case VM_SYS_REMOVE: pop(); push(0); break; - case SYS_DRAW_PIXEL: { + case VM_SYS_DRAW_PIXEL: { int color = pop(); int y = pop(); int x = pop(); @@ -266,7 +266,7 @@ static void vm_syscall(int id) { push(0); break; } - case SYS_DRAW_RECT: { + case VM_SYS_DRAW_RECT: { int color = pop(); int h = pop(); int w = pop(); @@ -289,65 +289,65 @@ static void vm_syscall(int id) { push(0); break; } - case SYS_GET_WIDTH: push(get_screen_width()); break; - case SYS_GET_HEIGHT: push(get_screen_height()); break; + case VM_SYS_GET_WIDTH: push(get_screen_width()); break; + case VM_SYS_GET_HEIGHT: push(get_screen_height()); break; - case SYS_ATOI: { + case VM_SYS_ATOI: { int addr = pop(); if (addr >= 0 && addr < VM_MEMORY_SIZE) { - push(cli_atoi((char*)&memory[addr])); + push(k_atoi((char*)&memory[addr])); } else push(0); break; } - case SYS_ITOA: { + case VM_SYS_ITOA: { int addr = pop(); int val = pop(); if (addr >= 0 && addr < VM_MEMORY_SIZE) { - cli_itoa(val, (char*)&memory[addr]); + k_itoa(val, (char*)&memory[addr]); } push(0); break; } - case SYS_PEEK: push(mem_read32(pop())); break; - case SYS_POKE: { + case VM_SYS_PEEK: push(mem_read32(pop())); break; + case VM_SYS_POKE: { int val = pop(); int addr = pop(); mem_write32(addr, val); push(0); break; } - case SYS_EXEC: pop(); push(-1); break; - case SYS_SYSTEM: pop(); push(-1); break; + case VM_SYS_EXEC: pop(); push(-1); break; + case VM_SYS_SYSTEM: pop(); push(-1); break; // --- New Builtins --- - case SYS_ISALNUM: { + case VM_SYS_ISALNUM: { int c = pop(); push(((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))); break; } - case SYS_ISALPHA: { + case VM_SYS_ISALPHA: { int c = pop(); push(((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))); break; } - case SYS_ISDIGIT: { + case VM_SYS_ISDIGIT: { int c = pop(); push((c >= '0' && c <= '9')); break; } - case SYS_TOLOWER: { + case VM_SYS_TOLOWER: { int c = pop(); if (c >= 'A' && c <= 'Z') push(c + 32); else push(c); break; } - case SYS_TOUPPER: { + case VM_SYS_TOUPPER: { int c = pop(); if (c >= 'a' && c <= 'z') push(c - 32); else push(c); break; } - case SYS_STRNCPY: { + case VM_SYS_STRNCPY: { int n = pop(); int src = pop(); int dest = pop(); @@ -361,7 +361,7 @@ static void vm_syscall(int id) { } else push(0); break; } - case SYS_STRNCAT: { + case VM_SYS_STRNCAT: { int n = pop(); int src = pop(); int dest = pop(); @@ -378,7 +378,7 @@ static void vm_syscall(int id) { } else push(0); break; } - case SYS_STRNCMP: { + case VM_SYS_STRNCMP: { int n = pop(); int s2 = pop(); int s1 = pop(); @@ -396,7 +396,7 @@ static void vm_syscall(int id) { } else push(0); break; } - case SYS_STRSTR: { + case VM_SYS_STRSTR: { int needle = pop(); int haystack = pop(); if (haystack >= 0 && haystack < VM_MEMORY_SIZE && needle >= 0 && needle < VM_MEMORY_SIZE) { @@ -416,7 +416,7 @@ static void vm_syscall(int id) { } else push(0); break; } - case SYS_STRRCHR: { + case VM_SYS_STRRCHR: { int c = pop(); int s = pop(); if (s >= 0 && s < VM_MEMORY_SIZE) { @@ -433,7 +433,7 @@ static void vm_syscall(int id) { } else push(0); break; } - case SYS_MEMMOVE: { + case VM_SYS_MEMMOVE: { int n = pop(); int src = pop(); int dest = pop(); @@ -476,7 +476,7 @@ int vm_exec(const uint8_t *code, int code_size) { } // Load program into memory at address 0 - cli_memset(memory, 0, VM_MEMORY_SIZE); + k_memset(memory, 0, VM_MEMORY_SIZE); for(int i=0; i #include @@ -1586,9 +1586,9 @@ void wm_handle_click(int x, int y) { if (existing) wm_bring_to_front(existing); else process_create_elf("/bin/settings.elf", NULL); } else if (item == 2) { // Shutdown - cli_cmd_shutdown(NULL); + k_shutdown(); } else if (item == 3) { // Restart - cli_cmd_reboot(NULL); + k_reboot(); } start_menu_open = false; @@ -1881,9 +1881,9 @@ void wm_handle_right_click(int x, int y) { } else if (str_starts_with(start_menu_pending_app, "About")) { wm_bring_to_front(&win_about); } else if (str_starts_with(start_menu_pending_app, "Shutdown")) { - cli_cmd_shutdown(NULL); + k_shutdown(); } else if (str_starts_with(start_menu_pending_app, "Restart")) { - cli_cmd_reboot(NULL); + k_reboot(); } start_menu_pending_app = NULL;