diff options
Diffstat (limited to 'kernel/src')
-rw-r--r-- | kernel/src/lib.rs | 10 | ||||
-rw-r--r-- | kernel/src/vga_text.rs | 139 |
2 files changed, 149 insertions, 0 deletions
diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 05b90ef..a27f0a7 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -4,8 +4,18 @@ extern crate compiler_builtins; +mod vga_text; + +use core::fmt::Write; + + #[no_mangle] pub extern "C" fn _start() -> ! { + + let mut stdout = vga_text::OStream::new(); + stdout.clear(); + write!(&mut stdout, "hello world!"); + loop {} } diff --git a/kernel/src/vga_text.rs b/kernel/src/vga_text.rs new file mode 100644 index 0000000..ef488e9 --- /dev/null +++ b/kernel/src/vga_text.rs @@ -0,0 +1,139 @@ +#[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(Clone, Copy)] +pub struct CharState(pub u8); + +impl CharState { + pub fn from_colors(fg: Color, bg: Color) -> Self { + Self((fg as u8) | ((bg as u8) << 4)) + } + + pub fn set_fg(&mut self, fg: Color) { + self.0 = (self.0 & 240) | (fg as u8) + } + + pub fn set_bg(&mut self, bg: Color) { + self.0 = (self.0 & 15) | ((bg as u8) << 4) + } +} + +#[derive(Clone, Copy)] +pub struct VgaChar { + pub state: CharState, + pub byte: u8 +} + +impl VgaChar { + pub fn from_state_and_byte(state: CharState, byte: u8) -> Self { + Self{ state, byte } + } +} + +pub struct OStream { + pos: (u8, u8), + cursor: *mut VgaChar, + state: CharState, +} + +impl OStream { + pub fn new() -> Self { + Self { + pos: (0, 0), + cursor: 0xb8000 as *mut VgaChar, + state: CharState::from_colors(Color::White, Color::Black) + } + } + + fn at(n: usize) -> *mut VgaChar { + (0xb8000 + (n << 1)) as *mut VgaChar + } + + fn compute_cursor(&mut self) { + self.cursor = Self::at(self.pos.0 as usize + self.pos.1 as usize * 80) + } + + pub fn set_col(&mut self, col: u8) { + self.pos.0 = core::cmp::min(col, 79); + self.compute_cursor() + } + + pub fn set_row(&mut self, row: u8) { + self.pos.1 = core::cmp::min(row, 24); + self.compute_cursor() + } + + pub fn set_cursor(&mut self, col: u8, row: u8) { + self.pos = (core::cmp::min(col, 79), core::cmp::min(row, 24)); + self.compute_cursor() + } + + fn set_char(&mut self, c: VgaChar) { + unsafe {self.cursor.write_volatile(c)} + } + + pub fn put_char(&mut self, c: VgaChar) { + if c.byte == b'\n' { + self.new_line(); + } else if self.pos.0 >= 79 { + self.new_line(); + self.put_char(c); + } else { + self.set_char(c); + self.cursor = self.cursor.wrapping_offset(1); + self.pos.0 += 1; + } + } + + pub fn put_byte(&mut self, b: u8) { + self.put_char(VgaChar::from_state_and_byte(self.state, b)) + } + + pub fn clear(&self) { + let c = VgaChar::from_state_and_byte(self.state, b' '); + for i in 0..2000 { + unsafe {Self::at(i).write_volatile(c)} + } + } + + pub fn new_line(&mut self) { + if self.pos.1 >= 24 { + self.set_col(0); + for i in 0..1920 { + unsafe {Self::at(i).write_volatile(*Self::at(i + 80))} + } + } else { + self.set_cursor(0, self.pos.1 + 1); + } + } + + pub fn set_state(&mut self, state: CharState) { + self.state = state + } +} + +impl core::fmt::Write for OStream { + fn write_str(&mut self, s: &str) -> core::fmt::Result { + for &b in s.as_bytes() { + self.put_byte(b) + } + Ok(()) + } +} |