Browse Source

Start work on PRT parsing

Isaac Woods 5 years ago
parent
commit
81981f35f0
2 changed files with 68 additions and 0 deletions
  1. 1 0
      aml/src/lib.rs
  2. 67 0
      aml/src/pci_routing.rs

+ 1 - 0
aml/src/lib.rs

@@ -47,6 +47,7 @@ pub(crate) mod name_object;
 pub(crate) mod namespace;
 pub(crate) mod opcode;
 pub(crate) mod parser;
+pub mod pci_routing;
 pub(crate) mod pkg_length;
 pub(crate) mod term_object;
 pub(crate) mod type1;

+ 67 - 0
aml/src/pci_routing.rs

@@ -0,0 +1,67 @@
+use crate::{AmlError, AmlValue};
+use bit_field::BitField;
+use core::convert::TryInto;
+use log::info;
+
+// TODO: maybe make this an enum with a variant for each _PRT type
+pub struct PciRoute {
+    device: u16,
+    function: u16,
+    pin: u8,
+    // TODO: complete this
+}
+
+/// A `PciRoutingTable` is used to interpret the data in a `_PRT` object, which provides a mapping
+/// from PCI interrupt pins to the inputs of the interrupt controller. One of these objects must be
+/// present under each PCI root bridge, and consists of a package of packages, each of which describes the
+/// mapping of a single PCI interrupt pin.
+pub struct PciRoutingTable {}
+
+impl PciRoutingTable {
+    /// Construct a `PciRoutingTable` from a `_PRT` object. Returns `AmlError::IncompatibleValueConversion` if
+    /// the value passed is not a package, or if any of the values within it are not packages.
+    pub fn from_prt(prt: &AmlValue) -> Result<PciRoutingTable, AmlError> {
+        if let AmlValue::Package(ref inner_values) = prt {
+            for value in inner_values {
+                if let AmlValue::Package(ref pin_package) = value {
+                    /*
+                     * Each inner package has the following structure:
+                     *   | Field      | Type      | Description                                               |
+                     *   | -----------|-----------|-----------------------------------------------------------|
+                     *   | Address    | Dword     | Address of the device. Same format as _ADR objects (high  |
+                     *   |            |           | word = #device, low word = #function)                     |
+                     *   | -----------|-----------|-----------------------------------------------------------|
+                     *   | Pin        | Byte      | The PCI pin (0 = INTA, 1 = INTB, 2 = INTC, 3 = INTC)      |
+                     *   | -----------|-----------|-----------------------------------------------------------|
+                     *   | Source     | Byte or   | Name of the device that allocates the interrupt to which  |
+                     *   |            | NamePath  | the above pin is connected. Can be fully qualified,       |
+                     *   |            |           | relative, or a simple NameSeg that utilizes namespace     |
+                     *   |            |           | search rules. Instead, if this is a byte value of 0, the  |
+                     *   |            |           | interrupt is allocated out of the GSI pool, and Source    |
+                     *   |            |           | Index should be utilised.                                 |
+                     *   | -----------|-----------|-----------------------------------------------------------|
+                     *   | Source     | Dword     | Index that indicates which resource descriptor in the     |
+                     *   | Index      |           | resource template of the device pointed to in the Source  |
+                     *   |            |           | field this interrupt is allocated from. If the Source     |
+                     *   |            |           | is zero, then this field is the GSI number to which the   |
+                     *   |            |           | pin is connected.                                         |
+                     *   | -----------|-----------|-----------------------------------------------------------|
+                     */
+                    info!("PRT pin: {:?}", pin_package);
+
+                    let address = pin_package[0].as_integer()?;
+                    let device = address.get_bits(16..32);
+                    let function = address.get_bits(16..32);
+                    let pin: u8 = pin_package[1].as_integer()?.try_into().expect("Invalid pin value!");
+                    info!("PRT pin: {:#x}, {:#x}, pin = {}", device, function, pin);
+                } else {
+                    return Err(AmlError::IncompatibleValueConversion);
+                }
+            }
+
+            Ok(PciRoutingTable {})
+        } else {
+            Err(AmlError::IncompatibleValueConversion)
+        }
+    }
+}