luajitos

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

luajit_init.c (38620B)


      1 #include <stdint.h>
      2 #include <stddef.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <ctype.h>
      6 
      7 /* LuaJIT headers */
      8 #include <lua.h>
      9 #include <lualib.h>
     10 #include <lauxlib.h>
     11 
     12 /* Graphics functions */
     13 #include "graphics.h"
     14 #include "vesa.h"
     15 
     16 /* Image decoder functions */
     17 #include "decoder.h"
     18 #include "decoder_BMP.h"
     19 #include "decoder_PNG.h"
     20 #include "decoder_JPEG.h"
     21 #include "compression/compression.h"
     22 #include "ramdisk.h"
     23 
     24 /* External functions and data from boot.s */
     25 extern void enter_usermode(void (*entry_point)(void));
     26 extern void syscall_handler(void);
     27 extern uint8_t tss[104];
     28 extern uint32_t kernel_stack_top;
     29 extern uint64_t gdt_start[];
     30 
     31 /* External exception handlers from exceptions.s */
     32 extern void double_fault_handler(void);
     33 extern void gpf_handler(void);
     34 extern void page_fault_handler(void);
     35 extern void irq12_handler(void);
     36 extern void irq1_handler(void);
     37 
     38 /* Serial port (COM1) */
     39 #define SERIAL_PORT 0x3F8
     40 
     41 /* VGA text mode buffer */
     42 static uint16_t* const VGA_MEMORY = (uint16_t*)0xB8000;
     43 static const size_t VGA_TEXT_WIDTH = 80;
     44 static const size_t VGA_TEXT_HEIGHT = 25;
     45 static size_t terminal_row = 0;
     46 static size_t terminal_column = 0;
     47 static uint8_t terminal_color = 0x0F;
     48 
     49 /* IDT entry structure */
     50 struct idt_entry {
     51     uint16_t offset_low;
     52     uint16_t selector;
     53     uint8_t zero;
     54     uint8_t type_attr;
     55     uint16_t offset_high;
     56 } __attribute__((packed));
     57 
     58 struct idt_ptr {
     59     uint16_t limit;
     60     uint32_t base;
     61 } __attribute__((packed));
     62 
     63 static struct idt_entry idt[256];
     64 static struct idt_ptr idtp;
     65 
     66 /* Serial port functions */
     67 static inline void serial_write(uint8_t data) {
     68     __asm__ volatile ("outb %0, %1" : : "a"(data), "Nd"(SERIAL_PORT));
     69 }
     70 
     71 static void serial_init(void) {
     72     __asm__ volatile ("outb %0, %1" : : "a"((uint8_t)0x00), "Nd"(SERIAL_PORT + 1)); // Disable interrupts
     73     __asm__ volatile ("outb %0, %1" : : "a"((uint8_t)0x80), "Nd"(SERIAL_PORT + 3)); // Enable DLAB
     74     __asm__ volatile ("outb %0, %1" : : "a"((uint8_t)0x03), "Nd"(SERIAL_PORT + 0)); // Set divisor low byte (38400 baud)
     75     __asm__ volatile ("outb %0, %1" : : "a"((uint8_t)0x00), "Nd"(SERIAL_PORT + 1)); // Set divisor high byte
     76     __asm__ volatile ("outb %0, %1" : : "a"((uint8_t)0x03), "Nd"(SERIAL_PORT + 3)); // 8 bits, no parity, one stop bit
     77     __asm__ volatile ("outb %0, %1" : : "a"((uint8_t)0xC7), "Nd"(SERIAL_PORT + 2)); // Enable FIFO
     78     __asm__ volatile ("outb %0, %1" : : "a"((uint8_t)0x0B), "Nd"(SERIAL_PORT + 4)); // IRQs enabled, RTS/DSR set
     79 }
     80 
     81 /* VGA functions */
     82 static inline uint16_t vga_entry(unsigned char uc, uint8_t color) {
     83     return (uint16_t)uc | (uint16_t)color << 8;
     84 }
     85 
     86 void terminal_initialize(void) {
     87     serial_init();
     88     for (size_t y = 0; y < VGA_TEXT_HEIGHT; y++) {
     89         for (size_t x = 0; x < VGA_TEXT_WIDTH; x++) {
     90             VGA_MEMORY[y * VGA_TEXT_WIDTH + x] = vga_entry(' ', terminal_color);
     91         }
     92     }
     93 }
     94 
     95 void terminal_putchar(char c) {
     96     /* Write to serial port */
     97     serial_write((uint8_t)c);
     98 
     99     /* Write to VGA */
    100     if (c == '\n') {
    101         terminal_column = 0;
    102         if (++terminal_row == VGA_TEXT_HEIGHT) {
    103             terminal_row = VGA_TEXT_HEIGHT - 1;
    104             for (size_t y = 0; y < VGA_TEXT_HEIGHT - 1; y++) {
    105                 for (size_t x = 0; x < VGA_TEXT_WIDTH; x++) {
    106                     VGA_MEMORY[y * VGA_TEXT_WIDTH + x] = VGA_MEMORY[(y + 1) * VGA_TEXT_WIDTH + x];
    107                 }
    108             }
    109             for (size_t x = 0; x < VGA_TEXT_WIDTH; x++) {
    110                 VGA_MEMORY[(VGA_TEXT_HEIGHT - 1) * VGA_TEXT_WIDTH + x] = vga_entry(' ', terminal_color);
    111             }
    112         }
    113         return;
    114     }
    115 
    116     VGA_MEMORY[terminal_row * VGA_TEXT_WIDTH + terminal_column] = vga_entry(c, terminal_color);
    117     if (++terminal_column == VGA_TEXT_WIDTH) {
    118         terminal_column = 0;
    119         if (++terminal_row == VGA_TEXT_HEIGHT) {
    120             terminal_row = VGA_TEXT_HEIGHT - 1;
    121         }
    122     }
    123 }
    124 
    125 void terminal_writestring(const char* data) {
    126     while (*data) terminal_putchar(*data++);
    127 }
    128 
    129 void terminal_writeint(int value) {
    130     if (value < 0) {
    131         terminal_putchar('-');
    132         value = -value;
    133     }
    134 
    135     char buffer[16];
    136     int i = 0;
    137 
    138     if (value == 0) {
    139         terminal_putchar('0');
    140         return;
    141     }
    142 
    143     while (value > 0) {
    144         buffer[i++] = '0' + (value % 10);
    145         value /= 10;
    146     }
    147 
    148     while (i > 0) {
    149         terminal_putchar(buffer[--i]);
    150     }
    151 }
    152 
    153 /* Simple delay function */
    154 static void delay(void) {
    155     for (volatile int i = 0; i < 10000000; i++);
    156 }
    157 
    158 /* System calls */
    159 #define SYSCALL_OSPRINT 1
    160 #define SYSCALL_GETRANDOM 2
    161 #define SYSCALL_READ_FILE 3
    162 
    163 /* ===== CSPRNG Implementation ===== */
    164 
    165 /* ChaCha20 state for CSPRNG */
    166 static uint32_t chacha_state[16];
    167 static int rng_initialized = 0;
    168 
    169 /* ChaCha20 quarter round */
    170 #define ROTL32(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
    171 #define QR(a, b, c, d) \
    172     a += b; d ^= a; d = ROTL32(d, 16); \
    173     c += d; b ^= c; b = ROTL32(b, 12); \
    174     a += b; d ^= a; d = ROTL32(d, 8); \
    175     c += d; b ^= c; b = ROTL32(b, 7);
    176 
    177 /* Try to get random number from CPU (RDRAND instruction) */
    178 static inline int rdrand32(uint32_t* value) {
    179     unsigned char ok;
    180     __asm__ volatile (
    181         "rdrand %0; setc %1"
    182         : "=r"(*value), "=qm"(ok)
    183     );
    184     return ok;
    185 }
    186 
    187 /* Try to get random seed from CPU (RDSEED instruction - better for seeding) */
    188 static inline int rdseed32(uint32_t* value) {
    189     unsigned char ok;
    190     __asm__ volatile (
    191         "rdseed %0; setc %1"
    192         : "=r"(*value), "=qm"(ok)
    193     );
    194     return ok;
    195 }
    196 
    197 /* Get CPU timestamp counter for entropy */
    198 static inline uint64_t rdtsc(void) {
    199     uint32_t lo, hi;
    200     __asm__ volatile ("rdtsc" : "=a"(lo), "=d"(hi));
    201     return ((uint64_t)hi << 32) | lo;
    202 }
    203 
    204 /* Check if RDRAND is supported */
    205 static int cpu_has_rdrand(void) {
    206     uint32_t eax, ebx, ecx, edx;
    207     __asm__ volatile (
    208         "cpuid"
    209         : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
    210         : "a"(1), "c"(0)
    211     );
    212     return (ecx & (1 << 30)) != 0;  /* RDRAND is bit 30 of ECX */
    213 }
    214 
    215 /* Read CPU temperature from thermal MSR (if available) */
    216 static uint32_t try_read_cpu_temp(void) {
    217     uint32_t eax, ebx, ecx, edx;
    218 
    219     /* Check if Digital Thermal Sensor is available (CPUID.06H) */
    220     __asm__ volatile (
    221         "cpuid"
    222         : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
    223         : "a"(6), "c"(0)
    224     );
    225 
    226     if (eax & 1) {  /* Digital temperature sensor supported */
    227         uint32_t lo, hi;
    228         /* Read IA32_THERM_STATUS MSR (0x19C) */
    229         __asm__ volatile (
    230             "rdmsr"
    231             : "=a"(lo), "=d"(hi)
    232             : "c"(0x19C)
    233         );
    234         return lo;  /* Lower 32 bits contain temperature reading */
    235     }
    236     return 0;
    237 }
    238 
    239 /* Read CMOS RTC for additional entropy */
    240 static uint32_t read_rtc_entropy(void) {
    241     uint32_t entropy = 0;
    242 
    243     /* Read various CMOS RTC registers for entropy */
    244     /* Port 0x70 = CMOS address, Port 0x71 = CMOS data */
    245     for (int reg = 0; reg < 10; reg++) {
    246         __asm__ volatile ("outb %0, $0x70" : : "a"((uint8_t)reg));
    247         uint8_t val;
    248         __asm__ volatile ("inb $0x71, %0" : "=a"(val));
    249         entropy = (entropy << 3) ^ val;
    250     }
    251 
    252     return entropy;
    253 }
    254 
    255 /* Keyboard functions for entropy collection */
    256 #define KBD_DATA_PORT 0x60
    257 #define KBD_STATUS_PORT 0x64
    258 
    259 static inline uint8_t kbd_read_data(void) {
    260     uint8_t data;
    261     __asm__ volatile ("inb %1, %0" : "=a"(data) : "Nd"((uint16_t)KBD_DATA_PORT));
    262     return data;
    263 }
    264 
    265 static inline uint8_t kbd_read_status(void) {
    266     uint8_t status;
    267     __asm__ volatile ("inb %1, %0" : "=a"(status) : "Nd"((uint16_t)KBD_STATUS_PORT));
    268     return status;
    269 }
    270 
    271 static inline int kbd_has_data(void) {
    272     return (kbd_read_status() & 0x01) != 0;
    273 }
    274 
    275 /* Collect entropy from keyboard timing */
    276 static uint32_t collect_keyboard_entropy(int num_keys) {
    277     uint32_t entropy = 0;
    278     int keys_collected = 0;
    279 
    280     /* Clear any pending keyboard data */
    281     while (kbd_has_data()) {
    282         kbd_read_data();
    283     }
    284 
    285     terminal_writestring("\n=== ENTROPY COLLECTION ===\n");
    286     terminal_writestring("Please press ");
    287 
    288     /* Print number */
    289     char num_str[4];
    290     int idx = 0;
    291     int n = num_keys;
    292     if (n >= 10) {
    293         num_str[idx++] = '0' + (n / 10);
    294         n %= 10;
    295     }
    296     num_str[idx++] = '0' + n;
    297     num_str[idx] = '\0';
    298     terminal_writestring(num_str);
    299 
    300     terminal_writestring(" random keys...\n");
    301 
    302     uint64_t last_tsc = rdtsc();
    303 
    304     while (keys_collected < num_keys) {
    305         if (kbd_has_data()) {
    306             uint8_t scancode = kbd_read_data();
    307 
    308             /* Only count key presses (bit 7 clear), ignore releases */
    309             if ((scancode & 0x80) == 0) {
    310                 uint64_t current_tsc = rdtsc();
    311                 uint64_t delta = current_tsc - last_tsc;
    312 
    313                 /* Mix in scancode, timing delta, and current TSC */
    314                 entropy ^= scancode;
    315                 entropy = (entropy << 7) | (entropy >> 25);  /* Rotate */
    316                 entropy ^= (uint32_t)delta;
    317                 entropy = (entropy << 13) | (entropy >> 19); /* Rotate */
    318                 entropy ^= (uint32_t)(current_tsc ^ (current_tsc >> 32));
    319 
    320                 last_tsc = current_tsc;
    321                 keys_collected++;
    322 
    323                 /* Visual feedback */
    324                 terminal_putchar('.');
    325             }
    326         }
    327     }
    328 
    329     terminal_writestring(" done!\n");
    330     return entropy;
    331 }
    332 
    333 /* Initialize ChaCha20 state with entropy */
    334 static void init_chacha_rng(void) {
    335     int has_rdrand = cpu_has_rdrand();
    336 
    337     /* ChaCha20 constants ("expand 32-byte k") */
    338     chacha_state[0] = 0x61707865;
    339     chacha_state[1] = 0x3320646e;
    340     chacha_state[2] = 0x79622d32;
    341     chacha_state[3] = 0x6b206574;
    342 
    343     /* Gather entropy from multiple sources for mixing */
    344     uint32_t cpu_temp = try_read_cpu_temp();
    345     uint32_t rtc_entropy = read_rtc_entropy();
    346     uint64_t initial_tsc = rdtsc();
    347 
    348     /* Collect keyboard timing entropy from user */
    349     /* DISABLED: uint32_t kbd_entropy = collect_keyboard_entropy(10); */
    350     uint32_t kbd_entropy = (uint32_t)(rdtsc() ^ (rdtsc() >> 32));  /* Use TSC instead for now */
    351 
    352     /* Seed state with hardware RNG or fallback to multiple entropy sources */
    353     for (int i = 4; i < 16; i++) {
    354         if (has_rdrand && rdseed32(&chacha_state[i])) {
    355             /* Got hardware random seed - most secure */
    356             /* Still mix in other entropy for defense in depth */
    357             chacha_state[i] ^= kbd_entropy;
    358             chacha_state[i] ^= cpu_temp;
    359             chacha_state[i] ^= rtc_entropy;
    360             continue;
    361         }
    362 
    363         /* Fallback: mix ALL entropy sources */
    364         uint64_t tsc = rdtsc();
    365         chacha_state[i] = (uint32_t)(tsc ^ (tsc >> 32));
    366         chacha_state[i] ^= cpu_temp;
    367         chacha_state[i] ^= rtc_entropy;
    368         chacha_state[i] ^= (uint32_t)initial_tsc;
    369         chacha_state[i] ^= kbd_entropy;
    370 
    371         /* Add timing jitter by doing variable work */
    372         for (volatile int j = 0; j < (i * 100); j++) {
    373             tsc = rdtsc();
    374             chacha_state[i] ^= (uint32_t)tsc;
    375         }
    376 
    377         /* Mix in CPU temp again (might have changed) */
    378         chacha_state[i] ^= try_read_cpu_temp();
    379 
    380         /* Mix in keyboard entropy rotated by position */
    381         chacha_state[i] ^= (kbd_entropy << i) | (kbd_entropy >> (32 - i));
    382     }
    383 
    384     rng_initialized = 1;
    385 }
    386 
    387 /* ChaCha20 block function */
    388 static void chacha20_block(uint32_t out[16]) {
    389     uint32_t x[16];
    390 
    391     /* Copy state */
    392     for (int i = 0; i < 16; i++) {
    393         x[i] = chacha_state[i];
    394     }
    395 
    396     /* 20 rounds */
    397     for (int i = 0; i < 10; i++) {
    398         /* Column rounds */
    399         QR(x[0], x[4], x[8], x[12]);
    400         QR(x[1], x[5], x[9], x[13]);
    401         QR(x[2], x[6], x[10], x[14]);
    402         QR(x[3], x[7], x[11], x[15]);
    403         /* Diagonal rounds */
    404         QR(x[0], x[5], x[10], x[15]);
    405         QR(x[1], x[6], x[11], x[12]);
    406         QR(x[2], x[7], x[8], x[13]);
    407         QR(x[3], x[4], x[9], x[14]);
    408     }
    409 
    410     /* Add original state */
    411     for (int i = 0; i < 16; i++) {
    412         out[i] = x[i] + chacha_state[i];
    413     }
    414 
    415     /* Increment counter */
    416     chacha_state[12]++;
    417     if (chacha_state[12] == 0) {
    418         chacha_state[13]++;
    419     }
    420 }
    421 
    422 /* Get random bytes (CSPRNG) */
    423 static void get_random_bytes(void* buf, size_t len) {
    424     uint8_t* bytes = (uint8_t*)buf;
    425     int has_rdrand = cpu_has_rdrand();
    426 
    427     /* RNG should already be initialized in kernel mode */
    428     if (!rng_initialized) {
    429         /* Shouldn't happen, but handle gracefully */
    430         return;
    431     }
    432 
    433     while (len > 0) {
    434         /* Try RDRAND first for direct hardware randomness */
    435         if (has_rdrand && len >= 4) {
    436             uint32_t val;
    437             if (rdrand32(&val)) {
    438                 for (int i = 0; i < 4 && len > 0; i++, len--) {
    439                     *bytes++ = (val >> (i * 8)) & 0xFF;
    440                 }
    441                 continue;
    442             }
    443         }
    444 
    445         /* Fallback to ChaCha20 */
    446         uint32_t block[16];
    447         chacha20_block(block);
    448 
    449         size_t to_copy = len < 64 ? len : 64;
    450         for (size_t i = 0; i < to_copy; i++) {
    451             bytes[i] = ((uint8_t*)block)[i];
    452         }
    453         bytes += to_copy;
    454         len -= to_copy;
    455     }
    456 }
    457 
    458 /* ===== End CSPRNG Implementation ===== */
    459 
    460 /* Syscall handler (called from syscall.s) */
    461 int handle_syscall(int syscall_num, uint32_t param1, uint32_t param2, uint32_t param3) {
    462     if (syscall_num == SYSCALL_OSPRINT) {
    463         terminal_writestring((const char*)param1);
    464 
    465         /* 250ms delay */
    466         unsigned long long start, end;
    467         __asm__ volatile ("rdtsc" : "=A"(start));
    468         do {
    469             __asm__ volatile ("rdtsc" : "=A"(end));
    470         } while ((end - start) < 500000000ULL); /* ~250ms at 2GHz CPU */
    471 
    472         return 0;
    473     }
    474     if (syscall_num == SYSCALL_GETRANDOM) {
    475         /* getrandom(void *buf, size_t buflen, unsigned int flags) */
    476         void* buf = (void*)param1;
    477         size_t buflen = (size_t)param2;
    478         /* unsigned int flags = param3; */ /* We ignore flags for now */
    479         (void)param3;
    480 
    481         /* Debug output */
    482         terminal_writestring("KERNEL: getrandom called, buflen=");
    483         char num[16];
    484         int i = 0, n = buflen;
    485         do { num[i++] = '0' + (n % 10); n /= 10; } while (n > 0);
    486         while (i > 0) { char c = num[--i]; terminal_putchar(c); }
    487         terminal_putchar('\n');
    488 
    489         if (!buf || buflen == 0) {
    490             terminal_writestring("KERNEL: getrandom returning -1 (EINVAL)\n");
    491             return -1;  /* EINVAL */
    492         }
    493 
    494         get_random_bytes(buf, buflen);
    495         terminal_writestring("KERNEL: getrandom returning ");
    496         i = 0; n = buflen;
    497         do { num[i++] = '0' + (n % 10); n /= 10; } while (n > 0);
    498         while (i > 0) { char c = num[--i]; terminal_putchar(c); }
    499         terminal_putchar('\n');
    500         return (int)buflen;  /* Return number of bytes written */
    501     }
    502     return -1;
    503 }
    504 
    505 /* TSS setup */
    506 void tss_install(void) {
    507     /* Zero out TSS */
    508     for (int i = 0; i < 104; i++) {
    509         tss[i] = 0;
    510     }
    511 
    512     /* Set kernel stack in TSS (used when transitioning from ring 3 to ring 0) */
    513     uint32_t *tss_ptr = (uint32_t*)tss;
    514     tss_ptr[1] = (uint32_t)&kernel_stack_top;  /* ESP0 */
    515     tss_ptr[2] = 0x10;                          /* SS0 (kernel data segment) */
    516 
    517     /* Write TSS descriptor to GDT at index 5 (offset 0x28) */
    518     uint32_t base = (uint32_t)tss;
    519     uint32_t limit = 104 - 1;
    520 
    521     /* TSS descriptor format */
    522     uint64_t tss_desc = limit & 0xFFFF;                    /* Limit low */
    523     tss_desc |= ((uint64_t)(base & 0xFFFF)) << 16;        /* Base low */
    524     tss_desc |= ((uint64_t)((base >> 16) & 0xFF)) << 32;  /* Base mid */
    525     tss_desc |= ((uint64_t)0x89) << 40;                    /* Type: available 32-bit TSS, present */
    526     tss_desc |= ((uint64_t)((limit >> 16) & 0xF)) << 48;  /* Limit high + flags */
    527     tss_desc |= ((uint64_t)((base >> 24) & 0xFF)) << 56;  /* Base high */
    528 
    529     gdt_start[5] = tss_desc;
    530 
    531     /* Load TSS */
    532     __asm__ volatile ("ltr %%ax" : : "a"(0x28));  /* TSS selector = 0x28 */
    533 }
    534 
    535 /* IDT setup */
    536 void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) {
    537     idt[num].offset_low = base & 0xFFFF;
    538     idt[num].offset_high = (base >> 16) & 0xFFFF;
    539     idt[num].selector = sel;
    540     idt[num].zero = 0;
    541     idt[num].type_attr = flags;
    542 }
    543 
    544 void idt_install(void) {
    545     idtp.limit = sizeof(idt) - 1;
    546     idtp.base = (uint32_t)&idt;
    547 
    548     /* Set up exception handlers (DPL=0, present, 32-bit interrupt gate) */
    549     idt_set_gate(0x08, (uint32_t)double_fault_handler, 0x08, 0x8E);  /* Double Fault */
    550     idt_set_gate(0x0d, (uint32_t)gpf_handler, 0x08, 0x8E);           /* General Protection Fault */
    551     idt_set_gate(0x0e, (uint32_t)page_fault_handler, 0x08, 0x8E);    /* Page Fault */
    552 
    553     /* Set up IRQ handlers */
    554     idt_set_gate(0x21, (uint32_t)irq1_handler, 0x08, 0x8E);          /* IRQ1 (Keyboard) */
    555     idt_set_gate(0x2C, (uint32_t)irq12_handler, 0x08, 0x8E);         /* IRQ12 (PS/2 Mouse) */
    556 
    557     /* Set up syscall gate (int 0x80) */
    558     idt_set_gate(0x80, (uint32_t)syscall_handler, 0x08, 0xEE);  /* DPL=3, present, 32-bit interrupt gate */
    559 
    560     /* Load IDT */
    561     __asm__ volatile ("lidt %0" : : "m"(idtp));
    562 }
    563 
    564 /* Debug counter for allocations */
    565 static int alloc_count = 0;
    566 
    567 /* Lua allocator */
    568 static void* lua_allocator(void* ud, void* ptr, size_t osize, size_t nsize) {
    569     (void)ud; (void)osize;
    570 
    571     if (nsize == 0) {
    572         free(ptr);
    573         return NULL;
    574     }
    575 
    576     if (ptr == NULL) {
    577         void* result = malloc(nsize);
    578         if (!result) {
    579             terminal_writestring("ERROR: Memory allocation failed\n");
    580         }
    581         return result;
    582     } else {
    583         void* result = realloc(ptr, nsize);
    584         if (!result) {
    585             terminal_writestring("ERROR: Memory reallocation failed\n");
    586         }
    587         return result;
    588     }
    589 }
    590 
    591 /* Test function - copy EXACT structure of os print */
    592 static int lua_test_dummy(lua_State* L) {
    593     const char* str = luaL_checkstring(L, 1);
    594     terminal_writestring("DEBUG: dummy got string: ");
    595     terminal_writestring(str);
    596     terminal_writestring("\n");
    597     return 0;
    598 }
    599 
    600 /* Lua binding for osprint (uses syscall in user mode) */
    601 static int lua_osprint(lua_State* L) {
    602     const char* str = luaL_checkstring(L, 1);
    603     terminal_writestring(str);
    604     return 0;
    605 }
    606 
    607 /* Note: All graphics functions are now in graphics.c */
    608 
    609 /* Custom string.sub implementation in C - rewritten based on working string.char */
    610 static int lua_string_sub(lua_State* L) {
    611     size_t len;
    612     const char* s = luaL_checklstring(L, 1, &len);
    613     int start = luaL_checkint(L, 2);
    614     int end = luaL_optint(L, 3, -1);
    615 
    616     /* Lua uses 1-based indexing */
    617     if (start < 0) start = len + start + 1;
    618     if (end < 0) end = len + end + 1;
    619     if (start < 1) start = 1;
    620     if (end > (int)len) end = len;
    621 
    622     /* Handle empty or invalid range */
    623     if (start > end) {
    624         lua_pushlstring(L, "", 0);
    625         return 1;
    626     }
    627 
    628     /* Calculate substring length */
    629     size_t sub_len = (size_t)(end - start + 1);
    630 
    631     /* Allocate buffer for substring */
    632     char* buffer = (char*)malloc(sub_len);
    633     if (!buffer) {
    634         lua_pushstring(L, "out of memory");
    635         lua_error(L);
    636         return 0;
    637     }
    638 
    639     /* Copy substring to buffer using memcpy */
    640     memcpy(buffer, s + start - 1, sub_len);
    641 
    642     /* Push the substring */
    643     lua_pushlstring(L, buffer, sub_len);
    644 
    645     /* Free buffer */
    646     free(buffer);
    647 
    648     return 1;
    649 }
    650 
    651 /* string.replace(str, pattern, replacement) */
    652 static int lua_string_replace(lua_State* L) {
    653     size_t str_len, pat_len, rep_len;
    654     const char* str = luaL_checklstring(L, 1, &str_len);
    655     const char* pattern = luaL_checklstring(L, 2, &pat_len);
    656     const char* replacement = luaL_checklstring(L, 3, &rep_len);
    657 
    658     if (pat_len == 0) {
    659         lua_pushvalue(L, 1);  /* Return original string */
    660         return 1;
    661     }
    662 
    663     /* Count occurrences */
    664     int count = 0;
    665     const char* p = str;
    666     while ((p = strstr(p, pattern)) != NULL) {
    667         count++;
    668         p += pat_len;
    669     }
    670 
    671     if (count == 0) {
    672         lua_pushvalue(L, 1);  /* Return original string */
    673         return 1;
    674     }
    675 
    676     /* Allocate result buffer */
    677     size_t new_len = str_len - (count * pat_len) + (count * rep_len);
    678     char* result = malloc(new_len + 1);
    679     if (!result) {
    680         lua_pushstring(L, "out of memory");
    681         lua_error(L);
    682         return 0;
    683     }
    684 
    685     /* Build result string */
    686     char* dst = result;
    687     const char* src = str;
    688     while (*src) {
    689         const char* match = strstr(src, pattern);
    690         if (match == NULL) {
    691             /* Copy remaining */
    692             while (*src) *dst++ = *src++;
    693             break;
    694         }
    695         /* Copy before match */
    696         while (src < match) *dst++ = *src++;
    697         /* Copy replacement */
    698         for (size_t i = 0; i < rep_len; i++) *dst++ = replacement[i];
    699         /* Skip pattern */
    700         src += pat_len;
    701     }
    702     *dst = '\0';
    703 
    704     lua_pushlstring(L, result, new_len);
    705     free(result);
    706     return 1;
    707 }
    708 
    709 /* string.trimr(str, char) - trim from right */
    710 static int lua_string_trimr(lua_State* L) {
    711     size_t len;
    712     const char* str = luaL_checklstring(L, 1, &len);
    713     size_t char_len;
    714     const char* trim_char = luaL_optlstring(L, 2, " ", &char_len);
    715     char c = trim_char[0];
    716 
    717     int end = len;
    718     while (end > 0 && str[end - 1] == c) {
    719         end--;
    720     }
    721 
    722     lua_pushlstring(L, str, end);
    723     return 1;
    724 }
    725 
    726 /* string.triml(str, char) - trim from left */
    727 static int lua_string_triml(lua_State* L) {
    728     size_t len;
    729     const char* str = luaL_checklstring(L, 1, &len);
    730     size_t char_len;
    731     const char* trim_char = luaL_optlstring(L, 2, " ", &char_len);
    732     char c = trim_char[0];
    733 
    734     int start = 0;
    735     while (start < (int)len && str[start] == c) {
    736         start++;
    737     }
    738 
    739     lua_pushlstring(L, str + start, len - start);
    740     return 1;
    741 }
    742 
    743 /* string.trim(str, char) - trim from both sides */
    744 static int lua_string_trim(lua_State* L) {
    745     size_t len;
    746     const char* str = luaL_checklstring(L, 1, &len);
    747     size_t char_len;
    748     const char* trim_char = luaL_optlstring(L, 2, " ", &char_len);
    749     char c = trim_char[0];
    750 
    751     int start = 0;
    752     while (start < (int)len && str[start] == c) {
    753         start++;
    754     }
    755 
    756     int end = len;
    757     while (end > start && str[end - 1] == c) {
    758         end--;
    759     }
    760 
    761     lua_pushlstring(L, str + start, end - start);
    762     return 1;
    763 }
    764 
    765 /* string.charAt(s, i) - fast single character access, returns single-char string */
    766 static int lua_string_charat(lua_State* L) {
    767     size_t len;
    768     const char* s = luaL_checklstring(L, 1, &len);
    769     int pos = luaL_checkint(L, 2);
    770 
    771     /* Lua uses 1-based indexing */
    772     if (pos < 0) pos = len + pos + 1;
    773 
    774     /* Check bounds */
    775     if (pos < 1 || pos > (int)len) {
    776         lua_pushlstring(L, "", 0);  /* Return empty string for out of bounds */
    777         return 1;
    778     }
    779 
    780     /* Allocate a buffer and copy the character - don't use pointer into Lua string! */
    781     char* buffer = (char*)malloc(1);
    782     if (!buffer) {
    783         lua_pushstring(L, "out of memory");
    784         lua_error(L);
    785         return 0;
    786     }
    787 
    788     buffer[0] = s[pos - 1];
    789     lua_pushlstring(L, buffer, 1);
    790     free(buffer);
    791 
    792     return 1;
    793 }
    794 
    795 /* string.byte(s, i, j) - returns byte values */
    796 static int lua_string_byte(lua_State* L) {
    797     size_t len;
    798     const char* s = luaL_checklstring(L, 1, &len);
    799     int start = luaL_optint(L, 2, 1);
    800     int end = luaL_optint(L, 3, start);
    801 
    802     /* Lua uses 1-based indexing */
    803     if (start < 0) start = len + start + 1;
    804     if (end < 0) end = len + end + 1;
    805     if (start < 1) start = 1;
    806     if (end > (int)len) end = len;
    807 
    808     if (start > end) return 0;  /* Empty range */
    809 
    810     int n = end - start + 1;
    811     if (n > (int)(len - start + 1)) n = len - start + 1;
    812 
    813     /* Push each byte value */
    814     for (int i = 0; i < n; i++) {
    815         lua_pushinteger(L, (unsigned char)s[start - 1 + i]);
    816     }
    817 
    818     return n;  /* Return number of values pushed */
    819 }
    820 
    821 /* string.char(...) - converts byte values to string */
    822 static int __attribute__((cdecl)) lua_string_char(lua_State* L) {
    823     int n = lua_gettop(L);  /* Number of arguments */
    824 
    825     if (n == 0) {
    826         lua_pushlstring(L, "", 0);
    827         return 1;
    828     }
    829 
    830     char* buffer = malloc(n + 1);
    831     if (!buffer) {
    832         lua_pushstring(L, "out of memory");
    833         lua_error(L);
    834         return 0;
    835     }
    836 
    837     for (int i = 0; i < n; i++) {
    838         int c = luaL_checkint(L, i + 1);
    839         if (c < 0 || c > 255) {
    840             free(buffer);
    841             lua_pushstring(L, "invalid byte value");
    842             lua_error(L);
    843             return 0;
    844         }
    845         buffer[i] = (char)c;
    846     }
    847 
    848     lua_pushlstring(L, buffer, n);
    849     free(buffer);
    850     return 1;
    851 }
    852 
    853 /* string.dump(function) - serialize function to bytecode */
    854 static int lua_string_dump(lua_State* L) {
    855     luaL_checktype(L, 1, LUA_TFUNCTION);
    856     lua_settop(L, 1);
    857 
    858     /* Use lua_dump to serialize the function */
    859     /* Note: We'd need a writer function for this, but for now return an error */
    860     lua_pushstring(L, "string.dump not fully implemented in bare metal mode");
    861     lua_error(L);
    862     return 0;
    863 }
    864 
    865 /* debug_funcaddr(func) - print the address of a function (for debugging) */
    866 static int lua_debug_funcaddr(lua_State* L) {
    867     if (lua_iscfunction(L, 1)) {
    868         lua_CFunction f = lua_tocfunction(L, 1);
    869         char buffer[64];
    870         /* Print address in hex */
    871         char* p = buffer;
    872         uintptr_t addr = (uintptr_t)f;
    873 
    874         *p++ = '0';
    875         *p++ = 'x';
    876 
    877         for (int i = 28; i >= 0; i -= 4) {
    878             int digit = (addr >> i) & 0xF;
    879             *p++ = digit < 10 ? '0' + digit : 'a' + digit - 10;
    880         }
    881         *p = '\0';
    882 
    883         lua_pushstring(L, buffer);
    884         return 1;
    885     } else if (lua_isfunction(L, 1)) {
    886         lua_pushstring(L, "<lua function>");
    887         return 1;
    888     } else {
    889         lua_pushstring(L, "<not a function>");
    890         return 1;
    891     }
    892 }
    893 
    894 /* string.reverse(s) - reverses a string */
    895 static int lua_string_reverse(lua_State* L) {
    896     size_t len;
    897     const char* s = luaL_checklstring(L, 1, &len);
    898 
    899     char* buffer = malloc(len);
    900     if (!buffer) {
    901         lua_pushstring(L, "out of memory");
    902         lua_error(L);
    903         return 0;
    904     }
    905 
    906     for (size_t i = 0; i < len; i++) {
    907         buffer[i] = s[len - 1 - i];
    908     }
    909 
    910     lua_pushlstring(L, buffer, len);
    911     free(buffer);
    912     return 1;
    913 }
    914 
    915 /* string.lower(s) - converts to lowercase */
    916 static int lua_string_lower(lua_State* L) {
    917     size_t len;
    918     const char* s = luaL_checklstring(L, 1, &len);
    919 
    920     char* buffer = malloc(len);
    921     if (!buffer) {
    922         lua_pushstring(L, "out of memory");
    923         lua_error(L);
    924         return 0;
    925     }
    926 
    927     for (size_t i = 0; i < len; i++) {
    928         buffer[i] = tolower((unsigned char)s[i]);
    929     }
    930 
    931     lua_pushlstring(L, buffer, len);
    932     free(buffer);
    933     return 1;
    934 }
    935 
    936 /* string.upper(s) - converts to uppercase */
    937 static int lua_string_upper(lua_State* L) {
    938     size_t len;
    939     const char* s = luaL_checklstring(L, 1, &len);
    940 
    941     char* buffer = malloc(len);
    942     if (!buffer) {
    943         lua_pushstring(L, "out of memory");
    944         lua_error(L);
    945         return 0;
    946     }
    947 
    948     for (size_t i = 0; i < len; i++) {
    949         buffer[i] = toupper((unsigned char)s[i]);
    950     }
    951 
    952     lua_pushlstring(L, buffer, len);
    953     free(buffer);
    954     return 1;
    955 }
    956 
    957 /* CompileString(code, [name]) - compiles Lua code and returns a function or nil, error */
    958 static int lua_compilestring(lua_State* L) {
    959     const char* code = luaL_checkstring(L, 1);
    960     const char* name = luaL_optstring(L, 2, "compiled");
    961 
    962     if (luaL_loadstring(L, code) != 0) {
    963         /* Return nil, error_message */
    964         lua_pushnil(L);
    965         lua_insert(L, -2);
    966         return 2;
    967     }
    968 
    969     /* Return compiled function */
    970     return 1;
    971 }
    972 
    973 /* RunString(code, [name]) - compiles and executes Lua code, returns success status */
    974 static int lua_runstring(lua_State* L) {
    975     const char* code = luaL_checkstring(L, 1);
    976     const char* name = luaL_optstring(L, 2, "runstring");
    977 
    978     if (luaL_loadstring(L, code) != 0) {
    979         /* Pop error message and return false */
    980         lua_pop(L, 1);
    981         lua_pushboolean(L, 0);
    982         return 1;
    983     }
    984 
    985     if (lua_pcall(L, 0, 0, 0) != 0) {
    986         /* Pop error message and return false */
    987         lua_pop(L, 1);
    988         lua_pushboolean(L, 0);
    989         return 1;
    990     }
    991 
    992     /* Return true on success */
    993     lua_pushboolean(L, 1);
    994     return 1;
    995 }
    996 
    997 /* Embedded packed ramdisk */
    998 extern char _binary_packed_bin_start[];
    999 extern char _binary_packed_bin_end[];
   1000 
   1001 /* Debug message for inline asm */
   1002 static const char msg_returned[] = "INLINE ASM: returned from lua_newstate\n";
   1003 
   1004 /* Convert unsigned int to string */
   1005 static void uint_to_str(uint32_t num, char* str) {
   1006     if (num == 0) {
   1007         str[0] = '0';
   1008         str[1] = '\0';
   1009         return;
   1010     }
   1011 
   1012     char temp[16];
   1013     int i = 0;
   1014 
   1015     while (num > 0) {
   1016         temp[i++] = '0' + (num % 10);
   1017         num /= 10;
   1018     }
   1019 
   1020     /* Reverse */
   1021     for (int j = 0; j < i; j++) {
   1022         str[j] = temp[i - 1 - j];
   1023     }
   1024     str[i] = '\0';
   1025 }
   1026 
   1027 /* User mode entry point - this runs in ring 3 */
   1028 __attribute__((naked)) void usermode_main(void) {
   1029     /* Ensure stack is 16-byte aligned for proper function calls */
   1030     /* Using naked attribute since we're manually managing the stack frame */
   1031     __asm__ volatile (
   1032         "and $-16, %%esp\n"
   1033         "sub $12, %%esp\n"
   1034         "push %%ebp\n"
   1035         "mov %%esp, %%ebp\n"
   1036         ::: "memory"
   1037     );
   1038 
   1039     /* Set up user mode data segments */
   1040     __asm__ volatile (
   1041         "mov $0x23, %%ax\n"
   1042         "mov %%ax, %%ds\n"
   1043         "mov %%ax, %%es\n"
   1044         "mov %%ax, %%fs\n"
   1045         "mov %%ax, %%gs\n"
   1046         : : : "ax"
   1047     );
   1048 
   1049     /* Enable SSE/SSE2 instructions - REQUIRED for LuaJIT */
   1050     /* Enable FPU by clearing CR0.EM (bit 2) and setting CR0.MP (bit 1) */
   1051     __asm__ volatile (
   1052         "mov %%cr0, %%eax\n"
   1053         "and $0xFFFFFFFB, %%eax\n"  /* Clear EM bit (bit 2) */
   1054         "or $0x00000002, %%eax\n"   /* Set MP bit (bit 1) */
   1055         "mov %%eax, %%cr0\n"
   1056         : : : "eax"
   1057     );
   1058 
   1059     /* Enable SSE by setting CR4.OSFXSR (bit 9) and CR4.OSXMMEXCPT (bit 10) */
   1060     __asm__ volatile (
   1061         "mov %%cr4, %%eax\n"
   1062         "or $0x00000600, %%eax\n"   /* Set bits 9 and 10 */
   1063         "mov %%eax, %%cr4\n"
   1064         : : : "eax"
   1065     );
   1066 
   1067     /* Create Lua state */
   1068     lua_State* L = lua_newstate(lua_allocator, NULL);
   1069 
   1070     if (!L) {
   1071         terminal_writestring("ERROR: Failed to create Lua state\n");
   1072         while(1) __asm__ volatile ("hlt");
   1073     }
   1074 
   1075     /* Load standard libraries */
   1076     luaL_openlibs(L);
   1077 
   1078     /* Disable JIT compiler - run in interpreter mode only */
   1079     lua_getglobal(L, "jit");
   1080     if (lua_istable(L, -1)) {
   1081         lua_getfield(L, -1, "off");
   1082         if (lua_isfunction(L, -1)) {
   1083             lua_call(L, 0, 0);
   1084         } else {
   1085             lua_pop(L, 1);
   1086         }
   1087         lua_pop(L, 1);
   1088     } else {
   1089         lua_pop(L, 1);
   1090     }
   1091 
   1092     /* Register core functions */
   1093     lua_pushcfunction(L, lua_osprint);
   1094     lua_setglobal(L, "osprint");
   1095 
   1096     lua_pushcfunction(L, lua_runstring);
   1097     lua_setglobal(L, "RunString");
   1098 
   1099     /* Register graphics functions */
   1100     lua_pushcfunction(L, lua_enter_graphics_mode);
   1101     lua_setglobal(L, "EnterGraphicsMode");
   1102 
   1103     lua_pushcfunction(L, lua_exit_graphics_mode);
   1104     lua_setglobal(L, "ExitGraphicsMode");
   1105 
   1106     lua_pushcfunction(L, lua_set_pixel);
   1107     lua_setglobal(L, "SetPixel");
   1108 
   1109     lua_pushcfunction(L, lua_draw_rect);
   1110     lua_setglobal(L, "DrawRect");
   1111 
   1112     lua_pushcfunction(L, lua_clear_screen);
   1113     lua_setglobal(L, "ClearScreen");
   1114 
   1115     lua_pushcfunction(L, lua_process_buffered_draw_ops);
   1116     lua_setglobal(L, "ProcessBufferedDrawOps");
   1117 
   1118     /* Register VESA functions */
   1119     lua_pushcfunction(L, lua_vesa_init);
   1120     lua_setglobal(L, "VESAInit");
   1121 
   1122     lua_pushcfunction(L, lua_vesa_set_mode);
   1123     lua_setglobal(L, "VESASetMode");
   1124 
   1125     lua_pushcfunction(L, lua_vesa_get_mode_info);
   1126     lua_setglobal(L, "VESAGetModeInfo");
   1127 
   1128     lua_pushcfunction(L, lua_vesa_list_modes);
   1129     lua_setglobal(L, "VESAListModes");
   1130 
   1131     lua_pushcfunction(L, lua_vesa_set_pixel);
   1132     lua_setglobal(L, "VESASetPixel");
   1133 
   1134     lua_pushcfunction(L, lua_vesa_draw_rect);
   1135     lua_setglobal(L, "VESADrawRect");
   1136 
   1137     lua_pushcfunction(L, lua_vesa_clear_screen);
   1138     lua_setglobal(L, "VESAClearScreen");
   1139 
   1140     lua_pushcfunction(L, lua_vesa_process_buffered_draw_ops);
   1141     lua_setglobal(L, "VESAProcessBufferedDrawOps");
   1142 
   1143     /* Register image decoder functions */
   1144     lua_pushcfunction(L, lua_bmp_load);
   1145     lua_setglobal(L, "BMPLoad");
   1146     terminal_writestring("Registered BMPLoad function\n");
   1147 
   1148     /* Verify BMPLoad is in global */
   1149     lua_getglobal(L, "BMPLoad");
   1150     if (lua_isfunction(L, -1)) {
   1151         terminal_writestring("BMPLoad verification: SUCCESS\n");
   1152     } else {
   1153         terminal_writestring("BMPLoad verification: FAILED\n");
   1154     }
   1155     lua_pop(L, 1);
   1156 
   1157     /* lua_bmp_save and lua_png_save are commented out in decoder files */
   1158     // lua_pushcfunction(L, lua_bmp_save);
   1159     // lua_setglobal(L, "BMPSave");
   1160 
   1161     lua_pushcfunction(L, lua_png_load);
   1162     lua_setglobal(L, "PNGLoad");
   1163 
   1164     lua_pushcfunction(L, lua_jpeg_load);
   1165     lua_setglobal(L, "JPEGLoad");
   1166     terminal_writestring("Registered JPEGLoad function\n");
   1167 
   1168     /* Verify JPEGLoad is in global */
   1169     lua_getglobal(L, "JPEGLoad");
   1170     if (lua_isfunction(L, -1)) {
   1171         terminal_writestring("JPEGLoad verification: SUCCESS\n");
   1172     } else {
   1173         terminal_writestring("JPEGLoad verification: FAILED\n");
   1174     }
   1175     lua_pop(L, 1);
   1176 
   1177     // lua_pushcfunction(L, lua_png_save);
   1178     // lua_setglobal(L, "PNGSave");
   1179 
   1180     lua_pushcfunction(L, lua_image_draw);
   1181     lua_setglobal(L, "ImageDraw");
   1182 
   1183     lua_pushcfunction(L, lua_image_draw_scaled);
   1184     lua_setglobal(L, "ImageDrawScaled");
   1185 
   1186     lua_pushcfunction(L, lua_image_get_info);
   1187     lua_setglobal(L, "ImageGetInfo");
   1188 
   1189     lua_pushcfunction(L, lua_image_destroy);
   1190     lua_setglobal(L, "ImageDestroy");
   1191 
   1192     lua_pushcfunction(L, lua_image_rotate);
   1193     lua_setglobal(L, "ImageRotate");
   1194 
   1195     lua_pushcfunction(L, lua_image_get_width);
   1196     lua_setglobal(L, "ImageGetWidth");
   1197 
   1198     lua_pushcfunction(L, lua_image_get_height);
   1199     lua_setglobal(L, "ImageGetHeight");
   1200 
   1201     lua_pushcfunction(L, lua_image_get_pixel);
   1202     lua_setglobal(L, "ImageGetPixel");
   1203 
   1204     extern int lua_image_get_buffer_bgra(lua_State* L);
   1205     lua_pushcfunction(L, lua_image_get_buffer_bgra);
   1206     lua_setglobal(L, "ImageGetBufferBGRA");
   1207 
   1208     /* Register compression functions */
   1209     lua_pushcfunction(L, lua_deflate_compress);
   1210     lua_setglobal(L, "DeflateCompress");
   1211 
   1212     lua_pushcfunction(L, lua_deflate_decompress);
   1213     lua_setglobal(L, "DeflateDecompress");
   1214 
   1215     lua_pushcfunction(L, lua_lzma_compress);
   1216     lua_setglobal(L, "LZMACompress");
   1217 
   1218     lua_pushcfunction(L, lua_lzma_decompress);
   1219     lua_setglobal(L, "LZMADecompress");
   1220 
   1221     lua_pushcfunction(L, lua_gzip_compress);
   1222     lua_setglobal(L, "GZipCompress");
   1223 
   1224     lua_pushcfunction(L, lua_gzip_decompress);
   1225     lua_setglobal(L, "GZipDecompress");
   1226 
   1227     lua_pushcfunction(L, lua_adler32);
   1228     lua_setglobal(L, "Adler32");
   1229 
   1230     lua_pushcfunction(L, lua_crc32);
   1231     lua_setglobal(L, "CRC32");
   1232 
   1233     /* Register C ramdisk functions */
   1234     lua_pushcfunction(L, lua_ramdisk_create);
   1235     lua_setglobal(L, "CRamdiskCreate");
   1236 
   1237     lua_pushcfunction(L, lua_ramdisk_open);
   1238     lua_setglobal(L, "CRamdiskOpen");
   1239 
   1240     lua_pushcfunction(L, lua_ramdisk_read);
   1241     lua_setglobal(L, "CRamdiskRead");
   1242 
   1243     lua_pushcfunction(L, lua_ramdisk_write);
   1244     lua_setglobal(L, "CRamdiskWrite");
   1245 
   1246     lua_pushcfunction(L, lua_ramdisk_close);
   1247     lua_setglobal(L, "CRamdiskClose");
   1248 
   1249     lua_pushcfunction(L, lua_ramdisk_seek);
   1250     lua_setglobal(L, "CRamdiskSeek");
   1251 
   1252     lua_pushcfunction(L, lua_ramdisk_mkdir);
   1253     lua_setglobal(L, "CRamdiskMkdir");
   1254 
   1255     lua_pushcfunction(L, lua_ramdisk_exists);
   1256     lua_setglobal(L, "CRamdiskExists");
   1257 
   1258     lua_pushcfunction(L, lua_ramdisk_list);
   1259     lua_setglobal(L, "CRamdiskList");
   1260 
   1261     lua_pushcfunction(L, lua_ramdisk_remove);
   1262     lua_setglobal(L, "CRamdiskRemove");
   1263 
   1264     lua_pushcfunction(L, lua_ramdisk_find);
   1265     lua_setglobal(L, "CRamdiskFind");
   1266 
   1267     /* Initialize C ramdisk and load packed data */
   1268     terminal_writestring("Loading C ramdisk from packed data...\n");
   1269     c_ramdisk_root = ramdisk_create_root();
   1270     if (!c_ramdisk_root) {
   1271         terminal_writestring("ERROR: Failed to create C ramdisk root\n");
   1272         lua_close(L);
   1273         while(1) __asm__ volatile ("hlt");
   1274     }
   1275 
   1276     /* Load packed ramdisk data */
   1277     size_t packed_size = _binary_packed_bin_end - _binary_packed_bin_start;
   1278     terminal_writestring("Packed ramdisk size: ");
   1279     char size_str[16];
   1280     uint_to_str(packed_size, size_str);
   1281     terminal_writestring(size_str);
   1282     terminal_writestring(" bytes\n");
   1283 
   1284     int entries_loaded = ramdisk_load_packed(c_ramdisk_root, (uint8_t*)_binary_packed_bin_start, packed_size);
   1285     if (entries_loaded < 0) {
   1286         terminal_writestring("ERROR: Failed to load packed ramdisk\n");
   1287         lua_close(L);
   1288         while(1) __asm__ volatile ("hlt");
   1289     }
   1290 
   1291     terminal_writestring("Loaded ");
   1292     uint_to_str(entries_loaded, size_str);
   1293     terminal_writestring(size_str);
   1294     terminal_writestring(" entries from packed ramdisk\n");
   1295 
   1296     /* Expose C ramdisk root to Lua */
   1297     lua_pushlightuserdata(L, c_ramdisk_root);
   1298     lua_setglobal(L, "c_ramdisk_root");
   1299 
   1300     /* NOTE: init.lua is now loaded from ramdisk in kernel.c, not embedded */
   1301     /* This code is kept for reference but commented out */
   1302     /*
   1303     size_t script_size = _binary_build_init_with_ramdisk_lua_end - _binary_build_init_with_ramdisk_lua_start;
   1304 
   1305     if (luaL_loadbuffer(L, _binary_build_init_with_ramdisk_lua_start, script_size, "init.lua") != 0) {
   1306         terminal_writestring("ERROR: Failed to load init.lua: ");
   1307         terminal_writestring(lua_tostring(L, -1));
   1308         terminal_writestring("\n");
   1309         lua_close(L);
   1310         while(1) __asm__ volatile ("hlt");
   1311     }
   1312 
   1313     int result = lua_pcall(L, 0, 0, 0);
   1314 
   1315     if (result != 0) {
   1316         terminal_writestring("ERROR: Failed to execute init.lua: ");
   1317         const char* err = lua_tostring(L, -1);
   1318         if (err) {
   1319             terminal_writestring(err);
   1320         } else {
   1321             terminal_writestring("(no error message)");
   1322         }
   1323         terminal_writestring("\n");
   1324         lua_close(L);
   1325         while(1) __asm__ volatile ("hlt");
   1326     }
   1327     */
   1328 
   1329     /* Sleep for 10 seconds after running init.lua */
   1330     unsigned long long start, end;
   1331     __asm__ volatile ("rdtsc" : "=A"(start));
   1332     do {
   1333         __asm__ volatile ("rdtsc" : "=A"(end));
   1334     } while ((end - start) < 20000000000ULL); /* ~10 seconds at 2GHz CPU */
   1335 
   1336     terminal_writestring("System halted\n");
   1337     lua_close(L);
   1338 
   1339     while(1) __asm__ volatile ("hlt");
   1340 }