aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTianhao Wang <wth@riseup.net>2024-02-01 05:18:20 +0100
committerTianhao Wang <wth@riseup.net>2024-02-01 05:18:25 +0100
commitf8c1ef0109a8177cf4747a891e6c462c4ef59c92 (patch)
tree1d608c0b41b98304973e1d53bc82be848d83d022 /src
parent2bdafab229439dcd9968114ab232ed0a3a218bfb (diff)
add println! and panic! macro
The rust lazy_static requires interior mutability. I have to include a Mutex impl (spin::Mutex). But I'd like to implement my own primitives.
Diffstat (limited to 'src')
-rw-r--r--src/io.rs34
-rw-r--r--src/lib.rs26
-rw-r--r--src/machine/cgascr.rs27
3 files changed, 64 insertions, 23 deletions
diff --git a/src/io.rs b/src/io.rs
new file mode 100644
index 0000000..988db09
--- /dev/null
+++ b/src/io.rs
@@ -0,0 +1,34 @@
+use crate::machine::cgascr::CGAScreen;
+use core::fmt;
+use lazy_static::lazy_static;
+use spin::Mutex;
+
+// TODO I want my own locking primitive for practice, instead of stock spin lock
+lazy_static! {
+ // TODO perhaps remove the 'a lifetime from the struc defs
+ pub static ref CGASCREEN_GLOBAL: Mutex<CGAScreen> = Mutex::new(CGAScreen::new());
+}
+
+#[macro_export]
+macro_rules! print {
+ ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
+}
+
+#[macro_export]
+macro_rules! println {
+ () => ($crate::print!("\n"));
+ ($($arg:tt)*) => (print!("{}\n", format_args!($($arg)*)));
+}
+
+pub fn _print(args: fmt::Arguments) {
+ use core::fmt::Write;
+ CGASCREEN_GLOBAL.lock().write_fmt(args).unwrap();
+}
+
+pub fn clear() {
+ CGASCREEN_GLOBAL.lock().clear();
+}
+
+pub fn set_attr(attr: u8) {
+ CGASCREEN_GLOBAL.lock().setattr(attr);
+}
diff --git a/src/lib.rs b/src/lib.rs
index 459deef..5de826c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,31 +1,29 @@
#![allow(dead_code)]
#![allow(unused_imports)]
-
#![no_std]
#![no_main]
mod arch;
+mod io;
mod machine;
use core::panic::PanicInfo;
use machine::cgascr::CGAScreen;
+#[cfg(not(test))]
#[panic_handler]
-fn panic(_info: &PanicInfo) -> ! {
+fn panic(info: &PanicInfo) -> ! {
+ println!("{}", info);
loop {}
}
#[no_mangle]
pub extern "C" fn _entry() -> ! {
- let mut scr = CGAScreen::new();
- scr.show_coners();
- scr.setattr(0x1f);
- scr.clear();
- scr.show_coners();
-
- scr.print("--RuStuBs--\n");
- scr.print(" _._ _,-'\"\"`-._ ~Meow\n");
- scr.print(" (,-.`._,'( |\\`-/|\n");
- scr.print(" `-.-' \\ )-`( , o o)\n");
- scr.print(" `- \\`_`\"'-\n");
- scr.print("it works!\n");
+ io::set_attr(0x1f);
+ io::clear();
+ println!("--RuStuBs--");
+ println!(" _._ _,-'\"\"`-._ ~Meow");
+ println!(" (,-.`._,'( |\\`-/|");
+ println!(" `-.-' \\ )-`( , o o)");
+ println!(" `- \\`_`\"'-");
+ println!("it works!");
loop {}
}
diff --git a/src/machine/cgascr.rs b/src/machine/cgascr.rs
index 3fa7b95..0983b66 100644
--- a/src/machine/cgascr.rs
+++ b/src/machine/cgascr.rs
@@ -1,7 +1,10 @@
use crate::arch::x86_64::io_port::*;
use crate::arch::x86_64::misc::*;
-use core::{ptr, slice, str};
+use core::{fmt, ptr, slice, str};
+// TODO this is a "hard copy" of the c code, making little use
+// of the rust features. May rework this into cleaner code...
+//
// I would consider these cga parameters constant.
// the scroll() and clear() works with the assumption
// that the CGAScreen memory buffer is 64-bit aligned
@@ -27,15 +30,15 @@ const IR_PORT: u16 = 0x3d4;
const DR_PORT: u16 = 0x3d5;
#[allow(dead_code)]
-pub struct CGAScreen<'a> {
- pub cga_mem: &'a mut [u8],
+pub struct CGAScreen {
+ pub cga_mem: &'static mut [u8],
cursor_r: usize,
cursor_c: usize,
attr: u8,
}
#[allow(dead_code)]
-impl<'a> CGAScreen<'a> {
+impl CGAScreen {
pub fn new() -> Self {
Self {
cga_mem: unsafe {
@@ -52,6 +55,7 @@ impl<'a> CGAScreen<'a> {
col + row * MAX_COLS
}
+ #[inline(always)]
pub fn show(&self, row: usize, col: usize, c: char, attr: u8) {
let index = self.cal_offset(row, col);
@@ -62,6 +66,7 @@ impl<'a> CGAScreen<'a> {
}
pub fn putchar(&mut self, ch: char) {
+ // TODO use match syntax.
if ch == '\n' {
self.cursor_r += 1;
self.cursor_c = 0;
@@ -79,6 +84,7 @@ impl<'a> CGAScreen<'a> {
self.setpos(self.cursor_r, self.cursor_c);
}
+ #[inline(always)]
fn _check_scroll(&mut self) {
if self.cursor_r >= MAX_ROWS {
self.scroll(1);
@@ -186,12 +192,8 @@ impl<'a> CGAScreen<'a> {
offset as u32
}
- // Sanity Check of the cgascreen
- pub fn test(&self) {
- // TODO
- }
-
pub fn show_coners(&self) {
+ // TODO replace hardcoded
self.show(0, 0, 0xda as char, self.attr);
self.show(0, 79, 0xbf as char, self.attr);
self.show(24, 0, 0xc0 as char, self.attr);
@@ -208,3 +210,10 @@ impl<'a> CGAScreen<'a> {
self.attr = attr;
}
}
+
+impl fmt::Write for CGAScreen {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ self.print(s);
+ Ok(())
+ }
+}