feat(kernel): Add logging to the kernel (#2)
This PR will allow the kernel to have a simple logging using a FrameBuffer created by the bootloader crate. Reviewed-on: #2
This commit is contained in:
83
kernel/src/logger/logger.rs
Normal file
83
kernel/src/logger/logger.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
use bootloader_api::info::FrameBufferInfo;
|
||||
use conquer_once::spin::OnceCell;
|
||||
use core::fmt::Write;
|
||||
use spinning_top::Spinlock;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// The global logger instance used for the `log` crate.
|
||||
static LOGGER: OnceCell<LockedLogger> = OnceCell::uninit();
|
||||
|
||||
/// A logger instance protected by a spinlock.
|
||||
struct LockedLogger {
|
||||
framebuffer: Option<Spinlock<framebuffer::FrameBufferWriter>>,
|
||||
}
|
||||
|
||||
impl LockedLogger {
|
||||
/// Create a new instance that logs to the given framebuffer.
|
||||
pub fn new(
|
||||
framebuffer: &'static mut [u8],
|
||||
info: FrameBufferInfo,
|
||||
) -> Self {
|
||||
let framebuffer = Some(Spinlock::new(framebuffer::FrameBufferWriter::new(framebuffer, info)));
|
||||
|
||||
LockedLogger {
|
||||
framebuffer,
|
||||
}
|
||||
}
|
||||
|
||||
/// Force-unlocks the logger to prevent a deadlock.
|
||||
///
|
||||
/// ## Safety
|
||||
/// This method is not memory safe and should be only used when absolutely necessary.
|
||||
pub unsafe fn force_unlock(&self) {
|
||||
if let Some(framebuffer) = &self.framebuffer {
|
||||
unsafe { framebuffer.force_unlock() };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl log::Log for LockedLogger {
|
||||
fn enabled(&self, _metadata: &log::Metadata) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn log(&self, record: &log::Record) {
|
||||
if let Some(framebuffer) = &self.framebuffer {
|
||||
let mut framebuffer = framebuffer.lock();
|
||||
writeln!(framebuffer, "{:5}: {}", record.level(), record.args()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&self) {}
|
||||
}
|
||||
|
||||
/// Initialize a text-based logger using the given pixel-based framebuffer as output.
|
||||
pub fn init_logger(
|
||||
framebuffer: &'static mut [u8],
|
||||
info: FrameBufferInfo,
|
||||
) {
|
||||
let logger = LOGGER.get_or_init(move || {
|
||||
LockedLogger::new(
|
||||
framebuffer,
|
||||
info,
|
||||
)
|
||||
});
|
||||
log::set_logger(logger).expect("logger already set");
|
||||
#[cfg(debug_assertions)]
|
||||
log::set_max_level(log::LevelFilter::Debug);
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
log::set_max_level(log::LevelFilter::Info);
|
||||
|
||||
log::debug!("Framebuffer info: {:?}", info);
|
||||
}
|
||||
|
||||
pub fn force_unlock() {
|
||||
unsafe {
|
||||
LOGGER
|
||||
.get()
|
||||
.map(|l| l.force_unlock())
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user