FEAT: Verbose boot

This commit is contained in:
boreddevnl 2026-04-13 12:17:39 +02:00
parent a27b2c6423
commit e4603792b6
16 changed files with 296 additions and 87 deletions

95
src/core/kconsole.c Normal file
View file

@ -0,0 +1,95 @@
#include "kconsole.h"
#include "graphics.h"
#include "sys/spinlock.h"
#include <stddef.h>
static spinlock_t console_lock = SPINLOCK_INIT;
static int cursor_x = 0;
static int cursor_y = 0;
static bool kconsole_active = false;
static uint32_t text_color = 0xFFFFFFFF; // White
#define CHAR_WIDTH 8
#define CHAR_HEIGHT 10
void kconsole_init(void) {
cursor_x = 10;
cursor_y = 10;
kconsole_active = true;
// Initial clear screen during boot
graphics_clear_back_buffer(0x00000000);
graphics_mark_screen_dirty();
graphics_flip_buffer();
}
void kconsole_set_active(bool active) {
kconsole_active = active;
}
void kconsole_set_color(uint32_t color) {
uint64_t flags = spinlock_acquire_irqsave(&console_lock);
text_color = color;
spinlock_release_irqrestore(&console_lock, flags);
}
static void kconsole_scroll(void) {
if (cursor_y + CHAR_HEIGHT >= get_screen_height() - 10) {
graphics_scroll_back_buffer(CHAR_HEIGHT);
cursor_y -= CHAR_HEIGHT;
graphics_mark_screen_dirty();
graphics_flip_buffer();
}
}
static void kconsole_putc_nolock(char c) {
if (!kconsole_active) return;
if (c == '\n') {
cursor_x = 10;
cursor_y += CHAR_HEIGHT;
kconsole_scroll();
graphics_flip_buffer();
return;
}
if (c == '\r') {
cursor_x = 10;
return;
}
if (c == '\t') {
cursor_x += CHAR_WIDTH * 4;
return;
}
// Draw character
draw_char_bitmap(cursor_x, cursor_y, c, text_color);
graphics_mark_screen_dirty();
cursor_x += CHAR_WIDTH;
if (cursor_x + CHAR_WIDTH >= get_screen_width() - 10) {
cursor_x = 10;
cursor_y += CHAR_HEIGHT;
kconsole_scroll();
}
}
void kconsole_putc(char c) {
uint64_t flags = spinlock_acquire_irqsave(&console_lock);
kconsole_putc_nolock(c);
spinlock_release_irqrestore(&console_lock, flags);
}
void kconsole_write(const char *s) {
if (!s) return;
uint64_t flags = spinlock_acquire_irqsave(&console_lock);
while (*s) {
kconsole_putc_nolock(*s++);
}
// Flip buffer after a write batch during boot
graphics_flip_buffer();
spinlock_release_irqrestore(&console_lock, flags);
}

13
src/core/kconsole.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef KCONSOLE_H
#define KCONSOLE_H
#include <stdint.h>
#include <stdbool.h>
void kconsole_init(void);
void kconsole_set_color(uint32_t color);
void kconsole_putc(char c);
void kconsole_write(const char *s);
void kconsole_set_active(bool active);
#endif // KCONSOLE_H

View file

@ -18,6 +18,7 @@
#include "fat32.h"
#include "tar.h"
#include "vfs.h"
#include "core/kconsole.h"
#include "memory_manager.h"
#include "platform.h"
#include "wallpaper.h"
@ -91,26 +92,70 @@ static void init_serial() {
outb(0x3F8 + 4, 0x0B);
}
static spinlock_t serial_lock = SPINLOCK_INIT;
void serial_write(const char *str) {
while (*str) {
uint64_t flags = spinlock_acquire_irqsave(&serial_lock);
const char *p = str;
while (*p) {
char c = *p++;
while ((inb(0x3F8 + 5) & 0x20) == 0);
outb(0x3F8, *str++);
outb(0x3F8, c);
}
kconsole_write(str);
spinlock_release_irqrestore(&serial_lock, flags);
}
static void serial_write_num_locked(uint32_t n) {
if (n >= 10) serial_write_num_locked(n / 10);
char c = '0' + (n % 10);
while ((inb(0x3F8 + 5) & 0x20) == 0);
outb(0x3F8, c);
kconsole_putc(c);
}
void serial_write_num(uint32_t n) {
if (n >= 10) serial_write_num(n / 10);
uint64_t flags = spinlock_acquire_irqsave(&serial_lock);
serial_write_num_locked(n);
spinlock_release_irqrestore(&serial_lock, flags);
}
static void serial_write_hex_locked(uint64_t n) {
char *hex = "0123456789ABCDEF";
if (n >= 16) serial_write_hex_locked(n / 16);
char c = hex[n % 16];
while ((inb(0x3F8 + 5) & 0x20) == 0);
outb(0x3F8, '0' + (n % 10));
outb(0x3F8, c);
kconsole_putc(c);
}
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]);
uint64_t flags = spinlock_acquire_irqsave(&serial_lock);
serial_write_hex_locked(n);
spinlock_release_irqrestore(&serial_lock, flags);
}
void log_ok(const char *msg) {
serial_write("[ ");
kconsole_set_color(0xFF00FF00);
serial_write("OK");
kconsole_set_color(0xFFFFFFFF);
serial_write(" ] ");
serial_write(msg);
serial_write("\n");
}
void log_fail(const char *msg) {
serial_write("[ ");
kconsole_set_color(0xFFFF0000);
serial_write("FAIL");
kconsole_set_color(0xFFFFFFFF);
serial_write(" ] ");
serial_write(msg);
serial_write("\n");
}
// Kernel Entry Point
static void fat32_mkdir_recursive(const char *path) {
@ -141,64 +186,65 @@ static void fat32_mkdir_recursive(const char *path) {
void kmain(void) {
init_serial();
vfs_init();
serial_write("\n[DEBUG] Entering kmain...\n");
serial_write("\n");
platform_init();
serial_write("[DEBUG] platform_init OK\n");
log_ok("Platform initialized");
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("[INIT] HHDM Offset: 0x");
serial_write_hex(hhdm_offset);
serial_write("\n");
serial_write("[DEBUG] Kernel Phys: 0x");
serial_write("[INIT] Kernel Phys: 0x");
serial_write_hex(kernel_phys_base);
serial_write("\n");
serial_write("[DEBUG] Kernel Virt: 0x");
serial_write("[INIT] Kernel Virt: 0x");
serial_write_hex(kernel_virt_base);
serial_write("\n");
if (memmap_request.response != NULL) {
// The memory manager will now scan the memory map and manage all usable regions.
memory_manager_init_from_memmap(memmap_request.response);
serial_write("[DEBUG] memory_manager_init OK\n");
smp_init_bsp();
serial_write("[DEBUG] smp_init_bsp OK\n");
} else {
serial_write("[DEBUG] ERROR: No usable memory for heap! Check Limine memmap.\n");
hcf();
}
if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) {
serial_write("[DEBUG] No framebuffer! Halting.\n");
serial_write("[INIT] No framebuffer! Halting.\n");
hcf();
}
struct limine_framebuffer *fb = framebuffer_request.response->framebuffers[0];
graphics_init(fb);
serial_write("[DEBUG] graphics_init OK\n");
kconsole_init();
log_ok("Graphics and Console ready");
if (memmap_request.response != NULL) {
// The memory manager will now scan the memory map and manage all usable regions.
memory_manager_init_from_memmap(memmap_request.response);
log_ok("Memory manager ready");
smp_init_bsp();
log_ok("SMP BSP initialized");
} else {
log_fail("No usable memory for heap! Check Limine memmap.");
hcf();
}
gdt_init();
serial_write("[DEBUG] gdt_init OK\n");
log_ok("GDT initialized");
paging_init();
serial_write("[DEBUG] paging_init OK\n");
log_ok("Paging ready");
syscall_init();
serial_write("[DEBUG] syscall_init OK\n");
log_ok("Syscalls ready");
idt_init();
idt_register_interrupts();
idt_load();
serial_write("[DEBUG] idt_init OK\n");
log_ok("IDT ready");
process_init();
fat32_init();
serial_write("[DEBUG] fat32_init OK\n");
log_ok("FAT32 ready");
fat32_mkdir("/bin");
fat32_mkdir("/Library");
fat32_mkdir("/Library/images");
@ -214,11 +260,9 @@ void kmain(void) {
vfs_mount("/proc", "procfs", "procfs", procfs_get_ops(), NULL);
if (module_request.response == NULL) {
serial_write("[DEBUG] ERROR: Limine Module Response is NULL!\n");
log_fail("Limine module response NULL");
} else {
serial_write("[DEBUG] Limine Module Response found. Count: ");
serial_write_num(module_request.response->module_count);
serial_write("\n");
log_ok("Limine modules loaded");
for (uint64_t i = 0; i < module_request.response->module_count; i++) {
struct limine_file *mod = module_request.response->modules[i];
@ -230,7 +274,7 @@ void kmain(void) {
while(clean_path[len]) len++;
if (len >= 4 && clean_path[len-4] == '.' && clean_path[len-3] == 't' && clean_path[len-2] == 'a' && clean_path[len-1] == 'r') {
serial_write("[DEBUG] Parsing TAR initrd: ");
serial_write("[INIT] Parsing TAR initrd: ");
serial_write(clean_path);
serial_write("\n");
tar_parse(mod->address, mod->size);
@ -260,7 +304,7 @@ void kmain(void) {
// Initialize fonts now that FAT32 and modules are loaded
uint64_t current_rsp;
asm volatile("mov %%rsp, %0" : "=r"(current_rsp));
serial_write("[DEBUG] Stack Alignment: 0x");
serial_write("[INIT] Stack Alignment: 0x");
serial_write_hex(current_rsp);
serial_write("\n");
@ -276,11 +320,9 @@ void kmain(void) {
// Initialize SMP
if (smp_request.response != NULL) {
uint32_t online = smp_init(smp_request.response);
serial_write("[DEBUG] SMP init complete, CPUs online: ");
serial_write_num(online);
serial_write("\n");
log_ok("SMP initialized");
} else {
serial_write("[DEBUG] No SMP response from bootloader\n");
serial_write("[INIT] No SMP response from bootloader\n");
smp_init(NULL);
}

View file

@ -21,6 +21,8 @@ static int next_sd_index = 0; // For sda, sdb, sdc...
extern void serial_write(const char *str);
extern void serial_write_num(uint64_t num);
extern void log_ok(const char *msg);
extern void log_fail(const char *msg);
// === String Helpers ===
@ -306,14 +308,16 @@ void disk_register_partition(Disk *parent, uint32_t lba_offset, uint32_t sector_
dm_strcpy(mount_path + 5, part->devname);
if (vfs_mount(mount_path, part->devname, "fat32", fat32_get_realfs_ops(), vol)) {
serial_write("[VFS] Mounted ");
serial_write(mount_path);
serial_write(" to VFS\n");
char ok_msg[64];
dm_strcpy(ok_msg, "Mounted ");
dm_strcpy(ok_msg + 8, mount_path);
log_ok(ok_msg);
wm_notify_fs_change();
} else {
serial_write("[VFS] Failed to mount ");
serial_write(mount_path);
serial_write("\n");
char fail_msg[64];
dm_strcpy(fail_msg, "Failed to mount ");
dm_strcpy(fail_msg + 16, mount_path);
log_fail(fail_msg);
}
}
}
@ -499,7 +503,7 @@ void disk_manager_init(void) {
next_sd_index = 0;
next_drive_letter_idx = 0;
serial_write("[DISK] Disk manager initialized (VFS mode)\n");
log_ok("Disk manager ready");
// NOTE: Ramdisk (A:) is no longer registered here.
// RAMFS is managed directly by fat32.c and mounted at "/" via VFS.
}
@ -509,12 +513,13 @@ void disk_manager_scan(void) {
ahci_init();
if (ahci_get_port_count() == 0) {
serial_write("[DISK] No AHCI ports found, falling back to legacy IDE PIO...\n");
serial_write("[DISK] No AHCI ports found, falling back to legacy IDE...\n");
try_add_ata_drive(ATA_PRIMARY_IO, false, "IDE Primary Master");
try_add_ata_drive(ATA_PRIMARY_IO, true, "IDE Primary Slave");
try_add_ata_drive(ATA_SECONDARY_IO, false, "IDE Secondary Master");
try_add_ata_drive(ATA_SECONDARY_IO, true, "IDE Secondary Slave");
log_ok("IDE probing complete");
} else {
serial_write("[DISK] AHCI initialized successfully, skipping legacy IDE.\n");
log_ok("AHCI ports initialized, skipping IDE");
}
}

View file

@ -189,7 +189,7 @@ void vfs_init(void) {
}
mount_count = 0;
serial_write("[VFS] Virtual File System initialized\n");
serial_write("[VFS] Ready\n");
}
// ===============

View file

@ -479,7 +479,7 @@ void memory_validate(void) {
}
if (errors == 0) {
cmd_write("Memory validation: OK\n");
cmd_write("Memory validation: [OK]\n");
} else {
cmd_write("Memory validation failed with ");
cmd_write_int(errors);

View file

@ -1133,7 +1133,6 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
(cpcb->remote_port == port) &&
ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) &&
ip_addr_cmp(&cpcb->remote_ip, ipaddr)) {
/* linux returns EISCONN here, but ERR_USE should be OK for us */
return ERR_USE;
}
}

View file

@ -88,7 +88,7 @@ int network_init(void) {
ipv4_address_t ip;
network_get_ipv4_address(&ip);
extern void serial_write(const char *str);
serial_write("[NETWORK] IP Assigned: ");
serial_write("[NET] IP Assigned: ");
char buf[32];
k_itoa(ip.bytes[0], buf); serial_write(buf); serial_write(".");
k_itoa(ip.bytes[1], buf); serial_write(buf); serial_write(".");
@ -96,7 +96,7 @@ int network_init(void) {
k_itoa(ip.bytes[3], buf); serial_write(buf); serial_write("\n");
} else {
extern void serial_write(const char *str);
serial_write("[NETWORK] DHCP Failed during init\n");
serial_write("[NET] DHCP Failed during init\n");
}
// Set default DNS server (1.1.1.1)

View file

@ -212,7 +212,7 @@ process_t* process_create_elf(const char* filepath, const char* args_str) {
size_t elf_load_size = 0;
uint64_t entry_point = elf_load(filepath, new_proc->pml4_phys, &elf_load_size);
if (entry_point == 0) {
serial_write("[PROCESS] Failed to load ELF: ");
serial_write("[PROC] Failed to load ELF: ");
serial_write(filepath);
serial_write("\n");
// We technically leak the page table here, but let's ignore cleanup for now
@ -371,7 +371,7 @@ process_t* process_create_elf(const char* filepath, const char* args_str) {
current_process[0]->next = new_proc;
spinlock_release_irqrestore(&runqueue_lock, rflags);
serial_write("[PROCESS] Spawned ELF Executable: ");
serial_write("[PROC] Exec: ");
serial_write(filepath);
serial_write("\n");
return new_proc;

View file

@ -37,10 +37,13 @@ static uint32_t read_lapic_id(void) {
}
uint32_t smp_this_cpu_id(void) {
if (total_cpus <= 1) return 0;
if (total_cpus <= 1 || !cpu_states) return 0;
// Use GS-based self-pointer to get the structure first
cpu_state_t *state;
cpu_state_t *state = NULL;
// Safely check GS:0. If GS is not set or base is 0, this should be handled carefully.
// In BoredOS, if GS is not set, this might still fault depending on address space.
// However, the cpu_states check above covers the most likely early-boot failure.
asm volatile("movq %%gs:0, %0" : "=r"(state) : : "memory");
if (state) return state->cpu_id;

View file

@ -203,12 +203,14 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
if (cmd == GUI_CMD_WINDOW_CREATE) {
extern void serial_write(const char *str);
serial_write("Kernel: GUI_CMD_WINDOW_CREATE\n");
const char *title = (const char *)arg2;
serial_write("[WM] CreateWindow: ");
serial_write(title ? title : "Unknown");
serial_write("\n");
uint64_t *u_params = (uint64_t *)arg3;
if (!u_params) {
serial_write("Kernel: Error - params is NULL\n");
serial_write("[WM] Error - params is NULL\n");
return 0;
}
@ -216,14 +218,14 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
uint64_t params[4];
for (int i = 0; i < 4; i++) params[i] = u_params[i];
serial_write("Kernel: Window params copied.\n");
// params verified
Window *win = kmalloc(sizeof(Window));
if (!win) {
serial_write("Kernel: Error - kmalloc failed for Window\n");
serial_write("[WM] Error - kmalloc failed for Window\n");
return 0;
}
serial_write("Kernel: Window allocated.\n");
// win allocated
extern void mem_memset(void *dest, int val, size_t len);
mem_memset(win, 0, sizeof(Window));
@ -240,11 +242,8 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
kernel_title[i] = title[i];
}
kernel_title[title_len] = '\0';
serial_write("Kernel: Title copied: ");
serial_write(kernel_title);
serial_write("\n");
} else {
serial_write("Kernel: Warning - kernel_title kmalloc failed\n");
serial_write("[WM] Warning: kernel_title kmalloc failed\n");
}
// Basic initialization
@ -254,7 +253,7 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
win->w = (int)params[2];
win->h = (int)params[3];
serial_write("Kernel: Init win dims.\n");
// dims ready
// Sanity checks for dimensions
if (win->w <= 0 || win->w > 4096) win->w = 400;
@ -268,7 +267,7 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
win->font = NULL;
win->lock = SPINLOCK_INIT;
serial_write("Kernel: Dims initialized.\n");
// ready
size_t pixel_size = 0;
// Safe allocation
@ -283,7 +282,7 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
win->comp_pixels = kmalloc(pixel_size);
}
serial_write("Kernel: Buffers allocated.\n");
// buffs ok
if (win->pixels) {
extern void mem_memset(void *dest, int val, size_t len);
@ -294,7 +293,7 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
mem_memset(win->comp_pixels, 0, pixel_size);
}
serial_write("Kernel: Buffers cleared.\n");
serial_write("[WM] Buffers ready\n");
// Set callbacks
win->paint = user_window_paint;
@ -800,7 +799,7 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
Window *win = (Window *)arg2;
if (win) {
extern void serial_write(const char *str);
serial_write("Kernel: Setting window resizable to ");
serial_write("[WM] Resizable: ");
serial_write(arg3 ? "true\n" : "false\n");
win->resizable = (arg3 != 0);
}

View file

@ -239,8 +239,8 @@ int main(int argc, char** argv) {
}
if (strcmp(argv[1], "init") == 0) {
if (sys_network_init() == 0) printf("Network OK\n");
else printf("Network Fail\n");
if (sys_network_init() == 0) printf("Network [OK]\n");
else printf("Network [FAIL]\n");
return 0;
}

View file

@ -7,6 +7,7 @@
#include "io.h"
#include "font_manager.h"
#include "../mem/memory_manager.h"
#include "sys/spinlock.h"
static struct limine_framebuffer *g_fb = NULL;
static uint32_t g_bg_color = 0xFF696969;
@ -25,6 +26,7 @@ static int g_bg_image_h = 0;
static bool g_use_image = false;
static DirtyRect g_dirty = {0, 0, 0, 0, false};
static spinlock_t graphics_lock = SPINLOCK_INIT;
#define MAX_FB_WIDTH 2048
@ -163,15 +165,19 @@ void graphics_mark_dirty(int x, int y, int w, int h) {
return;
}
uint64_t flags = spinlock_acquire_irqsave(&graphics_lock);
merge_dirty_rect(x, y, w, h);
spinlock_release_irqrestore(&graphics_lock, flags);
}
void graphics_mark_screen_dirty(void) {
uint64_t flags = spinlock_acquire_irqsave(&graphics_lock);
g_dirty.x = 0;
g_dirty.y = 0;
g_dirty.w = get_screen_width();
g_dirty.h = get_screen_height();
g_dirty.active = true;
spinlock_release_irqrestore(&graphics_lock, flags);
}
DirtyRect graphics_get_dirty_rect(void) {
@ -179,11 +185,9 @@ DirtyRect graphics_get_dirty_rect(void) {
}
void graphics_clear_dirty(void) {
extern uint64_t wm_lock_acquire(void);
extern void wm_lock_release(uint64_t);
uint64_t rflags = wm_lock_acquire();
uint64_t flags = spinlock_acquire_irqsave(&graphics_lock);
g_dirty.active = false;
wm_lock_release(rflags);
spinlock_release_irqrestore(&graphics_lock, flags);
}
void graphics_clear_dirty_no_lock(void) {
@ -796,12 +800,22 @@ void graphics_clear_back_buffer(uint32_t color) {
}
void graphics_flip_buffer(void) {
if (!g_fb || !g_dirty.active) return;
if (!g_fb) return;
uint64_t flags = spinlock_acquire_irqsave(&graphics_lock);
if (!g_dirty.active) {
spinlock_release_irqrestore(&graphics_lock, flags);
return;
}
int x = g_dirty.x;
int y = g_dirty.y;
int w = g_dirty.w;
int h = g_dirty.h;
// Clear dirty state
g_dirty.active = false;
spinlock_release_irqrestore(&graphics_lock, flags);
if (x < 0) { w += x; x = 0; }
if (y < 0) { h += y; y = 0; }
@ -1021,3 +1035,26 @@ void graphics_blit_buffer(uint32_t *src, int dst_x, int dst_y, int w, int h) {
}
}
}
void graphics_scroll_back_buffer(int lines) {
if (!g_fb || lines <= 0 || lines >= (int)g_fb->height) return;
extern uint64_t wm_lock_acquire(void);
extern void wm_lock_release(uint64_t);
uint64_t rflags = wm_lock_acquire();
int sw = (int)g_fb->width;
int sh = (int)g_fb->height;
for (int y = 0; y < sh - lines; y++) {
uint32_t *dst = &g_back_buffer[y * sw];
uint32_t *src = &g_back_buffer[(y + lines) * sw];
for (int x = 0; x < sw; x++) dst[x] = src[x];
}
for (int y = sh - lines; y < sh; y++) {
uint32_t *dst = &g_back_buffer[y * sw];
for (int x = 0; x < sw; x++) dst[x] = 0;
}
wm_lock_release(rflags);
}

View file

@ -56,6 +56,7 @@ void graphics_clear_dirty_no_lock(void);
// Double buffering
void graphics_flip_buffer(void);
void graphics_clear_back_buffer(uint32_t color);
void graphics_scroll_back_buffer(int lines);
// Clipping
void graphics_set_clipping(int x, int y, int w, int h);

View file

@ -107,7 +107,7 @@ void wallpaper_process_pending(void) {
const char *path = (const char *)pending_wallpaper_path;
pending_wallpaper_path = NULL;
serial_str("[WP] Processing wallpaper: ");
serial_str("[WM] Processing wallpaper: ");
serial_str(path);
serial_str("\n");

View file

@ -21,6 +21,7 @@
#include "disk.h"
#include "../sys/work_queue.h"
#include "../sys/smp.h"
#include "../core/kconsole.h"
// Hello developer,
@ -44,6 +45,8 @@ void wm_lock_release(uint64_t flags) {
}
extern void serial_write(const char *str);
extern void log_ok(const char *msg);
extern void log_fail(const char *msg);
static bool str_eq(const char *s1, const char *s2) {
if (!s1 || !s2) return false;
@ -1919,7 +1922,7 @@ void wm_remove_window(Window *win) {
force_redraw = true;
} else {
wm_lock_release(rflags);
serial_write("WM: Window not found in all_windows list!\n");
log_fail("Window not found in all_windows list!");
return;
}
@ -3096,25 +3099,33 @@ void wm_process_deferred_thumbs(void) {
void wm_init(void) {
disk_manager_init();
log_ok("Disk Manager ready");
disk_manager_scan();
log_ok("Disk scanning complete");
cmd_init();
log_ok("Command CLI ready");
explorer_init();
log_ok("Explorer ready");
wallpaper_init();
log_ok("Wallpaper engine ready");
file_index_init();
log_ok("File Indexer ready");
// Try to load the file index from persistent cache
// If it doesn't exist, queue an async build
if (!file_index_load()) {
// No cache exists - queue async build to background
log_ok("No Index cache, background build started");
work_queue_submit(build_file_index_async, NULL);
} else {
// Cache loaded - mark as ready
log_ok("Index cache loaded");
lumos_index_built = true;
}
refresh_desktop_icons();
log_ok("Desktop icons refreshed");
// Initialize z-indices
win_cmd.z_index = 0;
@ -3131,6 +3142,10 @@ void wm_init(void) {
win_cmd.visible = false;
force_redraw = true;
serial_write("[WM] Initialization complete, transitioning to GUI\n");
kconsole_set_active(false);
graphics_flip_buffer();
}
uint32_t wm_get_ticks(void) {