diff --git a/kernel/.cargo/config.toml b/kernel/.cargo/config.toml index 0a329c6..0efc34f 100644 --- a/kernel/.cargo/config.toml +++ b/kernel/.cargo/config.toml @@ -3,4 +3,4 @@ target = "i686-unknown-none.json" rustflags = ["-Clink-arg=--script=link.x"] [unstable] -build-std = ["core"] \ No newline at end of file +build-std = ["core", "alloc"] \ No newline at end of file diff --git a/kernel/build b/kernel/build index 816908b..43974fc 100755 --- a/kernel/build +++ b/kernel/build @@ -38,7 +38,7 @@ real_target=${!target} real_target=$(basename $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 if [[ "$CONFIG_BUILD_GRUB" = "true" ]]; then diff --git a/kernel/src/kernel/arch/x86/interrupts.rs b/kernel/src/kernel/arch/x86/interrupts.rs index 67db256..57d1c77 100644 --- a/kernel/src/kernel/arch/x86/interrupts.rs +++ b/kernel/src/kernel/arch/x86/interrupts.rs @@ -1,5 +1,6 @@ //! Provides interrupt-related functions #![cfg(any(target_arch = "x86"))] +#![allow(static_mut_refs)] use core::{alloc::{Allocator, Layout}, arch::asm, mem::MaybeUninit}; @@ -76,9 +77,7 @@ fn load_idt(base: *const u8, size: usize) { }); } unsafe { - asm!( - "lidt {}", in(reg) IDTR.as_ptr() as usize - ) + asm!("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 func = unsafe { idt.funcs[i].assume_init() } as usize as u32; let user_callable = idt.user_callable[i]; - let output: u64 = func & 0b1111111111111111; + let output: u64 = (func & 0b1111111111111111) as u64; } } diff --git a/kernel/src/kernel/mem.rs b/kernel/src/kernel/mem.rs index 00e5b64..e9ba4e0 100644 --- a/kernel/src/kernel/mem.rs +++ b/kernel/src/kernel/mem.rs @@ -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_INITALIZED: bool = false; @@ -86,9 +87,9 @@ fn memory_map_alloc_init(memmap: crate::boot::MemoryMap) -> Result<(), crate::Er #[allow(static_mut_refs)] let alloc = MemoryMapAlloc::new(unsafe { ALLOCATOR_MEMMAP.assume_init_mut() })?; - #[allow(static_mut_refs)] unsafe { - ALLOCATOR.write(alloc); + #[allow(static_mut_refs)] + ALLOCATOR.add_alloc(alloc); } unsafe { ALLOCATOR_INITALIZED = true; @@ -348,6 +349,101 @@ pub const FREE_MEMORY_UNAVAILABLE: i16 = -1; /// Error returned when memory wasn't allocated. 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 fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 { let result = self.allocate(layout); diff --git a/kernel/src/kernel/mod.rs b/kernel/src/kernel/mod.rs index fc9ca62..72299be 100644 --- a/kernel/src/kernel/mod.rs +++ b/kernel/src/kernel/mod.rs @@ -8,19 +8,23 @@ #![feature(ptr_alignment_type)] #![feature(allocator_api)] #![feature(slice_ptr_get)] +#![feature(stmt_expr_attributes)] #![feature(nonnull_provenance)] #![feature(min_specialization)] +#![feature(ptr_as_uninit)] #![allow(internal_features)] #![feature(core_intrinsics)] // tidy-alphabetical-end -pub mod indep_boot_entry; +extern crate alloc; + pub mod arch; pub mod boot; pub mod cmdline; mod constants; pub mod display; mod errors; +pub mod indep_boot_entry; pub mod mem; pub mod multiboot2; pub mod output; diff --git a/kernel/src/kernel/psfont.rs b/kernel/src/kernel/psfont.rs index 2990173..a0fc667 100644 --- a/kernel/src/kernel/psfont.rs +++ b/kernel/src/kernel/psfont.rs @@ -1,12 +1,11 @@ //! PC Screen Font stuff +use alloc::vec::Vec; + /// The font selected to be the "main" font. I selected Linux's /// ISO01-12x22 font. pub const FONT1: &[u8; 12107] = include_bytes!("iso01-12x22.psfu"); -/// One glyph for [RawPCScreenFont]. -pub type RawGlyph = [u8]; - /// PC Screen Font magic number. pub const PSF_MAGIC: u32 = 0x864ab572; @@ -29,7 +28,7 @@ pub struct RawPCScreenFont { /// The width of each glyph. pub width: u32, /// The glyphs. - pub glyphs: *const RawGlyph, + pub glyphs: Vec<u8>, } /// The glyph type for [PCScreenFont]. @@ -40,7 +39,7 @@ pub struct Glyph { pub height: u32, /// The width of this glyph. pub width: u32, - /// The raw glyph data. + /// The raw glyph data(and unicode translation table). pub data: &'static [u8], } @@ -55,16 +54,16 @@ pub struct PCScreenFont { /// The width of each glyph. pub width: u32, /// The glyphs. - pub glyphs: &'static [Glyph], + pub glyphs: Vec<Glyph>, /// 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. pub const ERR_INVALID_MAGIC: i16 = -1; /// 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 { magic: u32::from_le_bytes(data[0..3].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()), height: u32::from_le_bytes(data[24..27].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 { return Err(crate::Error::new("Invalid magic", ERR_INVALID_MAGIC)); @@ -83,26 +82,45 @@ pub fn parse_raw_pc_screen_font(data: &[u8]) -> Result<RawPCScreenFont, crate::E } /// 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 { - let unitable: &[&[u8]] = &[]; - let unistr = data.glyphs.byte_add(data.bytes_per_glyph as usize*data.num_glyphs as usize); + if data.flags == 0 { + let mut unitable: Vec<Vec<u8>> = Vec::with_capacity(data.num_glyphs as usize * core::mem::size_of::<Vec<u8>>()); - let mut i = 0usize; - let mut f = 0usize; - loop { - let g = i+f; - if i>=data.num_glyphs as usize { - break; + 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 f = 0usize; + loop { + let g = i + f; + if i >= data.num_glyphs as usize { + break; + } + let char = (*unistr)[g]; + if char == 0xFF { + i += 1; + f = 0; + continue; + } + unitable[i].push(char); + f += 1; } - let char = (*unistr)[g]; - if char == 0xFF { - i += 1; - f = 0; - continue; - } - unitable[g]; - f += 1; + + let out = PCScreenFont { + version: data.version, + flags: data.flags, + height: data.height, + width: data.width, + glyphs: core::mem::transmute(data.glyphs), + unitable: Some(unitable), + }; + return Ok(out); } let out = PCScreenFont { @@ -110,9 +128,17 @@ pub fn parse_pc_screen_font(data: RawPCScreenFont) -> Result<PCScreenFont, crate flags: data.flags, height: data.height, width: data.width, - glyphs: &*(core::ptr::from_raw_parts(data.glyphs as *const Glyph, data.num_glyphs as usize) as *const [Glyph]), - unitable + glyphs: core::mem::transmute(data.glyphs), + unitable: None, }; 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) +}