pub trait PhysicalMemory: Send {
    // Required methods
    fn phys_read_raw_iter(
        &mut self,
        data: PhysicalReadMemOps<'_, '_, '_, '_>
    ) -> Result<()>;
    fn phys_write_raw_iter(
        &mut self,
        data: PhysicalWriteMemOps<'_, '_, '_, '_>
    ) -> Result<()>;
    fn metadata(&self) -> PhysicalMemoryMetadata;

    // Provided methods
    fn set_mem_map(&mut self, _mem_map: &[PhysicalMemoryMapping]) { ... }
    fn phys_read_into<T: Pod + ?Sized>(
        &mut self,
        addr: PhysicalAddress,
        out: &mut T
    ) -> Result<()>
       where Self: Sized { ... }
    fn phys_write<T: Pod + ?Sized>(
        &mut self,
        addr: PhysicalAddress,
        data: &T
    ) -> Result<()>
       where Self: Sized { ... }
    fn into_phys_view(self) -> PhysicalMemoryView<Self>
       where Self: Sized { ... }
    fn phys_view(&mut self) -> PhysicalMemoryView<Fwd<&mut Self>>
       where Self: Sized { ... }
    fn into_mem_view(self) -> PhysicalMemoryView<Self>
       where Self: Sized { ... }
    fn mem_view(&mut self) -> PhysicalMemoryView<Fwd<&mut Self>>
       where Self: Sized { ... }
}
Expand description

The PhysicalMemory trait is implemented by memory backends and provides a generic way to read and write from/to physical memory.

All addresses are of the type PhysicalAddress and can contain additional information about the page the address resides in. This information is usually only needed when implementing caches.

There are only 2 methods which are required to be implemented by the provider of this trait.

Examples

Implementing PhysicalMemory for a memory backend:

use std::vec::Vec;
use std::convert::TryInto;

use memflow::mem::{
    MemoryMap,
    PhysicalMemoryMapping,
    phys_mem::{
        PhysicalMemory,
        PhysicalMemoryMetadata,
    },
    mem_data::{
        MemOps,
        PhysicalReadMemOps,
        PhysicalWriteMemOps,
        opt_call,
    }
};

use memflow::cglue::{CIterator, CTup2, CTup3};

use memflow::types::{PhysicalAddress, Address, umem};
use memflow::error::Result;

pub struct MemoryBackend {
    mem: Box<[u8]>,
}

impl PhysicalMemory for MemoryBackend {
    fn phys_read_raw_iter(
        &mut self,
        MemOps {
            inp,
            mut out,
            ..
        }: PhysicalReadMemOps,
    ) -> Result<()> {
        inp
            .for_each(|CTup3(addr, meta_addr, mut data)| {
                let addr: usize = addr.to_umem().try_into().unwrap();
                let len = data.len();
                data.copy_from_slice(&self.mem[addr..(addr + len)]);
                opt_call(out.as_deref_mut(), CTup2(meta_addr, data));
            });
        Ok(())
    }

    fn phys_write_raw_iter(
        &mut self,
        MemOps {
            inp,
            mut out,
            ..
        }: PhysicalWriteMemOps,
    ) -> Result<()> {
        inp
            .for_each(|CTup3(addr, meta_addr, data)| {
                let addr: usize = addr.to_umem().try_into().unwrap();
                let len = data.len();
                self.mem[addr..(addr + len)].copy_from_slice(&data);
                opt_call(out.as_deref_mut(), CTup2(meta_addr, data));
            });
        Ok(())
    }

    fn metadata(&self) -> PhysicalMemoryMetadata {
        PhysicalMemoryMetadata {
            max_address: (self.mem.len() - 1).into(),
            real_size: self.mem.len() as umem,
            readonly: false,
            ideal_batch_size: u32::MAX
        }
    }
}

Reading from PhysicalMemory:

use memflow::types::Address;
use memflow::mem::PhysicalMemory;

fn read<T: PhysicalMemory>(mem: &mut T) {
    let mut addr = 0u64;
    mem.phys_read_into(Address::from(0x1000).into(), &mut addr).unwrap();
    println!("addr: {:x}", addr);
}

Required Methods§

source

fn phys_read_raw_iter( &mut self, data: PhysicalReadMemOps<'_, '_, '_, '_> ) -> Result<()>

source

fn phys_write_raw_iter( &mut self, data: PhysicalWriteMemOps<'_, '_, '_, '_> ) -> Result<()>

source

fn metadata(&self) -> PhysicalMemoryMetadata

Retrieve metadata about the physical memory

This function will return metadata about the underlying physical memory object, currently including address space size and read-only status.

Examples
use memflow::types::{size, mem};
use memflow::mem::PhysicalMemory;

let metadata = mem.metadata();

assert_eq!(metadata.max_address.to_umem(), mem::mb(16) - 1);
assert_eq!(metadata.real_size, mem::mb(16));
assert_eq!(metadata.readonly, false);

Provided Methods§

source

fn set_mem_map(&mut self, _mem_map: &[PhysicalMemoryMapping])

Sets the memory mapping for the physical memory

In case a connector cannot acquire memory mappings on it’s own this function allows the OS plugin to set the memory mapping at a later stage of initialization.

The only reason this is needed for some connectors is to avoid catastrophic failures upon reading invalid address.

By default this is a no-op.

source

fn phys_read_into<T: Pod + ?Sized>( &mut self, addr: PhysicalAddress, out: &mut T ) -> Result<()>
where Self: Sized,

source

fn phys_write<T: Pod + ?Sized>( &mut self, addr: PhysicalAddress, data: &T ) -> Result<()>
where Self: Sized,

source

fn into_phys_view(self) -> PhysicalMemoryView<Self>
where Self: Sized,

source

fn phys_view(&mut self) -> PhysicalMemoryView<Fwd<&mut Self>>
where Self: Sized,

source

fn into_mem_view(self) -> PhysicalMemoryView<Self>
where Self: Sized,

source

fn mem_view(&mut self) -> PhysicalMemoryView<Fwd<&mut Self>>
where Self: Sized,

Implementations on Foreign Types§

source§

impl<CGlueO: Deref<Target = CGlueT> + DerefMut + Send, CGlueT> PhysicalMemory for Fwd<CGlueO>
where CGlueT: PhysicalMemory,

source§

fn phys_read_raw_iter( &mut self, data: PhysicalReadMemOps<'_, '_, '_, '_> ) -> Result<()>

source§

fn phys_write_raw_iter( &mut self, data: PhysicalWriteMemOps<'_, '_, '_, '_> ) -> Result<()>

source§

fn metadata(&self) -> PhysicalMemoryMetadata

source§

fn set_mem_map(&mut self, _mem_map: &[PhysicalMemoryMapping])

Implementors§