Files
CappuccinOS/src/main.rs

251 lines
6.0 KiB
Rust

#![feature(abi_x86_interrupt, naked_functions, const_mut_refs)]
#![allow(clippy::needless_return)]
#![no_std]
#![no_main]
use core::ffi::CStr;
use alloc::vec::Vec;
use limine::KernelFileRequest;
use crate::drivers::fs::{
initramfs,
vfs::{vfs_open, UserCred},
};
extern crate alloc;
pub mod arch;
pub mod drivers;
pub mod libs;
pub mod mem;
pub static KERNEL_REQUEST: KernelFileRequest = KernelFileRequest::new(0);
#[no_mangle]
pub extern "C" fn _start() -> ! {
drivers::serial::init_serial();
arch::gdt::gdt_init();
arch::interrupts::idt_init();
arch::interrupts::exceptions::exceptions_init();
arch::interrupts::enable_interrupts();
// TODO: memory stuff
mem::pmm::pmm_init();
mem::init_allocator();
drivers::acpi::init_acpi();
kmain()
}
pub fn kmain() -> ! {
let _ = drivers::fs::vfs::add_vfs("/", alloc::boxed::Box::new(initramfs::init()));
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
drivers::pci::enumerate_pci_bus();
let mut file = vfs_open("/firstdir/seconddirbutlonger/yeah.txt").unwrap();
drivers::storage::ide::init();
let mut nested_file = vfs_open("/mnt/boot/limine/limine.cfg").unwrap();
crate::println!(
"LIMINE BOOT: {:X?}",
nested_file
.ops
.open(0, UserCred { uid: 0, gid: 0 }, nested_file.as_ptr())
);
// let file = vfs_open("/example.txt").unwrap();
crate::println!(
"YEAH.TXT: {:X?}",
&file
.ops
.open(0, UserCred { uid: 0, gid: 0 }, file.as_ptr())
.unwrap()
);
// as a sign that we didnt panic
draw_gradient();
// loop {
// let ch = read_serial();
// if ch == b'\x00' {
// continue;
// }
// if ch == b'\x08' {
// write_serial(b'\x08');
// write_serial(b' ');
// write_serial(b'\x08');
// }
// if ch > 0x20 && ch < 0x7F {
// write_serial(ch);
// }
// }
hcf();
}
fn draw_gradient() {
let fb = drivers::video::get_framebuffer().unwrap();
let length = (fb.height * fb.width) * (fb.bpp / 8);
let pages = length / crate::mem::pmm::PAGE_SIZE;
let buffer_ptr = crate::mem::PHYSICAL_MEMORY_MANAGER.alloc(pages);
if buffer_ptr.is_null() {
panic!("Failed to allocate screen buffer")
}
let buffer = unsafe {
core::slice::from_raw_parts_mut(
crate::mem::PHYSICAL_MEMORY_MANAGER
.alloc(pages)
.cast::<u32>(),
length,
)
};
for y in 0..fb.height {
for x in 0..fb.width {
let r = (255 * x) / (fb.width - 1);
let g = (255 * y) / (fb.height - 1);
let b = 255 - r;
let pixel = ((r as u32) << 16) | ((g as u32) << 8) | (b as u32);
buffer[((y * fb.pitch) / (fb.bpp / 8)) + x] = pixel
}
}
fb.blit_screen(buffer, None);
crate::mem::PHYSICAL_MEMORY_MANAGER.dealloc(buffer_ptr, pages);
}
#[macro_export]
macro_rules! println {
() => ($crate::print!("\n"));
($($arg:tt)*) => ($crate::print!("{}\n", &alloc::format!($($arg)*)));
}
#[macro_export]
macro_rules! print {
($($arg:tt)*) => (
$crate::drivers::serial::write_string(&alloc::format!($($arg)*).replace('\n', "\n\r"))
)
}
#[macro_export]
macro_rules! log_info {
($($arg:tt)*) => ($crate::println!("\x1B[97m[ \x1B[90m? \x1B[97m]\x1B[0m {}", &alloc::format!($($arg)*)));
}
#[macro_export]
macro_rules! log_serial {
($($arg:tt)*) => (
$crate::drivers::serial::write_string(&alloc::format!($($arg)*).replace('\n', "\n\r"))
);
}
#[macro_export]
macro_rules! log_error {
($($arg:tt)*) => ($crate::println!("\x1B[97m[ \x1B[91m! \x1B[97m]\x1B[0m {}", &alloc::format!($($arg)*)));
}
#[macro_export]
macro_rules! log_ok {
($($arg:tt)*) => ($crate::println!("\x1B[97m[ \x1B[92m* \x1B[97m]\x1B[0;m {}", &alloc::format!($($arg)*)));
}
#[derive(Debug)]
pub struct KernelFeatures {
pub fat_in_mem: bool,
}
impl KernelFeatures {
fn update_option(&mut self, option: &str, value: &str) {
#[allow(clippy::single_match)]
match option {
"fat_in_mem" => self.fat_in_mem = value == "true",
_ => {}
}
}
}
// TODO: Do this vastly differently
pub static KERNEL_FEATURES: libs::cell::LazyCell<KernelFeatures> =
libs::cell::LazyCell::new(parse_kernel_cmdline);
fn parse_kernel_cmdline() -> KernelFeatures {
let mut kernel_features: KernelFeatures = KernelFeatures { fat_in_mem: true };
let kernel_file_response = KERNEL_REQUEST.get_response().get();
if kernel_file_response.is_none() {
return kernel_features;
}
let cmdline_ptr = kernel_file_response
.unwrap()
.kernel_file
.get()
.unwrap()
.cmdline
.as_ptr();
if cmdline_ptr.is_none() {
return kernel_features;
}
let cmdline = unsafe { CStr::from_ptr(cmdline_ptr.unwrap()) };
let kernel_arguments = cmdline
.to_str()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>();
crate::println!("{kernel_arguments:?}");
for item in kernel_arguments {
let parts: Vec<&str> = item.split('=').collect();
if parts.len() == 2 {
let (option, value) = (parts[0], parts[1]);
kernel_features.update_option(option, value);
}
}
return kernel_features;
}
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
crate::println!("{info}");
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
let rbp: u64;
unsafe {
core::arch::asm!("mov {0:r}, rbp", out(reg) rbp);
};
crate::arch::stack_trace::print_stack_trace(6, rbp);
}
hcf();
}
pub fn hcf() -> ! {
loop {
unsafe {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
core::arch::asm!("hlt");
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
core::arch::asm!("wfi");
}
}
}