Commit 4d349192 authored by Dan Robertson's avatar Dan Robertson

Allow PCI Config space parsing to handle types

 - Update the PCI config space parsing to be able to handle multiple
   types.
 - Use a trait to abstract out reading from the config space in order to
   allow testing/fuzzing of the parser.
parent 42adde58
......@@ -342,6 +342,8 @@ dependencies = [
name = "pcid"
version = "0.1.0"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
......
......@@ -3,6 +3,8 @@ name = "pcid"
version = "0.1.0"
[dependencies]
bitflags = "1.0"
byteorder = "1.2"
redox_syscall = "0.1"
serde = "1.0"
serde_derive = "1.0"
......
This diff is collapsed.
#[derive(Debug)]
use std::fmt;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum PciBar {
None,
Memory(u32),
Port(u16)
}
impl PciBar {
pub fn is_none(&self) -> bool {
match self {
&PciBar::None => true,
_ => false,
}
}
}
impl From<u32> for PciBar {
fn from(bar: u32) -> Self {
if bar & 0xFFFFFFFC == 0 {
......@@ -16,3 +27,13 @@ impl From<u32> for PciBar {
}
}
}
impl fmt::Display for PciBar {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&PciBar::Memory(address) => write!(f, "{:>08X}", address),
&PciBar::Port(address) => write!(f, "{:>04X}", address),
&PciBar::None => write!(f, "None")
}
}
}
#[derive(Debug)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum PciClass {
Legacy,
Storage,
......@@ -48,3 +48,30 @@ impl From<u8> for PciClass {
}
}
}
impl Into<u8> for PciClass {
fn into(self) -> u8 {
match self {
PciClass::Legacy => 0x00,
PciClass::Storage => 0x01,
PciClass::Network => 0x02,
PciClass::Display => 0x03,
PciClass::Multimedia => 0x04,
PciClass::Memory => 0x05,
PciClass::Bridge => 0x06,
PciClass::SimpleComms => 0x07,
PciClass::Peripheral => 0x08,
PciClass::Input => 0x09,
PciClass::Docking => 0x0A,
PciClass::Processor => 0x0B,
PciClass::SerialBus => 0x0C,
PciClass::Wireless => 0x0D,
PciClass::IntelligentIo => 0x0E,
PciClass::SatelliteComms => 0x0F,
PciClass::Cryptography => 0x10,
PciClass::SignalProc => 0x11,
PciClass::Unknown => 0xFF,
PciClass::Reserved(reserved) => reserved
}
}
}
use std::ops::DerefMut;
use byteorder::{LittleEndian, ByteOrder};
use super::{PciDev, PciHeader};
use super::PciDev;
pub trait ConfigReader {
unsafe fn read_range(&self, offset: u8, len: u8) -> Vec<u8> {
assert!(len > 3 && len % 4 == 0);
let mut ret = Vec::with_capacity(len as usize);
let results = (offset..offset + len).step_by(4).fold(Vec::new(), |mut acc, offset| {
let val = self.read_u32(offset);
acc.push(val);
acc
});
ret.set_len(len as usize);
LittleEndian::write_u32_into(&*results, &mut ret);
ret
}
unsafe fn read_u32(&self, offset: u8) -> u32;
}
pub struct PciFunc<'pci> {
pub dev: &'pci PciDev<'pci>,
pub num: u8
}
impl<'pci> PciFunc<'pci> {
pub fn header(&self) -> Option<PciHeader> {
if unsafe { self.read(0) } != 0xFFFFFFFF {
let mut header = PciHeader::default();
{
let dwords = header.deref_mut();
dwords.iter_mut().fold(0usize, |offset, dword| {
*dword = unsafe { self.read(offset as u8) };
offset + 4
});
}
Some(header)
} else {
None
}
}
pub unsafe fn read(&self, offset: u8) -> u32 {
impl<'pci> ConfigReader for PciFunc<'pci> {
unsafe fn read_u32(&self, offset: u8) -> u32 {
self.dev.read(self.num, offset)
}
}
This diff is collapsed.
......@@ -3,14 +3,14 @@ pub use self::bus::{PciBus, PciBusIter};
pub use self::class::PciClass;
pub use self::dev::{PciDev, PciDevIter};
pub use self::func::PciFunc;
pub use self::header::PciHeader;
pub use self::header::{PciHeader, PciHeaderError, PciHeaderType};
mod bar;
mod bus;
mod class;
mod dev;
mod func;
mod header;
pub mod header;
pub struct Pci;
......@@ -28,10 +28,10 @@ impl Pci {
let address = 0x80000000 | ((bus as u32) << 16) | ((dev as u32) << 11) | ((func as u32) << 8) | ((offset as u32) & 0xFC);
let value: u32;
asm!("mov dx, 0xCF8
out dx, eax
mov dx, 0xCFC
in eax, dx"
: "={eax}"(value) : "{eax}"(address) : "dx" : "intel", "volatile");
out dx, eax
mov dx, 0xCFC
in eax, dx"
: "={eax}"(value) : "{eax}"(address) : "dx" : "intel", "volatile");
value
}
......@@ -39,11 +39,11 @@ impl Pci {
pub unsafe fn write(&self, bus: u8, dev: u8, func: u8, offset: u8, value: u32) {
let address = 0x80000000 | ((bus as u32) << 16) | ((dev as u32) << 11) | ((func as u32) << 8) | ((offset as u32) & 0xFC);
asm!("mov dx, 0xCF8
out dx, eax"
: : "{eax}"(address) : "dx" : "intel", "volatile");
out dx, eax"
: : "{eax}"(address) : "dx" : "intel", "volatile");
asm!("mov dx, 0xCFC
out dx, eax"
: : "{eax}"(value) : "dx" : "intel", "volatile");
out dx, eax"
: : "{eax}"(value) : "dx" : "intel", "volatile");
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment