//! Logging (as in terms of console / serial output) use { core::fmt::Write, limine::{TerminalRequest, TerminalResponse}, spin::{Lazy, Mutex}, uart_16550::SerialPort, }; pub 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)?; let mut sc = SERIAL_CONSOLE.lock(); sc.write_fmt(args)?; Ok(()) }) } struct TermLogger(&'static TerminalResponse); unsafe impl Send for TermLogger {} impl TermLogger { pub fn new() -> Self { static TERM_REQ: TerminalRequest = TerminalRequest::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), ts) = (self.0.write(), self.0.terminals()) { for term in ts { w(term, s); } } Ok(()) } }