Add MCFG parsing for PCIe.

This commit is contained in:
4lDO2
2020-04-12 11:18:20 +02:00
parent 55645674d3
commit 31d5a95cf9
4 changed files with 96 additions and 0 deletions
+1
View File
@@ -21,6 +21,7 @@ use crate::pci::cap::Capability as PciCapability;
mod config;
mod driver_interface;
mod pci;
mod pcie;
pub struct DriverHandler {
config: config::DriverConfig,
+91
View File
@@ -0,0 +1,91 @@
use std::{fs, io, mem, slice};
use smallvec::SmallVec;
pub const MCFG_NAME: [u8; 4] = *b"MCFG";
#[repr(packed)]
#[derive(Clone, Copy, Debug)]
pub struct Mcfg {
// base sdt fields
name: [u8; 4],
length: u32,
revision: u8,
checksum: u8,
oem_id: [u8; 6],
oem_table_id: [u8; 8],
oem_revision: u32,
creator_id: [u8; 4],
_rsvd: [u8; 8],
base_addrs: [PcieAlloc; 0],
}
unsafe impl plain::Plain for Mcfg {}
/// The "Memory Mapped Enhanced Configuration Space Base Address Allocation Structure" (yes, it's
/// called that).
#[repr(packed)]
#[derive(Clone, Copy, Debug)]
pub struct PcieAlloc {
pub base_addr: u64,
pub seg_group_num: u16,
pub start_bus: u8,
pub end_bus: u8,
_rsvd: [u8; 4],
}
unsafe impl plain::Plain for PcieAlloc {}
impl Mcfg {
pub fn base_addr_structs(&self) -> &[PcieAlloc] {
let total_length = mem::size_of::<Self>();
let len = total_length - 44;
// safe because the length cannot be changed arbitrarily
unsafe { slice::from_raw_parts(&self.base_addrs as *const PcieAlloc, len / mem::size_of::<PcieAlloc>()) }
}
}
pub struct Mcfgs {
tables: SmallVec<[Vec<u8>; 2]>,
}
impl Mcfgs {
pub fn tables<'a>(&'a self) -> impl Iterator<Item = &'a Mcfg> + 'a {
self.tables.iter().filter_map(|bytes| {
let mcfg = plain::from_bytes::<Mcfg>(bytes).ok()?;
if mcfg.length as usize > bytes.len() {
return None;
}
Some(mcfg)
})
}
pub fn fetch() -> io::Result<Self> {
let table_dir = fs::read_dir("acpi:tables")?;
let tables = table_dir.map(|table_direntry| -> io::Result<Option<_>> {
let table_direntry = table_direntry?;
let table_path = table_direntry.path();
let table_filename = match table_path.file_name() {
Some(n) => n.to_str().ok_or(io::Error::new(io::ErrorKind::InvalidData, "Non-UTF-8 ACPI table filename"))?,
None => return Ok(None),
};
if table_filename.starts_with("MCFG") {
Ok(Some(fs::read(table_path)?))
} else {
Ok(None)
}
}).filter_map(|result_option| result_option.transpose()).collect::<Result<SmallVec<_>, _>>()?;
Ok(Self {
tables,
})
}
pub fn at_bus(&self, bus: u8) -> Option<(&Mcfg, &PcieAlloc)> {
self.tables().find_map(|table| {
Some((table, table.base_addr_structs().iter().find(|addr_struct| {
(addr_struct.start_bus..addr_struct.end_bus).contains(&bus)
})?))
})
}
}