-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from AdamGoodApp/development
Development
- Loading branch information
Showing
5 changed files
with
206 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
/target | ||
**/*.rs.bk | ||
|
||
Cargo.lock | ||
Cargo.lock | ||
|
||
.DS_Store |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,14 @@ | ||
[package] | ||
name = "adz_os" | ||
version = "0.2.0" | ||
version = "0.3.0" | ||
authors = ["Adam Rais <[email protected]>"] | ||
edition = "2018" | ||
|
||
[dependencies] | ||
bootloader = "0.6.0" | ||
bootloader = "0.6.0" | ||
volatile = "0.2.3" | ||
spin = "0.4.9" | ||
|
||
[dependencies.lazy_static] | ||
version = "1.0" | ||
features = ["spin_no_std"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
use volatile::Volatile; | ||
use core::fmt; | ||
use lazy_static::lazy_static; | ||
use spin::Mutex; | ||
|
||
#[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 { | ||
fn new(foreground: Color, background: Color) -> ColorCode { | ||
ColorCode((background as u8) << 4 | (foreground as u8)) | ||
} | ||
} | ||
|
||
#[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 Writer { | ||
column_position: usize, | ||
color_code: ColorCode, | ||
buffer: &'static mut Buffer, | ||
} | ||
|
||
impl Writer { | ||
|
||
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; | ||
|
||
self.buffer.chars[row][col].write(ScreenChar { | ||
ascii_character: byte, | ||
color_code: color_code, | ||
}); | ||
|
||
self.column_position += 1; | ||
} | ||
} | ||
} | ||
|
||
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), | ||
} | ||
} | ||
} | ||
|
||
fn new_line(&mut self) { | ||
for row in 1..BUFFER_HEIGHT { | ||
for col in 0..BUFFER_WIDTH { | ||
let character = self.buffer.chars[row][col].read(); | ||
self.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 { | ||
self.buffer.chars[row][col].write(blank); | ||
} | ||
} | ||
} | ||
|
||
impl fmt::Write for Writer { | ||
fn write_str(&mut self, s: &str) -> fmt::Result { | ||
self.write_string(s); | ||
Ok(()) | ||
} | ||
} | ||
|
||
// We want our WRITER function to be Static/Global and mutable. | ||
// Mut can introduce race conditions where other threads could overwrite our static variable. | ||
// Mutex solves this problem by locking the variable when a thread is writing. | ||
// However, our basic kernel does not support this type of Mutex, | ||
// Instead we can use Spinlocking which constantly calls lock on the variable in a loop | ||
// untill the thread does not need the variable anymore. | ||
lazy_static! { | ||
pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer { | ||
column_position: 0, | ||
color_code: ColorCode::new(Color::Yellow, Color::Black), | ||
buffer: unsafe { &mut *(0xb8000 as *mut Buffer) }, | ||
}); | ||
} | ||
|
||
|
||
// custom print macros | ||
#[macro_export] | ||
macro_rules! print { | ||
($($arg:tt)*) => ($crate::vga_buffer::_print(format_args!($($arg)*))); | ||
} | ||
|
||
#[macro_export] | ||
macro_rules! println { | ||
() => ($crate::print!("\n")); | ||
($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*))); | ||
} | ||
|
||
#[doc(hidden)] | ||
pub fn _print(args: fmt::Arguments) { | ||
use core::fmt::Write; | ||
WRITER.lock().write_fmt(args).unwrap(); | ||
} |