Add iterator over ranges property.
Bug: 237249743
Test: m vmbase_example_bin pvmfw_bin
Change-Id: I2866f4121a0e60e99e0b188182fe1ed37cd213be
diff --git a/libs/libfdt/src/iterators.rs b/libs/libfdt/src/iterators.rs
index a80aa1b..41fd492 100644
--- a/libs/libfdt/src/iterators.rs
+++ b/libs/libfdt/src/iterators.rs
@@ -15,6 +15,7 @@
//! Iterators over cells, and various layers on top of them.
use crate::{AddrCells, SizeCells};
+use core::marker::PhantomData;
use core::{mem::size_of, ops::Range, slice::ChunksExact};
/// Iterator over cells of a DT property.
@@ -72,17 +73,12 @@
type Item = Reg<u64>;
fn next(&mut self) -> Option<Self::Item> {
- let make_double = |a, b| (u64::from(a) << 32) | u64::from(b);
-
- let addr = match self.addr_cells {
- AddrCells::Single => self.cells.next()?.into(),
- AddrCells::Double => make_double(self.cells.next()?, self.cells.next()?),
- };
+ let addr = FromAddrCells::from_addr_cells(&mut self.cells, self.addr_cells)?;
// If the parent node specifies a value of 0 for #size-cells, 'size' shall be omitted.
- let size = match self.size_cells {
- SizeCells::None => None,
- SizeCells::Single => Some(self.cells.next()?.into()),
- SizeCells::Double => Some(make_double(self.cells.next()?, self.cells.next()?)),
+ let size = if self.size_cells == SizeCells::None {
+ None
+ } else {
+ Some(FromSizeCells::from_size_cells(&mut self.cells, self.size_cells)?)
};
Some(Self::Item { addr, size })
@@ -112,3 +108,100 @@
Some(addr..addr.checked_add(size)?)
}
}
+
+/// Iterator over the 'ranges' property of a DT node.
+#[derive(Debug)]
+pub struct RangesIterator<'a, A, P, S> {
+ cells: CellIterator<'a>,
+ addr_cells: AddrCells,
+ parent_addr_cells: AddrCells,
+ size_cells: SizeCells,
+ _addr: PhantomData<A>,
+ _parent_addr: PhantomData<P>,
+ _size: PhantomData<S>,
+}
+
+/// An address range from the 'ranges' property of a DT node.
+#[derive(Clone, Debug)]
+pub struct AddressRange<A, P, S> {
+ /// The physical address of the range within the child bus's address space.
+ pub addr: A,
+ /// The physical address of the range in the parent bus's address space.
+ pub parent_addr: P,
+ /// The size of the range in the child's address space.
+ pub size: S,
+}
+
+impl<'a, A, P, S> RangesIterator<'a, A, P, S> {
+ pub(crate) fn new(
+ cells: CellIterator<'a>,
+ addr_cells: AddrCells,
+ parent_addr_cells: AddrCells,
+ size_cells: SizeCells,
+ ) -> Self {
+ Self {
+ cells,
+ addr_cells,
+ parent_addr_cells,
+ size_cells,
+ _addr: Default::default(),
+ _parent_addr: Default::default(),
+ _size: Default::default(),
+ }
+ }
+}
+
+impl<'a, A: FromAddrCells, P: FromAddrCells, S: FromSizeCells> Iterator
+ for RangesIterator<'a, A, P, S>
+{
+ type Item = AddressRange<A, P, S>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let addr = FromAddrCells::from_addr_cells(&mut self.cells, self.addr_cells)?;
+ let parent_addr = FromAddrCells::from_addr_cells(&mut self.cells, self.parent_addr_cells)?;
+ let size = FromSizeCells::from_size_cells(&mut self.cells, self.size_cells)?;
+ Some(AddressRange { addr, parent_addr, size })
+ }
+}
+
+trait FromAddrCells: Sized {
+ fn from_addr_cells(cells: &mut CellIterator, cell_count: AddrCells) -> Option<Self>;
+}
+
+impl FromAddrCells for u64 {
+ fn from_addr_cells(cells: &mut CellIterator, cell_count: AddrCells) -> Option<Self> {
+ Some(match cell_count {
+ AddrCells::Single => cells.next()?.into(),
+ AddrCells::Double => (cells.next()? as Self) << 32 | cells.next()? as Self,
+ _ => panic!("Invalid addr_cells {:?} for u64", cell_count),
+ })
+ }
+}
+
+impl FromAddrCells for u128 {
+ fn from_addr_cells(cells: &mut CellIterator, cell_count: AddrCells) -> Option<Self> {
+ Some(match cell_count {
+ AddrCells::Single => cells.next()?.into(),
+ AddrCells::Double => (cells.next()? as Self) << 32 | cells.next()? as Self,
+ AddrCells::Triple => {
+ (cells.next()? as Self) << 64
+ | (cells.next()? as Self) << 32
+ | cells.next()? as Self
+ }
+ })
+ }
+}
+
+trait FromSizeCells: Sized {
+ fn from_size_cells(cells: &mut CellIterator, cell_count: SizeCells) -> Option<Self>;
+}
+
+impl FromSizeCells for u64 {
+ fn from_size_cells(cells: &mut CellIterator, cell_count: SizeCells) -> Option<Self> {
+ Some(match cell_count {
+ SizeCells::Single => cells.next()?.into(),
+ SizeCells::Double => (cells.next()? as Self) << 32 | cells.next()? as Self,
+ _ => panic!("Invalid size_cells {:?} for u64", cell_count),
+ })
+ }
+}
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index 0cc781e..64e6746 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -20,7 +20,7 @@
mod iterators;
-pub use iterators::{CellIterator, MemRegIterator, Reg, RegIterator};
+pub use iterators::{AddressRange, CellIterator, MemRegIterator, RangesIterator, Reg, RegIterator};
use core::ffi::{c_int, c_void, CStr};
use core::fmt;
@@ -148,10 +148,11 @@
}
/// Value of a #address-cells property.
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum AddrCells {
Single = 1,
Double = 2,
+ Triple = 3,
}
impl TryFrom<c_int> for AddrCells {
@@ -161,13 +162,14 @@
match fdt_err(res)? {
x if x == Self::Single as c_int => Ok(Self::Single),
x if x == Self::Double as c_int => Ok(Self::Double),
+ x if x == Self::Triple as c_int => Ok(Self::Triple),
_ => Err(FdtError::BadNCells),
}
}
}
/// Value of a #size-cells property.
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum SizeCells {
None = 0,
Single = 1,
@@ -224,6 +226,25 @@
}
}
+ /// Retrieves the standard ranges property.
+ pub fn ranges<A, P, S>(&self) -> Result<Option<RangesIterator<'a, A, P, S>>> {
+ let ranges = CStr::from_bytes_with_nul(b"ranges\0").unwrap();
+ if let Some(cells) = self.getprop_cells(ranges)? {
+ let parent = self.parent()?;
+ let addr_cells = self.address_cells()?;
+ let parent_addr_cells = parent.address_cells()?;
+ let size_cells = self.size_cells()?;
+ Ok(Some(RangesIterator::<A, P, S>::new(
+ cells,
+ addr_cells,
+ parent_addr_cells,
+ size_cells,
+ )))
+ } else {
+ Ok(None)
+ }
+ }
+
/// Retrieve the value of a given <string> property.
pub fn getprop_str(&self, name: &CStr) -> Result<Option<&CStr>> {
let value = if let Some(bytes) = self.getprop(name)? {