From 819f77daf3a808b43840f4ffe14aa4b988196619 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Sun, 11 Mar 2018 11:36:58 -0600
Subject: [PATCH] Add support for graphical debug, to be used during ACPI phase

---
 Cargo.toml                                   |   1 +
 res/unifont.font                             | Bin 0 -> 4096 bytes
 src/arch/x86_64/debug.rs                     |  41 +++++
 src/arch/x86_64/graphical_debug/debug.rs     |  83 ++++++++++
 src/arch/x86_64/graphical_debug/display.rs   | 150 +++++++++++++++++++
 src/arch/x86_64/graphical_debug/mod.rs       |  71 +++++++++
 src/arch/x86_64/graphical_debug/mode_info.rs |  37 +++++
 src/arch/x86_64/graphical_debug/primitive.rs |  47 ++++++
 src/arch/x86_64/macros.rs                    |   2 +-
 src/arch/x86_64/mod.rs                       |   7 +
 src/arch/x86_64/start.rs                     |  10 ++
 11 files changed, 448 insertions(+), 1 deletion(-)
 create mode 100644 res/unifont.font
 create mode 100644 src/arch/x86_64/debug.rs
 create mode 100644 src/arch/x86_64/graphical_debug/debug.rs
 create mode 100644 src/arch/x86_64/graphical_debug/display.rs
 create mode 100644 src/arch/x86_64/graphical_debug/mod.rs
 create mode 100644 src/arch/x86_64/graphical_debug/mode_info.rs
 create mode 100644 src/arch/x86_64/graphical_debug/primitive.rs

diff --git a/Cargo.toml b/Cargo.toml
index e7e116a4..82e2d60f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -30,6 +30,7 @@ default-features = false
 default = ["acpi"]
 acpi = []
 doc = []
+graphical_debug = []
 live = []
 multi_core = []
 pti = []
diff --git a/res/unifont.font b/res/unifont.font
new file mode 100644
index 0000000000000000000000000000000000000000..a00366d5f559bc6fb3c20b9ee9cf8320219013b5
GIT binary patch
literal 4096
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

literal 0
HcmV?d00001

diff --git a/src/arch/x86_64/debug.rs b/src/arch/x86_64/debug.rs
new file mode 100644
index 00000000..198ca29a
--- /dev/null
+++ b/src/arch/x86_64/debug.rs
@@ -0,0 +1,41 @@
+use core::fmt;
+use spin::MutexGuard;
+
+use devices::uart_16550::SerialPort;
+use syscall::io::Pio;
+
+use super::device::serial::COM1;
+#[cfg(feature = "graphical_debug")]
+use super::graphical_debug::{DEBUG_DISPLAY, DebugDisplay};
+
+pub struct Writer<'a> {
+    serial: MutexGuard<'a, SerialPort<Pio<u8>>>,
+    #[cfg(feature = "graphical_debug")]
+    display: MutexGuard<'a, Option<DebugDisplay>>
+}
+
+impl<'a> Writer<'a> {
+    pub fn new() -> Writer<'a> {
+        Writer {
+            serial: COM1.lock(),
+            #[cfg(feature = "graphical_debug")]
+            display: DEBUG_DISPLAY.lock(),
+        }
+    }
+}
+
+impl<'a> fmt::Write for Writer<'a> {
+    #[cfg(not(feature = "graphical_debug"))]
+    fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
+        self.serial.write_str(s)
+    }
+
+    #[cfg(feature = "graphical_debug")]
+    fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
+        if let Some(ref mut display) = *self.display {
+            display.write_str(s)
+        } else {
+            self.serial.write_str(s)
+        }
+    }
+}
diff --git a/src/arch/x86_64/graphical_debug/debug.rs b/src/arch/x86_64/graphical_debug/debug.rs
new file mode 100644
index 00000000..338b9a1e
--- /dev/null
+++ b/src/arch/x86_64/graphical_debug/debug.rs
@@ -0,0 +1,83 @@
+use core::fmt;
+
+use super::Display;
+
+pub struct DebugDisplay {
+    display: Display,
+    x: usize,
+    y: usize,
+    w: usize,
+    h: usize,
+}
+
+impl DebugDisplay {
+    pub fn new(display: Display) -> DebugDisplay {
+        let w = display.width/8;
+        let h = display.height/16;
+        DebugDisplay {
+            display,
+            x: 0,
+            y: 0,
+            w: w,
+            h: h,
+        }
+    }
+
+    pub fn write(&mut self, c: char) {
+        if self.x >= self.w || c == '\n' {
+            self.x = 0;
+            self.y += 1;
+        }
+
+        if self.y >= self.h {
+            let new_y = self.h - 1;
+            let d_y = self.y - new_y;
+
+            self.display.scroll(d_y * 16);
+
+            self.display.rect(
+                0, (self.h - d_y) * 16,
+                self.w * 8, d_y * 16,
+                0x000000
+            );
+
+            self.display.sync(
+                0, 0,
+                self.w * 8, self.h * 16
+            );
+
+            self.y = new_y;
+        }
+
+        if c != '\n' {
+            self.display.rect(
+                self.x * 8, self.y * 16,
+                8, 16,
+                0x000000
+            );
+
+            self.display.char(
+                self.x * 8, self.y * 16,
+                c,
+                0xFFFFFF
+            );
+
+            self.display.sync(
+                self.x, self.y,
+                8, 16
+            );
+
+            self.x += 1;
+        }
+    }
+}
+
+impl fmt::Write for DebugDisplay {
+    fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
+        for c in s.chars() {
+            self.write(c);
+        }
+
+        Ok(())
+    }
+}
diff --git a/src/arch/x86_64/graphical_debug/display.rs b/src/arch/x86_64/graphical_debug/display.rs
new file mode 100644
index 00000000..b2f79f6f
--- /dev/null
+++ b/src/arch/x86_64/graphical_debug/display.rs
@@ -0,0 +1,150 @@
+use alloc::allocator::{Alloc, Layout};
+use alloc::heap::Heap;
+use core::{cmp, slice};
+
+use super::FONT;
+use super::primitive::{fast_set32, fast_set64, fast_copy};
+
+/// A display
+pub struct Display {
+    pub width: usize,
+    pub height: usize,
+    pub onscreen: &'static mut [u32],
+    pub offscreen: &'static mut [u32],
+}
+
+impl Display {
+    pub fn new(width: usize, height: usize, onscreen: usize) -> Display {
+        let size = width * height;
+        let offscreen = unsafe { Heap.alloc(Layout::from_size_align_unchecked(size * 4, 4096)).unwrap() };
+        unsafe { fast_set64(offscreen as *mut u64, 0, size/2) };
+        Display {
+            width: width,
+            height: height,
+            onscreen: unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) },
+            offscreen: unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) }
+        }
+    }
+
+    /// Draw a rectangle
+    pub fn rect(&mut self, x: usize, y: usize, w: usize, h: usize, color: u32) {
+        let start_y = cmp::min(self.height, y);
+        let end_y = cmp::min(self.height, y + h);
+
+        let start_x = cmp::min(self.width, x);
+        let len = cmp::min(self.width, x + w) - start_x;
+
+        let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;
+
+        let stride = self.width * 4;
+
+        let offset = y * stride + start_x * 4;
+        offscreen_ptr += offset;
+
+        let mut rows = end_y - start_y;
+        while rows > 0 {
+            unsafe {
+                fast_set32(offscreen_ptr as *mut u32, color, len);
+            }
+            offscreen_ptr += stride;
+            rows -= 1;
+        }
+    }
+
+    /// Invert a rectangle
+    pub fn invert(&mut self, x: usize, y: usize, w: usize, h: usize) {
+        let start_y = cmp::min(self.height, y);
+        let end_y = cmp::min(self.height, y + h);
+
+        let start_x = cmp::min(self.width, x);
+        let len = cmp::min(self.width, x + w) - start_x;
+
+        let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;
+
+        let stride = self.width * 4;
+
+        let offset = y * stride + start_x * 4;
+        offscreen_ptr += offset;
+
+        let mut rows = end_y - start_y;
+        while rows > 0 {
+            let mut row_ptr = offscreen_ptr;
+            let mut cols = len;
+            while cols > 0 {
+                unsafe {
+                    let color = *(row_ptr as *mut u32);
+                    *(row_ptr as *mut u32) = !color;
+                }
+                row_ptr += 4;
+                cols -= 1;
+            }
+            offscreen_ptr += stride;
+            rows -= 1;
+        }
+    }
+
+    /// Draw a character
+    pub fn char(&mut self, x: usize, y: usize, character: char, color: u32) {
+        if x + 8 <= self.width && y + 16 <= self.height {
+            let mut dst = self.offscreen.as_mut_ptr() as usize + (y * self.width + x) * 4;
+
+            let font_i = 16 * (character as usize);
+            if font_i + 16 <= FONT.len() {
+                for row in 0..16 {
+                    let row_data = FONT[font_i + row];
+                    for col in 0..8 {
+                        if (row_data >> (7 - col)) & 1 == 1 {
+                            unsafe { *((dst + col * 4) as *mut u32)  = color; }
+                        }
+                    }
+                    dst += self.width * 4;
+                }
+            }
+        }
+    }
+
+    // Scroll the screen
+    pub fn scroll(&mut self, lines: usize) {
+        let offset = cmp::min(self.height, lines) * self.width;
+        let size = self.offscreen.len() - offset;
+        unsafe {
+            let to = self.offscreen.as_mut_ptr();
+            let from = to.offset(offset as isize);
+            fast_copy(to as *mut u8, from as *const u8, size * 4);
+        }
+    }
+
+    /// Copy from offscreen to onscreen
+    pub fn sync(&mut self, x: usize, y: usize, w: usize, h: usize) {
+        let start_y = cmp::min(self.height, y);
+        let end_y = cmp::min(self.height, y + h);
+
+        let start_x = cmp::min(self.width, x);
+        let len = (cmp::min(self.width, x + w) - start_x) * 4;
+
+        let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;
+        let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize;
+
+        let stride = self.width * 4;
+
+        let offset = y * stride + start_x * 4;
+        offscreen_ptr += offset;
+        onscreen_ptr += offset;
+
+        let mut rows = end_y - start_y;
+        while rows > 0 {
+            unsafe {
+                fast_copy(onscreen_ptr as *mut u8, offscreen_ptr as *const u8, len);
+            }
+            offscreen_ptr += stride;
+            onscreen_ptr += stride;
+            rows -= 1;
+        }
+    }
+}
+
+impl Drop for Display {
+    fn drop(&mut self) {
+        unsafe { Heap.dealloc(self.offscreen.as_mut_ptr() as *mut u8, Layout::from_size_align_unchecked(self.offscreen.len() * 4, 4096)) };
+    }
+}
diff --git a/src/arch/x86_64/graphical_debug/mod.rs b/src/arch/x86_64/graphical_debug/mod.rs
new file mode 100644
index 00000000..a8b2a701
--- /dev/null
+++ b/src/arch/x86_64/graphical_debug/mod.rs
@@ -0,0 +1,71 @@
+use spin::Mutex;
+
+use memory::Frame;
+use paging::{ActivePageTable, Page, PhysicalAddress, VirtualAddress};
+use paging::entry::EntryFlags;
+
+pub use self::debug::DebugDisplay;
+use self::display::Display;
+use self::mode_info::VBEModeInfo;
+use self::primitive::fast_set64;
+
+pub mod debug;
+pub mod display;
+pub mod mode_info;
+pub mod primitive;
+
+pub static FONT: &'static [u8] = include_bytes!("../../../../res/unifont.font");
+
+pub static DEBUG_DISPLAY: Mutex<Option<DebugDisplay>> = Mutex::new(None);
+
+pub fn init(active_table: &mut ActivePageTable) {
+    //TODO: Unmap mode_info and map physbaseptr in kernel space
+
+    println!("Starting graphical debug");
+
+    let width;
+    let height;
+    let physbaseptr;
+
+    {
+        let mode_info_addr = 0x5200;
+
+        {
+            let page = Page::containing_address(VirtualAddress::new(mode_info_addr));
+            let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().get()));
+            let result = active_table.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::NO_EXECUTE);
+            result.flush(active_table);
+        }
+
+        let mode_info = unsafe { &*(mode_info_addr as *const VBEModeInfo) };
+
+        width = mode_info.xresolution as usize;
+        height = mode_info.yresolution as usize;
+        physbaseptr = mode_info.physbaseptr as usize;
+    }
+
+    {
+        let size = width * height;
+
+        {
+            let start_page = Page::containing_address(VirtualAddress::new(physbaseptr));
+            let end_page = Page::containing_address(VirtualAddress::new(physbaseptr + size * 4));
+            for page in Page::range_inclusive(start_page, end_page) {
+                let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().get()));
+                let result = active_table.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::HUGE_PAGE);
+                result.flush(active_table);
+            }
+        }
+
+        unsafe { fast_set64(physbaseptr as *mut u64, 0, size/2) };
+
+        *DEBUG_DISPLAY.lock() = Some(DebugDisplay::new(Display::new(width, height, physbaseptr)));
+    }
+}
+
+pub fn fini(_active_table: &mut ActivePageTable) {
+    //TODO: Unmap physbaseptr
+    *DEBUG_DISPLAY.lock() = None;
+
+    println!("Finished graphical debug");
+}
diff --git a/src/arch/x86_64/graphical_debug/mode_info.rs b/src/arch/x86_64/graphical_debug/mode_info.rs
new file mode 100644
index 00000000..7d59af64
--- /dev/null
+++ b/src/arch/x86_64/graphical_debug/mode_info.rs
@@ -0,0 +1,37 @@
+/// The info of the VBE mode
+#[derive(Copy, Clone, Default, Debug)]
+#[repr(packed)]
+pub struct VBEModeInfo {
+    attributes: u16,
+    win_a: u8,
+    win_b: u8,
+    granularity: u16,
+    winsize: u16,
+    segment_a: u16,
+    segment_b: u16,
+    winfuncptr: u32,
+    bytesperscanline: u16,
+    pub xresolution: u16,
+    pub yresolution: u16,
+    xcharsize: u8,
+    ycharsize: u8,
+    numberofplanes: u8,
+    bitsperpixel: u8,
+    numberofbanks: u8,
+    memorymodel: u8,
+    banksize: u8,
+    numberofimagepages: u8,
+    unused: u8,
+    redmasksize: u8,
+    redfieldposition: u8,
+    greenmasksize: u8,
+    greenfieldposition: u8,
+    bluemasksize: u8,
+    bluefieldposition: u8,
+    rsvdmasksize: u8,
+    rsvdfieldposition: u8,
+    directcolormodeinfo: u8,
+    pub physbaseptr: u32,
+    offscreenmemoryoffset: u32,
+    offscreenmemsize: u16,
+}
diff --git a/src/arch/x86_64/graphical_debug/primitive.rs b/src/arch/x86_64/graphical_debug/primitive.rs
new file mode 100644
index 00000000..16c2536a
--- /dev/null
+++ b/src/arch/x86_64/graphical_debug/primitive.rs
@@ -0,0 +1,47 @@
+#[cfg(target_arch = "x86_64")]
+#[inline(always)]
+#[cold]
+pub unsafe fn fast_copy(dst: *mut u8, src: *const u8, len: usize) {
+    asm!("cld
+        rep movsb"
+        :
+        : "{rdi}"(dst as usize), "{rsi}"(src as usize), "{rcx}"(len)
+        : "cc", "memory", "rdi", "rsi", "rcx"
+        : "intel", "volatile");
+}
+
+#[cfg(target_arch = "x86_64")]
+#[inline(always)]
+#[cold]
+pub unsafe fn fast_copy64(dst: *mut u64, src: *const u64, len: usize) {
+    asm!("cld
+        rep movsq"
+        :
+        : "{rdi}"(dst as usize), "{rsi}"(src as usize), "{rcx}"(len)
+        : "cc", "memory", "rdi", "rsi", "rcx"
+        : "intel", "volatile");
+}
+
+#[cfg(target_arch = "x86_64")]
+#[inline(always)]
+#[cold]
+pub unsafe fn fast_set32(dst: *mut u32, src: u32, len: usize) {
+    asm!("cld
+        rep stosd"
+        :
+        : "{rdi}"(dst as usize), "{eax}"(src), "{rcx}"(len)
+        : "cc", "memory", "rdi", "rcx"
+        : "intel", "volatile");
+}
+
+#[cfg(target_arch = "x86_64")]
+#[inline(always)]
+#[cold]
+pub unsafe fn fast_set64(dst: *mut u64, src: u64, len: usize) {
+    asm!("cld
+        rep stosq"
+        :
+        : "{rdi}"(dst as usize), "{rax}"(src), "{rcx}"(len)
+        : "cc", "memory", "rdi", "rcx"
+        : "intel", "volatile");
+}
diff --git a/src/arch/x86_64/macros.rs b/src/arch/x86_64/macros.rs
index 1772c3d8..d41ee933 100644
--- a/src/arch/x86_64/macros.rs
+++ b/src/arch/x86_64/macros.rs
@@ -3,7 +3,7 @@
 macro_rules! print {
     ($($arg:tt)*) => ({
         use core::fmt::Write;
-        let _ = write!($crate::arch::device::serial::COM1.lock(), $($arg)*);
+        let _ = write!($crate::arch::debug::Writer::new(), $($arg)*);
     });
 }
 
diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs
index ffa90a96..b7857d29 100644
--- a/src/arch/x86_64/mod.rs
+++ b/src/arch/x86_64/mod.rs
@@ -1,12 +1,19 @@
 #[macro_use]
 pub mod macros;
 
+/// Debugging support
+pub mod debug;
+
 /// Devices
 pub mod device;
 
 /// Global descriptor table
 pub mod gdt;
 
+/// Graphical debug
+#[cfg(feature = "graphical_debug")]
+mod graphical_debug;
+
 /// Interrupt descriptor table
 pub mod idt;
 
diff --git a/src/arch/x86_64/start.rs b/src/arch/x86_64/start.rs
index 1d92afc0..afba151a 100644
--- a/src/arch/x86_64/start.rs
+++ b/src/arch/x86_64/start.rs
@@ -9,6 +9,8 @@ use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, AtomicUsize, ATOMIC_USIZE
 use allocator;
 #[cfg(feature = "acpi")]
 use acpi;
+#[cfg(feature = "graphical_debug")]
+use arch::x86_64::graphical_debug;
 use arch::x86_64::pti;
 use device;
 use gdt;
@@ -100,6 +102,10 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
         // Setup kernel heap
         allocator::init(&mut active_table);
 
+        // Use graphical debug
+        #[cfg(feature="graphical_debug")]
+        graphical_debug::init(&mut active_table);
+
         // Initialize devices
         device::init(&mut active_table);
 
@@ -113,6 +119,10 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
         // Initialize memory functions after core has loaded
         memory::init_noncore();
 
+        // Stop graphical debug
+        #[cfg(feature="graphical_debug")]
+        graphical_debug::fini(&mut active_table);
+
         BSP_READY.store(true, Ordering::SeqCst);
 
         slice::from_raw_parts(env_base as *const u8, env_size)
-- 
GitLab