summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Cunningham <c@localhost>2022-08-22 20:54:54 -0700
committerChristian Cunningham <c@localhost>2022-08-22 20:54:54 -0700
commit188a08c3a340005d59d497e836993cb9349c9cbe (patch)
treea69cc6cc1ced12043b706dc62f5a1645d9061adb /src
Initial state
Diffstat (limited to 'src')
-rw-r--r--src/.kernel.rs.swpbin0 -> 12288 bytes
-rw-r--r--src/.sync.rs.swpbin0 -> 12288 bytes
-rw-r--r--src/kernel.rs34
-rw-r--r--src/sync.rs62
-rw-r--r--src/vga/.buffer.rs.swpbin0 -> 20480 bytes
-rw-r--r--src/vga/.mod.rs.swpbin0 -> 12288 bytes
-rw-r--r--src/vga/buffer.rs157
-rw-r--r--src/vga/mod.rs33
8 files changed, 286 insertions, 0 deletions
diff --git a/src/.kernel.rs.swp b/src/.kernel.rs.swp
new file mode 100644
index 0000000..ed00d5b
--- /dev/null
+++ b/src/.kernel.rs.swp
Binary files differ
diff --git a/src/.sync.rs.swp b/src/.sync.rs.swp
new file mode 100644
index 0000000..462e2ef
--- /dev/null
+++ b/src/.sync.rs.swp
Binary files 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<T> where T: ?Sized {
+ /// The internal data to safely share
+ data: UnsafeCell<T>,
+}
+
+/// # Allow thread sharing
+unsafe impl<T> Send for NullLock<T> where T: ?Sized + Send {}
+/// # Allow thread sharing
+unsafe impl<T> Sync for NullLock<T> where T: ?Sized + Send {}
+
+impl<T> NullLock<T> {
+ /// # Create a new instance of the lock
+ pub const fn new(data: T) -> Self {
+ Self {
+ data: UnsafeCell::new(data),
+ }
+ }
+}
+
+impl<T> interface::Mutex for NullLock<T> {
+ /// # 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
--- /dev/null
+++ b/src/vga/.buffer.rs.swp
Binary files differ
diff --git a/src/vga/.mod.rs.swp b/src/vga/.mod.rs.swp
new file mode 100644
index 0000000..6071785
--- /dev/null
+++ b/src/vga/.mod.rs.swp
Binary files 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<ScreenChar>; 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<VgaWriter> {
+ #[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<VgaWriter> {
+ 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<VgaWriter> = 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))
+ }
+}