diff --git a/.DS_Store b/.DS_Store index f3699de..3e18b3a 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/Makefile b/Makefile index 802f6f7..8e16f76 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ LDFLAGS = -m elf_x86_64 -nostdlib -static -pie --no-dynamic-linker \ NASMFLAGS = -f elf64 # Limine Version -LIMINE_VERSION = 10.8.2 +LIMINE_VERSION = 7.0.0 LIMINE_URL_BASE = https://github.com/limine-bootloader/limine/raw/v$(LIMINE_VERSION) .PHONY: all clean run limine-setup @@ -86,25 +86,26 @@ $(KERNEL_ELF): $(OBJ_FILES) $(MAKE) -C $(SRC_DIR)/userland # Create ISO -$(ISO_IMAGE): $(KERNEL_ELF) limine.conf limine-setup +$(ISO_IMAGE): $(KERNEL_ELF) limine.cfg limine-setup rm -rf $(ISO_DIR) mkdir -p $(ISO_DIR) mkdir -p $(ISO_DIR)/EFI/BOOT # Copy Kernel and Config cp $(KERNEL_ELF) $(ISO_DIR)/ - # Build ISO limine.conf natively with modules - cp limine.conf $(ISO_DIR)/ + # 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 \ if [ -f "$$f" ]; then \ basename=$$(basename "$$f"); \ cp "$$f" $(ISO_DIR)/bin/; \ - echo " module_path: boot():/bin/$$basename" >> $(ISO_DIR)/limine.conf; \ + echo " MODULE_PATH=boot:///bin/$$basename" >> $(ISO_DIR)/limine.cfg; \ fi \ done # Copy README + @if [ -f README.md ]; then cp README.md $(ISO_DIR)/; fi # Copy Wallpaper (if it exists) @if [ -f src/kernel/wallpaper.ppm ]; then cp src/kernel/wallpaper.ppm $(ISO_DIR)/; fi @@ -133,11 +134,8 @@ clean: rm -rf $(BUILD_DIR) $(ISO_DIR) $(ISO_IMAGE) run: $(ISO_IMAGE) - dd if=/dev/zero of=disk.img bs=1M count=64 - mformat -i disk.img -F :: qemu-system-x86_64 -m 2G -serial stdio -cdrom $< -boot d \ -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 \ - -no-reboot -d int -D qemu-debug.log + diff --git a/boredos.iso b/boredos.iso index 95bd27c..b0d0f6f 100644 Binary files a/boredos.iso and b/boredos.iso differ diff --git a/build/cmd.o b/build/cmd.o index 1559945..d5ebab8 100644 Binary files a/build/cmd.o and b/build/cmd.o differ diff --git a/build/disk_manager.o b/build/disk_manager.o index 935469e..5b63bf2 100644 Binary files a/build/disk_manager.o and b/build/disk_manager.o differ diff --git a/build/explorer.o b/build/explorer.o index 813ed6c..ebbe0e4 100644 Binary files a/build/explorer.o and b/build/explorer.o differ diff --git a/build/fat32.o b/build/fat32.o index a41bfc6..59647a5 100644 Binary files a/build/fat32.o and b/build/fat32.o differ diff --git a/build/idt.o b/build/idt.o index c82d835..2f38f96 100644 Binary files a/build/idt.o and b/build/idt.o differ diff --git a/build/main.o b/build/main.o index c790d61..45433a6 100644 Binary files a/build/main.o and b/build/main.o differ diff --git a/build/memory_manager.o b/build/memory_manager.o index f9c9b8f..2f848a3 100644 Binary files a/build/memory_manager.o and b/build/memory_manager.o differ diff --git a/build/platform.o b/build/platform.o index bf3c2bd..10da7ae 100644 Binary files a/build/platform.o and b/build/platform.o differ diff --git a/disk.img b/disk.img index fa13297..c63159a 100644 Binary files a/disk.img and b/disk.img differ diff --git a/limine b/limine index 38ff2c8..36783ec 160000 --- a/limine +++ b/limine @@ -1 +1 @@ -Subproject commit 38ff2c855aabb92e4cfa2cc7ef0c8af665ecba94 +Subproject commit 36783ec43af4db4841a1e80770355fd1e98f091b diff --git a/limine.cfg b/limine.cfg new file mode 100644 index 0000000..93f41ba --- /dev/null +++ b/limine.cfg @@ -0,0 +1,8 @@ +TIMEOUT=3 +TERM_PALETTE=ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff +TERM_BACKGROUND=00000000 +WALLPAPER=splash.jpg + +:BoredOS + PROTOCOL=limine + KERNEL_PATH=boot:///boredos.elf diff --git a/limine.conf b/limine.conf deleted file mode 100644 index 29323b5..0000000 --- a/limine.conf +++ /dev/null @@ -1,11 +0,0 @@ -timeout: 3 - -# Graphics mode and Splash screen -term_palette: ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff -term_background: #00000000 -wallpaper: boot():/splash.jpg - -/BoredOS - protocol: limine - - kernel_path: boot():/boredos.elf diff --git a/src/kernel/cmd.c b/src/kernel/cmd.c index 3e23838..fa8d84d 100644 --- a/src/kernel/cmd.c +++ b/src/kernel/cmd.c @@ -731,50 +731,6 @@ static const CommandEntry commands[] = { {NULL, NULL} }; -// Helper to build full path with cmd window's drive context -static void cmd_build_full_path(const char *relative_path, char *full_path) { - if (!cmd_state) { - if (relative_path[0]) { - cmd_strcpy(full_path, relative_path); - } else { - full_path[0] = 'A'; - full_path[1] = ':'; - full_path[2] = '/'; - full_path[3] = 0; - } - return; - } - - // If path already has drive letter, use it as-is - if (relative_path && relative_path[1] == ':') { - cmd_strcpy(full_path, relative_path); - return; - } - - // Build path with cmd_state's drive and directory - int i = 0; - full_path[i++] = cmd_state->current_drive; - full_path[i++] = ':'; - - // Add current directory - const char *dir = cmd_state->current_dir; - while (*dir && i < 509) { - full_path[i++] = *dir++; - } - - // Add path argument - if (relative_path && relative_path[0]) { - if (i > 2 && full_path[i-1] != '/') { - full_path[i++] = '/'; - } - const char *p = relative_path; - while (*p && i < 509) { - full_path[i++] = *p++; - } - } - - full_path[i] = 0; -} // Helper to sync cmd window directory after cd static void cmd_update_dir(const char *path) { diff --git a/src/kernel/disk_manager.c b/src/kernel/disk_manager.c index 21a4abe..0c8c43f 100644 --- a/src/kernel/disk_manager.c +++ b/src/kernel/disk_manager.c @@ -93,11 +93,12 @@ static int ata_identify(uint16_t port_base, bool slave) { if (status == 0) return 0; // Wait until BSY clears - while (inb(port_base + ATA_REG_STATUS) & ATA_SR_BSY) { - // Simple timeout could be added here + int timeout = 10000; + while ((inb(port_base + ATA_REG_STATUS) & ATA_SR_BSY) && --timeout > 0) { status = inb(port_base + ATA_REG_STATUS); if (status == 0) return 0; // Check again } + if (timeout <= 0) return 0; // Hardware didn't respond // Check for error if (inb(port_base + ATA_REG_STATUS) & ATA_SR_ERR) { diff --git a/src/kernel/explorer.c b/src/kernel/explorer.c index 19b0679..f243594 100644 --- a/src/kernel/explorer.c +++ b/src/kernel/explorer.c @@ -43,7 +43,7 @@ static int dropdown_menu_item_height = 25; #define CONTEXT_MENU_ITEM_HEIGHT 25 // Clipboard state -static char clipboard_path[256] = ""; +static char clipboard_path[FAT32_MAX_PATH] = ""; static int clipboard_action = 0; // 0=None, 1=Copy, 2=Cut #define FILE_CONTEXT_ITEMS 2 // "Open with Text Editor" and "Open with Markdown Viewer" @@ -259,7 +259,7 @@ static void dialog_confirm_create_file(Window *win) { if (!check_desktop_limit_explorer(win)) return; - char full_path[256]; + char full_path[FAT32_MAX_PATH]; explorer_strcpy(full_path, state->dialog_creation_path); if (full_path[explorer_strlen(full_path) - 1] != '/') { explorer_strcat(full_path, "/"); @@ -283,7 +283,7 @@ static void dialog_confirm_create_file(Window *win) { static void dialog_force_create_file(Window *win) { ExplorerState *state = (ExplorerState*)win->data; - char full_path[256]; + char full_path[FAT32_MAX_PATH]; explorer_strcpy(full_path, state->dialog_creation_path); if (full_path[explorer_strlen(full_path) - 1] != '/') { explorer_strcat(full_path, "/"); @@ -304,7 +304,7 @@ static void dialog_confirm_create_folder(Window *win) { if (!check_desktop_limit_explorer(win)) return; - char full_path[256]; + char full_path[FAT32_MAX_PATH]; explorer_strcpy(full_path, state->dialog_creation_path); if (full_path[explorer_strlen(full_path) - 1] != '/') { explorer_strcat(full_path, "/"); @@ -331,7 +331,7 @@ bool explorer_delete_permanently(const char *path) { for (int i = 0; i < count; i++) { if (explorer_strcmp(entries[i].name, ".") == 0 || explorer_strcmp(entries[i].name, "..") == 0) continue; - char child_path[256]; + char child_path[FAT32_MAX_PATH]; explorer_strcpy(child_path, path); if (child_path[explorer_strlen(child_path) - 1] != '/') { explorer_strcat(child_path, "/"); @@ -379,13 +379,13 @@ bool explorer_delete_recursive(const char *path) { drive_prefix[0] = path[0]; } - char dest_path[256]; + char dest_path[FAT32_MAX_PATH]; explorer_strcpy(dest_path, drive_prefix); explorer_strcat(dest_path, "/RecycleBin/"); explorer_strcat(dest_path, filename); // Save origin - char origin_path[256]; + char origin_path[FAT32_MAX_PATH]; explorer_strcpy(origin_path, dest_path); explorer_strcat(origin_path, ".origin"); FAT32_FileHandle *fh = fat32_open(origin_path, "w"); @@ -446,7 +446,7 @@ static bool explorer_copy_recursive(const char *src_path, const char *dest_path) for (int i = 0; i < count; i++) { if (explorer_strcmp(files[i].name, ".") == 0 || explorer_strcmp(files[i].name, "..") == 0) continue; - char s_sub[256], d_sub[256]; + char s_sub[FAT32_MAX_PATH], d_sub[FAT32_MAX_PATH]; explorer_strcpy(s_sub, src_path); if (s_sub[explorer_strlen(s_sub)-1] != '/') explorer_strcat(s_sub, "/"); explorer_strcat(s_sub, files[i].name); @@ -482,7 +482,7 @@ static bool explorer_copy_recursive(const char *src_path, const char *dest_path) } static void explorer_copy_file_internal(const char *src_path, const char *dest_dir) { - char filename[256]; + char filename[FAT32_MAX_FILENAME]; int len = explorer_strlen(src_path); int i = len - 1; while (i >= 0 && src_path[i] != '/') i--; @@ -490,7 +490,7 @@ static void explorer_copy_file_internal(const char *src_path, const char *dest_d for (int k = i + 1; k < len; k++) filename[j++] = src_path[k]; filename[j] = 0; - char dest_path[256]; + char dest_path[FAT32_MAX_PATH]; explorer_strcpy(dest_path, dest_dir); if (dest_path[explorer_strlen(dest_path) - 1] != '/') { explorer_strcat(dest_path, "/"); @@ -565,7 +565,7 @@ void explorer_create_shortcut(Window *win, const char *target_path) { for (int k = i + 1; k < len; k++) filename[j++] = target_path[k]; filename[j] = 0; - char shortcut_path[256]; + char shortcut_path[FAT32_MAX_PATH]; explorer_strcpy(shortcut_path, state->current_path); if (shortcut_path[explorer_strlen(shortcut_path)-1] != '/') explorer_strcat(shortcut_path, "/"); explorer_strcat(shortcut_path, filename); @@ -649,7 +649,7 @@ static int explorer_build_context_menu(Window *win, ExplorerContextItem *items_o // === Explorer Logic === static uint32_t explorer_get_folder_color(const char *folder_path) { - char color_file_path[256]; + char color_file_path[FAT32_MAX_PATH]; explorer_strcpy(color_file_path, folder_path); if (color_file_path[explorer_strlen(color_file_path) - 1] != '/') { explorer_strcat(color_file_path, "/"); @@ -669,7 +669,7 @@ static uint32_t explorer_get_folder_color(const char *folder_path) { } static void explorer_set_folder_color(const char *folder_path, uint32_t color) { - char color_file_path[256]; + char color_file_path[FAT32_MAX_PATH]; explorer_strcpy(color_file_path, folder_path); if (color_file_path[explorer_strlen(color_file_path) - 1] != '/') { explorer_strcat(color_file_path, "/"); @@ -687,19 +687,19 @@ static void explorer_restore_file(Window *win, int item_idx) { ExplorerState *state = (ExplorerState*)win->data; if (item_idx < 0 || item_idx >= state->item_count) return; - char recycle_path[256]; + char recycle_path[FAT32_MAX_PATH]; explorer_strcpy(recycle_path, state->current_path); if (recycle_path[explorer_strlen(recycle_path) - 1] != '/') explorer_strcat(recycle_path, "/"); explorer_strcat(recycle_path, state->items[item_idx].name); - char origin_file_path[256]; + char origin_file_path[FAT32_MAX_PATH]; explorer_strcpy(origin_file_path, recycle_path); explorer_strcat(origin_file_path, ".origin"); - char original_path[256] = {0}; + char original_path[FAT32_MAX_PATH] = {0}; FAT32_FileHandle *fh = fat32_open(origin_file_path, "r"); if (fh) { - int len = fat32_read(fh, original_path, 255); + int len = fat32_read(fh, original_path, FAT32_MAX_PATH - 1); if (len > 0) original_path[len] = 0; fat32_close(fh); } @@ -725,7 +725,7 @@ 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 && i < EXPLORER_MAX_FILES; i++) { + for (int i = 0; i < count && state->item_count < EXPLORER_MAX_FILES; i++) { // Skip .color files if (explorer_strcmp(entries[i].name, ".color") == 0) { continue; @@ -741,8 +741,8 @@ static void explorer_load_directory(Window *win, const char *path) { state->items[state->item_count].size = entries[i].size; if (state->items[state->item_count].is_directory) { - char subfolder_path[256]; - explorer_strcpy(subfolder_path, state->current_path); + char subfolder_path[FAT32_MAX_PATH]; + explorer_strcpy(subfolder_path, path); if (subfolder_path[explorer_strlen(subfolder_path) - 1] != '/') { explorer_strcat(subfolder_path, "/"); } @@ -763,7 +763,7 @@ static void explorer_load_directory(Window *win, const char *path) { static void explorer_navigate_to(Window *win, const char *dirname) { ExplorerState *state = (ExplorerState*)win->data; - char new_path[256]; + char new_path[FAT32_MAX_PATH]; if (explorer_strcmp(dirname, "..") == 0) { // Go to parent directory @@ -827,7 +827,7 @@ static void explorer_open_item(Window *win, int index) { return; } - char full_path[256]; + char full_path[FAT32_MAX_PATH]; explorer_strcpy(full_path, state->current_path); if (full_path[explorer_strlen(full_path) - 1] != '/') { explorer_strcat(full_path, "/"); @@ -863,7 +863,7 @@ static void explorer_open_item(Window *win, int index) { // Generic shortcut FAT32_FileHandle *fh = fat32_open(full_path, "r"); if (fh) { - char buf[256]; + char buf[FAT32_MAX_PATH]; int len = fat32_read(fh, buf, 255); fat32_close(fh); if (len > 0) { @@ -898,7 +898,7 @@ static void explorer_draw_file_icon(int x, int y, bool is_dir, uint32_t color, c draw_paint_icon(x + 5, y + 5, ""); } else if (explorer_str_ends_with(filename, ".jpg") || explorer_str_ends_with(filename, ".JPG")) { // Build full path for thumbnail loading - char full_path[256]; + char full_path[FAT32_MAX_PATH]; explorer_strcpy(full_path, current_path); if (full_path[explorer_strlen(full_path) - 1] != '/') explorer_strcat(full_path, "/"); explorer_strcat(full_path, filename); @@ -922,7 +922,7 @@ static void explorer_paint(Window *win) { draw_rect(offset_x, offset_y, win->w - 8, win->h - 28, COLOR_DARK_BG); // Draw Drive Button (modern rounded style) - char drive_label[8]; + char drive_label[9]; // 8 chars + null // Extract drive from the window's current_path instead of using global current_drive char current_drv = 'A'; if (state->current_path[0] && state->current_path[1] == ':') { @@ -939,6 +939,7 @@ static void explorer_paint(Window *win) { drive_label[5] = 'v'; drive_label[6] = ' '; drive_label[7] = ']'; + drive_label[8] = 0; // Button at x+4, y+3, w=60 (rounded) draw_rounded_rect_filled(win->x + 4, offset_y + 3, 60, 22, 5, COLOR_DARK_PANEL); @@ -1209,7 +1210,7 @@ static void explorer_paint(Window *win) { if (state->file_context_menu_visible) { // Convert window-relative coordinates to screen coordinates for drawing int menu_screen_x = win->x + state->file_context_menu_x; - int menu_screen_y = win->y + state->file_context_menu_y; + int menu_screen_y = win->y + state->file_context_menu_y + 20; // Adjusted for title bar (20px) ExplorerContextItem menu_items[20]; int count = explorer_build_context_menu(win, menu_items); @@ -1250,7 +1251,7 @@ static void explorer_handle_click(Window *win, int x, int y) { // Handle dialog clicks if (state->dialog_state == DIALOG_CREATE_FILE || state->dialog_state == DIALOG_CREATE_FOLDER) { int dlg_x = win->w / 2 - 150; - int dlg_y = win->h / 2 - 60; + int dlg_y = win->h / 2 - 80; // Create button if (x >= dlg_x + 50 && x < dlg_x + 130 && @@ -1279,9 +1280,10 @@ static void explorer_handle_click(Window *win, int x, int y) { } return; } + return; // Clicked inside dialog but not on button - consume click } else if (state->dialog_state == DIALOG_DELETE_CONFIRM) { int dlg_x = win->w / 2 - 150; - int dlg_y = win->h / 2 - 60; + int dlg_y = win->h / 2 - 80; // Adjusted for title bar offset // Delete button if (x >= dlg_x + 50 && x < dlg_x + 130 && @@ -1296,9 +1298,10 @@ static void explorer_handle_click(Window *win, int x, int y) { dialog_close(win); return; } + return; // Consume click } else if (state->dialog_state == DIALOG_REPLACE_CONFIRM) { int dlg_x = win->w / 2 - 150; - int dlg_y = win->h / 2 - 60; + int dlg_y = win->h / 2 - 80; if (x >= dlg_x + 50 && x < dlg_x + 130 && y >= dlg_y + 70 && y < dlg_y + 95) { dialog_confirm_replace(win); @@ -1309,9 +1312,10 @@ static void explorer_handle_click(Window *win, int x, int y) { dialog_close(win); return; } + return; } else if (state->dialog_state == DIALOG_REPLACE_MOVE_CONFIRM) { int dlg_x = win->w / 2 - 150; - int dlg_y = win->h / 2 - 60; + int dlg_y = win->h / 2 - 80; if (x >= dlg_x + 50 && x < dlg_x + 130 && y >= dlg_y + 70 && y < dlg_y + 95) { dialog_confirm_replace_move(win); @@ -1322,9 +1326,10 @@ static void explorer_handle_click(Window *win, int x, int y) { dialog_close(win); return; } + return; } else if (state->dialog_state == DIALOG_CREATE_REPLACE_CONFIRM) { int dlg_x = win->w / 2 - 150; - int dlg_y = win->h / 2 - 60; + int dlg_y = win->h / 2 - 80; if (x >= dlg_x + 50 && x < dlg_x + 130 && y >= dlg_y + 70 && y < dlg_y + 95) { dialog_force_create_file(win); @@ -1335,20 +1340,22 @@ static void explorer_handle_click(Window *win, int x, int y) { dialog_close(win); return; } + return; } else if (state->dialog_state == DIALOG_ERROR) { int dlg_x = win->w / 2 - 150; - int dlg_y = win->h / 2 - 60; + int dlg_y = win->h / 2 - 80; if (x >= dlg_x + 110 && x < dlg_x + 190 && y >= dlg_y + 70 && y < dlg_y + 95) { dialog_close(win); return; } + return; } else if (state->dialog_state == DIALOG_RENAME) { int dlg_x = win->w / 2 - 150; - int dlg_y = win->h / 2 - 60; + int dlg_y = win->h / 2 - 80; if (x >= dlg_x + 50 && x < dlg_x + 130 && y >= dlg_y + 65 && y < dlg_y + 90) { - char new_path[256]; + char new_path[FAT32_MAX_PATH]; explorer_strcpy(new_path, state->current_path); if (new_path[explorer_strlen(new_path)-1] != '/') explorer_strcat(new_path, "/"); explorer_strcat(new_path, state->dialog_input); @@ -1362,6 +1369,15 @@ static void explorer_handle_click(Window *win, int x, int y) { dialog_close(win); return; } + + if (x >= dlg_x + 10 && x < dlg_x + 290 && y >= dlg_y + 35 && y < dlg_y + 55) { + state->dialog_input_cursor = (x - dlg_x - 15) / 8; + if (state->dialog_input_cursor > (int)explorer_strlen(state->dialog_input)) { + state->dialog_input_cursor = explorer_strlen(state->dialog_input); + } + return; + } + return; // Consume click } // Handle Drive Menu Selection @@ -1525,7 +1541,7 @@ static void explorer_handle_key(Window *win, char c) { } else if (state->dialog_state == DIALOG_CREATE_FOLDER) { dialog_confirm_create_folder(win); } else if (state->dialog_state == DIALOG_RENAME) { - char new_path[256]; + char new_path[FAT32_MAX_PATH]; explorer_strcpy(new_path, state->current_path); if (new_path[explorer_strlen(new_path)-1] != '/') explorer_strcat(new_path, "/"); explorer_strcat(new_path, state->dialog_input); @@ -1725,7 +1741,7 @@ static void explorer_handle_file_context_menu_click(Window *win, int x, int y) { if (clicked_action == 0) return; // Execute Action - char full_path[256]; + char full_path[FAT32_MAX_PATH]; if (state->file_context_menu_item >= 0) { explorer_strcpy(full_path, state->current_path); if (full_path[explorer_strlen(full_path) - 1] != '/') explorer_strcat(full_path, "/"); @@ -1943,6 +1959,8 @@ Window* explorer_create_window(const char *path) { Window *win = (Window*)kmalloc(sizeof(Window)); ExplorerState *state = (ExplorerState*)kmalloc(sizeof(ExplorerState)); + if (!state || !win) return NULL; + mem_memset(state, 0, sizeof(ExplorerState)); win->title = "Files"; win->x = 300 + (explorer_win_count * 30); @@ -1962,9 +1980,6 @@ Window* explorer_create_window(const char *path) { state->last_clicked_item = -1; state->explorer_scroll_row = 0; state->dialog_state = DIALOG_NONE; - state->dropdown_menu_visible = false; - state->drive_menu_visible = false; - state->file_context_menu_visible = false; explorer_wins[explorer_win_count++] = win; wm_add_window(win); @@ -1977,6 +1992,9 @@ Window* explorer_create_window(const char *path) { void explorer_init(void) { ExplorerState *state = (ExplorerState*)kmalloc(sizeof(ExplorerState)); + if (!state) return; + mem_memset(state, 0, sizeof(ExplorerState)); + win_explorer.title = "Files"; win_explorer.x = 300; win_explorer.y = 100; @@ -1991,7 +2009,11 @@ void explorer_init(void) { win_explorer.handle_right_click = explorer_handle_right_click; win_explorer.data = state; - state->drive_menu_visible = false; + state->selected_item = -1; + state->last_clicked_item = -1; + state->explorer_scroll_row = 0; + state->dialog_state = DIALOG_NONE; + explorer_wins[explorer_win_count++] = &win_explorer; explorer_load_directory(&win_explorer, "A:/"); } diff --git a/src/kernel/explorer.h b/src/kernel/explorer.h index f934d5f..01500c6 100644 --- a/src/kernel/explorer.h +++ b/src/kernel/explorer.h @@ -2,6 +2,7 @@ #define EXPLORER_H #include "wm.h" +#include "fat32.h" #include // External windows references (for opening other apps) @@ -15,7 +16,7 @@ extern Window win_markdown; #define DIALOG_INPUT_MAX 256 typedef struct { - char name[256]; + char name[FAT32_MAX_FILENAME]; bool is_directory; uint32_t size; uint32_t color; @@ -25,7 +26,7 @@ typedef struct { ExplorerItem items[EXPLORER_MAX_FILES]; int item_count; int selected_item; - char current_path[256]; + char current_path[FAT32_MAX_PATH]; int last_clicked_item; uint32_t last_click_time; int explorer_scroll_row; @@ -34,11 +35,11 @@ typedef struct { int dialog_state; char dialog_input[DIALOG_INPUT_MAX]; int dialog_input_cursor; - char dialog_target_path[256]; + char dialog_target_path[FAT32_MAX_PATH]; bool dialog_target_is_dir; - char dialog_dest_dir[256]; - char dialog_creation_path[256]; - char dialog_move_src[256]; + char dialog_dest_dir[FAT32_MAX_PATH]; + char dialog_creation_path[FAT32_MAX_PATH]; + char dialog_move_src[FAT32_MAX_PATH]; // Dropdown menu state bool dropdown_menu_visible; diff --git a/src/kernel/fat32.c b/src/kernel/fat32.c index 263903d..c46f73e 100644 --- a/src/kernel/fat32.c +++ b/src/kernel/fat32.c @@ -4,6 +4,7 @@ #include "disk.h" #include #include +#include "wm.h" #define MAX_FILES 256 @@ -87,14 +88,8 @@ static void fs_strcat(char *dest, const char *src) { fs_strcpy(dest, src); } -static bool fs_ends_with(const char *str, const char *suffix) { - int str_len = fs_strlen(str); - int suffix_len = fs_strlen(suffix); - if (suffix_len > str_len) return false; - return fs_strcmp(str + str_len - suffix_len, suffix) == 0; -} -static bool fs_starts_with(const char *str, const char *prefix) { +bool fs_starts_with(const char *str, const char *prefix) { while (*prefix) { if (*prefix++ != *str++) return false; } @@ -147,8 +142,6 @@ static char parse_drive_from_path(const char **path_ptr) { // Normalize path (remove .., ., etc) void fat32_normalize_path(const char *path, char *normalized) { - - char temp[FAT32_MAX_PATH]; int temp_len = 0; const char *p = path; @@ -167,9 +160,9 @@ void fat32_normalize_path(const char *path, char *normalized) { while (p[i]) { while (p[i] == '/') i++; if (!p[i]) break; - char component[256]; + char component[FAT32_MAX_FILENAME]; int j = 0; - while (p[i] && p[i] != '/' && j < 255) { + while (p[i] && p[i] != '/' && j < (FAT32_MAX_FILENAME - 1)) { component[j++] = p[i++]; } component[j] = 0; @@ -183,12 +176,15 @@ void fat32_normalize_path(const char *path, char *normalized) { temp[temp_len] = 0; } } else { - if (temp[temp_len - 1] != '/') { - temp[temp_len++] = '/'; - temp[temp_len] = 0; + int comp_len = fs_strlen(component); + if (temp_len + comp_len + 2 < FAT32_MAX_PATH) { + if (temp[temp_len - 1] != '/') { + temp[temp_len++] = '/'; + temp[temp_len] = 0; + } + fs_strcat(temp, component); + temp_len = fs_strlen(temp); } - fs_strcat(temp, component); - temp_len = fs_strlen(temp); } } if (temp_len > 1 && temp[temp_len - 1] == '/') temp[--temp_len] = 0; @@ -368,6 +364,7 @@ static int ramfs_write(FAT32_FileHandle *handle, const void *buffer, int size) { break; } } + wm_notify_fs_change(); return bytes_written; } @@ -1137,12 +1134,30 @@ static int realfs_list_directory(char drive, const char *path, FAT32_FileInfo *e // === Public API (Dispatch) === void fat32_init(void) { + // Explicitly zero out all structures for RAMFS safety + for (int i = 0; i < MAX_FILES; i++) { + files[i].used = false; + files[i].full_path[0] = 0; + files[i].filename[0] = 0; + files[i].parent_path[0] = 0; + files[i].size = 0; + files[i].attributes = 0; + files[i].start_cluster = 0; + } + // Initialize FAT table for RAMFS for (int i = 0; i < MAX_CLUSTERS; i++) { fat_table[i] = 0; } fat_table[0] = 0xFFFFFFF8; fat_table[1] = 0xFFFFFFFF; + + // Zero out cluster data + for (int i = 0; i < MAX_CLUSTERS; i++) { + for (int j = 0; j < FAT32_CLUSTER_SIZE; j++) { + cluster_data[i][j] = 0; + } + } // Create root directory entry for RAMFS FileEntry *root = ramfs_find_free_entry(); @@ -1353,6 +1368,7 @@ bool fat32_mkdir(const char *path) { entry->size = 0; entry->attributes = ATTR_DIRECTORY; + wm_notify_fs_change(); asm volatile("push %0; popfq" : : "r"(rflags)); return true; } @@ -1372,6 +1388,7 @@ bool fat32_rmdir(const char *path) { } entry->used = false; + wm_notify_fs_change(); asm volatile("push %0; popfq" : : "r"(rflags)); return true; } @@ -1397,6 +1414,7 @@ bool fat32_delete(const char *path) { } entry->used = false; + wm_notify_fs_change(); result = true; } else { // Real FAT32 deletion @@ -1445,7 +1463,7 @@ bool fat32_rename(const char *old_path, const char *new_path) { // Check destination if (ramfs_find_file(new_path)) { asm volatile("push %0; popfq" : : "r"(rflags)); return false; } - int old_len = fs_strlen(old_path); + size_t old_len = fs_strlen(old_path); // Logic from original rename... for (int i = 0; i < MAX_FILES; i++) { if (!files[i].used) continue; @@ -1472,6 +1490,7 @@ bool fat32_rename(const char *old_path, const char *new_path) { fs_strcat(files[i].parent_path, suffix); } } + wm_notify_fs_change(); asm volatile("push %0; popfq" : : "r"(rflags)); return true; } @@ -1516,16 +1535,14 @@ int fat32_list_directory(const char *path, FAT32_FileInfo *entries, int max_entr if (drive == 'A') { char normalized[FAT32_MAX_PATH]; fat32_normalize_path(p, normalized); - FileEntry *dir = ramfs_find_file(normalized); - if (dir && (dir->attributes & ATTR_DIRECTORY)) { - for (int i = 0; i < MAX_FILES && count < max_entries; i++) { - if (files[i].used && fs_strcmp(files[i].parent_path, normalized) == 0) { - fs_strcpy(entries[count].name, files[i].filename); - entries[count].size = files[i].size; - entries[count].is_directory = (files[i].attributes & ATTR_DIRECTORY) != 0; - entries[count].start_cluster = files[i].start_cluster; - count++; - } + + for (int i = 0; i < MAX_FILES && count < max_entries; i++) { + if (files[i].used && fs_strcmp(files[i].parent_path, normalized) == 0) { + fs_strcpy(entries[count].name, files[i].filename); + entries[count].size = files[i].size; + entries[count].is_directory = (files[i].attributes & ATTR_DIRECTORY) != 0; + entries[count].start_cluster = files[i].start_cluster; + count++; } } } else { diff --git a/src/kernel/fat32.h b/src/kernel/fat32.h index 5837b90..a130654 100644 --- a/src/kernel/fat32.h +++ b/src/kernel/fat32.h @@ -129,6 +129,7 @@ char fat32_get_current_drive(void); // Utilities void fat32_normalize_path(const char *path, char *normalized); +bool fs_starts_with(const char *str, const char *prefix); // Desktop Limit void fat32_set_desktop_limit(int limit); diff --git a/src/kernel/main.c b/src/kernel/main.c index 0c41312..362aa76 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -75,6 +75,19 @@ void serial_write(const char *str) { } } +void serial_write_num(uint32_t n) { + if (n >= 10) serial_write_num(n / 10); + while ((inb(0x3F8 + 5) & 0x20) == 0); + outb(0x3F8, '0' + (n % 10)); +} + +void serial_write_hex(uint64_t n) { + char *hex = "0123456789ABCDEF"; + if (n >= 16) serial_write_hex(n / 16); + while ((inb(0x3F8 + 5) & 0x20) == 0); + outb(0x3F8, hex[n % 16]); +} + // Kernel Entry Point void kmain(void) { init_serial(); @@ -82,12 +95,39 @@ void kmain(void) { platform_init(); serial_write("[DEBUG] platform_init OK\n"); + + extern uint64_t hhdm_offset; + extern uint64_t kernel_phys_base; + extern uint64_t kernel_virt_base; + + serial_write("[DEBUG] HHDM Offset: 0x"); + serial_write_hex(hhdm_offset); + serial_write("\n"); + serial_write("[DEBUG] Kernel Phys: 0x"); + serial_write_hex(kernel_phys_base); + serial_write("\n"); + serial_write("[DEBUG] Kernel Virt: 0x"); + serial_write_hex(kernel_virt_base); + serial_write("\n"); uint64_t heap_phys_addr = 0; size_t heap_size = 0; if (memmap_request.response != NULL) { + serial_write("[DEBUG] Memory Map entries: "); + serial_write_num(memmap_request.response->entry_count); + serial_write("\n"); for (uint64_t i = 0; i < memmap_request.response->entry_count; i++) { struct limine_memmap_entry *entry = memmap_request.response->entries[i]; + serial_write("[DEBUG] Map entry "); + serial_write_num(i); + serial_write(": base="); + serial_write_hex(entry->base); + serial_write(" len="); + serial_write_hex(entry->length); + serial_write(" type="); + serial_write_num(entry->type); + serial_write("\n"); + if (entry->type == LIMINE_MEMMAP_USABLE) { if (entry->length > heap_size) { heap_size = entry->length; @@ -100,10 +140,15 @@ void kmain(void) { if (heap_size > 512 * 1024 * 1024) heap_size = 512 * 1024 * 1024; if (heap_phys_addr != 0) { + serial_write("[DEBUG] Selected heap base (Phys): 0x"); + serial_write_hex(heap_phys_addr); + serial_write(", Size: "); + serial_write_num(heap_size / 1024 / 1024); + serial_write(" MB\n"); memory_manager_init_at((void*)p2v(heap_phys_addr), heap_size); serial_write("[DEBUG] memory_manager_init OK\n"); } else { - serial_write("[DEBUG] ERROR: No usable memory for heap!\n"); + serial_write("[DEBUG] ERROR: No usable memory for heap! Check Limine memmap.\n"); hcf(); } @@ -135,26 +180,51 @@ void kmain(void) { serial_write("[DEBUG] Skipping user mode test, proceeding with normal boot.\n"); fat32_init(); - if (module_request.response != NULL) { + serial_write("[DEBUG] fat32_init OK\n"); + fat32_mkdir("/bin"); + serial_write("[DEBUG] /bin directory created/checked\n"); + + if (module_request.response == NULL) { + serial_write("[DEBUG] ERROR: Limine Module Response is NULL!\n"); + } else { + serial_write("[DEBUG] Limine Module Response found. Count: "); + serial_write_num(module_request.response->module_count); + serial_write("\n"); for (uint64_t i = 0; i < module_request.response->module_count; i++) { struct limine_file *mod = module_request.response->modules[i]; - FAT32_FileHandle *fh = fat32_open(mod->path, "w"); + serial_write("[DEBUG] Found module: "); + serial_write(mod->path); + serial_write(" adr=0x"); + serial_write_hex((uint64_t)mod->address); + serial_write(" size="); + serial_write_num(mod->size); + serial_write("\n"); + + const char *clean_path = mod->path; + // Strip boot():/ or boot:/// prefixes common in different Limine versions + if (fs_starts_with(clean_path, "boot():")) clean_path += 7; + else if (fs_starts_with(clean_path, "boot:///")) clean_path += 8; + + serial_write("[DEBUG] Stripped module path: "); + serial_write(clean_path); + serial_write("\n"); + + FAT32_FileHandle *fh = fat32_open(clean_path, "w"); if (fh && fh->valid) { - fat32_write(fh, mod->address, mod->size); + int written = fat32_write(fh, mod->address, mod->size); fat32_close(fh); - serial_write("[DEBUG] Limine Module loaded into RAMFS: "); - serial_write(mod->path); + serial_write("[DEBUG] Module successfully copied to RAMFS. Written bytes: "); + serial_write_num(written); + serial_write("\n"); + } else { + serial_write("[DEBUG] ERROR: Failed to create file in RAMFS for module: "); + serial_write(clean_path); serial_write("\n"); } } } - int ENABLE_USER_TEST = 1; - #ifdef ENABLE_USER_TEST - process_init(); - #endif - asm("cli"); ps2_init(); asm("sti"); diff --git a/src/kernel/platform.c b/src/kernel/platform.c index a6caac0..81eb213 100644 --- a/src/kernel/platform.c +++ b/src/kernel/platform.c @@ -11,9 +11,9 @@ static volatile struct limine_kernel_address_request kernel_addr_request __attri .revision = 0, .response = NULL }; -static uint64_t hhdm_offset = 0; -static uint64_t kernel_phys_base = 0; -static uint64_t kernel_virt_base = 0; +uint64_t hhdm_offset = 0; +uint64_t kernel_phys_base = 0; +uint64_t kernel_virt_base = 0; void platform_init(void) { if (hhdm_request.response) { hhdm_offset = hhdm_request.response->offset; } if (kernel_addr_request.response) { diff --git a/src/kernel/wm.c b/src/kernel/wm.c index ece8c02..1999743 100644 --- a/src/kernel/wm.c +++ b/src/kernel/wm.c @@ -61,7 +61,7 @@ static int drag_offset_y = 0; // File Dragging State bool is_dragging_file = false; -static char drag_file_path[256]; +static char drag_file_path[FAT32_MAX_PATH]; static int drag_icon_type = 0; static int drag_start_x = 0; static int drag_start_y = 0; @@ -83,6 +83,8 @@ static bool cursor_visible = true; static int last_cursor_x = 400; static int last_cursor_y = 300; +static bool periodic_refresh_pending = false; + // --- Desktop State --- #define MAX_DESKTOP_ICONS 32 typedef struct { @@ -509,7 +511,7 @@ void draw_elf_icon(int x, int y, const char *label) { #define THUMB_CACHE_SIZE 8 #define THUMB_PIXELS (48 * 48) static struct { - char path[256]; + char path[FAT32_MAX_PATH]; uint32_t pixels[THUMB_PIXELS]; bool valid; bool failed; // Mark as failed so we don't retry @@ -518,7 +520,7 @@ static int thumb_cache_next = 0; // Round-robin eviction // Deferred Thumbnail Request Queue #define THUMB_QUEUE_SIZE 16 -static char thumb_request_queue[THUMB_QUEUE_SIZE][256]; +static char thumb_request_queue[THUMB_QUEUE_SIZE][FAT32_MAX_PATH]; static int thumb_queue_head = 0; static int thumb_queue_tail = 0; @@ -2318,6 +2320,15 @@ void wm_handle_key(char c) { } void wm_process_input(void) { + if (periodic_refresh_pending) { + if (!is_dragging && !is_dragging_file) { + refresh_desktop_icons(); + explorer_refresh_all(); + force_redraw = true; + } + periodic_refresh_pending = false; + } + uint64_t rflags; asm volatile("pushfq; pop %0; cli" : "=r"(rflags)); while (key_head != key_tail) { @@ -2399,17 +2410,9 @@ void wm_timer_tick(void) { timer_ticks++; if (!is_dragging && !is_dragging_file) { - desktop_refresh_timer++; - if (desktop_refresh_timer >= 300) { - refresh_desktop_icons(); - explorer_refresh_all(); - desktop_refresh_timer = 0; - force_redraw = true; - } + // Periodic refresh removed - now triggered by FS events } - - static uint8_t last_second = 0xFF; outb(0x70, 0x00); @@ -2432,3 +2435,7 @@ void wm_timer_tick(void) { graphics_clear_dirty(); } } + +void wm_notify_fs_change(void) { + periodic_refresh_pending = true; +} diff --git a/src/kernel/wm.h b/src/kernel/wm.h index bb7bfaa..e651938 100644 --- a/src/kernel/wm.h +++ b/src/kernel/wm.h @@ -79,6 +79,7 @@ void wm_timer_tick(void); uint32_t wm_get_ticks(void); int wm_get_desktop_icon_count(void); void wm_show_message(const char *title, const char *message); +void wm_notify_fs_change(void); // Hook for external rendering (e.g. VM overlay) extern void (*wm_custom_paint_hook)(void);