// Copyright (c) 2025 shibedrill // SPDX-License-Identifier: MIT const PAGE_SIZE: usize = 4096; use crate::boot::modules::MODULE_RESPONSE; use crate::boot::params::EXECUTABLE_FILE_RESPONSE; use crate::{LOGGER, LogLevel, format}; use alloc::string::String; use lazy_static::lazy_static; use limine::memmap::*; use limine::request::{ExecutableAddressRequest, HhdmRepsonse, HhdmRequest}; use limine::request::{MemmapRequest, MemmapResponse}; use talc::*; pub extern crate alloc; pub mod paging; lazy_static! { pub static ref MEMMAP_RESPONSE: &'static MemmapResponse = MEMMAP_REQUEST .response() .expect("Bootloader did not supply memory map"); } pub fn log_memory() { if !MEMMAP_RESPONSE.entries().is_empty() { let mut log_msg: String = String::from("Memory map:"); let mut usable: u64 = 0; let mut reclaimable: u64 = 0; let mut hardware: u64 = 0; let mut unusable: u64 = 0; for entry in MEMMAP_RESPONSE.entries() { log_msg.push_str(&format!( "\n\t0x{:x} bytes ({} pages) @ 0x{:x}: {}", entry.length, entry.length as usize / PAGE_SIZE, entry.base, match entry.type_ { MEMMAP_ACPI_NVS => { hardware += entry.length; "ACPI (reserved)" } MEMMAP_ACPI_RECLAIMABLE => { reclaimable += entry.length; "ACPI (reclaimable)" } MEMMAP_BAD_MEMORY => { unusable += entry.length; "damaged/unusable" } MEMMAP_BOOTLOADER_RECLAIMABLE => { reclaimable += entry.length; "bootloader (reclaimable)" } MEMMAP_EXECUTABLE_AND_MODULES => { unusable += entry.length; "executable & modules" } MEMMAP_FRAMEBUFFER => { hardware += entry.length; "framebuffer" } MEMMAP_RESERVED => { unusable += entry.length; "reserved" } MEMMAP_USABLE => { usable += entry.length; "usable" } _ => "unidentified", } )); } log_trace!("{log_msg}"); let total = usable + reclaimable + hardware + unusable; log_info!( "Memory report: \n\tFree: 0x{usable:x}\n\tAvailable: 0x{reclaimable:x}\n\tUsable: 0x{:x}\n\tHardware: 0x{hardware:x}\n\tUnusable: 0x{unusable:x}\n\tTotal: 0x{total:x}", usable + reclaimable, ); } else { panic!("Memory map contains no entries"); } } pub fn log_address() { if let Some(resp) = ADDRESS_REQUEST.response() { log_info!("Kernel physical start address: 0x{:x}", resp.physical_base); log_info!("Kernel virtual start address: 0x{:x}", resp.virtual_base); log_info!( "Kernel physical start address (calculated): 0x{:x}", 0i64 - resp.virtual_base as i64 + resp.physical_base as i64 ); } else { log_warning!("No kernel address response provided."); } log_info!( "Higher Half direct map offset: 0x{:x}", HHDM_RESPONSE.offset ); } // Have to initialize all of these before reclaiming bootloader memory pub fn init_statics() { let _ = EXECUTABLE_FILE_RESPONSE; let _ = HHDM_RESPONSE; let _ = MODULE_RESPONSE; let _ = MEMMAP_RESPONSE; } #[used] #[unsafe(link_section = ".requests")] pub static ADDRESS_REQUEST: ExecutableAddressRequest = limine::request::ExecutableAddressRequest::new(); #[used] #[unsafe(link_section = ".requests")] pub static MEMMAP_REQUEST: MemmapRequest = limine::request::MemmapRequest::new(); #[used] #[unsafe(link_section = ".requests")] pub static HHDM_REQUEST: HhdmRequest = limine::request::HhdmRequest::new(); lazy_static! { pub static ref HHDM_RESPONSE: &'static HhdmRepsonse = HHDM_REQUEST .response() .expect("Did not get HHDM response from bootloader"); } // TODO: 1mb kernel heap. Need to figure out how to make this less stupid... static mut ARENA: [u8; 100000] = [0; 100000]; #[global_allocator] static ALLOCATOR: Talck, ClaimOnOom> = Talc::new(unsafe { ClaimOnOom::new(Span::from_array(core::ptr::addr_of!(ARENA).cast_mut())) }) .lock();