boredos_mirror/src/kernel/main.c
2026-02-26 21:45:57 +01:00

187 lines
5.1 KiB
C

#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "limine.h"
#include "graphics.h"
#include "gdt.h"
#include "idt.h"
#include "paging.h"
#include "syscall.h"
#include "process.h"
#include "ps2.h"
#include "wm.h"
#include "io.h"
#include "fat32.h"
#include "memory_manager.h"
#include "platform.h"
#include "wallpaper.h"
// --- Limine Requests ---
__attribute__((used, section(".requests")))
static volatile LIMINE_BASE_REVISION(2);
__attribute__((used, section(".requests")))
static volatile struct limine_framebuffer_request framebuffer_request = {
.id = LIMINE_FRAMEBUFFER_REQUEST,
.revision = 1
};
__attribute__((used, section(".requests")))
static volatile struct limine_memmap_request memmap_request = {
.id = LIMINE_MEMMAP_REQUEST,
.revision = 0
};
__attribute__((used, section(".requests")))
static volatile struct limine_module_request module_request = {
.id = LIMINE_MODULE_REQUEST,
.revision = 0
};
__attribute__((used, section(".requests_start")))
static volatile struct limine_request *const requests_start_marker[] = {
(struct limine_request *)&framebuffer_request,
(struct limine_request *)&memmap_request,
(struct limine_request *)&module_request,
NULL
};
__attribute__((used, section(".requests_end")))
static volatile struct limine_request *const requests_end_marker[] = {
NULL
};
static void hcf(void) {
asm("cli");
for (;;) {
asm("hlt");
}
}
// Simple serial port initialization and output for debugging
static void init_serial() {
outb(0x3F8 + 1, 0x00);
outb(0x3F8 + 3, 0x80);
outb(0x3F8 + 0, 0x03);
outb(0x3F8 + 1, 0x00);
outb(0x3F8 + 3, 0x03);
outb(0x3F8 + 2, 0xC7);
outb(0x3F8 + 4, 0x0B);
}
void serial_write(const char *str) {
while (*str) {
while ((inb(0x3F8 + 5) & 0x20) == 0);
outb(0x3F8, *str++);
}
}
// Kernel Entry Point
void kmain(void) {
init_serial();
serial_write("\n[DEBUG] Entering kmain...\n");
platform_init();
serial_write("[DEBUG] platform_init OK\n");
// 1. Memory Detection and Heap Init
uint64_t heap_phys_addr = 0;
size_t heap_size = 0;
if (memmap_request.response != NULL) {
for (uint64_t i = 0; i < memmap_request.response->entry_count; i++) {
struct limine_memmap_entry *entry = memmap_request.response->entries[i];
if (entry->type == LIMINE_MEMMAP_USABLE) {
if (entry->length > heap_size) {
heap_size = entry->length;
heap_phys_addr = entry->base;
}
}
}
}
if (heap_size > 512 * 1024 * 1024) heap_size = 512 * 1024 * 1024; // Cap at 512MB
if (heap_phys_addr != 0) {
memory_manager_init_at((void*)p2v(heap_phys_addr), heap_size);
serial_write("[DEBUG] memory_manager_init OK\n");
} else {
serial_write("[DEBUG] ERROR: No usable memory for heap!\n");
hcf();
}
// 2. Graphics Init
if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) {
serial_write("[DEBUG] No framebuffer! Halting.\n");
hcf();
}
struct limine_framebuffer *fb = framebuffer_request.response->framebuffers[0];
graphics_init(fb);
serial_write("[DEBUG] graphics_init OK\n");
// 3. GDT & TSS Init
gdt_init();
serial_write("[DEBUG] gdt_init OK\n");
// 4. Paging Init
paging_init();
serial_write("[DEBUG] paging_init OK\n");
// 5. Syscall Init
syscall_init();
serial_write("[DEBUG] syscall_init OK\n");
// 6. Interrupts Init
idt_init();
idt_register_interrupts();
idt_load();
serial_write("[DEBUG] idt_init OK\n");
process_init();
serial_write("[DEBUG] Skipping user mode test, proceeding with normal boot.\n");
// Initialize FAT32 RAMFS and mount Limine modules
fat32_init();
if (module_request.response != NULL) {
for (uint64_t i = 0; i < module_request.response->module_count; i++) {
struct limine_file *mod = module_request.response->modules[i];
// mod->path typically starts with a '/' from Limine
FAT32_FileHandle *fh = fat32_open(mod->path, "w");
if (fh && fh->valid) {
fat32_write(fh, mod->address, mod->size);
fat32_close(fh);
serial_write("[DEBUG] Limine Module loaded into RAMFS: ");
serial_write(mod->path);
serial_write("\n");
}
}
}
int ENABLE_USER_TEST = 1; // Set to 1 to test User Mode ring 3 jump
#ifdef ENABLE_USER_TEST
process_init();
// The desktop is PID 0
#endif
// 3. PS/2 Init (Mouse/Keyboard)
asm("cli");
ps2_init();
asm("sti");
// 4. Window Manager Init (Draws initial desktop)
wm_init();
// Re-enable interrupts since we removed sti from idt_load
asm volatile("sti");
// 5. Main loop - just wait for interrupts
// Timer interrupt will drive the redraw system
while (1) {
wm_process_input();
wm_process_deferred_thumbs();
wallpaper_process_pending();
asm("hlt");
}
}