use core::{ marker::PhantomData, ops::{Deref, DerefMut, Index, IndexMut}, ptr::NonNull, }; use alloc::{boxed::Box, slice, vec::Vec}; use crate::mem::MemoryRegion; pub struct PhysicalBox { data: NonNull, #[allow(dead_code)] region: MemoryRegion, physical_address: usize, _marker: PhantomData, } impl PhysicalBox { pub fn new(data: T) -> Self { let (memory_region, paddr) = MemoryRegion::contiguous_physical(size_of::() as u64).expect("Failed to allocate"); // UNWRAP: We know this isn't null. let ptr = NonNull::new(memory_region.mut_ptr_at_offset(0)).unwrap(); unsafe { ptr.write(data) }; Self { data: ptr, region: memory_region, physical_address: paddr as usize, _marker: PhantomData, } } } impl PhysicalBox { pub fn physical_address(&self) -> usize { self.physical_address } } impl Deref for PhysicalBox { type Target = T; fn deref(&self) -> &Self::Target { // SAFETY: // - Alignment: This is page aligned. // - Dereferenceable: Guaranteed in same allocation. // - Aliasing: The borrow rules ensure this unsafe { self.data.as_ref() } } } impl DerefMut for PhysicalBox { fn deref_mut(&mut self) -> &mut Self::Target { // SAFETY: // - Alignment: This is page aligned. // - Dereferenceable: Guaranteed in same allocation. // - Aliasing: The borrow rules ensure this unsafe { self.data.as_mut() } } } impl PhysicalBox<[T]> { pub fn default_with_count(default: T, len: usize) -> Self where T: Clone, { let layout = core::alloc::Layout::array::(len).expect("Layout overflow"); // TODO: Implement a function like alloc that takes a layout. let (memory_region, paddr) = MemoryRegion::contiguous_physical(layout.size() as u64).expect("Failed to allocate"); let ptr: *mut T = memory_region.mut_ptr_at_offset(0); for i in 0..len { unsafe { ptr.add(i).write(default.clone()); } } let slice_ptr = core::ptr::slice_from_raw_parts_mut(ptr, len); Self { // UNWRAP: We know this isn't null. data: NonNull::new(slice_ptr).unwrap(), region: memory_region, physical_address: paddr as usize, _marker: PhantomData, } } pub fn from_vec(mut vec: Vec) -> Self { let len = vec.len(); let layout = core::alloc::Layout::array::(len).expect("Layout overflow"); // TODO: Implement a function like alloc that takes a layout. let (memory_region, paddr) = MemoryRegion::contiguous_physical(layout.size() as u64).expect("Failed to allocate"); let ptr: *mut T = memory_region.mut_ptr_at_offset(0); for (i, item) in vec.into_iter().enumerate() { unsafe { ptr.add(i).write(item); } } let slice_ptr = core::ptr::slice_from_raw_parts_mut(ptr, len); Self { // UNWRAP: We know this isn't null. data: NonNull::new(slice_ptr).unwrap(), region: memory_region, physical_address: paddr as usize, _marker: PhantomData, } } pub fn len(&self) -> usize { (**self).len() } } impl Index for PhysicalBox<[T]> where I: slice::SliceIndex<[T]>, { type Output = I::Output; fn index(&self, index: I) -> &Self::Output { &(**self)[index] } } impl IndexMut for PhysicalBox<[T]> where I: slice::SliceIndex<[T]>, { fn index_mut(&mut self, index: I) -> &mut Self::Output { &mut (**self)[index] } } /// SAFETY: We are the only owner of this pointer. unsafe impl Send for PhysicalBox where Box: Send {} /// SAFETY: You must have a mutable reference to this /// type to modify the data at the pointer. unsafe impl Sync for PhysicalBox where Box: Sync {} impl Drop for PhysicalBox { fn drop(&mut self) { // SAFETY: // - We own this data. unsafe { core::ptr::drop_in_place(self.data.as_ptr()) } } }