From 188a08c3a340005d59d497e836993cb9349c9cbe Mon Sep 17 00:00:00 2001 From: Christian Cunningham Date: Mon, 22 Aug 2022 20:54:54 -0700 Subject: Initial state --- src/.kernel.rs.swp | Bin 0 -> 12288 bytes src/.sync.rs.swp | Bin 0 -> 12288 bytes src/kernel.rs | 34 +++++++++++ src/sync.rs | 62 +++++++++++++++++++ src/vga/.buffer.rs.swp | Bin 0 -> 20480 bytes src/vga/.mod.rs.swp | Bin 0 -> 12288 bytes src/vga/buffer.rs | 157 +++++++++++++++++++++++++++++++++++++++++++++++++ src/vga/mod.rs | 33 +++++++++++ 8 files changed, 286 insertions(+) create mode 100644 src/.kernel.rs.swp create mode 100644 src/.sync.rs.swp create mode 100644 src/kernel.rs create mode 100644 src/sync.rs create mode 100644 src/vga/.buffer.rs.swp create mode 100644 src/vga/.mod.rs.swp create mode 100644 src/vga/buffer.rs create mode 100644 src/vga/mod.rs (limited to 'src') diff --git a/src/.kernel.rs.swp b/src/.kernel.rs.swp new file mode 100644 index 0000000..ed00d5b Binary files /dev/null and b/src/.kernel.rs.swp differ diff --git a/src/.sync.rs.swp b/src/.sync.rs.swp new file mode 100644 index 0000000..462e2ef Binary files /dev/null and b/src/.sync.rs.swp differ diff --git a/src/kernel.rs b/src/kernel.rs new file mode 100644 index 0000000..8218691 --- /dev/null +++ b/src/kernel.rs @@ -0,0 +1,34 @@ +//! # Kernel +//! +//! Kernel Start + +#![no_std] // don't link the Rust standard library +#![no_main] // disable all Rust-level entry points +#![feature(const_mut_refs)] + +mod sync; +mod vga; +use vga::*; +use core::panic::PanicInfo; + +/// This function is called on panic. +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} + +fn kernel_init() { + WRITER.init(); +} + +#[no_mangle] +pub extern "C" fn _start() -> ! { + kernel_init(); + + WRITER.write_string("Hello World!"); + WRITER.write_string("\n\nHi\n"); + println!("{}", 5); + //print_something(); + + loop {} +} diff --git a/src/sync.rs b/src/sync.rs new file mode 100644 index 0000000..cd626fa --- /dev/null +++ b/src/sync.rs @@ -0,0 +1,62 @@ +//! # Synchronization module +//! +//! Provides synchronization objects for thread-safe memory sharing. +use core::cell::UnsafeCell; + +/// # Synchronization interfaces +/// +/// Provides Synchronization traits. +pub mod interface { + /// # Mutex Trait + /// + /// Basic Locking primitive to allow single-process access to data + pub trait Mutex { + /// # The data + /// + /// Each mutex protects some internal data from modification across + /// processes when it is in use. This is important if the process + /// is preempted while the function is using it. + type Data; + /// # Locking mechanism + /// + /// Locks the mutex to access the data in a closure. + /// The data can be read and modified in this closure without worry + /// of poisoning the data across processes. + fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R; + } +} + +/// # Basic Lock Structure +pub struct NullLock where T: ?Sized { + /// The internal data to safely share + data: UnsafeCell, +} + +/// # Allow thread sharing +unsafe impl Send for NullLock where T: ?Sized + Send {} +/// # Allow thread sharing +unsafe impl Sync for NullLock where T: ?Sized + Send {} + +impl NullLock { + /// # Create a new instance of the lock + pub const fn new(data: T) -> Self { + Self { + data: UnsafeCell::new(data), + } + } +} + +impl interface::Mutex for NullLock { + /// # Underlying data of the lock + type Data = T; + + /// # Locking mechanism + /// + /// Locks the Mutex, and passes a mutable reference + /// to the encapsulated data to a closure. + fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut T) -> R) -> R { + let data = unsafe { &mut *self.data.get() }; + + f(data) + } +} diff --git a/src/vga/.buffer.rs.swp b/src/vga/.buffer.rs.swp new file mode 100644 index 0000000..0ce0feb Binary files /dev/null and b/src/vga/.buffer.rs.swp differ diff --git a/src/vga/.mod.rs.swp b/src/vga/.mod.rs.swp new file mode 100644 index 0000000..6071785 Binary files /dev/null and b/src/vga/.mod.rs.swp differ diff --git a/src/vga/buffer.rs b/src/vga/buffer.rs new file mode 100644 index 0000000..34c665d --- /dev/null +++ b/src/vga/buffer.rs @@ -0,0 +1,157 @@ +use super::*; +use core::fmt; +use volatile::Volatile; +use crate::sync::NullLock; +use crate::sync::interface::Mutex; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(C)] +struct ScreenChar { + ascii_character: u8, + color_code: ColorCode, +} + +const BUFFER_HEIGHT: usize = 25; +const BUFFER_WIDTH: usize = 80; + +#[repr(transparent)] +struct Buffer { + chars: [[Volatile; BUFFER_WIDTH]; BUFFER_HEIGHT], +} + +pub struct VgaWriter { + column_position: usize, + color_code: ColorCode, + buffer: Option<&'static mut Buffer>, +} + +impl VgaWriter { + pub fn write_byte(&mut self, byte: u8) { + match byte { + b'\n' => self.new_line(), + byte => { + if self.column_position >= BUFFER_WIDTH { + self.new_line(); + } + + let row = BUFFER_HEIGHT - 1; + let col = self.column_position; + + let color_code = self.color_code; + if let Some(buffer) = &mut self.buffer { + buffer.chars[row][col].write(ScreenChar { +ascii_character: byte, +color_code, +}); + } + self.column_position += 1; + } + } + } + + fn new_line(&mut self) { + for row in 1..BUFFER_HEIGHT { + for col in 0..BUFFER_WIDTH { + if let Some(buffer) = &mut self.buffer { + let character = buffer.chars[row][col].read(); + buffer.chars[row - 1][col].write(character); + } + } + } + self.clear_row(BUFFER_HEIGHT - 1); + self.column_position = 0; + } + + fn clear_row(&mut self, row: usize) { + let blank = ScreenChar { + ascii_character: b' ', + color_code: self.color_code, + }; + for col in 0..BUFFER_WIDTH { + if let Some(buffer) = &mut self.buffer { + buffer.chars[row][col].write(blank); + } + } + } + + pub fn write_string(&mut self, s: &str) { + for byte in s.bytes() { + match byte { + // printable ASCII byte or newline + 0x20..=0x7e | b'\n' => self.write_byte(byte), + // not part of printable ASCII range + _ => self.write_byte(0xfe), + } + + } + } +} + +impl NullLock { + #[allow(dead_code)] + pub fn write_byte(&self, byte: u8) { + self.lock(|writer| { + writer.write_byte(byte); + }); + } + + #[allow(dead_code)] + fn new_line(&self) { + self.lock(|writer| { + writer.new_line(); + }); + } + + #[allow(dead_code)] + fn clear_row(&self, row: usize) { + self.lock(|writer| { + writer.clear_row(row); + }); + } + + pub fn write_string(&self, s: &str) { + self.lock(|writer| { + writer.write_string(s); + }); + } +} + +impl fmt::Write for VgaWriter { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.write_string(s); + Ok(()) + } +} + +impl NullLock { + pub fn init(&self) { + self.lock(|writer| { + writer.buffer = Some(unsafe { &mut *(0xb8000 as *mut Buffer) }); + }) + } +} + +#[doc(hidden)] +pub fn _print(args: fmt::Arguments) { + use core::fmt::Write; + WRITER.lock(|writer| { + writer.write_fmt(args).unwrap(); + }); +} + +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ($crate::vga::_print(format_args!($($arg)*))); +} + +#[macro_export] +macro_rules! println { + () => (print!("\n")); + ($($arg:tt)*) => (print!("{}\n", format_args!($($arg)*))); +} + +pub static WRITER: NullLock = NullLock::new(VgaWriter { + column_position: 0, + color_code: ColorCode::new(Color::Yellow, Color::Black), + buffer: None, +}); diff --git a/src/vga/mod.rs b/src/vga/mod.rs new file mode 100644 index 0000000..13dffe0 --- /dev/null +++ b/src/vga/mod.rs @@ -0,0 +1,33 @@ +mod buffer; +pub use buffer::*; + +#[allow(dead_code)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u8)] +pub enum Color { + Black = 0, + Blue = 1, + Green = 2, + Cyan = 3, + Red = 4, + Magenta = 5, + Brown = 6, + LightGray = 7, + DarkGray = 8, + LightBlue = 9, + LightGreen = 10, + LightCyan = 11, + LightRed = 12, + Pink = 13, + Yellow = 14, + White = 15, +} +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(transparent)] +struct ColorCode(u8); + +impl ColorCode { + const fn new(foreground: Color, background: Color) -> ColorCode { + ColorCode((background as u8) << 4 | (foreground as u8)) + } +} -- cgit v1.2.1