- Created driver framework with probe/init lifecycle. Drivers register via REGISTER_DRIVER macro which places pointers in a .drivers linker section. - During boot, init_drivers() iterates the section, probes each driver (checking if hardware is present), and initializes those that respond OK. - Added .drivers section to linker.ld with __drivers_start/__drivers_end symbols for iteration. - Also added .rodata.* pattern to the .rodata section for string literals placed in sub-sections by the compiler. - No drivers are registered yet; the VGA driver will be the first. Tested: boots cleanly with driver scan completing (0 registered, 0 loaded).
92 lines
2.1 KiB
C
92 lines
2.1 KiB
C
#include <multiboot2.h>
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include "gdt.h"
|
|
#include "idt.h"
|
|
#include "pic.h"
|
|
#include "port_io.h"
|
|
#include "pmm.h"
|
|
#include "paging.h"
|
|
#include "kmalloc.h"
|
|
#include "driver.h"
|
|
|
|
void offset_print(const char *str)
|
|
{
|
|
while (*str) {
|
|
outb(0xE9, *str);
|
|
str++;
|
|
}
|
|
}
|
|
|
|
void print_hex(uint32_t val)
|
|
{
|
|
const char *hex = "0123456789ABCDEF";
|
|
outb(0xE9, '0');
|
|
outb(0xE9, 'x');
|
|
for (int i = 28; i >= 0; i -= 4) {
|
|
outb(0xE9, hex[(val >> i) & 0xF]);
|
|
}
|
|
outb(0xE9, '\n');
|
|
}
|
|
|
|
void kernel_main(uint32_t magic, uint32_t addr) {
|
|
if (magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
|
|
offset_print("Invalid magic number: ");
|
|
print_hex(magic);
|
|
return;
|
|
}
|
|
|
|
offset_print("Booting...\n");
|
|
|
|
init_gdt();
|
|
offset_print("GDT initialized\n");
|
|
|
|
init_idt();
|
|
offset_print("IDT initialized\n");
|
|
|
|
init_pic();
|
|
offset_print("PIC initialized\n");
|
|
|
|
init_pmm(addr);
|
|
offset_print("PMM initialized\n");
|
|
|
|
init_paging();
|
|
offset_print("Paging initialized\n");
|
|
|
|
/* Test paging: allocate a page and write to it */
|
|
void *test_page = paging_alloc_page();
|
|
if (test_page) {
|
|
offset_print("Allocated virtual page at: ");
|
|
print_hex((uint32_t)test_page);
|
|
*((volatile uint32_t *)test_page) = 0xDEADBEEF;
|
|
offset_print("Virtual page write/read OK\n");
|
|
paging_free_page(test_page);
|
|
} else {
|
|
offset_print("FAILED to allocate virtual page\n");
|
|
}
|
|
|
|
init_kmalloc();
|
|
offset_print("Memory allocator initialized\n");
|
|
|
|
init_drivers();
|
|
offset_print("Drivers initialized\n");
|
|
|
|
/* Test kmalloc/kfree */
|
|
uint32_t *test_alloc = (uint32_t *)kmalloc(64);
|
|
if (test_alloc) {
|
|
*test_alloc = 42;
|
|
offset_print("kmalloc(64) = ");
|
|
print_hex((uint32_t)test_alloc);
|
|
kfree(test_alloc);
|
|
offset_print("kfree OK\n");
|
|
} else {
|
|
offset_print("FAILED to kmalloc\n");
|
|
}
|
|
|
|
/* Enable interrupts */
|
|
asm volatile("sti");
|
|
offset_print("Interrupts enabled\n");
|
|
|
|
offset_print("Hello, world\n");
|
|
}
|