Make display::TextDisplay::get_size be failable and implement a better power on test method
Some checks failed
Format code / Format the kernel (push) Waiting to run
Continuous Integration / ci (push) Has been cancelled

This commit is contained in:
Arthur Beck 2025-03-31 16:39:11 -05:00
parent fc11d393ff
commit 6d3c77056c
Signed by: ArthurB
GPG key ID: CA200B389F0F6BC9
8 changed files with 83 additions and 58 deletions

View file

@ -69,12 +69,20 @@ impl crate::display::TextDisplay for FramebufferInfo {
Ok(()) Ok(())
} }
fn get_size(&self) -> (u32, u32) { (self.width, self.height) } fn get_size(&self) -> Result<(u32, u32), crate::Error<'static>> {
Ok((self.width, self.height))
}
fn scroll(&self) { fn scroll(&self) {
let mut addr = self.address as usize; let mut addr = self.address as usize;
addr += self.pitch as usize; addr += self.pitch as usize;
unsafe { core::ptr::copy(addr as *const u8, self.address as usize as *mut u8, (self.pitch*(self.height-1)) as usize); } unsafe {
core::ptr::copy(
addr as *const u8,
self.address as usize as *mut u8,
(self.pitch * (self.height - 1)) as usize,
);
}
for x in 0..self.width { for x in 0..self.width {
self.write_char((x, self.height - 1), b' ', crate::display::COLOR_DEFAULT); self.write_char((x, self.height - 1), b' ', crate::display::COLOR_DEFAULT);

View file

@ -26,20 +26,21 @@ pub trait TextDisplay: core::fmt::Write {
color: Color, color: Color,
) -> Result<(), crate::Error<'static>>; ) -> Result<(), crate::Error<'static>>;
/// Gets the size of the screen. /// Gets the size of the screen.
fn get_size(&self) -> (u32, u32); fn get_size(&self) -> Result<(u32, u32), crate::Error<'static>>;
/// Scroll the screen up one character. Clear the bottom row. /// Scroll the screen up one character. Clear the bottom row.
fn scroll(&self); fn scroll(&self);
} }
impl dyn TextDisplay + '_ { impl dyn TextDisplay + '_ {
/// Clears the screen. /// Clears the screen.
pub fn clear_screen(&self, color: Color) { pub fn clear_screen(&self, color: Color) -> Result<(), crate::Error<'static>> {
let (width, height) = self.get_size(); let (width, height) = self.get_size()?;
for x in 0..width { for x in 0..width {
for y in 0..height { for y in 0..height {
self.write_char((x, y), b' ', color).unwrap(); self.write_char((x, y), b' ', color).unwrap();
} }
} }
Ok(())
} }
/// Writes a &str to the screen. /// Writes a &str to the screen.
@ -49,7 +50,7 @@ impl dyn TextDisplay + '_ {
str: &str, str: &str,
color: Color, color: Color,
) -> Result<(u32, u32), crate::Error<'static>> { ) -> Result<(u32, u32), crate::Error<'static>> {
let (width, height) = self.get_size(); let (width, height) = self.get_size()?;
let (mut x, mut y) = pos; let (mut x, mut y) = pos;
for char in str.as_bytes() { for char in str.as_bytes() {
if y >= height { if y >= height {
@ -76,7 +77,7 @@ impl dyn TextDisplay + '_ {
str: &[u8], str: &[u8],
color: Color, color: Color,
) -> Result<(u32, u32), crate::Error<'static>> { ) -> Result<(u32, u32), crate::Error<'static>> {
let (width, _) = self.get_size(); let (width, _) = self.get_size()?;
let (mut x, mut y) = pos; let (mut x, mut y) = pos;
for char in str { for char in str {
self.write_char((x, y), *char, color)?; self.write_char((x, y), *char, color)?;
@ -98,7 +99,9 @@ impl dyn TextDisplay + '_ {
pub struct NoneTextDisplay {} pub struct NoneTextDisplay {}
impl TextDisplay for NoneTextDisplay { impl TextDisplay for NoneTextDisplay {
fn get_size(&self) -> (u32, u32) { (1, 1) } fn get_size(&self) -> Result<(u32, u32), crate::Error<'static>> {
Ok((1,1))
}
fn write_char(&self, _: (u32, u32), _: u8, _: Color) -> Result<(), crate::Error<'static>> { fn write_char(&self, _: (u32, u32), _: u8, _: Color) -> Result<(), crate::Error<'static>> {
Ok(()) Ok(())
} }

View file

@ -3,15 +3,11 @@
#![allow(unexpected_cfgs)] #![allow(unexpected_cfgs)]
#![allow(static_mut_refs)] #![allow(static_mut_refs)]
use core::alloc::{Allocator, Layout};
use crate::display::{COLOR_DEFAULT, NoneTextDisplay}; use crate::display::{COLOR_DEFAULT, NoneTextDisplay};
use crate::output::*; use crate::output::*;
use aphrodite_proc_macros::*; use aphrodite_proc_macros::*;
const MEM_TEST_SIZES: [usize; 8] = [1, 2, 4, 8, 16, 32, 64, 128];
/// The real entrypoint to the kernel. `internel/arch/*/entry.rs` files /// The real entrypoint to the kernel. `internel/arch/*/entry.rs` files
/// eventually call this. /// eventually call this.
#[kernel_item(IndepBootEntry)] #[kernel_item(IndepBootEntry)]
@ -24,7 +20,6 @@ fn indep_boot_entry(
crate::arch::Architecture::ExampleDummy, crate::arch::Architecture::ExampleDummy,
"Somehow the kernel successfully booted into IndepBootEntry with a dummy architecture" "Somehow the kernel successfully booted into IndepBootEntry with a dummy architecture"
); );
crate::arch::output::sdebugsln("IndepBootEntry called");
let display = display.unwrap_or(&NoneTextDisplay {}); let display = display.unwrap_or(&NoneTextDisplay {});
@ -33,48 +28,8 @@ fn indep_boot_entry(
let mem_map = BI.memory_map.unwrap(); let mem_map = BI.memory_map.unwrap();
crate::mem::MemMapAllocInit(mem_map).unwrap(); crate::mem::MemMapAllocInit(mem_map).unwrap();
let allocator = crate::mem::MemMapAlloc().unwrap();
tdebugsln("Testing allocator...", display).unwrap(); crate::power_on_tests::run(display);
for size in MEM_TEST_SIZES {
tdebugs("Number of allocations: ", display).unwrap();
tdebugbnpln(
&crate::u64_as_u8_slice(allocator.number_of_allocations()),
display,
)
.unwrap();
tdebugs("Allocating ", display).unwrap();
tdebugbnp(&crate::usize_as_u8_slice(size), display).unwrap();
tdebugsnpln(" byte(s) of memory...", display).unwrap();
let allocation = allocator.allocate(Layout::from_size_align(size, 1).unwrap());
if let Err(_) = allocation {
terrors("Failed to allocate: ", display).unwrap();
unsafe { crate::mem::LAST_MEMMAP_ERR.unwrap_err().display_np(display) }
panic!("Allocation failure");
} else if let Ok(ptr) = allocation {
tdebugs("Successfully allocated! Address is ", display).unwrap();
tdebugbnp(&crate::usize_as_u8_slice(ptr.addr().get()), display).unwrap();
tdebugsnpln(".", display).unwrap();
tdebugsln("", display).unwrap();
tdebugsln("Deallocating memory...", display).unwrap();
unsafe {
allocator.deallocate(
ptr.as_non_null_ptr(),
Layout::from_size_align(size, 1).unwrap(),
)
}
if let Err(err) = unsafe { crate::mem::LAST_MEMMAP_ERR } {
terrors("Failed to deallocate: ", display).unwrap();
err.display_np(display);
panic!("Deallocation failure");
} else {
tdebugsln("Successfully deallocated!", display).unwrap();
}
}
tdebugsln("", display).unwrap();
}
loop {} loop {}
} }

View file

@ -66,7 +66,7 @@ static mut ALLOCATOR_MEMMAP: MaybeUninit<MemoryMap> = MaybeUninit::uninit();
static mut ALLOCATOR_INITALIZED: bool = false; static mut ALLOCATOR_INITALIZED: bool = false;
#[kernel_item(MemMapAlloc)] #[kernel_item(MemMapAlloc)]
fn get_allocator() -> Option<&'static MemoryMapAlloc<'static>> { pub fn get_allocator() -> Option<&'static MemoryMapAlloc<'static>> {
if unsafe { ALLOCATOR_INITALIZED } { if unsafe { ALLOCATOR_INITALIZED } {
#[allow(static_mut_refs)] #[allow(static_mut_refs)]
return Some(unsafe { ALLOCATOR.assume_init_ref() }); return Some(unsafe { ALLOCATOR.assume_init_ref() });

View file

@ -38,6 +38,8 @@ pub mod psfont;
mod traits; mod traits;
mod util; mod util;
pub(crate) mod power_on_tests;
#[macro_use] #[macro_use]
pub(crate) mod cfg; pub(crate) mod cfg;

View file

@ -61,7 +61,7 @@ macro_rules! message_funcs {
/// Outputs a message u8 to the terminal. /// Outputs a message u8 to the terminal.
pub fn [< t $func_name u >](s: u8, info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> { pub fn [< t $func_name u >](s: u8, info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> {
let (width, _) = info.get_size(); let (width, _) = info.get_size()?;
unsafe { unsafe {
if cfg!($level = "false") { if cfg!($level = "false") {
return Ok(()); return Ok(());
@ -127,7 +127,7 @@ macro_rules! message_funcs {
/// Outputs a message u8 to the terminal without a prefix. /// Outputs a message u8 to the terminal without a prefix.
pub fn [< t $func_name unp >](s: u8, info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> { pub fn [< t $func_name unp >](s: u8, info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> {
let (width, _) = info.get_size(); let (width, _) = info.get_size()?;
unsafe { unsafe {
if cfg!($level = "false") { if cfg!($level = "false") {
return Ok(()); return Ok(());

View file

@ -0,0 +1,50 @@
use crate::{display::TextDisplay, output::*};
use core::alloc::{Allocator, Layout};
const MEM_TEST_SIZES: [usize; 8] = [1, 2, 4, 8, 16, 32, 64, 128];
pub fn run(display: &dyn TextDisplay) {
let allocator = crate::mem::get_allocator().unwrap();
tdebugsln("Testing allocator...", display).unwrap();
for size in MEM_TEST_SIZES {
tdebugs("Number of allocations: ", display).unwrap();
tdebugbnpln(
&crate::u64_as_u8_slice(allocator.number_of_allocations()),
display,
)
.unwrap();
tdebugs("Allocating ", display).unwrap();
tdebugbnp(&crate::usize_as_u8_slice(size), display).unwrap();
tdebugsnpln(" byte(s) of memory...", display).unwrap();
let allocation = allocator.allocate(Layout::from_size_align(size, 1).unwrap());
if let Err(_) = allocation {
terrors("Failed to allocate: ", display).unwrap();
unsafe { crate::mem::LAST_MEMMAP_ERR.unwrap_err().display_np(display) }
panic!("Allocator test failure");
} else if let Ok(ptr) = allocation {
tdebugs("Successfully allocated! Address is ", display).unwrap();
tdebugbnp(&crate::usize_as_u8_slice(ptr.addr().get()), display).unwrap();
tdebugsnpln(".", display).unwrap();
tdebugsln("", display).unwrap();
tdebugsln("Deallocating memory...", display).unwrap();
unsafe {
allocator.deallocate(
ptr.as_non_null_ptr(),
Layout::from_size_align(size, 1).unwrap(),
)
}
if let Err(err) = unsafe { crate::mem::LAST_MEMMAP_ERR } {
terrors("Failed to deallocate: ", display).unwrap();
err.display_np(display);
panic!("Deallocation failure");
} else {
tdebugsln("Successfully deallocated!", display).unwrap();
}
}
tdebugsln("", display).unwrap();
}
}

View file

@ -0,0 +1,7 @@
use crate::display::TextDisplay;
mod memmapalloc;
pub fn run(display: &dyn TextDisplay) {
memmapalloc::run(display);
}