use std::path::Path;
use crate::backend::MemoryOps;
use crate::dmp::{DmpInfo, DmpMem};
use crate::error::Result;
use crate::host::VmHandle;
use crate::kd::KdMemory;
use crate::memory::TranslationCache;
use crate::types::{Dtb, PhysAddr, VirtAddr};
pub enum PhysMem {
Live(VmHandle),
Dmp(Box<DmpMem>),
Remote(KdMemory),
}
impl PhysMem {
pub fn live() -> Result<Self> {
Ok(Self::Live(VmHandle::new()?))
}
pub fn dmp(path: &Path) -> Result<Self> {
Ok(Self::Dmp(Box::new(DmpMem::open(path)?)))
}
pub fn remote(memory: KdMemory) -> Self {
Self::Remote(memory)
}
pub fn dmp_info(&self) -> Option<&DmpInfo> {
match self {
Self::Dmp(d) => Some(d.info()),
_ => None,
}
}
pub fn ram_base(&self) -> u64 {
match self {
Self::Live(h) => h.ram_base(),
Self::Dmp(_) | Self::Remote(_) => 0,
}
}
pub fn ram_size(&self) -> u64 {
match self {
Self::Live(h) => h.ram_size(),
Self::Dmp(_) | Self::Remote(_) => 0,
}
}
pub fn halt_epoch(&self) -> Option<u64> {
match self {
Self::Remote(kd) => kd.translation_cache().map(TranslationCache::halt_epoch),
Self::Dmp(_) => Some(0),
Self::Live(_) => None,
}
}
}
impl MemoryOps<PhysAddr> for PhysMem {
fn read_bytes(&self, addr: PhysAddr, buf: &mut [u8]) -> Result<()> {
match self {
Self::Live(h) => h.read_bytes(addr, buf),
Self::Dmp(d) => d.read_bytes(addr, buf),
Self::Remote(kd) => kd.read_bytes(addr, buf),
}
}
fn write_bytes(&self, addr: PhysAddr, buf: &[u8]) -> Result<()> {
match self {
Self::Live(h) => h.write_bytes(addr, buf),
Self::Dmp(d) => d.write_bytes(addr, buf),
Self::Remote(kd) => kd.write_bytes(addr, buf),
}
}
fn read_virtual_direct(&self, addr: VirtAddr, root: Dtb, buf: &mut [u8]) -> Option<Result<()>> {
match self {
Self::Remote(kd) => kd.read_virtual_direct(addr, root, buf),
Self::Live(_) | Self::Dmp(_) => None,
}
}
fn translation_cache(&self) -> Option<&TranslationCache> {
match self {
Self::Remote(kd) => kd.translation_cache(),
Self::Live(_) | Self::Dmp(_) => None,
}
}
}