diff options
| author | Clément Sibille <claymeuns@protonmail.com> | 2021-10-04 22:57:05 +0200 | 
|---|---|---|
| committer | Clément Sibille <claymeuns@protonmail.com> | 2021-10-04 22:57:05 +0200 | 
| commit | a16a4dc9ed895c3a2934c2e14e1ab515f4899971 (patch) | |
| tree | ea4e0919283e896199130f6ec014afd8206c7a3f | |
| parent | 25a24b8b167a7cb28c622039ea30e4afd166cd83 (diff) | |
Provide an interface for drawing on the screen in VGA text mode
This interface allows the user to write strings and move the cursor in VGA text mode.
This closes #1.
| -rw-r--r-- | kernel/src/io.rs | 7 | ||||
| -rw-r--r-- | kernel/src/lib.rs | 20 | ||||
| -rw-r--r-- | kernel/src/terminal.rs | 88 | 
3 files changed, 105 insertions, 10 deletions
diff --git a/kernel/src/io.rs b/kernel/src/io.rs new file mode 100644 index 0000000..b6b4cc7 --- /dev/null +++ b/kernel/src/io.rs @@ -0,0 +1,7 @@ +pub fn out8(address: u16, value: u8) { +    unsafe { +        asm!( +            "out dx, al", in("dx") address, in("al") value +        ) +    } +}
\ No newline at end of file diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 285ecff..b6bc55f 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -1,23 +1,23 @@ +#![feature(asm)]  #![no_std]  #![no_main] +use crate::terminal::Terminal;  use core::panic::PanicInfo; +mod io; +mod terminal; +  #[no_mangle]  pub extern "C" fn kmain() -> ! { -    let vga_buffer = 0xb8000 as *mut u8; - -    for (i, &byte) in b"LisibleOS Hello world".iter().enumerate() { -        unsafe { -            *vga_buffer.offset(i as isize * 2) = byte; -            *vga_buffer.offset(i as isize * 2 + 1) = 0xb; -        } -    } - +    let mut terminal = Terminal::new(); +    terminal.clear(); +    terminal.put_string(b"LisibleOS\n"); +    terminal.put_string(b"> ");      loop {}  }  #[panic_handler]  fn panic(_info: &PanicInfo) -> ! {      loop {} -}
\ No newline at end of file +} diff --git a/kernel/src/terminal.rs b/kernel/src/terminal.rs new file mode 100644 index 0000000..2a5cf1a --- /dev/null +++ b/kernel/src/terminal.rs @@ -0,0 +1,88 @@ +use crate::io; + +const VGA_BUFFER_POINTER: *mut u8 = 0xb8000 as *mut u8; +const VGA_BUFFER_SIZE: u16 = 4000; +const ROW_COUNT: u8 = 25; +const COL_COUNT: u8 = 80; +const VALUE_SIZE: u8 = 2; + +pub(crate) struct Terminal { +    current_row: u8, +    current_col: u8, +} + +impl Terminal { +    pub fn new() -> Self { +        Self { +            current_row: 0, +            current_col: 0, +        } +    } + +    pub fn put_string(&mut self, string: &[u8]) { +        for &character in string { +            self.put_char(character); +        } +        self.set_cursor_position(self.current_row, self.current_col); +    } + +    pub fn put_char(&mut self, c: u8) { +        if c == b'\n' { +            self.current_row += 1; +            if self.current_row == ROW_COUNT { +                self.current_row = 0; +            } + +            self.current_col = 0; +            return; +        } + +        unsafe { +            *VGA_BUFFER_POINTER.offset( +                ((self.current_col as isize + self.current_row as isize * COL_COUNT as isize) +                    * VALUE_SIZE as isize), +            ) = c; +        } +        self.compute_current_position(); +    } + +    fn compute_current_position(&mut self) { +        if self.current_col == COL_COUNT - 1 { +            if self.current_row == ROW_COUNT - 1 { +                self.current_col = 0; +                self.current_row = 0; +            } else { +                self.current_row = (self.current_row + 1) % ROW_COUNT; +            } +        } +        self.current_col = (self.current_col + 1) % COL_COUNT; +    } + +    pub fn put_char_at(&mut self, c: u8, row: u8, col: u8) { +        self.current_row = row; +        self.current_col = col; +        self.put_char(c); +    } + +    pub fn clear(&mut self) { +        for row in 0..ROW_COUNT { +            for col in 0..COL_COUNT { +                self.put_char_at(b' ', row, col); +            } +        } +        self.current_col = 0; +        self.current_row = 0; +    } + +    pub fn set_cursor_position(&mut self, row: u8, col: u8) { +        let cursor_position: u16 = (row * COL_COUNT + col) as u16; +        let address_register = 0x3D4; +        let data_register = 0x3D5; +        unsafe { +            io::out8(address_register, 0x0F); +            io::out8(data_register, (cursor_position & 0xFF) as u8); +            io::out8(address_register, 0x0E); +            io::out8(data_register, ((cursor_position >> 8) & 0xFF) as u8); +        } +    } +}  | 
