diff --git a/src/fdt/node.rs b/src/fdt/node.rs index b703493..3ff64ce 100644 --- a/src/fdt/node.rs +++ b/src/fdt/node.rs @@ -58,6 +58,10 @@ impl<'a> Node<'a> for FdtNode<'a> { parent_address_space: self.address_space(), } } + + fn parent_address_space(self) -> AddressSpaceProperties { + self.parent_address_space + } } impl<'a> FdtNode<'a> { diff --git a/src/lib.rs b/src/lib.rs index e40cea3..62203cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -139,6 +139,7 @@ use core::ops::{BitOr, Shl}; use zerocopy::big_endian; use crate::error::{PropertyError, StandardError}; +use crate::standard::AddressSpaceProperties; pub use crate::values::{ FdtStringListIterator, FromPropertyValue, PropEncodedArrayIterator, ToPropertyValue, }; @@ -244,6 +245,11 @@ pub trait Node<'a>: Copy { /// assert!(children.next().is_none()); /// ``` fn children(self) -> Self::Children; + + /// Returns the `#address-cells` and `#size-cells` properties of this + /// node's parent node. + #[must_use] + fn parent_address_space(self) -> AddressSpaceProperties; } /// A property of a device tree node. diff --git a/src/model/node.rs b/src/model/node.rs index 3016f77..c727f7c 100644 --- a/src/model/node.rs +++ b/src/model/node.rs @@ -118,6 +118,10 @@ impl<'a> Node<'a> for DeviceTreeNodeRef<'a> { parent_address_space: self.address_space(), } } + + fn parent_address_space(self) -> AddressSpaceProperties { + self.parent_address_space + } } mod private { diff --git a/src/standard.rs b/src/standard.rs index 66f58d2..f838c6e 100644 --- a/src/standard.rs +++ b/src/standard.rs @@ -22,7 +22,6 @@ pub use self::ranges::Range; pub use self::reg::Reg; pub use self::status::Status; use crate::error::{PropertyError, StandardError}; -use crate::fdt::FdtNode; use crate::{Node, Property}; pub(crate) const DEFAULT_ADDRESS_CELLS: u32 = 2; @@ -157,20 +156,17 @@ pub trait NodeStandard<'a>: Node<'a> { fn dma_coherent(self) -> bool { self.property("dma-coherent").is_some() } -} - -impl<'a, T: Node<'a>> NodeStandard<'a> for T {} -impl<'a> FdtNode<'a> { /// Returns the value of the standard `reg` property. /// /// # Errors /// /// Returns an error if the size of the value isn't a multiple of the /// expected number of address and size cells. - pub fn reg(self) -> Result> + 'a>, PropertyError> { - let address_cells = self.parent_address_space.address_cells as usize; - let size_cells = self.parent_address_space.size_cells as usize; + fn reg(self) -> Result> + use<'a, Self>>, PropertyError> { + let parent_address_space = self.parent_address_space(); + let address_cells = parent_address_space.address_cells as usize; + let size_cells = parent_address_space.size_cells as usize; if let Some(property) = self.property("reg") { Ok(Some( property @@ -188,13 +184,15 @@ impl<'a> FdtNode<'a> { /// /// Returns an error if the size of the value isn't a multiple of the /// expected number of cells. - pub fn ranges(self) -> Result> + 'a>, PropertyError> { + fn ranges( + self, + ) -> Result> + use<'a, Self>>, PropertyError> { if let Some(property) = self.property("ranges") { Ok(Some( property .as_prop_encoded_array([ self.address_cells().unwrap_or(DEFAULT_ADDRESS_CELLS) as usize, - self.parent_address_space.address_cells as usize, + self.parent_address_space().address_cells as usize, self.size_cells().unwrap_or(DEFAULT_SIZE_CELLS) as usize, ])? .map(Range::from_cells), @@ -210,13 +208,15 @@ impl<'a> FdtNode<'a> { /// /// Returns an error if the size of the value isn't a multiple of the /// expected number of cells. - pub fn dma_ranges(self) -> Result> + 'a>, PropertyError> { + fn dma_ranges( + self, + ) -> Result> + use<'a, Self>>, PropertyError> { if let Some(property) = self.property("dma-ranges") { Ok(Some( property .as_prop_encoded_array([ self.address_cells().unwrap_or(DEFAULT_ADDRESS_CELLS) as usize, - self.parent_address_space.address_cells as usize, + self.parent_address_space().address_cells as usize, self.size_cells().unwrap_or(DEFAULT_SIZE_CELLS) as usize, ])? .map(Range::from_cells), @@ -227,6 +227,8 @@ impl<'a> FdtNode<'a> { } } +impl<'a, T: Node<'a>> NodeStandard<'a> for T {} + /// The `#address-cells` and `#size-cells` properties of a node. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct AddressSpaceProperties { diff --git a/src/standard/cpus.rs b/src/standard/cpus.rs index a0774d6..ea805d8 100644 --- a/src/standard/cpus.rs +++ b/src/standard/cpus.rs @@ -11,6 +11,7 @@ use core::ops::Deref; use crate::error::{PropertyError, StandardError}; use crate::fdt::{Fdt, FdtNode}; +use crate::standard::NodeStandard; use crate::values::FdtStringListIterator; use crate::{Cells, Node, Property}; @@ -106,9 +107,7 @@ impl<'a, N: Node<'a>> Cpu { .map(Property::value_as) .transpose() } -} -impl<'a> Cpu> { /// Returns an iterator over the IDs of the CPU, from the standard `reg` /// property. /// @@ -117,7 +116,7 @@ impl<'a> Cpu> { /// Returns an error if a property's name or value cannot be read, or the /// `reg` property is missing, or the size of the value isn't a multiple of /// the expected number of address and size cells. - pub fn ids(self) -> Result> + 'a, StandardError> { + pub fn ids(self) -> Result> + use<'a, N>, StandardError> { Ok(self .node .reg()? diff --git a/src/standard/memory.rs b/src/standard/memory.rs index c18ad3a..814be29 100644 --- a/src/standard/memory.rs +++ b/src/standard/memory.rs @@ -182,18 +182,19 @@ impl<'a, N: Node<'a>> ReservedMemory { pub fn reusable(self) -> bool { self.node.property("reusable").is_some() } -} -impl<'a> ReservedMemory> { /// Returns the value of the standard `alloc-ranges` property. /// /// # Errors /// /// Returns an error if the size of the value isn't a multiple of the /// expected number of address and size cells. - pub fn alloc_ranges(self) -> Result> + 'a>, StandardError> { - let address_cells = self.node.parent_address_space.address_cells as usize; - let size_cells = self.node.parent_address_space.size_cells as usize; + pub fn alloc_ranges( + self, + ) -> Result> + use<'a, N>>, StandardError> { + let parent_address_space = self.node.parent_address_space(); + let address_cells = parent_address_space.address_cells as usize; + let size_cells = parent_address_space.size_cells as usize; if let Some(property) = self.node.property("alloc-ranges") { Ok(Some( property diff --git a/tests/model.rs b/tests/model.rs index 76e5984..283b95e 100644 --- a/tests/model.rs +++ b/tests/model.rs @@ -8,7 +8,9 @@ #![cfg(feature = "write")] +use dtoolkit::fdt::Fdt; use dtoolkit::model::{DeviceTree, DeviceTreeNode, DeviceTreeProperty}; +use dtoolkit::standard::{AddressSpaceProperties, NodeStandard}; use dtoolkit::{Node, Property}; #[test] @@ -183,3 +185,80 @@ fn device_tree_format() { " ); } + +#[test] +fn parent_address_space() { + let dtb = include_bytes!("dtb/test_props.dtb"); + let fdt = Fdt::new(dtb).unwrap(); + let tree = DeviceTree::from_fdt(&fdt); + + let standard_props_node = tree.find_node("/standard-props").unwrap(); + assert_eq!( + standard_props_node.parent_address_space(), + AddressSpaceProperties { + address_cells: 2, + size_cells: 2, + } + ); +} + +#[test] +fn reg() { + let dtb = include_bytes!("dtb/test_props.dtb"); + let fdt = Fdt::new(dtb).unwrap(); + let tree = DeviceTree::from_fdt(&fdt); + + let standard_props_node = tree.find_node("/standard-props").unwrap(); + let reg = standard_props_node + .reg() + .unwrap() + .unwrap() + .collect::>(); + assert_eq!(reg.len(), 2); + assert_eq!(reg[0].address::().unwrap(), 0x1234_5678_0000_3000); + assert_eq!(reg[0].size::().unwrap(), 32); + assert_eq!(reg[1].address::().unwrap(), 0xfe00); + assert_eq!(reg[1].size::().unwrap(), 256); +} + +#[test] +fn ranges() { + let dtb = include_bytes!("dtb/test_props.dtb"); + let fdt = Fdt::new(dtb).unwrap(); + let tree = DeviceTree::from_fdt(&fdt); + + let standard_props_node = tree.find_node("/standard-props").unwrap(); + let ranges = standard_props_node + .ranges() + .unwrap() + .unwrap() + .collect::>(); + assert_eq!(ranges.len(), 1); + assert_eq!(ranges[0].child_bus_address::().unwrap(), 0x1111_0000); + assert_eq!( + ranges[0].parent_bus_address::().unwrap(), + 0x2222_0000_3333_0000 + ); + assert_eq!(ranges[0].length::().unwrap(), 0x4444_0000); +} + +#[test] +fn dma_ranges() { + let dtb = include_bytes!("dtb/test_props.dtb"); + let fdt = Fdt::new(dtb).unwrap(); + let tree = DeviceTree::from_fdt(&fdt); + + let standard_props_node = tree.find_node("/standard-props").unwrap(); + let dma_ranges = standard_props_node + .dma_ranges() + .unwrap() + .unwrap() + .collect::>(); + assert_eq!(dma_ranges.len(), 1); + assert_eq!(dma_ranges[0].child_bus_address::().unwrap(), 0xaaaa); + assert_eq!( + dma_ranges[0].parent_bus_address::().unwrap(), + 0xbbbb_0000_cccc + ); + assert_eq!(dma_ranges[0].length::().unwrap(), 0xdddd); +}