Browse Source

Add spin lock and use for global VGA screen

Signed-off-by: main <magic_rb@redalder.org>
master
main 2 months ago
parent
commit
5952889359
Signed by: Magic_RB GPG Key ID: 08D5287CC5DDCA0E
  1. 1
      meson.build
  2. 7
      src/lib.rs
  3. 5
      src/rlibc/mod.rs
  4. 68
      src/rlibc/spin_lock.rs
  5. 62
      src/screen/mod.rs

1
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'

7
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");
}
}

5
src/rlibc/mod.rs

@ -1,2 +1,5 @@
mod memory;
pub use self::memory::*;
pub use memory::*;
mod spin_lock;
pub use spin_lock::*;

68
src/rlibc/spin_lock.rs

@ -0,0 +1,68 @@
use core::{cell::UnsafeCell, mem, sync::atomic::{AtomicBool, Ordering}};
pub struct SpinLock<T> {
lock: AtomicBool,
inner: UnsafeCell<Option<T>>
}
impl<T> SpinLock<T> {
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<T> {
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<T> {
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)
}
}
}

62
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<Screen> = SpinLock::new(Screen::new((80, 25), 0xB8000 as *mut ()));
#[allow(dead_code)]
#[repr(u8)]
@ -70,28 +68,27 @@ impl Into<u16> 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<Self> {
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) }
}

Loading…
Cancel
Save