161 lines
5.4 KiB
Rust
161 lines
5.4 KiB
Rust
#![no_std]
|
|
#![no_main]
|
|
|
|
pub mod limine_requests;
|
|
pub mod drivers;
|
|
pub mod arch;
|
|
pub mod mm;
|
|
pub mod ipc;
|
|
pub mod sched;
|
|
pub mod loader;
|
|
|
|
use core::panic::PanicInfo;
|
|
use limine_requests::*;
|
|
use sched::SCHEDULER;
|
|
|
|
// Include assembly trampolines directly into the binary
|
|
core::arch::global_asm!(include_str!("../asm/context.S"));
|
|
core::arch::global_asm!(include_str!("../asm/syscall_entry.S"));
|
|
core::arch::global_asm!(include_str!("../asm/ring3_enter.S"));
|
|
core::arch::global_asm!(include_str!("../asm/timer_isr.S"));
|
|
core::arch::global_asm!(include_str!("../asm/keyboard_isr.S"));
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn _start() -> ! {
|
|
// 1. Early Serial Initialization
|
|
drivers::serial::SerialPort::init();
|
|
|
|
kprintln!("\n=======================================================");
|
|
kprintln!(" opencoreC Microkernel v0.1.0 (x86_64)");
|
|
kprintln!("=======================================================");
|
|
|
|
// 2. Validate Limine Base Revision
|
|
unsafe {
|
|
if limine_base_revision[2] != 0 {
|
|
kprintln!("[WARN] Limine Base Revision 3 not supported by bootloader.");
|
|
}
|
|
}
|
|
|
|
// 3. Obtain Limine responses
|
|
let hhdm_offset = get_hhdm_offset().expect("Limine HHDM response missing");
|
|
let memmap_resp = unsafe { MEMMAP_REQUEST.response };
|
|
let kernel_addr_resp = unsafe { KERNEL_ADDRESS_REQUEST.response };
|
|
|
|
kprintln!("[BOOT] Limine HHDM Base Virtual Address: {:#018x}", hhdm_offset);
|
|
if !kernel_addr_resp.is_null() {
|
|
unsafe {
|
|
kprintln!("[BOOT] Kernel Physical Base: {:#018x}, Virtual Base: {:#018x}",
|
|
(*kernel_addr_resp).physical_base,
|
|
(*kernel_addr_resp).virtual_base
|
|
);
|
|
}
|
|
}
|
|
unsafe {
|
|
kprintln!("[DBG] MEMMAP resp ptr: {:#018x}", MEMMAP_REQUEST.response as u64);
|
|
kprintln!("[DBG] MODULE resp ptr: {:#018x}", MODULE_REQUEST.response as u64);
|
|
kprintln!("[DBG] SMP resp ptr: {:#018x}", SMP_REQUEST.response as u64);
|
|
}
|
|
|
|
// 4. Initialize Architecture (GDT, IDT, Syscall MSRs, SMP)
|
|
kprintln!("[BOOT] Initializing GDT, IDT, Fast-Path Syscall MSRs & SMP...");
|
|
unsafe {
|
|
arch::init();
|
|
}
|
|
kprintln!("[BOOT] CPU Subsystem Configured.");
|
|
|
|
// 5. Initialize Memory Subsystem (Physical Frame Allocator + Virtual Memory Manager)
|
|
kprintln!("[BOOT] Initializing Physical Frame Allocator & Paging...");
|
|
unsafe {
|
|
mm::init(memmap_resp);
|
|
}
|
|
|
|
// 6. Initialize Preemptive Hardware Timer (PIT 8254 @ 100 Hz)
|
|
kprintln!("[BOOT] Configuring PIT 8254 timer for Preemptive Multi-Tasking...");
|
|
unsafe {
|
|
drivers::timer::init(100);
|
|
drivers::keyboard::init();
|
|
}
|
|
|
|
// 7. Initialize IPC & Capability System
|
|
ipc::init();
|
|
|
|
// 8. Initialize Scheduler
|
|
sched::init();
|
|
|
|
// 9. Bring up SMP Cores (APs)
|
|
unsafe {
|
|
arch::smp::boot_aps();
|
|
}
|
|
|
|
// 10. Inspect and Load Initial Userspace Processes
|
|
unsafe {
|
|
let mod_resp = MODULE_REQUEST.response;
|
|
if !mod_resp.is_null() && (*mod_resp).module_count > 0 {
|
|
let count = (*mod_resp).module_count;
|
|
kprintln!("[BOOT] Detected {} userspace boot modules. Creating tasks...", count);
|
|
|
|
let sched_ptr = core::ptr::addr_of_mut!(SCHEDULER);
|
|
|
|
for i in 0..count {
|
|
let mod_file = *(*mod_resp).modules.add(i as usize);
|
|
let elf_slice = core::slice::from_raw_parts((*mod_file).address, (*mod_file).size as usize);
|
|
let name = match i {
|
|
0 => "init_server",
|
|
1 => "uart_driver",
|
|
2 => "sh",
|
|
_ => "user_server",
|
|
};
|
|
|
|
match loader::elf::load_elf(elf_slice, hhdm_offset) {
|
|
Ok(proc) => {
|
|
let tid = (*sched_ptr).create_user_thread(
|
|
name,
|
|
proc.entry_rip,
|
|
proc.user_rsp,
|
|
proc.pml4_paddr,
|
|
proc.kernel_stack_top,
|
|
);
|
|
kprintln!("[BOOT] Registered Preemptible Thread '{}' with TID {:?}", name, tid);
|
|
}
|
|
Err(err) => {
|
|
kprintln!("[ERROR] Failed to load module [{}]: {}", i, err);
|
|
}
|
|
}
|
|
}
|
|
|
|
kprintln!("[BOOT] Enabling Interrupts & Starting Preemptive Scheduler...");
|
|
kprintln!("-------------------------------------------------------");
|
|
|
|
// Pick first ready thread and switch to it with interrupts enabled
|
|
(*sched_ptr).schedule();
|
|
} else {
|
|
kprintln!("[BOOT] No userspace modules detected. Staying in Ring 0 idle loop.");
|
|
}
|
|
}
|
|
|
|
// Idle loop: wait for interrupts and let threads execute
|
|
loop {
|
|
unsafe {
|
|
core::arch::asm!("sti; hlt");
|
|
}
|
|
}
|
|
}
|
|
|
|
#[panic_handler]
|
|
fn panic(info: &PanicInfo) -> ! {
|
|
kprintln!("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
|
kprintln!(" KERNEL PANIC DETECTED ");
|
|
kprintln!("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
|
if let Some(location) = info.location() {
|
|
kprintln!("Location: {}:{}:{}", location.file(), location.line(), location.column());
|
|
}
|
|
kprintln!("Message: {}", info.message());
|
|
kprintln!("Halting CPU core.");
|
|
|
|
loop {
|
|
unsafe {
|
|
core::arch::asm!("cli; hlt");
|
|
}
|
|
}
|
|
}
|