summaryrefslogtreecommitdiff
path: root/crates/kernel/src/logger.rs
diff options
context:
space:
mode:
authorNathan Ringo <nathan@remexre.com>2024-09-02 01:02:29 -0500
committerNathan Ringo <nathan@remexre.com>2024-09-02 01:02:29 -0500
commit1afb23196b9882f85c8fbcfbfbd5f92a58960e14 (patch)
treec53a07d218763527e03844fb00a4a3c7565260b4 /crates/kernel/src/logger.rs
parent905e90461e4d15f80b1f0ae0f0fe1a5863be92b6 (diff)
Re-adds a bad logger.
Diffstat (limited to 'crates/kernel/src/logger.rs')
-rw-r--r--crates/kernel/src/logger.rs71
1 files changed, 71 insertions, 0 deletions
diff --git a/crates/kernel/src/logger.rs b/crates/kernel/src/logger.rs
new file mode 100644
index 0000000..696c9a6
--- /dev/null
+++ b/crates/kernel/src/logger.rs
@@ -0,0 +1,71 @@
+//! The logger used to store logs from the kernel. This accepts logs from the `log` crate, and
+//! delivers them to console devices.
+
+use core::fmt::{self, Write};
+
+/// Initializes the logger. This should be called exactly once, early in boot.
+pub fn init() {
+ log::set_logger(&Logger).expect("failed to set logger");
+ log::set_max_level(log::LevelFilter::Trace);
+ log::warn!("Using a bad unportable logger that only works on qemu-virt");
+}
+
+struct BadRiscvWrite;
+
+impl Write for BadRiscvWrite {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ let ptr = 0x10000000 as *mut u8;
+ for b in s.bytes() {
+ unsafe { ptr.write_volatile(b) };
+ }
+ Ok(())
+ }
+}
+
+pub struct Logger;
+
+impl log::Log for Logger {
+ fn enabled(&self, _metadata: &log::Metadata) -> bool {
+ true
+ }
+
+ fn log(&self, record: &log::Record) {
+ if !self.enabled(record.metadata()) {
+ return;
+ }
+
+ let body = |line| {
+ let level = match record.level() {
+ log::Level::Error => "\x1b[1;31mERR\x1b[0m",
+ log::Level::Warn => "\x1b[1;33mWRN\x1b[0m",
+ log::Level::Info => "\x1b[1;36mINF\x1b[0m",
+ log::Level::Debug => "\x1b[1;35mDBG\x1b[0m",
+ log::Level::Trace => "TRC",
+ };
+ let file = record.file().unwrap_or("???");
+ let args = record.args();
+
+ let result = if args.as_str() == Some("") {
+ // A silly convenience, but don't write the extra space if we're
+ // not going to write anything anyways.
+ writeln!(BadRiscvWrite, "[{level}][{file}:{line}]")
+ } else {
+ writeln!(BadRiscvWrite, "[{level}][{file}:{line}] {args}")
+ };
+
+ // UNWRAP: Since the fmt::Write impl for ConsoleInner has a
+ // contract promising that it won't ever return an error, this
+ // should be unreachable.
+ result.unwrap();
+ };
+
+ // Some contortions to avoid running afoul of the lifetime requirements
+ // of format_args...
+ match record.line() {
+ Some(line) => body(format_args!("{line}")),
+ None => body(format_args!("???")),
+ }
+ }
+
+ fn flush(&self) {}
+}