Skip to content

Commit

Permalink
Merge pull request #5 from AdamGoodApp/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
AdamGoodApp authored May 22, 2019
2 parents d105ecf + 445d68e commit d5d8f3c
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 15 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/target
**/*.rs.bk

Cargo.lock
Cargo.lock

.DS_Store
32 changes: 31 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions Cargo.toml
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"]
19 changes: 8 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,22 @@

use core::panic::PanicInfo;

static WELCOME_TEXT: &[u8] = b"Welcome to ADZ OS!";
mod vga_buffer;

static WELCOME_TEXT: &str = "Welcome to ADZ OS!";

// new entry point, linker looks for _start by default
#[no_mangle]
pub extern "C" fn _start() -> ! {
let vga_buffer = 0xb8000 as *mut u8;

for (i, &byte) in WELCOME_TEXT.iter().enumerate() {
unsafe {
*vga_buffer.offset(i as isize * 2) = byte;
*vga_buffer.offset(i as isize * 2 + 1) = 0xb;
}
}
println!("{}", WELCOME_TEXT);
println!("version: 2.3");

loop {}
loop{};
}

/// this function is called on panic.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
fn panic(info: &PanicInfo) -> ! {
println!("{}", info);
loop {}
}
156 changes: 156 additions & 0 deletions src/vga_buffer.rs
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();
}

0 comments on commit d5d8f3c

Please sign in to comment.