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 }