luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

kernel.c (44108B)


      1 /* Simple Kernel - Just boot and print message */
      2 #include <stdint.h>
      3 #include <stdlib.h>
      4 #include <stdio.h>
      5 #include <string.h>
      6 #include "terminal.h"
      7 #include "tss.h"
      8 #include "idt.h"
      9 #include "paging.h"
     10 #include "lua.h"
     11 #include "lualib.h"
     12 #include "lauxlib.h"
     13 #include "ramdisk.h"
     14 #include "splash.h"
     15 #include "vesa.h"
     16 #include "mouse.h"
     17 #include "usb.h"
     18 #include "keyboard.h"
     19 #include "decoder.h"
     20 #include "decoder_BMP.h"
     21 #include "decoder_PNG.h"
     22 #include "decoder_JPEG.h"
     23 #include "screen_config.h"
     24 #include "ata.h"
     25 #include "fde.h"
     26 #include "partition.h"
     27 #include "fat16.h"
     28 
     29 /* External function from boot.s */
     30 extern void enter_usermode(void (*entry_point)(void));
     31 
     32 /* External crypto initialization function */
     33 extern int luaopen_crypto(lua_State *L);
     34 
     35 /* External ATA initialization function */
     36 extern int luaopen_ata(lua_State *L);
     37 
     38 /* External FDE initialization function */
     39 extern int luaopen_fde(lua_State *L);
     40 
     41 /* External DiskFS initialization functions */
     42 extern void diskfs_init(void);
     43 extern int luaopen_diskfs(lua_State *L);
     44 
     45 /* External partition initialization function */
     46 extern int luaopen_partition(lua_State *L);
     47 
     48 /* External FAT16 initialization function */
     49 extern int luaopen_fat16(lua_State *L);
     50 
     51 /* External GRUB installation function */
     52 extern int luaopen_grub(lua_State *L);
     53 
     54 /* External JPEG encoder function */
     55 extern int luaopen_jpegencoder(lua_State *L);
     56 
     57 /* External FDE contexts array (defined in fde.c) */
     58 extern fde_context_t fde_contexts[4];
     59 
     60 /* Embedded packed ramdisk */
     61 extern char _binary_packed_bin_start[];
     62 extern char _binary_packed_bin_end[];
     63 
     64 /* Global Lua state for keyboard input callback */
     65 static lua_State* g_lua_state = NULL;
     66 
     67 /* Screen buffer for double buffering */
     68 static uint8_t screen_buffer[DEFAULT_SCREEN_WIDTH * DEFAULT_SCREEN_HEIGHT * (DEFAULT_SCREEN_BPP / 8)] __attribute__((aligned(4096)));
     69 static uint8_t* framebuffer_ptr = NULL;
     70 
     71 /* ============================================================================
     72  * Early Boot Password Prompt for FDE
     73  * ========================================================================= */
     74 
     75 /* Keyboard ports for polling */
     76 #define BOOT_KBD_DATA_PORT   0x60
     77 #define BOOT_KBD_STATUS_PORT 0x64
     78 
     79 /* US QWERTY scancode to ASCII (lowercase) */
     80 static const char boot_scancode_to_ascii[128] = {
     81     0,  27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
     82     '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
     83     0, /* Ctrl */
     84     'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
     85     0, /* Left shift */
     86     '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
     87     0, /* Right shift */
     88     '*',
     89     0, /* Alt */
     90     ' ', /* Space */
     91     0, /* Caps lock */
     92 };
     93 
     94 /* Shifted characters */
     95 static const char boot_scancode_to_ascii_shift[128] = {
     96     0,  27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b',
     97     '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
     98     0, /* Ctrl */
     99     'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',
    100     0, /* Left shift */
    101     '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?',
    102     0, /* Right shift */
    103     '*',
    104     0, /* Alt */
    105     ' ', /* Space */
    106 };
    107 
    108 #define BOOT_SC_LSHIFT_PRESS   0x2A
    109 #define BOOT_SC_LSHIFT_RELEASE 0xAA
    110 #define BOOT_SC_RSHIFT_PRESS   0x36
    111 #define BOOT_SC_RSHIFT_RELEASE 0xB6
    112 #define BOOT_SC_ENTER          0x1C
    113 #define BOOT_SC_BACKSPACE      0x0E
    114 
    115 static inline uint8_t boot_kbd_read_data(void) {
    116     uint8_t data;
    117     __asm__ volatile ("inb %1, %0" : "=a"(data) : "Nd"((uint16_t)BOOT_KBD_DATA_PORT));
    118     return data;
    119 }
    120 
    121 static inline uint8_t boot_kbd_read_status(void) {
    122     uint8_t status;
    123     __asm__ volatile ("inb %1, %0" : "=a"(status) : "Nd"((uint16_t)BOOT_KBD_STATUS_PORT));
    124     return status;
    125 }
    126 
    127 static inline int boot_kbd_has_data(void) {
    128     return (boot_kbd_read_status() & 0x01) != 0;
    129 }
    130 
    131 /* Global to track if we found and unlocked an encrypted partition */
    132 static int g_encrypted_partition_unlocked = 0;
    133 static uint8_t g_encrypted_bus = 0;
    134 static uint8_t g_encrypted_drive = 0;
    135 static uint32_t g_encrypted_part_start = 0;
    136 
    137 /**
    138  * Prompt for password and read from keyboard (blocking, polling mode)
    139  * Returns password length, stores password in buffer (NOT null-terminated during input)
    140  */
    141 static int boot_read_password(char *buffer, int max_len) {
    142     int len = 0;
    143     int shift_pressed = 0;
    144 
    145     /* Clear any pending keyboard data */
    146     while (boot_kbd_has_data()) {
    147         boot_kbd_read_data();
    148     }
    149 
    150     while (1) {
    151         /* Wait for key */
    152         while (!boot_kbd_has_data()) {
    153             __asm__ volatile ("pause");
    154         }
    155 
    156         uint8_t scancode = boot_kbd_read_data();
    157 
    158         /* Track shift state */
    159         if (scancode == BOOT_SC_LSHIFT_PRESS || scancode == BOOT_SC_RSHIFT_PRESS) {
    160             shift_pressed = 1;
    161             continue;
    162         }
    163         if (scancode == BOOT_SC_LSHIFT_RELEASE || scancode == BOOT_SC_RSHIFT_RELEASE) {
    164             shift_pressed = 0;
    165             continue;
    166         }
    167 
    168         /* Ignore key releases (bit 7 set) */
    169         if (scancode & 0x80) {
    170             continue;
    171         }
    172 
    173         /* Enter key - done */
    174         if (scancode == BOOT_SC_ENTER) {
    175             buffer[len] = '\0';
    176             terminal_writestring("\n");
    177             return len;
    178         }
    179 
    180         /* Backspace */
    181         if (scancode == BOOT_SC_BACKSPACE) {
    182             if (len > 0) {
    183                 len--;
    184                 terminal_writestring("\b \b");  /* Erase asterisk */
    185             }
    186             continue;
    187         }
    188 
    189         /* Convert to ASCII */
    190         char c;
    191         if (shift_pressed) {
    192             c = boot_scancode_to_ascii_shift[scancode];
    193         } else {
    194             c = boot_scancode_to_ascii[scancode];
    195         }
    196 
    197         /* Add printable characters to buffer */
    198         if (c >= 32 && c < 127 && len < max_len - 1) {
    199             buffer[len++] = c;
    200             terminal_writestring("*");  /* Echo asterisk */
    201         }
    202     }
    203 }
    204 
    205 /**
    206  * Check all ATA drives for encrypted partitions and prompt for password
    207  * Returns 1 if an encrypted partition was found and unlocked, 0 otherwise
    208  */
    209 static int boot_check_encrypted_drives(void) {
    210     terminal_writestring("\n[BOOT] Checking for encrypted partitions...\n");
    211 
    212     /* Check drives 0-3 (2 buses x 2 drives) */
    213     for (int bus = 0; bus < 2; bus++) {
    214         for (int drive = 0; drive < 2; drive++) {
    215             ata_drive_info_t *info = ata_get_drive_info(bus, drive);
    216             if (!info || !info->present) {
    217                 continue;
    218             }
    219 
    220             /* Skip non-ATA drives (CD-ROMs etc) - they don't have encrypted partitions */
    221             if (!info->is_ata) {
    222                 continue;
    223             }
    224 
    225             {
    226                 char dbg[100];
    227                 snprintf(dbg, sizeof(dbg), "[BOOT] Found drive %d:%d - %s\n", bus, drive, info->model);
    228                 terminal_writestring(dbg);
    229             }
    230 
    231             /* Check if drive has MBR partition table */
    232             if (!partition_has_mbr(bus, drive)) {
    233                 /* Check if whole disk is FDE formatted */
    234                 if (fde_is_formatted(bus, drive)) {
    235                     terminal_writestring("[BOOT] Found FDE-formatted disk (whole disk)\n");
    236                     terminal_writestring("[BOOT] Press ENTER to unlock (3 sec timeout)...\n");
    237 
    238                     /* Wait for ENTER with timeout */
    239                     int timeout = 300;  /* ~3 seconds */
    240                     int pressed = 0;
    241                     while (timeout > 0) {
    242                         if (boot_kbd_has_data()) {
    243                             uint8_t scancode = boot_kbd_read_data();
    244                             if (scancode == 0x1C) { pressed = 1; break; }  /* Enter */
    245                             if (scancode == 0x01) { break; }  /* ESC - skip */
    246                         }
    247                         for (volatile int d = 0; d < 100000; d++);  /* Short delay */
    248                         timeout--;
    249                     }
    250 
    251                     if (!pressed) {
    252                         terminal_writestring("[BOOT] Skipping encrypted disk\n");
    253                         continue;
    254                     }
    255 
    256                     /* Prompt for password */
    257                     char password[128];
    258                     terminal_writestring("Enter disk password: ");
    259                     int pass_len = boot_read_password(password, sizeof(password));
    260 
    261                     if (pass_len > 0) {
    262                         int result = fde_open(&fde_contexts[bus * 2 + drive], bus, drive,
    263                                              password, pass_len);
    264 
    265                         /* Securely wipe password from memory */
    266                         memset(password, 0, sizeof(password));
    267 
    268                         if (result == FDE_OK) {
    269                             terminal_writestring("[BOOT] Disk unlocked successfully!\n");
    270                             g_encrypted_partition_unlocked = 1;
    271                             g_encrypted_bus = bus;
    272                             g_encrypted_drive = drive;
    273                             g_encrypted_part_start = 0;
    274                             return 1;
    275                         } else {
    276                             terminal_writestring("[BOOT] Failed to unlock disk: ");
    277                             terminal_writestring(fde_error_string(result));
    278                             terminal_writestring("\n");
    279                         }
    280                     }
    281                 }
    282                 continue;
    283             }
    284 
    285             /* Read partition table */
    286             partition_info_t parts[4];
    287             if (partition_read_table(bus, drive, parts) != 0) {
    288                 continue;
    289             }
    290 
    291             /* Look for LuajitOS encrypted partition (type 0x4C) */
    292             for (int p = 0; p < 4; p++) {
    293                 if (!parts[p].exists) continue;
    294 
    295                 if (parts[p].type == PART_TYPE_LUAJITOS) {
    296                     char dbg[100];
    297                     snprintf(dbg, sizeof(dbg), "[BOOT] Found encrypted partition %d at sector %d (%d MB)\n",
    298                              p + 1, (int)parts[p].start_lba, (int)parts[p].size_mb);
    299                     terminal_writestring(dbg);
    300                     terminal_writestring("[BOOT] Press ENTER to unlock (3 sec timeout)...\n");
    301 
    302                     /* Wait for ENTER with timeout */
    303                     int timeout = 300;  /* ~3 seconds */
    304                     int pressed = 0;
    305                     while (timeout > 0) {
    306                         if (boot_kbd_has_data()) {
    307                             uint8_t scancode = boot_kbd_read_data();
    308                             if (scancode == 0x1C) { pressed = 1; break; }  /* Enter */
    309                             if (scancode == 0x01) { break; }  /* ESC - skip */
    310                         }
    311                         for (volatile int d = 0; d < 100000; d++);  /* Short delay */
    312                         timeout--;
    313                     }
    314 
    315                     if (!pressed) {
    316                         terminal_writestring("[BOOT] Skipping encrypted partition\n");
    317                         continue;
    318                     }
    319 
    320                     /* Prompt for password */
    321                     char password[128];
    322                     terminal_writestring("Enter disk password: ");
    323                     int pass_len = boot_read_password(password, sizeof(password));
    324 
    325                     if (pass_len > 0) {
    326                         int result = fde_open_partition(&fde_contexts[bus * 2 + drive],
    327                                                         bus, drive, parts[p].start_lba,
    328                                                         password, pass_len);
    329 
    330                         /* Securely wipe password from memory */
    331                         memset(password, 0, sizeof(password));
    332 
    333                         if (result == FDE_OK) {
    334                             terminal_writestring("[BOOT] Partition unlocked successfully!\n");
    335                             g_encrypted_partition_unlocked = 1;
    336                             g_encrypted_bus = bus;
    337                             g_encrypted_drive = drive;
    338                             g_encrypted_part_start = parts[p].start_lba;
    339                             return 1;
    340                         } else {
    341                             terminal_writestring("[BOOT] Failed to unlock partition: ");
    342                             terminal_writestring(fde_error_string(result));
    343                             terminal_writestring("\n");
    344                         }
    345                     }
    346                 }
    347             }
    348         }
    349     }
    350 
    351     terminal_writestring("[BOOT] No encrypted partitions found or unlocked\n");
    352     return 0;
    353 }
    354 
    355 /* ============================================================================
    356  * End Early Boot Password Prompt
    357  * ========================================================================= */
    358 
    359 /* Helper to convert uint to string */
    360 static void uint_to_str(uint32_t val, char* buf) {
    361     if (val == 0) {
    362         buf[0] = '0';
    363         buf[1] = '\0';
    364         return;
    365     }
    366 
    367     char temp[16];
    368     int i = 0;
    369     while (val > 0) {
    370         temp[i++] = '0' + (val % 10);
    371         val /= 10;
    372     }
    373 
    374     int j = 0;
    375     while (i > 0) {
    376         buf[j++] = temp[--i];
    377     }
    378     buf[j] = '\0';
    379 }
    380 
    381 /* Lua allocator function (reserved for future use) */
    382 __attribute__((unused))
    383 static void* lua_allocator(void* ud, void* ptr, size_t osize, size_t nsize) {
    384     (void)ud;
    385     (void)osize;
    386 
    387     if (nsize == 0) {
    388         free(ptr);
    389         return NULL;
    390     } else {
    391         return realloc(ptr, nsize);
    392     }
    393 }
    394 
    395 /* Simple delay function */
    396 static void simple_delay(void) {
    397     for (volatile int i = 0; i < 100000000; i++) {
    398         /* Just loop */
    399     }
    400 }
    401 
    402 /* Lua osprint function */
    403 static int lua_osprint(lua_State* L) {
    404     const char* str = luaL_checkstring(L, 1);
    405     terminal_writestring(str);
    406     return 0;
    407 }
    408 
    409 /* Keyboard input callback - called from keyboard interrupt handler */
    410 void keyboard_input_callback(const char* key, uint8_t scancode) {
    411     if (!g_lua_state) {
    412         return;
    413     }
    414 
    415     lua_State* L = g_lua_state;
    416 
    417     /* Try to call sys.sendInput if available */
    418     lua_getglobal(L, "sys");
    419     if (lua_istable(L, -1)) {
    420         lua_getfield(L, -1, "sendInput");
    421         if (lua_isfunction(L, -1)) {
    422             /* Call sys.sendInput(key, scancode) */
    423             lua_pushstring(L, key);
    424             lua_pushinteger(L, scancode);
    425             if (lua_pcall(L, 2, 0, 0) != 0) {
    426                 /* Error calling sendInput */
    427                 terminal_writestring("[KB] Error in sendInput: ");
    428                 const char* err = lua_tostring(L, -1);
    429                 if (err) terminal_writestring(err);
    430                 terminal_writestring("\n");
    431                 lua_pop(L, 1);
    432             }
    433             lua_pop(L, 1);  /* Pop sys */
    434             return;
    435         } else {
    436             lua_pop(L, 1);  /* Pop non-function */
    437         }
    438     }
    439     lua_pop(L, 1);  /* Pop sys or non-table */
    440 
    441     /* Fallback: if sys.sendInput doesn't exist, use old direct method */
    442     terminal_writestring("[KB] sys.sendInput not found, using fallback\n");
    443 
    444     /* Check if we're in prompt mode */
    445     lua_getglobal(L, "sys");
    446     if (lua_istable(L, -1)) {
    447         lua_getfield(L, -1, "promptMode");
    448         if (lua_istable(L, -1)) {
    449             lua_getfield(L, -1, "active");
    450             int promptModeActive = lua_toboolean(L, -1);
    451             lua_pop(L, 1);  /* Pop active */
    452 
    453             if (promptModeActive) {
    454                 /* In prompt mode - get the prompt window */
    455                 lua_getfield(L, -1, "window");
    456                 if (lua_istable(L, -1)) {
    457                     /* Use the prompt window instead of window_stack */
    458                     /* Get the onInput field from prompt window */
    459                     lua_getfield(L, -1, "onInput");
    460                     if (lua_isfunction(L, -1)) {
    461                         /* Call onInput(key, scancode) */
    462                         lua_pushstring(L, key);
    463                         lua_pushinteger(L, scancode);
    464                         if (lua_pcall(L, 2, 0, 0) != 0) {
    465                             terminal_writestring("[KB] Prompt onInput error: ");
    466                             const char* err = lua_tostring(L, -1);
    467                             if (err) terminal_writestring(err);
    468                             terminal_writestring("\n");
    469                             lua_pop(L, 1);
    470                         }
    471                     } else {
    472                         lua_pop(L, 1);  /* Pop non-function */
    473                     }
    474                     lua_pop(L, 1);  /* Pop window */
    475                     lua_pop(L, 1);  /* Pop promptMode */
    476                     lua_pop(L, 1);  /* Pop sys */
    477                     return;  /* Don't process normal window input */
    478                 } else {
    479                     lua_pop(L, 1);  /* Pop non-table window */
    480                 }
    481             }
    482             lua_pop(L, 1);  /* Pop promptMode */
    483         } else {
    484             lua_pop(L, 1);  /* Pop non-table */
    485         }
    486         lua_pop(L, 1);  /* Pop sys */
    487     } else {
    488         lua_pop(L, 1);  /* Pop non-table */
    489     }
    490 
    491     /* Get the active window (last window in _G.window_stack) */
    492     lua_getglobal(L, "window_stack");
    493     if (!lua_istable(L, -1)) {
    494         /* window_stack doesn't exist yet (init.lua hasn't run) */
    495         terminal_writestring("[KB] window_stack not a table\n");
    496         lua_pop(L, 1);
    497         return;
    498     }
    499 
    500     /* Get the table length */
    501     size_t stack_len = lua_objlen(L, -1);
    502     if (stack_len == 0) {
    503         /* No windows in stack yet */
    504         terminal_writestring("[KB] window_stack empty\n");
    505         lua_pop(L, 1);
    506         return;
    507     }
    508 
    509     /* Iterate backwards to find a window with onInput (skip windows without onInput) */
    510     int found_window = 0;
    511     for (int i = stack_len; i >= 1; i--) {
    512         /* Get window at index i */
    513         lua_rawgeti(L, -1, i);
    514         if (!lua_istable(L, -1)) {
    515             /* Not a valid window, skip */
    516             lua_pop(L, 1);
    517             continue;
    518         }
    519 
    520         /* Check if window is a background window (non-focusable) */
    521         lua_getfield(L, -1, "isBackground");
    522         if (lua_toboolean(L, -1)) {
    523             /* Background window, skip it */
    524             lua_pop(L, 2);  /* Pop isBackground and window */
    525             continue;
    526         }
    527         lua_pop(L, 1);  /* Pop isBackground */
    528 
    529         /* Check if window has onInput */
    530         lua_getfield(L, -1, "onInput");
    531         if (lua_isfunction(L, -1)) {
    532             /* Found a window with onInput! */
    533             found_window = 1;
    534             break;
    535         }
    536 
    537         /* No onInput, pop it and window, try next */
    538         lua_pop(L, 2);
    539     }
    540 
    541     if (!found_window) {
    542         /* No window with onInput found */
    543         terminal_writestring("[KB] No window with onInput\n");
    544         lua_pop(L, 1);  /* Pop window_stack */
    545         return;
    546     }
    547 
    548     /* Call onInput(key, scancode) */
    549     terminal_writestring("[KB] Calling callback\n");
    550     lua_pushstring(L, key);
    551     lua_pushinteger(L, scancode);
    552     if (lua_pcall(L, 2, 0, 0) != 0) {
    553         /* Error calling onInput */
    554         terminal_writestring("[KB] Error: ");
    555         const char* err = lua_tostring(L, -1);
    556         if (err) terminal_writestring(err);
    557         terminal_writestring("\n");
    558         lua_pop(L, 1);
    559     }
    560 
    561     lua_pop(L, 2);  /* Pop window table and window_stack */
    562 }
    563 
    564 /* Recursive directory listing from C */
    565 static void list_dir_recursive(lua_State* L, ramdisk_node_t* node, const char* path, int indent) {
    566     ramdisk_dir_list_t* list = ramdisk_list_dir(node);
    567     if (!list) return;
    568 
    569     for (uint32_t i = 0; i < list->count; i++) {
    570         /* Print indentation */
    571         for (int j = 0; j < indent; j++) {
    572             lua_getglobal(L, "osprint");
    573             lua_pushstring(L, "  ");
    574             lua_call(L, 1, 0);
    575         }
    576 
    577         /* Print type and name via Lua */
    578         lua_getglobal(L, "osprint");
    579         lua_pushstring(L, list->types[i] == RAMDISK_DIR ? "[DIR]  " : "[FILE] ");
    580         lua_call(L, 1, 0);
    581 
    582         lua_getglobal(L, "osprint");
    583         lua_pushstring(L, list->names[i]);
    584         lua_call(L, 1, 0);
    585 
    586         lua_getglobal(L, "osprint");
    587         lua_pushstring(L, "\n");
    588         lua_call(L, 1, 0);
    589 
    590         /* Recurse into directories */
    591         if (list->types[i] == RAMDISK_DIR) {
    592             char new_path[256];
    593             if (path[0] == '/' && path[1] == '\0') {
    594                 snprintf(new_path, sizeof(new_path), "/%s", list->names[i]);
    595             } else {
    596                 snprintf(new_path, sizeof(new_path), "%s/%s", path, list->names[i]);
    597             }
    598 
    599             ramdisk_node_t* child = ramdisk_traverse(node, list->names[i]);
    600             if (child) {
    601                 list_dir_recursive(L, child, new_path, indent + 1);
    602             }
    603         }
    604     }
    605 
    606     ramdisk_free_dir_list(list);
    607 }
    608 
    609 // Port I/O functions (you need these for bare metal)
    610 static inline uint8_t inb(uint16_t port) {
    611     uint8_t ret;
    612     __asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
    613     return ret;
    614 }
    615 
    616 void wait_for_vblank(void) {
    617 
    618     // Wait until we're NOT in vertical retrace (if we're currently in one)
    619     while (inb(0x3DA) & 0x08);
    620 
    621     // Wait until vertical retrace starts
    622     while (!(inb(0x3DA) & 0x08));
    623 
    624 }
    625 
    626 /* Lua wrapper for wait_for_vblank */
    627 static int lua_wait_for_vblank(lua_State* L) {
    628     (void)L;  /* Unused parameter */
    629     wait_for_vblank();
    630     return 0;
    631 }
    632 
    633 /* Copy framebuffer to screen buffer */
    634 void copy_framebuffer_to_buffer(void) {
    635     if (framebuffer_ptr) {
    636         memcpy(screen_buffer, framebuffer_ptr, DEFAULT_SCREEN_WIDTH * DEFAULT_SCREEN_HEIGHT * (DEFAULT_SCREEN_BPP / 8));
    637     }
    638 }
    639 
    640 /* Copy screen buffer to framebuffer with VBlank sync */
    641 void copy_buffer_to_framebuffer(void) {
    642     if (framebuffer_ptr) {
    643         // Wait for VBlank before copying to minimize tearing
    644         wait_for_vblank();
    645         memcpy(framebuffer_ptr, screen_buffer, DEFAULT_SCREEN_WIDTH * DEFAULT_SCREEN_HEIGHT * (DEFAULT_SCREEN_BPP / 8));
    646     }
    647 }
    648 
    649 /* Initialize framebuffer pointer from VESA state */
    650 void init_screen_buffer(void) {
    651     framebuffer_ptr = vesa_state.framebuffer;
    652 }
    653 
    654 /* Get screen buffer pointer for VESA drawing functions */
    655 uint8_t* get_screen_buffer_ptr(void) {
    656     return screen_buffer;
    657 }
    658 
    659 /* Lua wrapper for copy_framebuffer_to_buffer */
    660 static int lua_copy_framebuffer_to_buffer(lua_State* L) {
    661     (void)L;  /* Unused parameter */
    662     copy_framebuffer_to_buffer();
    663     return 0;
    664 }
    665 
    666 /* Lua wrapper for copy_buffer_to_framebuffer - skips cursor region if provided */
    667 static int lua_copy_buffer_to_framebuffer(lua_State* L) {
    668     /* Check if cursor region is provided to skip */
    669     if (lua_gettop(L) >= 4) {
    670         int cx = luaL_checkinteger(L, 1);
    671         int cy = luaL_checkinteger(L, 2);
    672         int cw = luaL_checkinteger(L, 3);
    673         int ch = luaL_checkinteger(L, 4);
    674 
    675         if (framebuffer_ptr) {
    676             wait_for_vblank();
    677 
    678             int screen_w = DEFAULT_SCREEN_WIDTH;
    679             int screen_h = DEFAULT_SCREEN_HEIGHT;
    680             int bpp = DEFAULT_SCREEN_BPP / 8;
    681 
    682             /* Clamp cursor region to screen */
    683             int cx1 = cx < 0 ? 0 : cx;
    684             int cy1 = cy < 0 ? 0 : cy;
    685             int cx2 = (cx + cw) > screen_w ? screen_w : (cx + cw);
    686             int cy2 = (cy + ch) > screen_h ? screen_h : (cy + ch);
    687 
    688             /* Copy row by row, skipping cursor region */
    689             for (int y = 0; y < screen_h; y++) {
    690                 uint8_t* src_row = screen_buffer + y * screen_w * bpp;
    691                 uint8_t* dst_row = framebuffer_ptr + y * screen_w * bpp;
    692 
    693                 if (y < cy1 || y >= cy2) {
    694                     /* Row is outside cursor Y range - copy entire row */
    695                     memcpy(dst_row, src_row, screen_w * bpp);
    696                 } else {
    697                     /* Row intersects cursor - copy left part, skip cursor, copy right part */
    698                     if (cx1 > 0) {
    699                         memcpy(dst_row, src_row, cx1 * bpp);
    700                     }
    701                     if (cx2 < screen_w) {
    702                         memcpy(dst_row + cx2 * bpp, src_row + cx2 * bpp, (screen_w - cx2) * bpp);
    703                     }
    704                 }
    705             }
    706         }
    707     } else {
    708         /* No cursor region - copy everything */
    709         copy_buffer_to_framebuffer();
    710     }
    711     return 0;
    712 }
    713 
    714 /* Lua wrapper to get screen buffer pointer (for direct manipulation) */
    715 static int lua_get_screen_buffer(lua_State* L) {
    716     lua_pushlightuserdata(L, screen_buffer);
    717     return 1;
    718 }
    719 
    720 int main_loop() {
    721     if (!g_lua_state) return 0;
    722 
    723     lua_State* L = g_lua_state;
    724 
    725     wait_for_vblank();
    726 
    727     // Call MainDraw() if it exists
    728     lua_getglobal(L, "MainDraw");
    729     if (lua_isfunction(L, -1)) {
    730         if (lua_pcall(L, 0, 0, 0) != 0) {
    731             // Error calling MainDraw
    732             const char* err = lua_tostring(L, -1);
    733             if (err) {
    734                 terminal_writestring("ERROR in MainDraw: ");
    735                 terminal_writestring(err);
    736                 terminal_writestring("\n");
    737             }
    738             lua_pop(L, 1);
    739             return 0;  // Stop loop on error
    740         }
    741     } else {
    742         lua_pop(L, 1);
    743     }
    744 
    745     return 1;  // Continue loop
    746 }
    747 
    748 
    749 /* Function that runs in usermode */
    750 void usermode_function(void) {
    751     /* Set up user mode data segments */
    752     __asm__ volatile (
    753         "mov $0x23, %%ax\n"     /* User data segment (0x20 | RPL 3) */
    754         "mov %%ax, %%ds\n"
    755         "mov %%ax, %%es\n"
    756         "mov $0x33, %%ax\n"     /* User TLS segment for FS (0x30 | RPL 3) */
    757         "mov %%ax, %%fs\n"
    758         "mov $0x3B, %%ax\n"     /* User TLS segment for GS (0x38 | RPL 3) */
    759         "mov %%ax, %%gs\n"
    760         : : : "ax"
    761     );
    762 
    763     terminal_writestring("entered usermode\n");
    764     terminal_writestring("Creating LuaJIT state...\n");
    765 
    766     /* Create Lua state with default allocator */
    767     lua_State* L = luaL_newstate();
    768 
    769     if (!L) {
    770         terminal_writestring("ERROR: Failed to create Lua state\n");
    771         while(1) __asm__ volatile ("hlt");
    772     }
    773 
    774     /* Store global Lua state for keyboard callback */
    775     g_lua_state = L;
    776 
    777     terminal_writestring("LuaJIT state created successfully!\n");
    778 
    779     /* Load standard libraries */
    780     terminal_writestring("Loading Lua standard libraries...\n");
    781     luaL_openlibs(L);
    782     terminal_writestring("Standard libraries loaded!\n");
    783     terminal_writestring("JIT compiler is enabled!\n");
    784 
    785     /* Initialize crypto library */
    786     terminal_writestring("Initializing crypto library...\n");
    787     luaopen_crypto(L);
    788     lua_setglobal(L, "crypto");
    789     terminal_writestring("Crypto library loaded!\n");
    790 
    791     /* Initialize ATA driver and Lua bindings */
    792     terminal_writestring("Initializing ATA driver...\n");
    793     ata_init();  /* Detect drives */
    794     luaopen_ata(L);
    795     lua_setglobal(L, "ata");
    796     terminal_writestring("ATA driver loaded!\n");
    797 
    798     /* Initialize FDE (Full Disk Encryption) module */
    799     terminal_writestring("Initializing FDE module...\n");
    800     luaopen_fde(L);
    801     lua_setglobal(L, "fde");
    802     terminal_writestring("FDE module loaded!\n");
    803 
    804     /* Check for encrypted partitions and prompt for password (before diskfs init) */
    805     boot_check_encrypted_drives();
    806 
    807     /* Initialize DiskFS module */
    808     terminal_writestring("Initializing DiskFS module...\n");
    809     diskfs_init();
    810     luaopen_diskfs(L);
    811     lua_setglobal(L, "diskfs");
    812     terminal_writestring("DiskFS module loaded!\n");
    813 
    814     /* Initialize partition module */
    815     terminal_writestring("Initializing partition module...\n");
    816     luaopen_partition(L);
    817     lua_setglobal(L, "partition");
    818     terminal_writestring("Partition module loaded!\n");
    819 
    820     /* Initialize FAT16 module */
    821     terminal_writestring("Initializing FAT16 module...\n");
    822     luaopen_fat16(L);
    823     lua_setglobal(L, "fat16");
    824     terminal_writestring("FAT16 module loaded!\n");
    825 
    826     /* Initialize GRUB module */
    827     terminal_writestring("Initializing GRUB module...\n");
    828     luaopen_grub(L);
    829     lua_setglobal(L, "grub");
    830     terminal_writestring("GRUB module loaded!\n");
    831 
    832     /* Initialize JPEG encoder module */
    833     terminal_writestring("Initializing JPEG encoder...\n");
    834     luaopen_jpegencoder(L);
    835     terminal_writestring("JPEG encoder loaded!\n");
    836 
    837     /* Register C ramdisk functions */
    838     terminal_writestring("Registering ramdisk functions...\n");
    839     lua_pushcfunction(L, lua_ramdisk_open);
    840     lua_setglobal(L, "CRamdiskOpen");
    841 
    842     lua_pushcfunction(L, lua_ramdisk_read);
    843     lua_setglobal(L, "CRamdiskRead");
    844 
    845     lua_pushcfunction(L, lua_ramdisk_write);
    846     lua_setglobal(L, "CRamdiskWrite");
    847 
    848     lua_pushcfunction(L, lua_ramdisk_close);
    849     lua_setglobal(L, "CRamdiskClose");
    850 
    851     lua_pushcfunction(L, lua_ramdisk_list);
    852     lua_setglobal(L, "CRamdiskList");
    853 
    854     lua_pushcfunction(L, lua_ramdisk_exists);
    855     lua_setglobal(L, "CRamdiskExists");
    856 
    857     lua_pushcfunction(L, lua_ramdisk_mkdir);
    858     lua_setglobal(L, "CRamdiskMkdir");
    859 
    860     lua_pushcfunction(L, lua_wait_for_vblank);
    861     lua_setglobal(L, "WaitForVBlank");
    862 
    863     terminal_writestring("Ramdisk functions registered\n");
    864 
    865     /* Register VESA functions */
    866     terminal_writestring("Registering VESA functions...\n");
    867     lua_pushcfunction(L, lua_vesa_init);
    868     lua_setglobal(L, "VESAInit");
    869 
    870     lua_pushcfunction(L, lua_vesa_set_mode);
    871     lua_setglobal(L, "VESASetMode");
    872 
    873     lua_pushcfunction(L, lua_vesa_clear_screen);
    874     lua_setglobal(L, "VESAClearScreen");
    875 
    876     lua_pushcfunction(L, lua_vesa_set_pixel);
    877     lua_setglobal(L, "VESASetPixel");
    878 
    879     lua_pushcfunction(L, lua_vesa_draw_rect);
    880     lua_setglobal(L, "VESADrawRect");
    881 
    882     lua_pushcfunction(L, lua_vesa_get_mode_info);
    883     lua_setglobal(L, "VESAGetModeInfo");
    884 
    885     lua_pushcfunction(L, lua_vesa_list_modes);
    886     lua_setglobal(L, "VESAListModes");
    887 
    888     lua_pushcfunction(L, lua_vesa_draw_text);
    889     lua_setglobal(L, "VESADrawText");
    890 
    891     lua_pushcfunction(L, lua_vesa_move_region);
    892     lua_setglobal(L, "VESAMoveRegion");
    893 
    894     lua_pushcfunction(L, lua_vesa_set_double_buffer_mode);
    895     lua_setglobal(L, "VESASetDoubleBufferMode");
    896 
    897     lua_pushcfunction(L, lua_copy_framebuffer_to_buffer);
    898     lua_setglobal(L, "VESACopyFramebufferToBuffer");
    899 
    900     lua_pushcfunction(L, lua_copy_buffer_to_framebuffer);
    901     lua_setglobal(L, "VESACopyBufferToFramebuffer");
    902 
    903     lua_pushcfunction(L, lua_get_screen_buffer);
    904     lua_setglobal(L, "VESAGetScreenBuffer");
    905 
    906     lua_pushcfunction(L, lua_vesa_process_buffered_draw_ops);
    907     lua_setglobal(L, "VESAProcessBufferedDrawOps");
    908 
    909     lua_pushcfunction(L, lua_vesa_create_window_buffer);
    910     lua_setglobal(L, "VESACreateWindowBuffer");
    911 
    912     lua_pushcfunction(L, lua_vesa_free_window_buffer);
    913     lua_setglobal(L, "VESAFreeWindowBuffer");
    914 
    915     lua_pushcfunction(L, lua_vesa_blit_window_buffer);
    916     lua_setglobal(L, "VESABlitWindowBuffer");
    917 
    918     lua_pushcfunction(L, lua_vesa_blit_window_buffer_region);
    919     lua_setglobal(L, "VESABlitWindowBufferRegion");
    920 
    921     extern int lua_vesa_blit_cursor(lua_State* L);
    922     lua_pushcfunction(L, lua_vesa_blit_cursor);
    923     lua_setglobal(L, "VESABlitCursor");
    924 
    925     extern int lua_vesa_cache_cursor(lua_State* L);
    926     lua_pushcfunction(L, lua_vesa_cache_cursor);
    927     lua_setglobal(L, "VESACacheCursor");
    928 
    929     extern int lua_vesa_draw_cursor(lua_State* L);
    930     lua_pushcfunction(L, lua_vesa_draw_cursor);
    931     lua_setglobal(L, "VESADrawCursor");
    932 
    933     extern int lua_vesa_move_cursor(lua_State* L);
    934     lua_pushcfunction(L, lua_vesa_move_cursor);
    935     lua_setglobal(L, "VESAMoveCursor");
    936 
    937     extern int lua_vesa_restore_cursor(lua_State* L);
    938     lua_pushcfunction(L, lua_vesa_restore_cursor);
    939     lua_setglobal(L, "VESARestoreCursor");
    940 
    941     lua_pushcfunction(L, lua_vesa_set_render_target);
    942     lua_setglobal(L, "VESASetRenderTarget");
    943 
    944     lua_pushcfunction(L, lua_vesa_inspect_buffer);
    945     lua_setglobal(L, "VESAInspectBuffer");
    946 
    947     /* Register screen configuration constants */
    948     lua_pushinteger(L, DEFAULT_SCREEN_WIDTH);
    949     lua_setglobal(L, "DEFAULT_SCREEN_WIDTH");
    950 
    951     lua_pushinteger(L, DEFAULT_SCREEN_HEIGHT);
    952     lua_setglobal(L, "DEFAULT_SCREEN_HEIGHT");
    953 
    954     lua_pushinteger(L, DEFAULT_SCREEN_BPP);
    955     lua_setglobal(L, "DEFAULT_SCREEN_BPP");
    956 
    957     terminal_writestring("VESA functions registered\n");
    958 
    959     /* Register mouse functions */
    960     terminal_writestring("Registering mouse functions...\n");
    961     lua_pushcfunction(L, lua_mouse_get_state);
    962     lua_setglobal(L, "MouseGetState");
    963 
    964     /* Register USB mouse functions */
    965     lua_pushcfunction(L, lua_usb_mouse_poll);
    966     lua_setglobal(L, "USBMousePoll");
    967 
    968     terminal_writestring("Mouse functions registered\n");
    969 
    970     /* Initialize C ramdisk and load packed data */
    971     terminal_writestring("Loading C ramdisk from packed data...\n");
    972     c_ramdisk_root = ramdisk_create_root();
    973     if (!c_ramdisk_root) {
    974         terminal_writestring("ERROR: Failed to create C ramdisk root\n");
    975         lua_close(L);
    976         while(1) __asm__ volatile ("hlt");
    977     }
    978 
    979     /* Load packed ramdisk data */
    980     size_t packed_size = _binary_packed_bin_end - _binary_packed_bin_start;
    981     terminal_writestring("Packed ramdisk size: ");
    982     char size_str[16];
    983     uint_to_str(packed_size, size_str);
    984     terminal_writestring(size_str);
    985     terminal_writestring(" bytes\n");
    986 
    987     int entries_loaded = ramdisk_load_packed(c_ramdisk_root, (uint8_t*)_binary_packed_bin_start, packed_size);
    988     if (entries_loaded < 0) {
    989         terminal_writestring("ERROR: Failed to load packed ramdisk\n");
    990         lua_close(L);
    991         while(1) __asm__ volatile ("hlt");
    992     }
    993 
    994     terminal_writestring("Loaded ");
    995     uint_to_str(entries_loaded, size_str);
    996     terminal_writestring(size_str);
    997     terminal_writestring(" entries from packed ramdisk\n");
    998 
    999     /* Display splash screen */
   1000     terminal_writestring("\n=== Displaying Splash Screen ===\n");
   1001     int splash_result = splash_show_from_file("/os/public/res/splash.bmp", SPLASH_DURATION_MS);
   1002     if (splash_result != 0) {
   1003         terminal_writestring("WARNING: Failed to display splash screen, continuing...\n");
   1004     }
   1005     terminal_writestring("=== Splash Screen Complete ===\n\n");
   1006 
   1007     /* Create fsRoot table in Lua */
   1008     terminal_writestring("Creating fsRoot table...\n");
   1009     lua_newtable(L);
   1010 
   1011     /* Add traverse function */
   1012     lua_pushstring(L, "traverse");
   1013     lua_pushlightuserdata(L, c_ramdisk_root);  /* Store root as upvalue */
   1014     lua_pushcclosure(L, lua_ramdisk_find, 1);
   1015     lua_settable(L, -3);
   1016 
   1017     /* Set as global fsRoot */
   1018     lua_setglobal(L, "fsRoot");
   1019     terminal_writestring("fsRoot table created\n");
   1020 
   1021     /* Register osprint function for Lua */
   1022     terminal_writestring("Registering osprint function...\n");
   1023     lua_pushcfunction(L, lua_osprint);
   1024     lua_setglobal(L, "osprint");
   1025 
   1026     /* Register image decoder functions */
   1027     terminal_writestring("Registering image decoder functions...\n");
   1028     lua_pushcfunction(L, lua_bmp_load);
   1029     lua_setglobal(L, "BMPLoad");
   1030 
   1031     /* lua_bmp_save and lua_png_save are commented out in decoder files */
   1032     // lua_pushcfunction(L, lua_bmp_save);
   1033     // lua_setglobal(L, "BMPSave");
   1034 
   1035     lua_pushcfunction(L, lua_png_load);
   1036     lua_setglobal(L, "PNGLoad");
   1037 
   1038     lua_pushcfunction(L, lua_jpeg_load);
   1039     lua_setglobal(L, "JPEGLoad");
   1040 
   1041     // lua_pushcfunction(L, lua_png_save);
   1042     // lua_setglobal(L, "PNGSave");
   1043 
   1044     lua_pushcfunction(L, lua_image_draw);
   1045     lua_setglobal(L, "ImageDraw");
   1046 
   1047     lua_pushcfunction(L, lua_image_draw_scaled);
   1048     lua_setglobal(L, "ImageDrawScaled");
   1049 
   1050     lua_pushcfunction(L, lua_image_get_info);
   1051     lua_setglobal(L, "ImageGetInfo");
   1052 
   1053     lua_pushcfunction(L, lua_image_destroy);
   1054     lua_setglobal(L, "ImageDestroy");
   1055 
   1056     lua_pushcfunction(L, lua_image_rotate);
   1057     lua_setglobal(L, "ImageRotate");
   1058 
   1059     lua_pushcfunction(L, lua_image_get_width);
   1060     lua_setglobal(L, "ImageGetWidth");
   1061 
   1062     lua_pushcfunction(L, lua_image_get_height);
   1063     lua_setglobal(L, "ImageGetHeight");
   1064 
   1065     lua_pushcfunction(L, lua_image_get_pixel);
   1066     lua_setglobal(L, "ImageGetPixel");
   1067 
   1068     extern int lua_image_get_buffer_bgra(lua_State* L);
   1069     lua_pushcfunction(L, lua_image_get_buffer_bgra);
   1070     lua_setglobal(L, "ImageGetBufferBGRA");
   1071 
   1072     /* Buffer drawing functions for Image library */
   1073     extern int lua_buffer_create(lua_State* L);
   1074     lua_pushcfunction(L, lua_buffer_create);
   1075     lua_setglobal(L, "BufferCreate");
   1076 
   1077     extern int lua_buffer_set_pixel(lua_State* L);
   1078     lua_pushcfunction(L, lua_buffer_set_pixel);
   1079     lua_setglobal(L, "BufferSetPixel");
   1080 
   1081     extern int lua_buffer_fill_circle(lua_State* L);
   1082     lua_pushcfunction(L, lua_buffer_fill_circle);
   1083     lua_setglobal(L, "BufferFillCircle");
   1084 
   1085     extern int lua_buffer_draw_line(lua_State* L);
   1086     lua_pushcfunction(L, lua_buffer_draw_line);
   1087     lua_setglobal(L, "BufferDrawLine");
   1088 
   1089     extern int lua_buffer_fill_rect(lua_State* L);
   1090     lua_pushcfunction(L, lua_buffer_fill_rect);
   1091     lua_setglobal(L, "BufferFillRect");
   1092 
   1093     extern int lua_buffer_fill(lua_State* L);
   1094     lua_pushcfunction(L, lua_buffer_fill);
   1095     lua_setglobal(L, "BufferFill");
   1096 
   1097     extern int lua_buffer_blit_row(lua_State* L);
   1098     lua_pushcfunction(L, lua_buffer_blit_row);
   1099     lua_setglobal(L, "BufferBlitRow");
   1100 
   1101     /* ImageBuffer - mutable userdata buffer for efficient drawing */
   1102     extern void lua_imagebuffer_register(lua_State* L);
   1103     lua_imagebuffer_register(L);
   1104 
   1105     extern int lua_imagebuffer_new(lua_State* L);
   1106     lua_pushcfunction(L, lua_imagebuffer_new);
   1107     lua_setglobal(L, "ImageBufferNew");
   1108 
   1109     /* Test simple Lua execution first */
   1110     terminal_writestring("Testing simple Lua expression...\n");
   1111     const char* simple_test = "osprint('Simple test works!\\n')";
   1112     int simple_result = luaL_dostring(L, simple_test);
   1113     if (simple_result != 0) {
   1114         terminal_writestring("ERROR: Simple test failed!\n");
   1115         const char* err = lua_tostring(L, -1);
   1116         if (err) terminal_writestring(err);
   1117         terminal_writestring("\n");
   1118     }
   1119 
   1120 
   1121     /* Load and run init.lua from ramdisk */
   1122     terminal_writestring("\n=== Loading init.lua ===\n");
   1123 
   1124     /* Read init.lua from ramdisk */
   1125     ramdisk_node_t* init_node = ramdisk_traverse(c_ramdisk_root, "os");
   1126     if (init_node) {
   1127         init_node = ramdisk_traverse(init_node, "init.lua");
   1128     }
   1129 
   1130     if (!init_node) {
   1131         terminal_writestring("ERROR: Could not find /os/init.lua in ramdisk\n");
   1132     } else {
   1133         terminal_writestring("Found init.lua, loading...\n");
   1134 
   1135         /* Verify it's a file */
   1136         if (init_node->type != RAMDISK_FILE) {
   1137             terminal_writestring("ERROR: /os/init.lua is not a file\n");
   1138         } else {
   1139             /* Get the file size */
   1140             uint32_t init_size = init_node->file.size;
   1141             terminal_writestring("init.lua size: ");
   1142             char size_buf[16];
   1143             uint_to_str(init_size, size_buf);
   1144             terminal_writestring(size_buf);
   1145             terminal_writestring(" bytes\n");
   1146 
   1147             /* Execute init.lua */
   1148             int init_result = luaL_loadbuffer(L, (const char*)init_node->file.data, init_size, "/os/init.lua");
   1149             if (init_result != 0) {
   1150                 terminal_writestring("ERROR: Failed to load init.lua: ");
   1151                 const char* err = lua_tostring(L, -1);
   1152                 if (err) terminal_writestring(err);
   1153                 terminal_writestring("\n");
   1154             } else {
   1155                 terminal_writestring("Executing init.lua...\n");
   1156                 int exec_result = lua_pcall(L, 0, 0, 0);
   1157                 if (exec_result != 0) {
   1158                     terminal_writestring("ERROR: Failed to execute init.lua: ");
   1159                     const char* err = lua_tostring(L, -1);
   1160                     if (err) terminal_writestring(err);
   1161                     terminal_writestring("\n");
   1162                 } else {
   1163                     terminal_writestring("init.lua executed successfully!\n");
   1164 
   1165                     while (main_loop()) { }
   1166                 }
   1167             }
   1168         }
   1169     }
   1170 
   1171     terminal_writestring("\n=== Boot Complete ===\n");
   1172     terminal_writestring("\nUsermode finished!\n");
   1173 
   1174     /* Note: We don't call lua_close(L) here because it can cause issues
   1175      * when trying to free memory in usermode. In a real OS, we would
   1176      * properly exit the process here. For now, just loop forever. */
   1177 
   1178     /* Infinite loop - pause to reduce CPU usage */
   1179     terminal_writestring("System halted. Loop forever...\n");
   1180     while(1) {
   1181         /* Just spin - hlt can cause GPF in usermode even with IOPL=3 */
   1182         for (volatile int i = 0; i < 10000000; i++);
   1183     }
   1184 }
   1185 
   1186 /* Kernel main (runs in ring 0) */
   1187 void kernel_main(void) {
   1188     terminal_initialize();
   1189     terminal_writestring("KERNEL RUNNING!\n");
   1190 
   1191     /* Enable FPU and SSE for LuaJIT */
   1192     terminal_writestring("Enabling FPU and SSE...\n");
   1193     __asm__ volatile (
   1194         /* Enable FPU */
   1195         "mov %%cr0, %%eax\n"
   1196         "and $0xFFFB, %%ax\n"      /* Clear EM bit (emulation) */
   1197         "or $0x2, %%ax\n"          /* Set MP bit (monitor coprocessor) */
   1198         "mov %%eax, %%cr0\n"
   1199         "fninit\n"                  /* Initialize FPU */
   1200 
   1201         /* Enable SSE (OSFXSR and OSXMMEXCPT in CR4) */
   1202         "mov %%cr4, %%eax\n"
   1203         "or $0x600, %%eax\n"       /* Set bits 9 and 10 (OSFXSR and OSXMMEXCPT) */
   1204         "mov %%eax, %%cr4\n"
   1205         : : : "eax"
   1206     );
   1207     terminal_writestring("FPU and SSE enabled!\n");
   1208 
   1209     /* Initialize paging for proper memory management */
   1210     paging_init();
   1211 
   1212     /* Install TSS (required for privilege level changes) */
   1213     tss_install();
   1214 
   1215     /* Install IDT for system calls and exception handlers */
   1216     idt_install();
   1217 
   1218     /* Remap PIC (Programmable Interrupt Controller) */
   1219     terminal_writestring("Remapping PIC...\n");
   1220     /* ICW1: Initialize PIC in cascade mode */
   1221     __asm__ volatile ("outb %0, $0x20" : : "a"((uint8_t)0x11));  /* Master PIC command */
   1222     __asm__ volatile ("outb %0, $0xA0" : : "a"((uint8_t)0x11));  /* Slave PIC command */
   1223 
   1224     /* ICW2: Set interrupt vector offsets */
   1225     __asm__ volatile ("outb %0, $0x21" : : "a"((uint8_t)0x20));  /* Master PIC: IRQ0-7 → INT 0x20-0x27 */
   1226     __asm__ volatile ("outb %0, $0xA1" : : "a"((uint8_t)0x28));  /* Slave PIC: IRQ8-15 → INT 0x28-0x2F */
   1227 
   1228     /* ICW3: Configure cascade */
   1229     __asm__ volatile ("outb %0, $0x21" : : "a"((uint8_t)0x04));  /* Master: slave on IRQ2 */
   1230     __asm__ volatile ("outb %0, $0xA1" : : "a"((uint8_t)0x02));  /* Slave: cascade identity */
   1231 
   1232     /* ICW4: Set 8086 mode */
   1233     __asm__ volatile ("outb %0, $0x21" : : "a"((uint8_t)0x01));  /* Master */
   1234     __asm__ volatile ("outb %0, $0xA1" : : "a"((uint8_t)0x01));  /* Slave */
   1235 
   1236     /* Mask all interrupts initially */
   1237     __asm__ volatile ("outb %0, $0x21" : : "a"((uint8_t)0xFF));  /* Master mask */
   1238     __asm__ volatile ("outb %0, $0xA1" : : "a"((uint8_t)0xFF));  /* Slave mask */
   1239     terminal_writestring("PIC remapped!\n");
   1240 
   1241     /* Initialize PS/2 mouse */
   1242     mouse_init();
   1243 
   1244     /* Initialize USB subsystem */
   1245     if (usb_init() == 0) {
   1246         terminal_writestring("USB initialized successfully\n");
   1247         usb_enumerate_devices();
   1248         usb_mouse_init();
   1249     } else {
   1250         terminal_writestring("USB initialization failed, continuing without USB\n");
   1251     }
   1252 
   1253     /* Initialize keyboard */
   1254     keyboard_init();
   1255 
   1256     /* Unmask IRQ1 (keyboard) in master PIC */
   1257     uint8_t mask;
   1258     __asm__ volatile ("inb $0x21, %0" : "=a"(mask));
   1259     mask &= ~0x02;  /* Clear bit 1 to unmask IRQ1 */
   1260     mask &= ~0x04;  /* Clear bit 2 to unmask IRQ2 (cascade from slave PIC) */
   1261     __asm__ volatile ("outb %0, $0x21" : : "a"(mask));
   1262 
   1263     /* Unmask IRQ12 (mouse) in slave PIC */
   1264     uint8_t slave_mask;
   1265     __asm__ volatile ("inb $0xA1, %0" : "=a"(slave_mask));
   1266     slave_mask &= ~0x10;  /* Clear bit 4 to unmask IRQ12 */
   1267     __asm__ volatile ("outb %0, $0xA1" : : "a"(slave_mask));
   1268 
   1269     /* Enable interrupts globally */
   1270     __asm__ volatile ("sti");
   1271 
   1272     terminal_writestring("Waiting 5 seconds...\n");
   1273 
   1274     /* Wait ~5 seconds */
   1275     for (int i = 0; i < 5; i++) {
   1276         simple_delay();
   1277         terminal_writestring(".");
   1278     }
   1279 
   1280     terminal_writestring("\nKernel finished!\n");
   1281     terminal_writestring("Switching to usermode...\n");
   1282 
   1283     /* Use the proper enter_usermode function from boot.s */
   1284     enter_usermode(usermode_function);
   1285 
   1286     /* Should never reach here */
   1287     terminal_writestring("ERROR: enter_usermode returned!\n");
   1288     while(1) __asm__ volatile ("hlt");
   1289 }