Bläddra i källkod

fix: `interrupt-cells` was being gathered incorrectly

Wesley Norris 3 år sedan
förälder
incheckning
fe313067dc
3 ändrade filer med 40 tillägg och 7 borttagningar
  1. 23 2
      src/node.rs
  2. 3 5
      src/standard_nodes.rs
  3. 14 0
      src/tests.rs

+ 23 - 2
src/node.rs

@@ -237,7 +237,7 @@ impl<'b, 'a: 'b> FdtNode<'b, 'a> {
     pub fn interrupt_cells(self) -> Option<usize> {
         let mut interrupt_cells = None;
 
-        if let Some(prop) = self.properties().find(|p| p.name == "#interrupt-cells") {
+        if let Some(prop) = self.property("#interrupt-cells") {
             interrupt_cells = BigEndianU32::from_bytes(prop.value).map(|n| n.get() as usize)
         }
 
@@ -246,7 +246,7 @@ impl<'b, 'a: 'b> FdtNode<'b, 'a> {
 
     /// `interrupts` property
     pub fn interrupts(self) -> Option<impl Iterator<Item = usize> + 'a> {
-        let sizes = self.interrupt_cells()?;
+        let sizes = self.parent_interrupt_cells()?;
 
         let mut interrupt = None;
         for prop in self.properties() {
@@ -279,6 +279,27 @@ impl<'b, 'a: 'b> FdtNode<'b, 'a> {
 
         cell_sizes
     }
+
+    pub(crate) fn parent_interrupt_cells(self) -> Option<usize> {
+        let mut interrupt_cells = None;
+        let parent = self
+            .property("interrupt-parent")
+            .and_then(|p| self.header.find_phandle(BigEndianU32::from_bytes(p.value)?.get()))
+            .or_else(|| {
+                Some(FdtNode {
+                    name: "",
+                    props: self.parent_props?,
+                    header: self.header,
+                    parent_props: None,
+                })
+            });
+
+        if let Some(size) = parent.and_then(|parent| parent.interrupt_cells()) {
+            interrupt_cells = Some(size);
+        }
+
+        interrupt_cells
+    }
 }
 
 /// The number of cells (big endian u32s) that addresses and sizes take

+ 3 - 5
src/standard_nodes.rs

@@ -138,7 +138,7 @@ impl<'b, 'a: 'b> Cpu<'b, 'a> {
         self.node
             .properties()
             .find(|p| p.name == "clock-frequency")
-            .or_else(|| self.parent.properties().find(|p| p.name == "clock-frequency"))
+            .or_else(|| self.parent.property("clock-frequency"))
             .map(|p| match p.value.len() {
                 4 => BigEndianU32::from_bytes(p.value).unwrap().get() as usize,
                 8 => BigEndianU64::from_bytes(p.value).unwrap().get() as usize,
@@ -152,7 +152,7 @@ impl<'b, 'a: 'b> Cpu<'b, 'a> {
         self.node
             .properties()
             .find(|p| p.name == "timebase-frequency")
-            .or_else(|| self.parent.properties().find(|p| p.name == "timebase-frequency"))
+            .or_else(|| self.parent.property("timebase-frequency"))
             .map(|p| match p.value.len() {
                 4 => BigEndianU32::from_bytes(p.value).unwrap().get() as usize,
                 8 => BigEndianU64::from_bytes(p.value).unwrap().get() as usize,
@@ -258,9 +258,7 @@ impl Memory<'_, '_> {
     pub fn initial_mapped_area(&self) -> Option<MappedArea> {
         let mut mapped_area = None;
 
-        if let Some(init_mapped_area) =
-            self.node.properties().find(|n| n.name == "initial_mapped_area")
-        {
+        if let Some(init_mapped_area) = self.node.property("initial_mapped_area") {
             let mut stream = FdtData::new(init_mapped_area.value);
             let effective_address = stream.u64().expect("effective address");
             let physical_address = stream.u64().expect("physical address");

+ 14 - 0
src/tests.rs

@@ -186,3 +186,17 @@ fn invalid_node() {
     let fdt = Fdt::new(TEST).unwrap();
     assert!(fdt.find_node("this/is/an invalid node///////////").is_none());
 }
+
+#[test]
+fn memory_node() {
+    let fdt = Fdt::new(TEST).unwrap();
+    assert_eq!(fdt.memory().regions().count(), 1);
+}
+
+#[test]
+fn interrupt_cells() {
+    let fdt = Fdt::new(TEST).unwrap();
+    let uart = fdt.find_node("/soc/uart").unwrap();
+    std::println!("{:?}", uart.parent_interrupt_cells());
+    assert_eq!(uart.interrupts().unwrap().collect::<std::vec::Vec<_>>(), std::vec![0xA]);
+}