#![allow(dead_code)]
use alloc::vec::Vec;
use core::{fmt::Debug, mem::size_of, slice::Iter};
use acpi::{sdt::Signature, AcpiTable};
use super::{
remapping::{Andd, Atsr, Drhd, Rhsa, Rmrr, Satc, Sidp},
SdtHeaderWrapper,
};
use crate::mm::paddr_to_vaddr;
#[derive(Debug)]
pub struct Dmar {
header: DmarHeader,
remapping_structures: Vec<Remapping>, }
#[derive(Debug)]
pub enum Remapping {
Drhd(Drhd),
Rmrr(Rmrr),
Atsr(Atsr),
Rhsa(Rhsa),
Andd(Andd),
Satc(Satc),
Sidp(Sidp),
}
#[derive(Debug, Clone, Copy)]
#[repr(u16)]
#[allow(clippy::upper_case_acronyms)]
pub enum RemappingType {
DRHD = 0,
RMRR = 1,
ATSR = 2,
RHSA = 3,
ANDD = 4,
SATC = 5,
SIDP = 6,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
struct DmarHeader {
header: SdtHeaderWrapper,
host_address_width: u8,
flags: u8,
reserved: [u8; 10],
}
impl AcpiTable for DmarHeader {
fn header(&self) -> &acpi::sdt::SdtHeader {
&self.header.0
}
}
impl Dmar {
pub fn new() -> Option<Self> {
if !super::ACPI_TABLES.is_completed() {
return None;
}
let acpi_table_lock = super::ACPI_TABLES.get().unwrap().lock();
let dmar_mapping = unsafe {
acpi_table_lock
.get_sdt::<DmarHeader>(Signature::DMAR)
.unwrap()?
};
let physical_address = dmar_mapping.physical_start();
let len = dmar_mapping.mapped_length();
let dmar_slice = unsafe {
core::slice::from_raw_parts_mut(
paddr_to_vaddr(physical_address + size_of::<DmarHeader>()) as *mut u8,
len - size_of::<DmarHeader>(),
)
};
let mut remapping_structures = Vec::new();
let mut index = 0;
let mut remain_length = len - size_of::<DmarHeader>();
unsafe {
while remain_length > 0 {
let length = *dmar_slice[index + 2..index + 4].as_ptr() as usize;
let typ = *dmar_slice[index..index + 2].as_ptr() as usize;
let bytes = &&dmar_slice[index..index + length];
let remapping = match typ {
0 => Remapping::Drhd(Drhd::from_bytes(bytes)),
1 => Remapping::Rmrr(Rmrr::from_bytes(bytes)),
2 => Remapping::Atsr(Atsr::from_bytes(bytes)),
3 => Remapping::Rhsa(Rhsa::from_bytes(bytes)),
4 => Remapping::Andd(Andd::from_bytes(bytes)),
5 => Remapping::Satc(Satc::from_bytes(bytes)),
6 => Remapping::Sidp(Sidp::from_bytes(bytes)),
_ => {
panic!("Unidentified remapping structure type");
}
};
remapping_structures.push(remapping);
index += length;
remain_length -= length;
}
}
Some(Dmar {
header: *dmar_mapping,
remapping_structures,
})
}
pub fn remapping_iter(&self) -> Iter<'_, Remapping> {
self.remapping_structures.iter()
}
}