diff options
| author | Clément Sibille <claymeuns@protonmail.com> | 2021-10-05 21:03:09 +0200 |
|---|---|---|
| committer | Clément Sibille <claymeuns@protonmail.com> | 2021-10-05 21:03:09 +0200 |
| commit | 58a7b22c3ec60380f6efdfd1493b8823fe0c17bc (patch) | |
| tree | 0e3103415574ad6e7336e00e8d43d7d41a0a7fe8 /kernel/src | |
| parent | a16a4dc9ed895c3a2934c2e14e1ab515f4899971 (diff) | |
Add terminal scrolling
This closes #2.
Diffstat (limited to 'kernel/src')
| -rw-r--r-- | kernel/src/io.rs | 12 | ||||
| -rw-r--r-- | kernel/src/lib.rs | 28 | ||||
| -rw-r--r-- | kernel/src/terminal.rs | 58 |
3 files changed, 77 insertions, 21 deletions
diff --git a/kernel/src/io.rs b/kernel/src/io.rs index b6b4cc7..def8665 100644 --- a/kernel/src/io.rs +++ b/kernel/src/io.rs @@ -1,7 +1,5 @@ -pub fn out8(address: u16, value: u8) { - unsafe { - asm!( - "out dx, al", in("dx") address, in("al") value - ) - } -}
\ No newline at end of file +pub unsafe fn out8(address: u16, value: u8) { + asm!( + "out dx, al", in("dx") address, in("al") value + ) +} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index b6bc55f..edb5704 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -12,8 +12,32 @@ mod terminal; pub extern "C" fn kmain() -> ! { let mut terminal = Terminal::new(); terminal.clear(); - terminal.put_string(b"LisibleOS\n"); - terminal.put_string(b"> "); + terminal.put_string(b"1 LisibleOS\n"); + terminal.put_string(b"2 > \n"); + terminal.put_string(b"3\n"); + terminal.put_string(b"4\n"); + terminal.put_string(b"5\n"); + terminal.put_string(b"6\n"); + terminal.put_string(b"7\n"); + terminal.put_string(b"8\n"); + terminal.put_string(b"9\n"); + terminal.put_string(b"10\n"); + terminal.put_string(b"11\n"); + terminal.put_string(b"12\n"); + terminal.put_string(b"13\n"); + terminal.put_string(b"14\n"); + terminal.put_string(b"15\n"); + terminal.put_string(b"16\n"); + terminal.put_string(b"17\n"); + terminal.put_string(b"18\n"); + terminal.put_string(b"19\n"); + terminal.put_string(b"20\n"); + terminal.put_string(b"21\n"); + terminal.put_string(b"22\n"); + terminal.put_string(b"23\n"); + terminal.put_string(b"24\n"); + terminal.put_string(b"25\n"); + terminal.put_string(b"26"); loop {} } diff --git a/kernel/src/terminal.rs b/kernel/src/terminal.rs index 2a5cf1a..9e3eec1 100644 --- a/kernel/src/terminal.rs +++ b/kernel/src/terminal.rs @@ -1,4 +1,5 @@ use crate::io; +use compiler_builtins::mem::memcpy; const VGA_BUFFER_POINTER: *mut u8 = 0xb8000 as *mut u8; const VGA_BUFFER_SIZE: u16 = 4000; @@ -28,15 +29,17 @@ impl Terminal { 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; + if self.current_row < ROW_COUNT - 1 { + self.current_row += 1; + } else { + self.scroll_y(-1); } self.current_col = 0; return; } + /// Safety: This is safe because VGA_BUFFER_POINTER points toward the VGA character buffer unsafe { *VGA_BUFFER_POINTER.offset( ((self.current_col as isize + self.current_row as isize * COL_COUNT as isize) @@ -48,32 +51,63 @@ impl Terminal { 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 { + if self.current_row != ROW_COUNT - 1 { self.current_row = (self.current_row + 1) % ROW_COUNT; + } else { + self.scroll_y(-1); } + self.current_col = 0; + } else { + self.current_col = (self.current_col + 1) % COL_COUNT; } - self.current_col = (self.current_col + 1) % COL_COUNT; + } + + fn scroll_y(&mut self, y: i8) { + // Safety: + // The starting pointer is in bound because it's the VGA character buffer pointer + // The end pointer isn't past the VGA character buffer pointer + // The offset doesn't overflow isize + // The offset doesn't rely on wrapping around the address space + let src = unsafe { VGA_BUFFER_POINTER.offset(COL_COUNT as isize * VALUE_SIZE as isize) }; + let dest = VGA_BUFFER_POINTER; + let size = (VGA_BUFFER_SIZE as usize - COL_COUNT as usize) * VALUE_SIZE as usize; + + // Safety: + // dest and src are valid pointer to the same object being the VGA character buffer + // This copy will not go past the VGA character buffer + unsafe { memcpy(dest, src, size) }; + + self.clear_line(ROW_COUNT - 1); } 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); + unsafe { + *VGA_BUFFER_POINTER.offset( + ((self.current_col as isize + self.current_row as isize * COL_COUNT as isize) + * VALUE_SIZE as isize), + ) = 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.clear_line(row) } self.current_col = 0; self.current_row = 0; } + fn clear_line(&mut self, row: u8) { + for col in 0..COL_COUNT { + self.put_char_at(b' ', row, col); + } + + self.current_row = row; + self.current_col = 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; |
