// Copyright (c) 2025 shibedrill // SPDX-License-Identifier: GPL-3.0-or-later use crate::constants::NEWLINE; use crate::memory::alloc::boxed::Box; use crate::{LOGGER, LogLevel, format, log_info, log_trace}; use alloc::string::String; use core::pin::*; use lazy_static::lazy_static; use limine::{ memory_map::EntryType, request::{ExecutableAddressRequest, HhdmRequest, MemoryMapRequest, PagingModeRequest}, response::HhdmResponse, }; use talc::*; pub extern crate alloc; pub struct FreeFrameBlockList { head: Option>>, } impl FreeFrameBlockList { pub fn push(&mut self) { if let Some(inner) = &self.head { } else { } } } // This structure represents a set of // contiguous free page frames pub struct FreeFrameBlock { /// Number of contiguous 4KiB frames this block holds num_frames: usize, /// Pointer to the next block next_block: Option>>, } impl FreeFrameBlock { fn num_frames(&self) -> usize { self.num_frames } fn next_block(&self) -> &Option>> { &self.next_block } } pub fn log_memory() { // Panic if this is absent. It's needed to set up the GDT and paging let mmap_response = MEMMAP_REQUEST .get_response() .expect("Bootloader did not supply memory map"); log_info!("Memory map received"); if !mmap_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 mmap_response.entries() { log_msg.push_str(&format!( "{NEWLINE}\t0x{:X} bytes @ 0x{:X}: {}", entry.length, entry.base, match entry.entry_type { EntryType::ACPI_NVS => { hardware += entry.length; "ACPI (reserved)" } EntryType::ACPI_RECLAIMABLE => { reclaimable += entry.length; "ACPI (reclaimable)" } EntryType::BAD_MEMORY => { unusable += entry.length; "damaged/unusable" } EntryType::BOOTLOADER_RECLAIMABLE => { reclaimable += entry.length; "bootloader (reclaimable)" } #[allow(unreachable_patterns, deprecated)] EntryType::EXECUTABLE_AND_MODULES | EntryType::KERNEL_AND_MODULES => { unusable += entry.length; "executable & modules" } EntryType::FRAMEBUFFER => { hardware += entry.length; "framebuffer" } EntryType::RESERVED => { unusable += entry.length; "reserved" } EntryType::USABLE => { usable += entry.length; "usable" } _ => "unidentified", } )); } log_trace!("{log_msg}"); let total = usable + reclaimable + hardware + unusable; log_info!( "Boot: Memory report: {NEWLINE}\tFree: 0x{usable:X}{NEWLINE}\tAvailable: 0x{reclaimable:X}{NEWLINE}\tUsable: 0x{:X}{NEWLINE}\tHardware: 0x{hardware:X}{NEWLINE}\tUnusable: 0x{unusable:X}{NEWLINE}\tTotal: 0x{total:X}", usable + reclaimable, ); } else { panic!("Memory map contains no entries"); } } pub fn log_address() { if let Some(resp) = ADDRESS_REQUEST.get_response() { log_info!( "Kernel physical start address: 0x{:X}", resp.physical_base() ); log_info!("Kernel virtual start address: 0x{:X}", resp.virtual_base()); } else { log_warning!("No kernel address response provided."); } log_info!( "Higher Half direct map offset: 0x{:X}", HHDM_RESPONSE.offset() ); } #[used] #[unsafe(link_section = ".requests")] pub static PAGING_REQUEST: PagingModeRequest = limine::request::PagingModeRequest::new(); #[used] #[unsafe(link_section = ".requests")] pub static ADDRESS_REQUEST: ExecutableAddressRequest = limine::request::ExecutableAddressRequest::new(); #[used] #[unsafe(link_section = ".requests")] pub static MEMMAP_REQUEST: MemoryMapRequest = limine::request::MemoryMapRequest::new(); #[used] #[unsafe(link_section = ".requests")] pub static HHDM_REQUEST: HhdmRequest = limine::request::HhdmRequest::new(); lazy_static! { pub static ref HHDM_RESPONSE: &'static HhdmResponse = HHDM_REQUEST .get_response() .expect("Did not get HHDM response from bootloader"); } // TODO: 10kb kernel heap. Need to figure out how to make this less stupid... static mut ARENA: [u8; 10000] = [0; 10000]; #[global_allocator] static ALLOCATOR: Talck, ClaimOnOom> = Talc::new(unsafe { ClaimOnOom::new(Span::from_array(core::ptr::addr_of!(ARENA).cast_mut())) }) .lock();