diff --git a/kernel/src/arch/x86_64/logging.rs b/kernel/src/arch/x86_64/logging.rs new file mode 100644 index 0000000..0ad5c07 --- /dev/null +++ b/kernel/src/arch/x86_64/logging.rs @@ -0,0 +1,46 @@ +//! Logging (as in terms of console / serial output) + +use core::fmt::Write; +use limine::{LimineTerminalRequest, LimineTerminalResponse}; +use spin::{Lazy, Mutex}; +use uart_16550::SerialPort; + +static SERIAL_CONSOLE: Mutex = Mutex::new(unsafe { SerialPort::new(0x3f8) }); +static TERMINAL_LOGGER: Lazy> = Lazy::new(|| Mutex::new(TermLogger::new())); + +pub fn init() { + SERIAL_CONSOLE.lock().init(); + Lazy::force(&TERMINAL_LOGGER); +} + +pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result { + x86_64::instructions::interrupts::without_interrupts(|| { + TERMINAL_LOGGER.lock().write_fmt(args)?; + SERIAL_CONSOLE.lock().write_fmt(args) + }) +} + +struct TermLogger(&'static LimineTerminalResponse); +unsafe impl Send for TermLogger {} +impl TermLogger { + pub fn new() -> Self { + static TERM_REQ: LimineTerminalRequest = LimineTerminalRequest::new(0); + Self( + TERM_REQ + .get_response() + .get() + .expect("failed to get terminal response"), + ) + } +} + +impl Write for TermLogger { + fn write_str(&mut self, s: &str) -> core::fmt::Result { + if let (Some(w), Some(ts)) = (self.0.write(), self.0.terminals()) { + for term in ts { + w(term, s); + } + } + Ok(()) + } +} diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 5a6814e..a276e1d 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -1,19 +1,17 @@ -use limine::{LimineHhdmRequest, LimineKernelFileRequest, LimineMmapRequest, LimineModuleRequest}; -use spin::Mutex; -use uart_16550::SerialPort; -use x86_64::VirtAddr; +pub use logging::log; use crate::allocator; +use limine::{LimineHhdmRequest, LimineKernelFileRequest, LimineMmapRequest, LimineModuleRequest}; +use x86_64::VirtAddr; mod gdt; mod interrupts; +mod logging; mod memory; -static SERIAL_CONSOLE: Mutex = Mutex::new(unsafe { SerialPort::new(0x3f8) }); - #[no_mangle] unsafe extern "C" fn _kernel_start() -> ! { - SERIAL_CONSOLE.lock().init(); + logging::init(); crate::logger::init().expect("failed to set logger"); log::info!("Initialising AKern {}", crate::VERSION); @@ -64,12 +62,6 @@ unsafe extern "C" fn _kernel_start() -> ! { ) } -/// Format args to serial console -pub fn serial_fmt(args: core::fmt::Arguments<'_>) -> core::fmt::Result { - use core::fmt::Write; - x86_64::instructions::interrupts::without_interrupts(|| SERIAL_CONSOLE.lock().write_fmt(args)) -} - /// Spin loop pub fn sloop() -> ! { loop { diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index f88219c..b7a9c0e 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -30,12 +30,12 @@ pub const VERSION: Version = Version { #[panic_handler] fn panic(info: &core::panic::PanicInfo) -> ! { // TODO: Better panic handler - let _ = crate::arch::serial_fmt(format_args!( + let _ = crate::arch::log(format_args!( "\x1b[1m\x1b[4m\x1b[38;5;125mKernel Panic\x1b[0m\r\n", )); if let Some(loc) = info.location() { - let _ = crate::arch::serial_fmt(format_args!( + let _ = crate::arch::log(format_args!( "Location: {}: {}, {}\r\n", loc.file(), loc.line(), @@ -44,7 +44,7 @@ fn panic(info: &core::panic::PanicInfo) -> ! { } if let Some(msg) = info.message() { - let _ = crate::arch::serial_fmt(format_args!("{msg}\r\n")); + let _ = crate::arch::log(format_args!("{msg}\r\n")); } loop {} diff --git a/kernel/src/logger.rs b/kernel/src/logger.rs index cc894eb..f0bfa0a 100644 --- a/kernel/src/logger.rs +++ b/kernel/src/logger.rs @@ -14,7 +14,7 @@ impl log::Log for Logger { fn log(&self, record: &log::Record) { let lvl = record.level(); - crate::arch::serial_fmt(format_args!( + crate::arch::log(format_args!( "\x1b[38;5;{}m{lvl}\x1b[0m [{}]: {}\r\n", match lvl { Level::Error => "160",