//! Kernel I/O helpers and logging frontend. //! //! Provides a lightweight logger implementation routing to UART and helper //! macros for printing from kernel code. use crate::println; use log::{Level, Metadata, Record}; use log::{LevelFilter, SetLoggerError}; use crate::uart::write_uart; /// Print a string to the kernel console (via UART). /// /// Accepts any type that implements `AsRef` to avoid unnecessary /// allocations at call sites. pub(crate) fn print>(content: T) { write_uart(content); } /// Logger implementation that routes kernel log records to the UART-based console. struct Logger; impl log::Log for Logger { fn enabled(&self, metadata: &Metadata) -> bool { metadata.level() <= Level::Info } fn log(&self, record: &Record) { if self.enabled(record.metadata()) { if let Some((file, line)) = record.file().zip(record.line()) { println!( "[{}] at {}:{} - {}", record.level(), file, line, record.args() ); } else { println!("[{}] - {}", record.level(), record.args()); } } } fn flush(&self) {} } static LOGGER: Logger = Logger; /// Initialize the kernel logger and set the default level. /// /// Returns an error if a global logger has already been set. pub fn init_log() -> Result<(), SetLoggerError> { log::set_logger(&LOGGER).map(|()| log::set_max_level(LevelFilter::Info)) } #[macro_export] macro_rules! print { ($($args:expr),*) => { $crate::io::print(alloc::format!($($args),*)) }; } #[macro_export] macro_rules! println { () => { $crate::print!("\n\r"); }; ($($args:expr),*) => { $crate::print!($($args),*); $crate::println!(); }; }