187 lines
5.4 KiB
Rust
187 lines
5.4 KiB
Rust
// Copyright (c) 2025 shibedrill
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#![no_std]
|
|
#![no_main]
|
|
#![feature(abi_x86_interrupt)]
|
|
|
|
mod arch;
|
|
mod boot;
|
|
mod constants;
|
|
mod interrupt;
|
|
#[macro_use]
|
|
mod log;
|
|
mod memory;
|
|
mod panic;
|
|
mod process;
|
|
mod util;
|
|
|
|
use arch::x86_64::interrupts::IDT;
|
|
use arch::x86_64::serial::SerialPort;
|
|
use boot::{BASE_REVISION, params, *};
|
|
use constants::*;
|
|
use log::*;
|
|
use memory::alloc::{boxed::Box, format, vec};
|
|
use params::*;
|
|
|
|
use lazy_static::lazy_static;
|
|
use limine::firmware::{
|
|
FIRMWARE_TYPE_EFI32, FIRMWARE_TYPE_EFI64, FIRMWARE_TYPE_SBI, FIRMWARE_TYPE_X86BIOS,
|
|
};
|
|
use spin::mutex::Mutex;
|
|
|
|
use crate::{
|
|
arch::{
|
|
asm,
|
|
x86_64::{
|
|
cpuid::{CPUID, virt_supported},
|
|
gdt::dump_gdt,
|
|
},
|
|
},
|
|
memory::HHDM_RESPONSE,
|
|
};
|
|
|
|
lazy_static! {
|
|
pub static ref SERIAL_3F8: Mutex<SerialPort> = Mutex::new(
|
|
arch::x86_64::serial::SerialPort::try_from_port(0x3f8).expect("Could not create port")
|
|
);
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
unsafe extern "C" fn main() -> ! {
|
|
// CRITICAL AREA
|
|
// Nothing non-essential should be done until we can initialize logging
|
|
// Otherwise it will fail silently
|
|
|
|
// 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.lock().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
|
|
let serial_logger = |msg: &str| SERIAL_3F8.lock().log_writeln(msg);
|
|
LOGGER.lock().add_device(Box::new(serial_logger));
|
|
}
|
|
log_trace!("Configured kernel logging devices");
|
|
}
|
|
|
|
// END OF CRITICAL AREA
|
|
// Fallible code can be placed below this comment
|
|
|
|
// Initialize all statics so the bootloader memory can be reclaimed
|
|
memory::init_statics();
|
|
|
|
// Ensure IDT exists
|
|
IDT.load();
|
|
|
|
log_info!(
|
|
"Kernel cmdline: {}",
|
|
EXECUTABLE_FILE_RESPONSE.executable_file().cmdline()
|
|
);
|
|
log_info!(
|
|
"Kernel file path: {}",
|
|
EXECUTABLE_FILE_RESPONSE.executable_file().path()
|
|
);
|
|
|
|
// Branding
|
|
for line in ASCII_LOGO {
|
|
let mut locked = SERIAL_3F8.lock();
|
|
locked.log_write("\t\t");
|
|
locked.log_writeln(line);
|
|
}
|
|
SERIAL_3F8
|
|
.lock()
|
|
.log_writeln("\tWelcome to the Gila microkernel!\n");
|
|
log_info!("Booting gila version {}", kernel_version_string());
|
|
|
|
match boot::FIRMWARE_TYPE_REQUEST.response() {
|
|
Some(resp) => log_info!(
|
|
"Firmware type: {}",
|
|
match resp.firmware_type {
|
|
FIRMWARE_TYPE_SBI => "SBI",
|
|
FIRMWARE_TYPE_EFI32 => "UEFI (32-bit)",
|
|
FIRMWARE_TYPE_EFI64 => "UEFI (64-bit)",
|
|
FIRMWARE_TYPE_X86BIOS => "x86 BIOS",
|
|
_ => "Unknown",
|
|
}
|
|
),
|
|
None => log_warning!("Firmware type: No response"),
|
|
}
|
|
|
|
log_info!("Trans rights!");
|
|
|
|
if let Some(framebuffer_response) = FRAMEBUFFER_REQUEST.response() {
|
|
let fb = framebuffer_response.framebuffers_rev1().unwrap()[0];
|
|
log_info!("Framebuffer response received");
|
|
for mode in fb.modes() {
|
|
log_trace!(
|
|
"Mode: {}x{}, {} bits per pixel",
|
|
mode.width,
|
|
mode.height,
|
|
mode.bpp
|
|
);
|
|
}
|
|
} else {
|
|
log_info!("Framebuffer response absent, graphics disabled",);
|
|
}
|
|
|
|
let smp_response = MP_REQUEST.response();
|
|
match smp_response {
|
|
None => log_info!("Multiprocessing response not received"),
|
|
Some(resp) => {
|
|
log_info!("Multiprocessing response received");
|
|
log_trace!("{} CPUs found", resp.cpus().len());
|
|
}
|
|
}
|
|
|
|
let rsdp_response = RSDP_REQUEST.response();
|
|
match rsdp_response {
|
|
None => log_info!("RDSP response not received"),
|
|
Some(resp) => {
|
|
log_info!("RSDP response received");
|
|
log_trace!("RSDT address: 0x{:x}", resp.address as usize)
|
|
}
|
|
}
|
|
|
|
boot::modules::log_modules();
|
|
|
|
memory::log_memory();
|
|
memory::log_address();
|
|
|
|
if let Some(string) = CPUID.get_processor_brand_string() {
|
|
log_info!("CPU brand string: {}", string.as_str());
|
|
}
|
|
if let Some(string) = CPUID.get_vendor_info() {
|
|
log_info!("CPU vendor: {}", string.as_str());
|
|
}
|
|
if let Some(string) = CPUID.get_hypervisor_info() {
|
|
log_info!("Hypervisor: {:?}", string.identify());
|
|
}
|
|
log_info!("Virtualization provider: {:?}", virt_supported());
|
|
|
|
let l4_start = x86_64::registers::control::Cr3::read().0.start_address();
|
|
log_info!("Physical address of current L4 table: 0x{:x}", l4_start);
|
|
log_info!(
|
|
"Virtual address of current L4 table: 0x{:x}",
|
|
l4_start.as_u64() + HHDM_RESPONSE.offset
|
|
);
|
|
|
|
//iter_table(4, &PML4);
|
|
log_info!("Long mode: {}", asm::long_mode());
|
|
dump_gdt();
|
|
|
|
panic!("Finished boot, but cannot start init because processes not implemented!");
|
|
}
|