Files
2025-03-10 13:35:27 +00:00

162 lines
4.0 KiB
Rust

#![no_std]
#![feature(abi_x86_interrupt, breakpoint)]
#![warn(
clippy::correctness,
clippy::nursery,
clippy::unnecessary_cast,
clippy::all,
clippy::suspicious,
clippy::perf,
rustdoc::missing_errors_doc,
rustdoc::missing_panics_doc
)]
extern crate alloc;
use crate::{
arch::x86_64::{
// cpu::apic::enable_apic,
drivers::{
ascii::screensize_chars, framebuffer::display::screensize_px,
},
gdt,
interrupts,
memory::{
FRAME_ALLOCATOR,
allocation::{
heap_alloc::init_heap, page_alloc::FoundryOSFrameAllocator,
},
init_page_table, mapping,
units::MemoryUnits,
},
},
prelude::*,
};
use alloc::{boxed::Box, format};
use core::arch::asm;
use limine::BaseRevision;
use x86_64::VirtAddr;
pub mod arch;
/// Commonly used re-exports.
pub mod prelude;
pub mod resources;
// We aren't using much of this right now.
#[allow(unused)]
pub mod std;
mod step;
pub mod util;
/// 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();
pub fn hcf() -> ! {
loop {
unsafe {
#[cfg(target_arch = "x86_64")]
asm!("hlt");
}
}
}
#[derive(Debug)]
pub struct NoError {}
impl core::fmt::Display for NoError {
fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
Ok(())
}
}
pub struct NoTags;
impl core::error::Error for NoError {}
/// Panicking before this is initialised is unwise. We should probably extract
/// very early init into it's own function because Stack Traces may require
/// allocations etc.
#[inline(never)]
pub fn boot() -> Result<(), Box<dyn core::error::Error>> {
if !BASE_REVISION.is_supported() {
return Err("Base revision not supported.".into());
}
let memory_map = mapping::get_memory_map();
print_log!(" Initialising Serial... ");
let res = arch::x86_64::drivers::serial::init();
serial_print!(" Initialising Serial... ");
if res.is_err() {
debugln!("[Not Detected]")
} else {
debugln!("[Success]");
}
debugln!(
"Display is {:?} chars, {:?} px.",
screensize_chars(),
screensize_px()
);
debug!(" Setting Up Global Descriptor Table... ");
gdt::init();
debugln!("[Success]");
debug!(" Setting Up Interrupt Descriptor Table... ");
interrupts::init_idt();
debugln!("[Success]");
debugln!(" Initialising Memory Subsystem... ");
let physical_memory_offset =
VirtAddr::new(*mapping::PHYSICAL_MEMORY_OFFSET);
init_page_table(physical_memory_offset);
FoundryOSFrameAllocator::init(memory_map);
let available_bytes =
FRAME_ALLOCATOR.get().unwrap().lock().available_memory();
debugln!(
" => Available Memory: {}",
MemoryUnits::from_bytes(available_bytes as usize)
);
// Allocations should be all fine past this point.
debugln!(" Initialising Heap... ");
match unsafe { init_heap() } {
Ok(_) => debugln!(" [Success]"),
Err(why) => return Err(format!("{:?}", why).into()),
}
debug!(" Enabling PICs... ");
interrupts::enable_pic();
debugln!("[Success]");
// debug!(" Disabling PICs... ");
// interrupts::disable_pic();
// debugln!("[Success]");
// debug!(" Initialising APIC... ");
// enable_apic();
// debugln!("[Success]");
debug!(" Enabling Interrupts... ");
x86_64::instructions::interrupts::enable();
debugln!("[Success]");
Ok(())
}
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo<'_>) -> ! {
debugln!("{:?}", _info);
hcf()
}