#![no_std] #![feature(abi_x86_interrupt)] #![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::{ // TODO: Fix nesting under `arch`. A lot of code does not NEED to run on // x86_64. Note that the panic handler does. arch::x86_64::{ cpu::apic::enable_apic, drivers::{ ascii::screensize_chars, framebuffer::display::screensize_px, }, memory::{ FRAME_ALLOCATOR, allocation::{ heap_alloc::init_heap, page_alloc::FoundryOSFrameAllocator, }, init_page_table, units::MemoryUnits, }, }, prelude::*, }; use arch::x86_64::memory::mapping; use core::arch::asm; use limine::BaseRevision; use x86_64::VirtAddr; pub mod arch; pub mod resources; #[allow(unused)] // We aren't using much of this right now. pub mod std; pub mod util; pub mod prelude { pub use crate::{ debug, debugln, eprint, eprintln, print, print_log, println, println_log, serial_print, serial_println, std::debug::_debug, std::io::{_print, _print_err, _print_log, _serial_write}, }; } /// 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"); } } } /// 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. pub fn boot() -> Result<(), &'static str> { if !BASE_REVISION.is_supported() { return Err("Base revision not supported"); } use arch::x86_64::{gdt, interrupts}; 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..."); let dimensions = screensize_chars(); let dimensions2 = screensize_px(); debugln!(" => (px) : {}x{} ", dimensions2.0, dimensions2.1); debugln!(" => (chars) : {}x{} ", dimensions.0, dimensions.1); debugln!(" [Success]"); 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) ); debugln!("[Success]"); debugln!(" Initialising Heap... "); if unsafe { init_heap() }.is_err() { return Err("Failed to initialise heap: error"); } debugln!(" [Success]"); // 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(()) }