os/src/vga_text.rs

98 lines
1.9 KiB
Rust

use crate::lazy_static;
use core::fmt::{Arguments, Write};
use spin::Mutex;
use x86_64::instructions::interrupts::without_interrupts;
#[repr(u8)]
pub enum Color {
Black = 0x0,
Blue = 0x1,
Green = 0x2,
Cyan = 0x3,
Red = 0x4,
Magenta = 0x5,
Brown = 0x6,
Gray = 0x7,
}
const VGA_COLUMNS: usize = 80;
const VGA_ROWS: usize = 25;
#[repr(transparent)]
struct Buffer([[(u8, u8); VGA_COLUMNS]; VGA_ROWS]);
pub struct VgaWriter {
buf: &'static mut Buffer,
row: usize,
col: usize,
}
impl VgaWriter {
fn write_byte(&mut self, c: u8) {
self.buf.0[self.row][self.col] = (c, 0xb);
self.col += 1;
if self.col == VGA_COLUMNS {
self.new_line()
}
}
fn new_line(&mut self) {
if self.row == VGA_ROWS - 1 {
for i in 0..(VGA_ROWS - 1) {
self.buf.0[i] = self.buf.0[i + 1];
}
self.buf.0[VGA_ROWS - 1] = [(0, 0); VGA_COLUMNS];
} else {
self.row += 1;
}
self.col = 0;
}
}
impl Write for VgaWriter {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
for byte in s.bytes() {
if byte == b'\n' {
self.new_line();
} else {
self.write_byte(byte);
}
}
Ok(())
}
}
lazy_static! {
static ref VGA_TEXT: Mutex<VgaWriter> = {
Mutex::new(VgaWriter {
buf: unsafe { &mut *(0xb8000 as *mut Buffer) },
row: 0,
col: 0,
})
};
}
pub fn _print(args: Arguments) {
without_interrupts(|| {
write!(VGA_TEXT.lock(), "{}", args).unwrap();
})
}
#[macro_export]
macro_rules! print {
($($t:tt)+) => {
$crate::vga_text::_print(::core::format_args!($($t)+))
};
}
#[macro_export]
macro_rules! println {
() => {
$crate::print!("\n")
};
($($t:tt)+) => {
$crate::print!("{}\n", ::core::format_args!($($t)+))
};
}