Files
XunilOS/kernel/src/main.rs
T
csd4ni3l 17f2a3c7e4 Update template to newest version which fixes edk2, make aarch64 compile
(nothing yet) by stubbing lots of functions and modules, make the frame
allocator and heap multiarch, make kernel panic print inside of serial
on x86_64
2026-05-14 18:46:17 +02:00

162 lines
4.8 KiB
Rust

#![no_std]
#![no_main]
#![cfg_attr(target_arch = "x86_64", feature(abi_x86_interrupt))]
#![feature(naked_functions_rustic_abi)]
extern crate alloc;
use core::fmt::Write;
use limine::BaseRevision;
use limine::request::{
DateAtBootRequest, FramebufferRequest, HhdmRequest, MemoryMapRequest, RequestsEndMarker,
RequestsStartMarker,
};
pub mod arch;
pub mod driver;
pub mod mm;
pub mod task;
pub mod util;
use crate::arch::arch::{infinite_idle, init, kernel_crash, run_elf};
use crate::driver::graphics::base::rgb;
use crate::driver::graphics::framebuffer::{init_framebuffer, with_framebuffer};
use crate::driver::keyboard::init_keyboard;
use crate::driver::serial::{ConsoleWriter, init_serial_console, with_serial_console};
use crate::driver::timer::TIMER;
use crate::util::serial_print;
#[repr(C, align(16))]
struct AlignedElf([u8; include_bytes!("../../assets/init").len()]);
static INIT_ELF: AlignedElf = AlignedElf(*include_bytes!("../../assets/init"));
static INIT_ELF_BYTES: &[u8] = &INIT_ELF.0;
/// Sets the base revision to the latest revision supported by the crate.
/// See specification for further info.
/// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler.
#[used]
// The .requests section allows limine to find the requests faster and more safely.
#[unsafe(link_section = ".requests")]
static BASE_REVISION: BaseRevision = BaseRevision::new();
#[used]
#[unsafe(link_section = ".requests")]
static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
static HHDM_REQUEST: HhdmRequest = HhdmRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
static MEMORY_MAP_REQUEST: MemoryMapRequest = MemoryMapRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
static DATE_AT_BOOT_REQUEST: DateAtBootRequest = DateAtBootRequest::new();
/// Define the stand and end markers for Limine requests.
#[used]
#[unsafe(link_section = ".requests_start_marker")]
static _START_MARKER: RequestsStartMarker = RequestsStartMarker::new();
#[used]
#[unsafe(link_section = ".requests_end_marker")]
static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new();
#[macro_export]
macro_rules! print {
($($arg:tt)*) => {
$crate::_print(core::format_args!($($arg)*))
};
}
#[macro_export]
macro_rules! println {
() => {
$crate::_print(core::format_args!("\n"))
};
($($arg:tt)*) => {
$crate::_print(core::format_args!("{}\n", core::format_args!($($arg)*)))
};
}
#[doc(hidden)]
pub fn _print(args: core::fmt::Arguments) {
with_framebuffer(|fb| {
with_serial_console(|console| {
let mut writer = ConsoleWriter {
fb,
console,
should_center: false,
};
let _ = writer.write_fmt(args);
});
});
}
#[unsafe(no_mangle)]
unsafe extern "C" fn kmain() -> ! {
// All limine requests must also be referenced in a called function, otherwise they may be
// removed by the linker.
assert!(BASE_REVISION.is_supported());
if let Some(hhdm_response) = HHDM_REQUEST.get_response() {
if let Some(memory_map_response) = MEMORY_MAP_REQUEST.get_response() {
init(hhdm_response, memory_map_response);
} else {
kernel_crash(); // Could not get required info from Limine's memory map.
}
} else {
kernel_crash(); // Could not get required info from Limine's higher-half direct mapping.
}
if let Some(framebuffer_response) = FRAMEBUFFER_REQUEST.get_response() {
if let Some(limine_framebuffer) = framebuffer_response.framebuffers().next() {
init_framebuffer(&limine_framebuffer);
#[cfg(target_arch = "x86_64")]
with_framebuffer(|fb| fb.setup_x86_64());
}
}
init_serial_console();
init_keyboard();
if let Some(date_at_boot_response) = DATE_AT_BOOT_REQUEST.get_response() {
TIMER.set_date_at_boot(date_at_boot_response.timestamp().as_secs());
} else {
println!("Could not get date at boot. Will default to 0.")
}
#[cfg(target_arch = "x86_64")]
run_elf(INIT_ELF_BYTES, false);
loop {}
}
#[panic_handler]
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
#[cfg(target_arch = "x86_64")]
{
serial_print("\nKERNEL PANIC:\n");
serial_print(_info.message().as_str().unwrap());
serial_print("\n");
}
with_framebuffer(|mut fb| {
fb.clear(rgb(180, 0, 0));
with_serial_console(|console| {
console.clear();
let mut writer = ConsoleWriter {
fb: &mut fb,
console,
should_center: true,
};
let _ = writer.write_str("KERNEL PANIC\n\n");
let _ = writer.write_fmt(core::format_args!("{}", _info));
});
});
infinite_idle();
}