bootproof/src/logger.rs

102 lines
2.2 KiB
Rust

use crate::misc::halt;
use core::fmt::Write;
pub enum LoggerBackend {
None,
// It is impossible to get ownership of an Output,
// so instead we must pass in the entire boot system table.
UefiStdio(uefi::prelude::SystemTable<uefi::prelude::Boot>),
}
enum LoggerOutput {
Stdout,
Stderr
}
pub struct Logger<'a> {
backend: &'a LoggerBackend,
output: LoggerOutput
}
impl LoggerBackend {
pub fn stdout<'a>(&'a self) -> Logger<'a> {
Logger {
backend: self,
output: LoggerOutput::Stdout
}
}
pub fn stderr<'a>(&'a self) -> Logger<'a> {
Logger {
backend: self,
output: LoggerOutput::Stderr
}
}
}
impl Write for Logger<'_> {
fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
match self.backend {
LoggerBackend::UefiStdio(st) => {
let output = match &self.output {
LoggerOutput::Stdout => st.stdout(),
LoggerOutput::Stderr => st.stderr()
};
output.write_str(s)
},
_ => {
// There's pretty much no way to recover from a missing logger.
// What are we supposed to do-- log the error?
Ok(())
},
}
}
}
pub static mut LOGGER_BACKEND: LoggerBackend = LoggerBackend::None;
#[macro_export]
macro_rules! log {
($( $arg:expr ),* ) => {
unsafe {
use core::fmt::Write;
core::writeln!(LOGGER_BACKEND.stderr(), $( $arg ),*).unwrap();
}
}
}
#[macro_export]
macro_rules! print {
($( $arg:expr ),* ) => {
unsafe {
use core::fmt::Write;
core::write!(LOGGER_BACKEND.stdout(), $( $arg ),*).unwrap();
}
}
}
#[macro_export]
macro_rules! println {
($( $arg:expr ),* ) => {
unsafe {
use core::fmt::Write;
core::writeln!(LOGGER_BACKEND.stdout(), $( $arg ),*).unwrap();
}
}
}
#[macro_export]
macro_rules! panic {
($( $arg:expr ),* ) => {
log!($( $arg ),*);
halt();
}
}
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
log!("{}", info);
halt();
}