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
Generated
+2
View File
@@ -837,9 +837,11 @@ dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
"plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/redox-os/syscall.git)",
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thiserror 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
+2
View File
@@ -16,8 +16,10 @@ bincode = "1.2"
bitflags = "1"
byteorder = "1.2"
libc = "0.2"
plain = "0.2"
redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
smallvec = "1"
thiserror = "1"
toml = "0.5"
+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)
})?))
})
}
}