kernel.c
1 #include "kernel.h" 2 #include "gdt.h" 3 #include "idt.h" 4 #include "memory.h" 5 #include "io_uring.h" 6 #include "string.h" 7 #include "fs.h" 8 #include "initrd.h" 9 #include "process.h" 10 #include "elf.h" 11 #include "paging.h" 12 #include "vfs.h" 13 #include "keyboard.h" 14 #include "console.h" 15 16 // Multiboot information structure 17 struct multiboot_info { 18 uint32_t flags; 19 uint32_t mem_lower; 20 uint32_t mem_upper; 21 uint32_t boot_device; 22 uint32_t cmdline; 23 uint32_t mods_count; 24 uint32_t mods_addr; 25 // ... 26 } __attribute__((packed)); 27 28 // Helper function to create VGA entry 29 static inline uint16_t vga_entry(unsigned char uc, uint8_t color) { 30 return (uint16_t) uc | (uint16_t) color << 8; 31 } 32 33 // Initialize terminal - now delegates to console 34 void terminal_init(void) { 35 // Clear screen with initial color 36 uint8_t color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); 37 uint16_t* terminal_buffer = (uint16_t*) VGA_ADDRESS; 38 39 for (size_t y = 0; y < VGA_HEIGHT; y++) { 40 for (size_t x = 0; x < VGA_WIDTH; x++) { 41 const size_t index = y * VGA_WIDTH + x; 42 terminal_buffer[index] = vga_entry(' ', color); 43 } 44 } 45 } 46 47 // Put character to terminal - now delegates to console 48 void terminal_putchar(char c) { 49 if (system_console) { 50 console_putchar(c); 51 } 52 } 53 54 // Write data to terminal - now delegates to console 55 void terminal_write(const char* data, size_t size) { 56 if (system_console) { 57 console_write(data, size); 58 } 59 } 60 61 // Write string to terminal - now delegates to console 62 void terminal_writestring(const char* data) { 63 if (system_console) { 64 console_write(data, strlen(data)); 65 } 66 } 67 68 // Clear terminal - now delegates to console 69 void terminal_clear(void) { 70 if (system_console) { 71 console_clear(); 72 } 73 } 74 75 // Set terminal color - now delegates to console 76 void terminal_setcolor(uint8_t color) { 77 if (system_console) { 78 uint8_t fg = color & 0x0F; 79 uint8_t bg = (color >> 4) & 0x0F; 80 console_set_color(fg, bg); 81 } 82 } 83 84 // Get current terminal cursor position - now delegates to console 85 void terminal_get_cursor(size_t* row, size_t* column) { 86 if (system_console) { 87 uint32_t x, y; 88 console_get_cursor(&x, &y); 89 if (row) *row = y; 90 if (column) *column = x; 91 } else { 92 if (row) *row = 0; 93 if (column) *column = 0; 94 } 95 } 96 97 // Kernel panic - halt the system 98 void kernel_panic(const char* message) { 99 __asm__ volatile("cli"); // Disable interrupts 100 101 terminal_setcolor(vga_entry_color(VGA_COLOR_WHITE, VGA_COLOR_RED)); 102 terminal_writestring("\n\nKERNEL PANIC: "); 103 terminal_writestring(message); 104 terminal_writestring("\nSystem halted.\n"); 105 106 // Halt the CPU 107 while (1) { 108 __asm__ volatile("hlt"); 109 } 110 } 111 112 // External functions 113 extern void test_io_uring(void); 114 115 // Timer tick counter 116 volatile uint32_t timer_ticks = 0; 117 118 // Actual timer handler 119 static void timer_tick(void) { 120 timer_ticks++; 121 122 // TODO sometime fix ts 123 // Simple round-robin scheduling every 10 ticks 124 // if (timer_ticks % 10 == 0 && current_process) { 125 // process_yield(); 126 // } 127 } 128 129 // Timer interrupt handler (matches interrupt_handler_t) 130 void timer_handler(void) { 131 timer_tick(); 132 133 // Send End Of Interrupt to PIC 134 outb(0x20, 0x20); 135 } 136 137 // Kernel main entry point 138 void kernel_main(uint32_t magic, uint32_t addr) { 139 // Multiboot information structure 140 struct multiboot_info* mbi = (struct multiboot_info*)addr; 141 142 // Initialize terminal FIRST 143 terminal_init(); 144 terminal_writestring("Terminal initialized\n"); 145 146 // Initialize console early for unified VGA management 147 console_early_init(); 148 terminal_writestring("Console early init OK\n"); 149 150 // Check multiboot magic 151 if (magic != 0x2BADB002) { 152 terminal_writestring("Bad magic number!\n"); 153 while (1) { hlt(); } 154 } 155 156 terminal_writestring("Multiboot OK\n"); 157 158 // Initialize GDT 159 terminal_writestring("Init GDT...\n"); 160 gdt_init(); 161 terminal_writestring("GDT OK\n"); 162 163 // Initialize IDT 164 terminal_writestring("Init IDT...\n"); 165 idt_init(); 166 terminal_writestring("IDT OK\n"); 167 168 // Initialize memory FIRST 169 terminal_writestring("Init memory...\n"); 170 171 uint32_t total_mem_bytes; 172 if (mbi->flags & 0x1) { 173 // mem_upper is in KB, represents memory above 1MB 174 total_mem_bytes = (mbi->mem_upper + 1024) * 1024; 175 } else { 176 total_mem_bytes = 128 * 1024 * 1024; // Fallback default 128MB 177 } 178 179 memory_init(total_mem_bytes); 180 terminal_writestring("Memory detected: "); 181 char mbuf[12]; 182 itoa(total_mem_bytes / (1024 * 1024), mbuf, 10); 183 terminal_writestring(mbuf); 184 terminal_writestring(" MB\n"); 185 186 // Initialize paging 187 terminal_writestring("Init paging...\n"); 188 paging_init(); 189 terminal_writestring("Paging OK\n"); 190 191 // Initialize VFS 192 terminal_writestring("Init VFS...\n"); 193 vfs_init(); 194 terminal_writestring("VFS OK\n"); 195 196 // Initialize PIC FIRST - remap IRQs to interrupts 32-47 197 // Send initialization command to both PICs 198 outb(0x20, 0x11); // Master PIC command 199 outb(0xA0, 0x11); // Slave PIC command 200 201 // Set IRQ base addresses 202 outb(0x21, 0x20); // Master PIC: IRQs 0-7 -> interrupts 32-39 203 outb(0xA1, 0x28); // Slave PIC: IRQs 8-15 -> interrupts 40-47 204 205 // Configure PIC cascade 206 outb(0x21, 0x04); // Master PIC: slave on IRQ2 207 outb(0xA1, 0x02); // Slave PIC: cascade identity 208 209 // Set 8086 mode 210 outb(0x21, 0x01); // Master PIC 211 outb(0xA1, 0x01); // Slave PIC 212 213 // Unmask all IRQs initially 214 outb(0x21, 0x00); // Master PIC mask 215 outb(0xA1, 0x00); // Slave PIC mask 216 217 terminal_writestring("PIC initialized\n"); 218 219 // Initialize keyboard AFTER PIC 220 terminal_writestring("Init keyboard...\n"); 221 keyboard_init(); 222 terminal_writestring("Keyboard OK\n"); 223 224 // Initialize console 225 terminal_writestring("Init console...\n"); 226 console_late_init(); 227 terminal_writestring("Console OK\n"); 228 229 // Initialize timer (IRQ0) 230 register_interrupt_handler(32, timer_handler); // IRQ0 is interrupt 32 231 232 // Set up PIT for ~100Hz 233 uint32_t divisor = 1193180 / 100; // 100Hz 234 outb(0x43, 0x36); // Command byte 235 outb(0x40, divisor & 0xFF); // Low byte 236 outb(0x40, divisor >> 8); // High byte 237 terminal_writestring("Timer initialized at 100Hz\n"); 238 239 // Enable interrupts! 240 __asm__ volatile("sti"); 241 terminal_writestring("Interrupts enabled\n"); 242 243 // If we get here, basic initialization worked 244 terminal_writestring("\nBasic init complete!\n"); 245 246 // Initialize io_uring subsystem 247 terminal_writestring("Init io_uring...\n"); 248 io_uring_init(); 249 terminal_writestring("io_uring OK\n"); 250 251 // Initialize filesystem 252 terminal_writestring("Init filesystem...\n"); 253 fs_init(); 254 terminal_writestring("Filesystem OK\n"); 255 256 // Load initrd 257 if (mbi->mods_count > 0) { 258 terminal_writestring("Loading initrd...\n"); 259 uint32_t* mod_start = (uint32_t*)mbi->mods_addr; 260 uint32_t initrd_location = *mod_start; 261 uint32_t initrd_end = *(mod_start + 1); 262 263 terminal_writestring("Initrd at 0x"); 264 char buf[9]; 265 itoa(initrd_location, buf, 16); 266 terminal_writestring(buf); 267 terminal_writestring(", size: "); 268 itoa(initrd_end - initrd_location, buf, 10); 269 terminal_writestring(buf); 270 terminal_writestring(" bytes\n"); 271 272 // Initialize initrd filesystem 273 fs_root = initrd_init(initrd_location); 274 } else { 275 terminal_writestring("No initrd found!\n"); 276 } 277 278 // Initialize process management 279 terminal_writestring("Init processes...\n"); 280 process_init(); 281 terminal_writestring("Processes OK\n"); 282 283 terminal_writestring("\nAll systems initialized!\n"); 284 terminal_writestring("io_uring kernel ready.\n\n"); 285 286 // List files in initrd 287 if (fs_root) { 288 terminal_writestring("Files in initrd:\n"); 289 int i = 0; 290 struct dirent* node = 0; 291 while ((node = fs_readdir(fs_root, i)) != 0) { 292 terminal_writestring(" - "); 293 terminal_writestring(node->name); 294 terminal_writestring("\n"); 295 i++; 296 } 297 terminal_writestring("\n"); 298 } 299 300 // Try to run hello_uring 301 terminal_writestring("Attempting to execute hello_uring...\n"); 302 int result = process_exec("hello_uring"); 303 if (result < 0) { 304 terminal_writestring("Failed to execute hello_uring\n"); 305 } 306 307 terminal_writestring("\nKernel execution complete.\n"); 308 309 // Main kernel loop 310 while (1) { 311 hlt(); 312 } 313 }