use {limine::SmpRequest, xml::XMLElement}; use embedded_graphics::pixelcolor::Rgb888; use crate::{arch::x86_64::graphics::DISPLAY, kmain::DEVICE_TREE}; pub mod memory; mod cpuid; mod gdt; mod graphics; pub(crate) mod interrupts; mod logging; pub mod pci; pub mod virtio; pub use {logging::log, memory::PAGE_SIZE}; use { crate::allocator, limine::{HhdmRequest, KernelFileRequest, MemmapRequest, ModuleRequest}, x86_64::VirtAddr, }; extern "C" { fn _initial_kernel_heap_start(); fn _initial_kernel_heap_size(); } const INITIAL_KERNEL_HEAP_START: *mut u8 = _initial_kernel_heap_start as _; const INITIAL_KERNEL_HEAP_SIZE: *const () = _initial_kernel_heap_size as _; #[no_mangle] unsafe extern "C" fn _kernel_start() -> ! { logging::init(); crate::logger::init().expect("failed to set logger"); log::info!("Initialising AKern {}", crate::VERSION); static HDHM_REQ: HhdmRequest = HhdmRequest::new(0); memory::init_pt(VirtAddr::new( HDHM_REQ .get_response() .get() .expect("tried to get physical memory mapping offset from Limine") .offset, )); allocator::init(INITIAL_KERNEL_HEAP_START, INITIAL_KERNEL_HEAP_SIZE as _); static MMAP_REQ: MemmapRequest = MemmapRequest::new(0); memory::initialize( MMAP_REQ .get_response() .get() .expect("tried to get memory map from Limine") .memmap(), ); gdt::init(); interrupts::init(); static KFILE_REQ: KernelFileRequest = KernelFileRequest::new(0); static MOD_REQ: ModuleRequest = ModuleRequest::new(0); static SMP: SmpRequest = SmpRequest::new(0); let smp = SMP.get_response().get().unwrap(); use crate::alloc::string::ToString; let cpuinfo = cpuid::master().unwrap(); let brand_string = cpuinfo.brand_string().unwrap_or("Unknown").to_string(); DEVICE_TREE.force_unlock(); pci::init(); let mut dt = DEVICE_TREE.lock(); let cpus = dt.devices.get_mut("CPUs").unwrap(); let mut cpu = XMLElement::new("cpu"); let core_count = smp.cpu_count.to_string(); cpu.set_attribute("core count", core_count); cpu.set_attribute("brand string", brand_string); let cpu_speed = 0; cpu.set_attribute("speed", "Unknown"); if false { // disable() // disable interrupts (if still not done) let i = 0; let start = cpuinfo.time_stamp_counter(); log::info!("{:?}", start.unwrap().invariant_tsc()); for x in 0..1000 {} let end = cpuinfo.time_stamp_counter(); } let mut cpu_features = xml::XMLElement::new("CPU Features"); { let x2 = cpuinfo.x2apic(); let apic = cpuinfo.apic(); let avx = cpuinfo.avx(); cpu_features.set_attribute("apic", apic.to_string()); cpu_features.set_attribute("avx", apic.to_string()); cpu_features.set_attribute("x2apic", x2.to_string()); } cpu.set_child(cpu_features); cpus.push(cpu); drop(dt); // Graphics test { graphics::init(); let mut dis = DISPLAY.lock(); use {able_graphics_library::raw_pixel, embedded_graphics::prelude::RgbColor}; dis.set_color(Rgb888::GREEN); dis.line(1, 1, 10, 10, 4); // dis.line(1, 200, 100, 10, 1); // dis.line(1, 1, 200, 10, 1); } crate::kmain::kmain( KFILE_REQ .get_response() .get() .and_then(|r| r.kernel_file.get()) .expect("failed to get kernel file from Limine") .cmdline .to_str() .map(core::ffi::CStr::to_str) .transpose() .expect("expected valid cmdline string") .unwrap_or_default(), MOD_REQ .get_response() .get() .and_then(|m| m.modules().get(0)) .map(|file| unsafe { core::slice::from_raw_parts( file.base.as_ptr().expect("invalid initrd"), file.length as usize, ) }), ) } /// Spin loop pub fn sloop() -> ! { loop { x86_64::instructions::hlt(); } } pub fn hardware_random_u64() -> u64 { use {log::trace, rdrand::RdRand}; let gen = RdRand::new().unwrap(); let ret = gen.try_next_u64().unwrap(); trace!("Random {}", ret); ret }