diff --git a/meson.build b/meson.build index 00c2842..9bdf752 100644 --- a/meson.build +++ b/meson.build @@ -41,6 +41,7 @@ rust_lib = custom_target( , 'src/idt/entry.rs' , 'src/idt/mod.rs' , 'src/rlibc/memory.rs' + , 'src/rlibc/spin_lock.rs' , 'src/rlibc/mod.rs' , 'src/screen/mod.rs' , 'src/lib.rs' diff --git a/src/lib.rs b/src/lib.rs index b10d6a0..1a896f9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,9 +33,8 @@ unsafe fn outportb(port: u16, byte: u8) #[export_name = "main"] fn main() { - let mut screen = screen::Screen::new().expect("Can't open VGA screen"); - write!(screen, "Hello, world!\ntest new line\n"); + screen::print("Hello, world!\ntest new line\n"); /* for i in 0..80 { @@ -67,7 +66,7 @@ fn main() { gdt::gdt_flush(); - write!(screen, "\n\nHello"); + screen::print("\n\nHello"); idt::IDT[0] = idt::Entry::new(idt::isr0 as u32, 0x08, 0x8E.into()); idt::IDT[1] = idt::Entry::new(idt::isr1 as u32, 0x08, 0x8E.into()); idt::IDT[2] = idt::Entry::new(idt::isr2 as u32, 0x08, 0x8E.into()); @@ -103,6 +102,6 @@ fn main() { idt::idt_load(); - write!(screen, "\n\nIDT"); + screen::print("\n\nIDT"); } } diff --git a/src/rlibc/mod.rs b/src/rlibc/mod.rs index db8dc63..d8f43a5 100644 --- a/src/rlibc/mod.rs +++ b/src/rlibc/mod.rs @@ -1,2 +1,5 @@ mod memory; -pub use self::memory::*; +pub use memory::*; + +mod spin_lock; +pub use spin_lock::*; diff --git a/src/rlibc/spin_lock.rs b/src/rlibc/spin_lock.rs new file mode 100644 index 0000000..8317202 --- /dev/null +++ b/src/rlibc/spin_lock.rs @@ -0,0 +1,68 @@ +use core::{cell::UnsafeCell, mem, sync::atomic::{AtomicBool, Ordering}}; + +pub struct SpinLock { + lock: AtomicBool, + inner: UnsafeCell> +} + +impl SpinLock { + pub const fn new(inner: T) -> Self { + Self { + lock: AtomicBool::new(true), + inner: UnsafeCell::new(Some(inner)) + } + } + + pub fn take(&self) -> T { + loop { + while self.lock.load(Ordering::Relaxed) == false {} + if let Ok(_) = self.lock.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed) + { + break; + } + } + + if let Some(inner) = unsafe { &mut *self.inner.get() }.take() { + inner + } else { + panic!() + } + } + + pub fn take_maybe(&self) -> Option { + if self.lock.load(Ordering::Relaxed) == false { + if let Ok(_) = self.lock.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed) { + unsafe { &mut *self.inner.get() }.take() + } else { + None + } + } else { + None + } + } + + pub fn put(&self, inner: T) { + loop { + while self.lock.load(Ordering::Relaxed) == true {} + if let Ok(_) = self.lock.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) + { + break; + } + } + + unsafe { &mut *self.inner.get() }.insert(inner); + } + + pub fn put_maybe(&self, inner: T) -> Option { + if self.lock.load(Ordering::Relaxed) == true { + if let Ok(_) = self.lock.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) { + unsafe { &mut *self.inner.get() }.insert(inner); + None + } else { + Some(inner) + } + } else { + Some(inner) + } + } +} diff --git a/src/screen/mod.rs b/src/screen/mod.rs index 42aeb08..340139c 100644 --- a/src/screen/mod.rs +++ b/src/screen/mod.rs @@ -1,10 +1,8 @@ use core::fmt::Write; -use crate::rlibc::{memcpy, memsetw}; +use crate::rlibc::{SpinLock, memcpy, memsetw}; -static mut SCREEN_LOCK: bool = false; -static SCREEN_SIZE: (usize, usize) = (80, 25); -const VGA_BUF: *mut ScreenChar = 0xB8000 as *mut ScreenChar; +pub static mut SCREEN: SpinLock = SpinLock::new(Screen::new((80, 25), 0xB8000 as *mut ())); #[allow(dead_code)] #[repr(u8)] @@ -70,28 +68,27 @@ impl Into for ScreenChar { } } -pub struct Screen { - cursor: (u16, u16) +struct Screen { + cursor: (u16, u16), + size: (usize, usize), + buffer: *mut ScreenChar } impl Screen { - pub fn new() -> Option { - if unsafe { SCREEN_LOCK } { - return None - } else { - unsafe { SCREEN_LOCK = true; } - Screen { - cursor: (0, 0) - }.into() + pub const fn new(size: (usize, usize), buffer: *mut ()) -> Self { + Screen { + cursor: (0, 0), + size, + buffer: buffer as *mut ScreenChar } } - pub fn scroll(&mut self) { + fn scroll(&mut self) { unsafe { - for i in 0..SCREEN_SIZE.1 { - memcpy(VGA_BUF.add(i * SCREEN_SIZE.0) as *mut u8, VGA_BUF.add((i + 1) * SCREEN_SIZE.0) as *mut u8, SCREEN_SIZE.1 * 2); + for i in 0..self.size.1 { + memcpy(self.buffer.add(i * self.size.0) as *mut u8, self.buffer.add((i + 1) * self.size.0) as *mut u8, self.size.1 * 2); } - memsetw(VGA_BUF.add(SCREEN_SIZE.0* (SCREEN_SIZE.1 - 1)) as *mut u16, ScreenChar::new(BackgroundColor::Black, ForegroundColor::White, ' ').into(), SCREEN_SIZE.0); + memsetw(self.buffer.add(self.size.0* (self.size.1 - 1)) as *mut u16, ScreenChar::new(BackgroundColor::Black, ForegroundColor::White, ' ').into(), self.size.0); } } @@ -100,15 +97,15 @@ impl Screen { self.cursor = (0, self.cursor.1 + 1); } else if char >= ' ' && char <= '~' { unsafe { - VGA_BUF.add((self.cursor.1 * SCREEN_SIZE.0 as u16) as usize + self.cursor.0 as usize).write_volatile(ScreenChar::new(background_color, foreground_color, char)) + self.buffer.add((self.cursor.1 * self.size.0 as u16) as usize + self.cursor.0 as usize).write_volatile(ScreenChar::new(background_color, foreground_color, char)) } self.cursor.0 += 1; } - if self.cursor.0 >= SCREEN_SIZE.0 as u16 { + if self.cursor.0 >= self.size.0 as u16 { self.cursor = (0, self.cursor.1 + 1); } - if self.cursor.1 >= SCREEN_SIZE.1 as u16 { + if self.cursor.1 >= self.size.1 as u16 { self.cursor.1 -= 1; self.scroll(); } @@ -121,20 +118,17 @@ impl Screen { } } -impl Write for Screen { - fn write_str(&mut self, s: &str) -> core::fmt::Result { - self.put_str(BackgroundColor::Black, ForegroundColor::White, s); - Ok(()) - } +pub fn print(string: &str) { + let mut screen = unsafe { SCREEN.take() }; - fn write_char(&mut self, c: char) -> core::fmt::Result { - self.putc(BackgroundColor::Black, ForegroundColor::White, c); - Ok(()) - } + screen.put_str(BackgroundColor::Black, ForegroundColor::White, string); + unsafe { SCREEN.put(screen) } } -impl Drop for Screen { - fn drop(&mut self) { - unsafe { SCREEN_LOCK = false; } - } +pub fn println(string: &str) { + let mut screen = unsafe { SCREEN.take() }; + + screen.put_str(BackgroundColor::Black, ForegroundColor::White, string); + screen.putc(BackgroundColor::Black, ForegroundColor::White, '\n'); + unsafe { SCREEN.put(screen) } }