ableos/kernel/src/arch/x86_64/mod.rs

210 lines
5.6 KiB
Rust

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;
pub mod graphics;
pub(crate) mod interrupts;
pub 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(400, 400, 700, 100, 50);
// dis.set_color(Rgb888::new(100, 23, 100));
// dis.line(100, 100, 400, 400, 3);
// dis.line(100, 100, 700, 100, 1);
dis.set_color(Rgb888::YELLOW);
let thick = 3;
let p1 = (400, 30);
let p2 = (200, 150);
let p3 = (600, 150);
let p4 = (200, 350);
let p5 = (600, 350);
let p6 = (400, 470);
{
//HEXAGON
dis.line(p1.0, p1.1, p2.0, p2.1, thick);
dis.line(p1.0, p1.1, p3.0, p3.1, thick);
dis.line(p2.0, p2.1, p4.0, p4.1, thick);
dis.line(p3.0, p3.1, p5.0, p5.1, thick);
dis.line(p6.0, p6.1, p4.0, p4.1, thick);
dis.line(p6.0, p6.1, p5.0, p5.1, thick);
}
{
dis.line(600, 150, 200, 350, thick);
dis.line(600, 350, 400, 250, thick);
}
{
dis.set_color(Rgb888::WHITE);
let hp1 = (350, 150);
let hp2 = (350, 350);
let hp3 = (450, 250);
let hp4 = (350, 250);
let hp5 = (450, 150);
let hp6 = (450, 350);
dis.line(hp1.0, hp1.1, hp2.0, hp2.1, thick);
dis.line(hp3.0, hp3.1, hp4.0, hp4.1, thick);
dis.line(hp5.0, hp5.1, hp6.0, hp6.1, thick);
}
dis.swap_buffers();
}
let rand = xml::XMLElement::new("Random");
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,
)
}),
)
}
use embedded_graphics::prelude::WebColors;
/// 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
}
pub fn get_edid() {}