gila/src/kernel/main.rs

204 lines
6.6 KiB
Rust

// Copyright (c) 2025 shibedrill
// SPDX-License-Identifier: GPL-3.0-or-later
#![no_std]
#![no_main]
#![feature(allocator_api)]
#![feature(abi_x86_interrupt)]
mod arch;
mod boot;
mod constants;
mod device;
mod interrupt;
#[macro_use]
mod log;
mod memory;
mod panic;
mod process;
#[macro_use]
mod util;
#[cfg(target_arch = "x86_64")]
use arch::x86_64::serial::Serialport;
use boot::{modules::*, params, *};
use constants::*;
use limine::firmware_type::FirmwareType;
use log::*;
use memory::alloc::{format, string::*, vec};
use memory::{HHDM_RESPONSE, MEMMAP_REQUEST};
use params::*;
use limine::memory_map::EntryType;
#[allow(unused_imports)]
use lzma_rs::lzma_decompress;
#[unsafe(no_mangle)]
unsafe extern "C" fn main() -> ! {
// Assert supported bootloader version
assert!(BASE_REVISION.is_supported());
// Set up logging level from params
// Nothing we can do here if this fails since no log subscribers are initialized yet
if let Some(level) = PARAMS.get("-loglevel")
&& let Ok(parsed_level) = LogLevel::try_from(level.as_str())
{
LOGGER.set_level(parsed_level);
}
// Add subscribers to logger
if let Some(device) = PARAMS.get("-logdev") {
let log_device_list: vec::Vec<&str> = device.split(',').collect();
if log_device_list.contains(&"display") {
// Append display console to log subs
}
if log_device_list.contains(&"serial") {
// TODO: Set up device discovery
#[cfg(target_arch = "x86_64")]
LOGGER.add_subscriber(Serialport::new(0x3f8));
}
log_trace!("Boot: Configured kernel logging devices");
}
log_info!(
"Boot: Kernel cmdline: {}",
String::from_utf8_lossy(
limine::file::File::string(EXECUTABLE_FILE_RESPONSE.file()).to_bytes()
)
);
log_info!(
"Boot: Kernel file path: {}",
String::from_utf8_lossy(EXECUTABLE_FILE_RESPONSE.file().path().to_bytes())
);
log_info!("Boot: Booting gila version {}", kernel_version_string());
log_info!("Boot: Enabled features: {}", FEATURE_FLAGS.to_string());
match boot::FIRMWARE_TYPE_REQUEST.get_response() {
Some(resp) => log_info!(
"Boot: Firmware type: {}",
match resp.firmware_type() {
FirmwareType::SBI => "SBI",
FirmwareType::UEFI_32 => "UEFI (32-bit)",
FirmwareType::UEFI_64 => "UEFI (64-bit)",
FirmwareType::X86_BIOS => "x86 BIOS",
_ => "Unknown",
}
),
None => log_warning!("Boot: Firmware type: No response"),
}
log_info!("Boot: Trans rights!");
device::init_statics();
if let Some(framebuffer_response) = FRAMEBUFFER_REQUEST.get_response() {
let fb = framebuffer_response.framebuffers().next().unwrap();
log_info!("Boot: Framebuffer response received");
log_trace!(
"Boot: Framebuffer dimensions: {}x{}, {} bits per pixel",
fb.width(),
fb.height(),
fb.bpp()
);
} else {
log_info!("Boot: Framebuffer response absent, graphics disabled",);
}
let smp_response = MP_REQUEST.get_response();
match smp_response {
None => log_info!("MP: Multiprocessing response not received"),
Some(resp) => {
log_info!("MP: Multiprocessing response received");
log_trace!("MP: {} CPUs found", resp.cpus().len());
}
}
if !MODULE_RESPONSE.modules().is_empty() {
let mut log_msg: String = String::from("Boot: Kernel modules list:\n");
for module in MODULE_RESPONSE.modules() {
log_msg.push_str(&format!(
"\t\t{}",
String::from_utf8_lossy(module.path().to_bytes())
));
}
log_trace!("{log_msg}")
}
// 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!("Boot: Memory map received");
if !mmap_response.entries().is_empty() {
let mut log_msg: String = String::from("Boot: 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!(
"\n\t\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:\n\t\tFree: {usable}\n\t\tAvailable: {reclaimable}\n\t\tUsable: {}\n\t\tHardware: {hardware}\n\t\tUnusable: {unusable}\n\t\tTotal: {}",
usable + reclaimable,
total
);
} else {
panic!("Memory map contains no entries");
}
log_info!("HHDM offset: 0x{:X}", HHDM_RESPONSE.offset());
panic!("Bailing");
#[allow(unreachable_code)]
loop {
for _i in 0..50000000u64 {
crate::arch::asm::nop();
}
core::hint::black_box(());
log_trace!("Heartbeat");
}
}