From d2095d8d0f7837b673d537ededa201700e3060fc Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jeremy@system76.com>
Date: Sun, 17 Mar 2019 09:31:34 -0600
Subject: [PATCH] Add in-memory logging, retrievable from sys:log

---
 src/arch/x86_64/debug.rs |  9 +++++++++
 src/arch/x86_64/start.rs |  4 ++++
 src/lib.rs               |  3 +++
 src/log.rs               | 35 +++++++++++++++++++++++++++++++++++
 src/scheme/sys/log.rs    | 17 +++++++++++++++++
 src/scheme/sys/mod.rs    |  2 ++
 6 files changed, 70 insertions(+)
 create mode 100644 src/log.rs
 create mode 100644 src/scheme/sys/log.rs

diff --git a/src/arch/x86_64/debug.rs b/src/arch/x86_64/debug.rs
index 1c173a7d..aeddf40b 100644
--- a/src/arch/x86_64/debug.rs
+++ b/src/arch/x86_64/debug.rs
@@ -3,6 +3,7 @@ use core::fmt;
 use spin::Mutex;
 use spin::MutexGuard;
 
+use log::{LOG, Log};
 #[cfg(feature = "qemu_debug")]
 use syscall::io::Io;
 use syscall::io::Pio;
@@ -18,6 +19,7 @@ use super::device::serial::COM1;
 pub static QEMU: Mutex<Pio<u8>> = Mutex::new(Pio::<u8>::new(0x402));
 
 pub struct Writer<'a> {
+    log: MutexGuard<'a, Option<Log>>,
     #[cfg(feature = "graphical_debug")]
     display: MutexGuard<'a, Option<DebugDisplay>>,
     #[cfg(feature = "qemu_debug")]
@@ -29,6 +31,7 @@ pub struct Writer<'a> {
 impl<'a> Writer<'a> {
     pub fn new() -> Writer<'a> {
         Writer {
+            log: LOG.lock(),
             #[cfg(feature = "graphical_debug")]
             display: DEBUG_DISPLAY.lock(),
             #[cfg(feature = "qemu_debug")]
@@ -39,6 +42,12 @@ impl<'a> Writer<'a> {
     }
 
     pub fn write(&mut self, buf: &[u8]) {
+        {
+            if let Some(ref mut log) = *self.log {
+                log.write(buf);
+            }
+        }
+
         #[cfg(feature = "graphical_debug")]
         {
             if let Some(ref mut display) = *self.display {
diff --git a/src/arch/x86_64/start.rs b/src/arch/x86_64/start.rs
index e1351162..d3ed63f2 100644
--- a/src/arch/x86_64/start.rs
+++ b/src/arch/x86_64/start.rs
@@ -16,6 +16,7 @@ use device;
 use gdt;
 use idt;
 use interrupt;
+use log;
 use memory;
 use paging;
 
@@ -111,6 +112,9 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
         // Setup kernel heap
         allocator::init(&mut active_table);
 
+        // Activate memory logging
+        log::init();
+
         // Use graphical debug
         #[cfg(feature="graphical_debug")]
         graphical_debug::init(&mut active_table);
diff --git a/src/lib.rs b/src/lib.rs
index 6161003f..e0a9969b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -82,6 +82,9 @@ pub mod event;
 /// External functions
 pub mod externs;
 
+/// Logging
+pub mod log;
+
 /// Memory management
 pub mod memory;
 
diff --git a/src/log.rs b/src/log.rs
new file mode 100644
index 00000000..b0866cf3
--- /dev/null
+++ b/src/log.rs
@@ -0,0 +1,35 @@
+use alloc::collections::VecDeque;
+use spin::Mutex;
+
+pub static LOG: Mutex<Option<Log>> = Mutex::new(None);
+
+pub fn init() {
+    *LOG.lock() = Some(Log::new(1024 * 1024));
+}
+
+pub struct Log {
+    data: VecDeque<u8>,
+    size: usize,
+}
+
+impl Log {
+    pub fn new(size: usize) -> Log {
+        Log {
+            data: VecDeque::with_capacity(size),
+            size: size
+        }
+    }
+
+    pub fn read(&self) -> (&[u8], &[u8]) {
+        self.data.as_slices()
+    }
+
+    pub fn write(&mut self, buf: &[u8]) {
+        for &b in buf {
+            while self.data.len() + 1 >= self.size {
+                self.data.pop_front();
+            }
+            self.data.push_back(b);
+        }
+    }
+}
diff --git a/src/scheme/sys/log.rs b/src/scheme/sys/log.rs
new file mode 100644
index 00000000..ec34da22
--- /dev/null
+++ b/src/scheme/sys/log.rs
@@ -0,0 +1,17 @@
+use alloc::vec::Vec;
+
+use log::LOG;
+use syscall::error::Result;
+
+pub fn resource() -> Result<Vec<u8>> {
+    let mut vec = Vec::new();
+
+    if let Some(ref log) = *LOG.lock() {
+        let slices = log.read();
+        vec.reserve_exact(slices.0.len() + slices.1.len());
+        vec.extend_from_slice(slices.0);
+        vec.extend_from_slice(slices.1);
+    }
+
+    Ok(vec)
+}
diff --git a/src/scheme/sys/mod.rs b/src/scheme/sys/mod.rs
index 85ccab24..71ab698c 100644
--- a/src/scheme/sys/mod.rs
+++ b/src/scheme/sys/mod.rs
@@ -14,6 +14,7 @@ mod context;
 mod cpu;
 mod exe;
 mod iostat;
+mod log;
 mod scheme;
 mod scheme_num;
 mod syscall;
@@ -43,6 +44,7 @@ impl SysScheme {
         files.insert(b"cpu", Box::new(move || cpu::resource()));
         files.insert(b"exe", Box::new(move || exe::resource()));
         files.insert(b"iostat", Box::new(move || iostat::resource()));
+        files.insert(b"log", Box::new(move || log::resource()));
         files.insert(b"scheme", Box::new(move || scheme::resource()));
         files.insert(b"scheme_num", Box::new(move || scheme_num::resource()));
         files.insert(b"syscall", Box::new(move || syscall::resource()));
-- 
GitLab