use crate::{MemoryRead, MemoryWrite};
pub trait LoadDriver {
type DriverType: KernelMemoryRead + KernelMemoryWrite + MapPhysical + TranslatePhysical;
fn load(&self) -> Option<Self::DriverType>;
fn unload(&self) -> Option<()>;
}
pub trait KernelMemoryRead: MemoryRead {}
pub trait KernelMemoryWrite: MemoryWrite {}
pub trait PhysicalMemoryRead {
fn try_read_bytes_physical_into(&self, physical_address: u64, buffer: &mut [u8]) -> Option<()>;
fn physical_reader(&self) -> PhysicalMemoryReader<Self>
where Self: Sized {
PhysicalMemoryReader::new(self)
}
fn virtual_reader(&self) -> VirtualMemoryReader<Self>
where Self: Sized + TranslatePhysical {
VirtualMemoryReader::new(self)
}
}
pub struct VirtualMemoryReader<'a, T: PhysicalMemoryRead + TranslatePhysical>(&'a T);
impl<'a, T: PhysicalMemoryRead + TranslatePhysical> VirtualMemoryReader<'a, T> {
fn new(api: &'a T) -> Self {
Self(api)
}
}
impl<'a, T: PhysicalMemoryRead + TranslatePhysical> MemoryRead for VirtualMemoryReader<'a, T> {
fn try_read_bytes_into(&self, address: u64, buffer: &mut [u8]) -> Option<()> {
let physical_address = self.0.physical_address(address)?;
self.0.try_read_bytes_physical_into(physical_address, buffer)
}
}
impl<'a, T: PhysicalMemoryRead + TranslatePhysical> KernelMemoryRead for VirtualMemoryReader<'a, T> {}
pub struct PhysicalMemoryReader<'a, T: PhysicalMemoryRead>(&'a T);
impl<'a, T: PhysicalMemoryRead> PhysicalMemoryReader<'a, T> {
pub fn new(api: &'a T) -> Self {
Self(api)
}
}
impl<'a, T: PhysicalMemoryRead> MemoryRead for PhysicalMemoryReader<'a, T> {
fn try_read_bytes_into(&self, address: u64, buffer: &mut [u8]) -> Option<()> {
self.0.try_read_bytes_physical_into(address, buffer)
}
}
pub trait PhysicalMemoryWrite {
fn try_write_bytes_physical(&self, physical_address: u64, buffer: &[u8]) -> Option<()>;
fn physical_writer(&self) -> PhysicalMemoryWriter<Self>
where Self: Sized {
PhysicalMemoryWriter::new(self)
}
fn physical(&self) -> PhysicalMemory<Self>
where Self: Sized + PhysicalMemoryRead {
PhysicalMemory::new(self)
}
fn virtual_writer(&self) -> VirtualMemoryWriter<Self>
where Self: Sized + TranslatePhysical {
VirtualMemoryWriter::new(self)
}
fn virtual_memory(&self) -> VirtualMemory<Self>
where Self: Sized + TranslatePhysical + PhysicalMemoryRead {
VirtualMemory::new(self)
}
}
pub struct VirtualMemory<'a, T: PhysicalMemoryRead + PhysicalMemoryWrite + TranslatePhysical>(&'a T);
impl<'a, T: PhysicalMemoryRead + PhysicalMemoryWrite + TranslatePhysical> VirtualMemory<'a, T> {
pub fn new(api: &'a T) -> Self {
Self(api)
}
}
impl<'a, T: PhysicalMemoryRead + PhysicalMemoryWrite + TranslatePhysical> MemoryRead for VirtualMemory<'a, T> {
fn try_read_bytes_into(&self, address: u64, buffer: &mut [u8]) -> Option<()> {
let physical_address = self.0.physical_address(address)?;
self.0.try_read_bytes_physical_into(physical_address, buffer)
}
}
impl<'a, T: PhysicalMemoryRead + PhysicalMemoryWrite + TranslatePhysical> MemoryWrite for VirtualMemory<'a, T> {
fn try_write_bytes(&self, address: u64, buffer: &[u8]) -> Option<()> {
let physical_address = self.0.physical_address(address)?;
self.0.try_write_bytes_physical(physical_address, buffer)
}
}
pub struct VirtualMemoryWriter<'a, T: PhysicalMemoryWrite + TranslatePhysical>(&'a T);
impl<'a, T: PhysicalMemoryWrite + TranslatePhysical> VirtualMemoryWriter<'a, T> {
pub fn new(api: &'a T) -> Self {
Self(api)
}
}
impl<'a, T: PhysicalMemoryWrite + TranslatePhysical> MemoryWrite for VirtualMemoryWriter<'a, T> {
fn try_write_bytes(&self, address: u64, buffer: &[u8]) -> Option<()> {
let physical_address = self.0.physical_address(address)?;
self.0.try_write_bytes_physical(physical_address, buffer)
}
}
impl<'a, T: PhysicalMemoryWrite + TranslatePhysical> KernelMemoryWrite for VirtualMemoryWriter<'a, T> {}
pub struct PhysicalMemoryWriter<'a, T: PhysicalMemoryWrite>(&'a T);
impl<'a, T: PhysicalMemoryWrite> PhysicalMemoryWriter<'a, T> {
pub fn new(api: &'a T) -> Self {
Self(api)
}
}
impl<'a, T: PhysicalMemoryWrite> MemoryWrite for PhysicalMemoryWriter<'a, T> {
fn try_write_bytes(&self, address: u64, buffer: &[u8]) -> Option<()> {
self.0.try_write_bytes_physical(address, buffer)
}
}
pub struct PhysicalMemory<'a, T: PhysicalMemoryRead + PhysicalMemoryWrite>(&'a T);
impl<'a, T: PhysicalMemoryRead + PhysicalMemoryWrite> PhysicalMemory<'a, T> {
pub fn new(api: &'a T) -> Self {
Self(api)
}
}
impl<'a, T: PhysicalMemoryRead + PhysicalMemoryWrite> MemoryRead for PhysicalMemory<'a, T> {
fn try_read_bytes_into(&self, address: u64, buffer: &mut [u8]) -> Option<()> {
self.0.try_read_bytes_physical_into(address, buffer)
}
}
impl<'a, T: PhysicalMemoryRead + PhysicalMemoryWrite> MemoryWrite for PhysicalMemory<'a, T> {
fn try_write_bytes(&self, address: u64, buffer: &[u8]) -> Option<()> {
self.0.try_write_bytes_physical(address, buffer)
}
}
pub trait MapPhysical {
unsafe fn map_io_space(&self, physical_address: u64, size: usize) -> Option<u64>;
unsafe fn unmap_io_space(&self, virtual_address: u64, size: usize) -> Option<()>;
fn map_physical(&self, physical_address: u64, size: usize) -> Option<MappedPhysicalMemory<Self>>
where
Self: Sized + KernelMemoryRead + KernelMemoryWrite,
{
unsafe {
self.map_io_space(physical_address, size)
.map(|base| MappedPhysicalMemory::new(self, base, size))
}
}
fn map_virtual(&self, virtual_address: u64, size: usize) -> Option<MappedPhysicalMemory<Self>>
where
Self: Sized + KernelMemoryRead + KernelMemoryWrite + TranslatePhysical,
{
let phys = self.physical_address(virtual_address)?;
self.map_physical(phys, size)
}
}
impl<T: MapPhysical + KernelMemoryRead> PhysicalMemoryRead for T {
fn try_read_bytes_physical_into(&self, physical_address: u64, buffer: &mut [u8]) -> Option<()> {
unsafe {
let map = self.map_io_space(physical_address, buffer.len())?;
self.try_read_bytes_into(map, buffer)?;
self.unmap_io_space(map, buffer.len())?;
Some(())
}
}
}
impl<T: MapPhysical + KernelMemoryWrite> PhysicalMemoryWrite for T {
fn try_write_bytes_physical(&self, physical_address: u64, buffer: &[u8]) -> Option<()> {
unsafe {
let map = self.map_io_space(physical_address, buffer.len())?;
self.try_write_bytes(map, buffer)?;
self.unmap_io_space(map, buffer.len())?;
Some(())
}
}
}
pub trait TranslatePhysical {
fn physical_address(&self, virtual_address: u64) -> Option<u64>;
}
pub struct MappedPhysicalMemory<'a, T: MapPhysical + KernelMemoryRead + KernelMemoryWrite> {
api: &'a T,
base: u64,
size: usize,
}
impl<'a, T: MapPhysical + KernelMemoryRead + KernelMemoryWrite> MappedPhysicalMemory<'a, T> {
pub(crate) unsafe fn new(api: &'a T, base: u64, size: usize) -> Self {
Self { api, base, size }
}
}
impl<'a, T: MapPhysical + KernelMemoryRead + KernelMemoryWrite> crate::MemoryRead
for MappedPhysicalMemory<'a, T>
{
fn try_read_bytes_into(&self, address: u64, buffer: &mut [u8]) -> Option<()> {
if address + buffer.len() as u64 > self.base + self.size as u64 {
return None;
}
self.api
.try_read_bytes_into(self.base as u64 + address, buffer)
}
}
impl<'a, T: MapPhysical + KernelMemoryRead + KernelMemoryWrite> crate::MemoryWrite
for MappedPhysicalMemory<'a, T>
{
fn try_write_bytes(&self, address: u64, buffer: &[u8]) -> Option<()> {
if address + buffer.len() as u64 > self.base + self.size as u64 {
return None;
}
self.api.try_write_bytes(self.base as u64 + address, buffer)
}
}
impl<'a, T: MapPhysical + KernelMemoryRead + KernelMemoryWrite> Drop
for MappedPhysicalMemory<'a, T>
{
fn drop(&mut self) {
unsafe { self.api.unmap_io_space(self.base, self.size).unwrap() }
}
}