summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClément Sibille <claymeuns@protonmail.com>2021-10-04 22:57:05 +0200
committerClément Sibille <claymeuns@protonmail.com>2021-10-04 22:57:05 +0200
commita16a4dc9ed895c3a2934c2e14e1ab515f4899971 (patch)
treeea4e0919283e896199130f6ec014afd8206c7a3f
parent25a24b8b167a7cb28c622039ea30e4afd166cd83 (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.rs7
-rw-r--r--kernel/src/lib.rs20
-rw-r--r--kernel/src/terminal.rs88
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);
+ }
+ }
+}
Go back to lisible.xyz