Advertisement
Ardente

Untitled

Apr 23rd, 2022
1,602
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 4.13 KB | None | 0 0
  1. use core::fmt;
  2. use lazy_static::lazy_static;
  3. use spin::Mutex;
  4. use volatile::Volatile;
  5.  
  6. lazy_static! {
  7.     pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer {
  8.         column_position: 0,
  9.         color_code: ColorCode::new(Color::Yellow, Color::Black),
  10.         buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
  11.     });
  12. }
  13.  
  14. #[allow(dead_code)]
  15. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  16. #[repr(u8)]
  17. pub enum Color {
  18.     Black = 0,
  19.     Blue = 1,
  20.     Green = 2,
  21.     Cyan = 3,
  22.     Red = 4,
  23.     Magenta = 5,
  24.     Brown = 6,
  25.     LightGray = 7,
  26.     DarkGray = 8,
  27.     LightBlue = 9,
  28.     LightGreen = 10,
  29.     LightCyan = 11,
  30.     LightRed = 12,
  31.     Pink = 13,
  32.     Yellow = 14,
  33.     White = 15,
  34. }
  35.  
  36. #[derive(Debug, Clone, Copy, Eq, PartialEq)]
  37. #[repr(transparent)]
  38. pub struct ColorCode(u8);
  39.  
  40. impl ColorCode {
  41.     pub fn new(foreground: Color, background: Color) -> ColorCode {
  42.         ColorCode((background as u8) << 4 | (foreground as u8))
  43.     }
  44. }
  45.  
  46. #[derive(Debug, Copy, Clone, Eq, PartialEq)]
  47. #[repr(C)]
  48. pub struct ScreenChar {
  49.     pub ascii_character: u8,
  50.     pub color_code: ColorCode,
  51. }
  52.  
  53. const BUFFER_HEIGHT: usize = 25;
  54. const BUFFER_WIDTH: usize = 80;
  55.  
  56. #[repr(transparent)]
  57. pub struct Buffer {
  58.     pub chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
  59. }
  60.  
  61. pub struct Writer {
  62.     pub column_position: usize,
  63.     pub color_code: ColorCode,
  64.     pub buffer: &'static mut Buffer,
  65. }
  66.  
  67. impl Writer {
  68.    pub fn write_byte(&mut self, byte: u8) {
  69.        match byte {
  70.            b'\n' => self.new_line(),
  71.            byte => {
  72.                if self.column_position >= BUFFER_WIDTH {
  73.                    self.new_line();
  74.                }
  75.  
  76.                let row = BUFFER_HEIGHT - 1;
  77.                let col = self.column_position;
  78.  
  79.                let color_code = self.color_code;
  80.                self.buffer.chars[row][col].write(ScreenChar {
  81.                    ascii_character: byte,
  82.                    color_code,
  83.                });
  84.                self.column_position += 1;
  85.            }
  86.        }
  87.    }
  88.  
  89.    pub fn write_string(&mut self, s: &str) {
  90.        for byte in s.bytes() {
  91.            match byte {
  92.                b'\n' => self.write_byte(byte),
  93.                0x20..=0x7e => self.write_byte(byte),
  94.                _ => self.write_byte(0xfe),
  95.            }
  96.        }
  97.    }
  98.  
  99.    fn new_line(&mut self) {
  100.        for row in 1..BUFFER_HEIGHT {
  101.            for col in 0..BUFFER_WIDTH {
  102.                let character = self.buffer.chars[row][col].read();
  103.                self.buffer.chars[row - 1][col].write(character);
  104.            }
  105.        }
  106.  
  107.        self.clear_row(BUFFER_HEIGHT - 1);
  108.        self.column_position = 0;
  109.    }
  110.  
  111.    fn clear_row(&mut self, row: usize) {
  112.        let blank = ScreenChar {
  113.            ascii_character: b' ',
  114.            color_code: self.color_code,
  115.        };
  116.  
  117.        for col in 0..BUFFER_WIDTH {
  118.            self.buffer.chars[row][col].write(blank);
  119.        }
  120.    }
  121. }
  122.  
  123. impl fmt::Write for Writer {
  124.    fn write_str(&mut self, s: &str) -> fmt::Result {
  125.        self.write_string(s);
  126.        Ok(())
  127.    }
  128. }
  129.  
  130. #[macro_export]
  131. macro_rules! print {
  132.    ($($arg:tt)*) => ($crate::vga_buffer::_print(format_args!($($arg)*)));
  133. }
  134.  
  135. #[macro_export]
  136. macro_rules! println {
  137.    () => ($crate::print!("\n"));
  138.    ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
  139. }
  140.  
  141. #[doc(hidden)]
  142. pub fn _print(args: fmt::Arguments) {
  143.    use core::fmt::Write;
  144.    use x86_64::instructions::interrupts;
  145.  
  146.    interrupts::without_interrupts(|| {
  147.        WRITER.lock().write_fmt(args).unwrap();
  148.    });
  149. }
  150.  
  151. #[test_case]
  152. fn test_println_output() {
  153.    use core::fmt::Write;
  154.    use x86_64::instructions::interrupts;
  155.  
  156.    let s = "Some test string that fits on a single line";
  157.    interrupts::without_interrupts(|| {
  158.        let mut writer = WRITER.lock();
  159.        writeln!(writer, "\n{}", s).expect("writeln failed");
  160.        for (i, c) in s.chars().enumerate() {
  161.            let screen_char = writer.buffer.chars[BUFFER_HEIGHT - 2][i].read();
  162.            assert_eq!(char::from(screen_char.ascii_character), c);
  163.        }
  164.    })
  165. }
  166.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement