PC Screen Fonts *should* parse correctly now, global memory management works. Still having issues with deallocating memory, however.

This commit is contained in:
Arthur Beck 2025-02-12 17:04:13 -06:00
parent ff12b11b9f
commit 942478b0e2
6 changed files with 163 additions and 38 deletions

View file

@ -3,4 +3,4 @@ target = "i686-unknown-none.json"
rustflags = ["-Clink-arg=--script=link.x"] rustflags = ["-Clink-arg=--script=link.x"]
[unstable] [unstable]
build-std = ["core"] build-std = ["core", "alloc"]

View file

@ -38,7 +38,7 @@
real_target=${!target} real_target=${!target}
real_target=$(basename $real_target) real_target=$(basename $real_target)
echo "Compiling target $target(with rust target of $real_target)" echo "Compiling target $target(with rust target of $real_target)"
cargo build --target "$real_target" --release -Zbuild-std --bin entrypoint_$target cargo build --target "$real_target" --release -Zbuild-std=core,alloc --bin entrypoint_$target
cp "target/$(echo $real_target | sed 's/\.json//')/release/entrypoint_$target" kernel-$target cp "target/$(echo $real_target | sed 's/\.json//')/release/entrypoint_$target" kernel-$target
if [[ "$CONFIG_BUILD_GRUB" = "true" ]]; then if [[ "$CONFIG_BUILD_GRUB" = "true" ]]; then

View file

@ -1,5 +1,6 @@
//! Provides interrupt-related functions //! Provides interrupt-related functions
#![cfg(any(target_arch = "x86"))] #![cfg(any(target_arch = "x86"))]
#![allow(static_mut_refs)]
use core::{alloc::{Allocator, Layout}, arch::asm, mem::MaybeUninit}; use core::{alloc::{Allocator, Layout}, arch::asm, mem::MaybeUninit};
@ -76,9 +77,7 @@ fn load_idt(base: *const u8, size: usize) {
}); });
} }
unsafe { unsafe {
asm!( asm!("lidt {}", in(reg) IDTR.as_ptr() as usize)
"lidt {}", in(reg) IDTR.as_ptr() as usize
)
} }
} }
@ -90,7 +89,7 @@ fn activate_idt(idt: Idt, alloc: crate::mem::MemoryMapAlloc) {
let vector = idt.vectors[i]; let vector = idt.vectors[i];
let func = unsafe { idt.funcs[i].assume_init() } as usize as u32; let func = unsafe { idt.funcs[i].assume_init() } as usize as u32;
let user_callable = idt.user_callable[i]; let user_callable = idt.user_callable[i];
let output: u64 = func & 0b1111111111111111; let output: u64 = (func & 0b1111111111111111) as u64;
} }
} }

View file

@ -63,7 +63,8 @@ impl Iterator for AllocationIter {
} }
} }
static mut ALLOCATOR: MaybeUninit<MemoryMapAlloc<'static>> = MaybeUninit::uninit(); #[global_allocator]
static mut ALLOCATOR: MaybeMemoryMapAlloc<'static> = MaybeMemoryMapAlloc::new(None);
static mut ALLOCATOR_MEMMAP: MaybeUninit<MemoryMap> = MaybeUninit::uninit(); static mut ALLOCATOR_MEMMAP: MaybeUninit<MemoryMap> = MaybeUninit::uninit();
static mut ALLOCATOR_INITALIZED: bool = false; static mut ALLOCATOR_INITALIZED: bool = false;
@ -86,9 +87,9 @@ fn memory_map_alloc_init(memmap: crate::boot::MemoryMap) -> Result<(), crate::Er
#[allow(static_mut_refs)] #[allow(static_mut_refs)]
let alloc = MemoryMapAlloc::new(unsafe { ALLOCATOR_MEMMAP.assume_init_mut() })?; let alloc = MemoryMapAlloc::new(unsafe { ALLOCATOR_MEMMAP.assume_init_mut() })?;
#[allow(static_mut_refs)]
unsafe { unsafe {
ALLOCATOR.write(alloc); #[allow(static_mut_refs)]
ALLOCATOR.add_alloc(alloc);
} }
unsafe { unsafe {
ALLOCATOR_INITALIZED = true; ALLOCATOR_INITALIZED = true;
@ -348,6 +349,101 @@ pub const FREE_MEMORY_UNAVAILABLE: i16 = -1;
/// Error returned when memory wasn't allocated. /// Error returned when memory wasn't allocated.
pub const MEMORY_NOT_ALLOCATED: i16 = -7; pub const MEMORY_NOT_ALLOCATED: i16 = -7;
/// Error returned when the [MaybeMemoryMapAlloc] doesn't have
/// an initalized allocator.
pub const MAYBE_MEMORY_MAP_ALLOC_UNINITALIZED: i16 = -8;
struct MaybeMemoryMapAlloc<'a> {
alloc: MaybeUninit<MemoryMapAlloc<'a>>,
initalized: bool
}
impl<'a> MaybeMemoryMapAlloc<'a> {
const fn new(alloc: Option<MemoryMapAlloc<'a>>) -> Self {
if alloc.is_none() {
return MaybeMemoryMapAlloc {
alloc: MaybeUninit::uninit(),
initalized: false,
}
}
MaybeMemoryMapAlloc {
alloc: MaybeUninit::new(alloc.unwrap()),
initalized: true,
}
}
const unsafe fn assume_init_ref(&self) -> &MemoryMapAlloc<'a> {
unsafe { self.alloc.assume_init_ref() }
}
/// Note that if the allocator isn't initalized then this will do nothing.
const fn add_alloc(&mut self, alloc: MemoryMapAlloc<'a>) {
if self.initalized {
return;
}
self.alloc.write(alloc);
self.initalized = true;
}
fn remove_alloc(&mut self) {
if !self.initalized {
return;
}
unsafe { self.alloc.assume_init_drop(); }
self.initalized = false;
}
}
unsafe impl<'a> GlobalAlloc for MaybeMemoryMapAlloc<'a> {
unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
if self.initalized {
unsafe {
LAST_MEMMAP_ERR = Err(crate::Error::new(
"MaybeMemoryMapAlloc not initalized",
MAYBE_MEMORY_MAP_ALLOC_UNINITALIZED,
))
}
return null_mut();
}
unsafe { self.alloc.assume_init_ref().alloc(layout) }
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) {
if self.initalized {
unsafe {
LAST_MEMMAP_ERR = Err(crate::Error::new(
"MaybeMemoryMapAlloc not initalized",
MAYBE_MEMORY_MAP_ALLOC_UNINITALIZED,
))
}
return;
}
unsafe { self.alloc.assume_init_ref().dealloc(ptr, layout) }
}
}
unsafe impl<'a> Allocator for MaybeMemoryMapAlloc<'a> {
fn allocate(&self, layout: core::alloc::Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
if !self.initalized {
unsafe {
LAST_MEMMAP_ERR = Err(crate::Error::new(
"MaybeMemoryMapAlloc not initalized",
MAYBE_MEMORY_MAP_ALLOC_UNINITALIZED,
))
}
return Err(core::alloc::AllocError {});
}
unsafe { self.alloc.assume_init_ref() }.allocate(layout)
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: core::alloc::Layout) {
if !self.initalized {
unsafe {
LAST_MEMMAP_ERR = Err(crate::Error::new(
"MaybeMemoryMapAlloc not initalized",
MAYBE_MEMORY_MAP_ALLOC_UNINITALIZED,
))
}
return;
}
unsafe { self.alloc.assume_init_ref().deallocate(ptr, layout) }
}
}
unsafe impl<'a> GlobalAlloc for MemoryMapAlloc<'a> { unsafe impl<'a> GlobalAlloc for MemoryMapAlloc<'a> {
unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 { unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
let result = self.allocate(layout); let result = self.allocate(layout);

View file

@ -8,19 +8,23 @@
#![feature(ptr_alignment_type)] #![feature(ptr_alignment_type)]
#![feature(allocator_api)] #![feature(allocator_api)]
#![feature(slice_ptr_get)] #![feature(slice_ptr_get)]
#![feature(stmt_expr_attributes)]
#![feature(nonnull_provenance)] #![feature(nonnull_provenance)]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(ptr_as_uninit)]
#![allow(internal_features)] #![allow(internal_features)]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
// tidy-alphabetical-end // tidy-alphabetical-end
pub mod indep_boot_entry; extern crate alloc;
pub mod arch; pub mod arch;
pub mod boot; pub mod boot;
pub mod cmdline; pub mod cmdline;
mod constants; mod constants;
pub mod display; pub mod display;
mod errors; mod errors;
pub mod indep_boot_entry;
pub mod mem; pub mod mem;
pub mod multiboot2; pub mod multiboot2;
pub mod output; pub mod output;

View file

@ -1,12 +1,11 @@
//! PC Screen Font stuff //! PC Screen Font stuff
use alloc::vec::Vec;
/// The font selected to be the "main" font. I selected Linux's /// The font selected to be the "main" font. I selected Linux's
/// ISO01-12x22 font. /// ISO01-12x22 font.
pub const FONT1: &[u8; 12107] = include_bytes!("iso01-12x22.psfu"); pub const FONT1: &[u8; 12107] = include_bytes!("iso01-12x22.psfu");
/// One glyph for [RawPCScreenFont].
pub type RawGlyph = [u8];
/// PC Screen Font magic number. /// PC Screen Font magic number.
pub const PSF_MAGIC: u32 = 0x864ab572; pub const PSF_MAGIC: u32 = 0x864ab572;
@ -29,7 +28,7 @@ pub struct RawPCScreenFont {
/// The width of each glyph. /// The width of each glyph.
pub width: u32, pub width: u32,
/// The glyphs. /// The glyphs.
pub glyphs: *const RawGlyph, pub glyphs: Vec<u8>,
} }
/// The glyph type for [PCScreenFont]. /// The glyph type for [PCScreenFont].
@ -40,7 +39,7 @@ pub struct Glyph {
pub height: u32, pub height: u32,
/// The width of this glyph. /// The width of this glyph.
pub width: u32, pub width: u32,
/// The raw glyph data. /// The raw glyph data(and unicode translation table).
pub data: &'static [u8], pub data: &'static [u8],
} }
@ -55,16 +54,16 @@ pub struct PCScreenFont {
/// The width of each glyph. /// The width of each glyph.
pub width: u32, pub width: u32,
/// The glyphs. /// The glyphs.
pub glyphs: &'static [Glyph], pub glyphs: Vec<Glyph>,
/// The unicode translation table. /// The unicode translation table.
pub unitable: &'static [&'static [u8]] pub unitable: Option<Vec<Vec<u8>>>,
} }
/// Error code returned when the PSF has an invalid magic number. /// Error code returned when the PSF has an invalid magic number.
pub const ERR_INVALID_MAGIC: i16 = -1; pub const ERR_INVALID_MAGIC: i16 = -1;
/// Parses a PC Screen Font into a [RawPCScreenFont]. /// Parses a PC Screen Font into a [RawPCScreenFont].
pub fn parse_raw_pc_screen_font(data: &[u8]) -> Result<RawPCScreenFont, crate::Error> { pub fn parse_raw_pc_screen_font(data: Vec<u8>) -> Result<RawPCScreenFont, crate::Error<'static>> {
let out = RawPCScreenFont { let out = RawPCScreenFont {
magic: u32::from_le_bytes(data[0..3].try_into().unwrap()), magic: u32::from_le_bytes(data[0..3].try_into().unwrap()),
version: u32::from_le_bytes(data[4..7].try_into().unwrap()), version: u32::from_le_bytes(data[4..7].try_into().unwrap()),
@ -74,7 +73,7 @@ pub fn parse_raw_pc_screen_font(data: &[u8]) -> Result<RawPCScreenFont, crate::E
bytes_per_glyph: u32::from_le_bytes(data[20..23].try_into().unwrap()), bytes_per_glyph: u32::from_le_bytes(data[20..23].try_into().unwrap()),
height: u32::from_le_bytes(data[24..27].try_into().unwrap()), height: u32::from_le_bytes(data[24..27].try_into().unwrap()),
width: u32::from_le_bytes(data[28..31].try_into().unwrap()), width: u32::from_le_bytes(data[28..31].try_into().unwrap()),
glyphs: &data[32..] as *const [u8] glyphs: data[32..].to_vec(),
}; };
if out.magic != PSF_MAGIC { if out.magic != PSF_MAGIC {
return Err(crate::Error::new("Invalid magic", ERR_INVALID_MAGIC)); return Err(crate::Error::new("Invalid magic", ERR_INVALID_MAGIC));
@ -83,16 +82,24 @@ pub fn parse_raw_pc_screen_font(data: &[u8]) -> Result<RawPCScreenFont, crate::E
} }
/// Parses a PC Screen Font into a [PCScreenFont]. /// Parses a PC Screen Font into a [PCScreenFont].
pub fn parse_pc_screen_font(data: RawPCScreenFont) -> Result<PCScreenFont, crate::Error<'static>> { pub fn parse_pc_screen_font(
data: RawPCScreenFont,
) -> Result<PCScreenFont, crate::Error<'static>> {
unsafe { unsafe {
let unitable: &[&[u8]] = &[]; if data.flags == 0 {
let unistr = data.glyphs.byte_add(data.bytes_per_glyph as usize*data.num_glyphs as usize); let mut unitable: Vec<Vec<u8>> = Vec::with_capacity(data.num_glyphs as usize * core::mem::size_of::<Vec<u8>>());
let unistr = (data
.glyphs
.as_slice()
as *const [u8])
.byte_add(data.bytes_per_glyph as usize * data.num_glyphs as usize);
let mut i = 0usize; let mut i = 0usize;
let mut f = 0usize; let mut f = 0usize;
loop { loop {
let g = i+f; let g = i + f;
if i>=data.num_glyphs as usize { if i >= data.num_glyphs as usize {
break; break;
} }
let char = (*unistr)[g]; let char = (*unistr)[g];
@ -101,7 +108,7 @@ pub fn parse_pc_screen_font(data: RawPCScreenFont) -> Result<PCScreenFont, crate
f = 0; f = 0;
continue; continue;
} }
unitable[g]; unitable[i].push(char);
f += 1; f += 1;
} }
@ -110,9 +117,28 @@ pub fn parse_pc_screen_font(data: RawPCScreenFont) -> Result<PCScreenFont, crate
flags: data.flags, flags: data.flags,
height: data.height, height: data.height,
width: data.width, width: data.width,
glyphs: &*(core::ptr::from_raw_parts(data.glyphs as *const Glyph, data.num_glyphs as usize) as *const [Glyph]), glyphs: core::mem::transmute(data.glyphs),
unitable unitable: Some(unitable),
};
return Ok(out);
}
let out = PCScreenFont {
version: data.version,
flags: data.flags,
height: data.height,
width: data.width,
glyphs: core::mem::transmute(data.glyphs),
unitable: None,
}; };
Ok(out) Ok(out)
} }
} }
/// Parses a Vec<u8> into a [PCScreenFont].
pub fn parse_psfu(
data: Vec<u8>,
) -> Result<PCScreenFont, crate::Error<'static>> {
let data = parse_raw_pc_screen_font(data)?;
parse_pc_screen_font(data)
}