libfdt: Add APIs for iterating and deleting subnodes
In detail, added following APIs for implementing FDT filtering:
- FdtNodeMut::first_subnode()
- FdtNodeMut::next_subnode()
- FdtNodeMut::delete_and_next_subnode()
Bug: 277993056
Test: atest liblibfdt.integration_test
Change-Id: I18f93910ed5d28c4dbb2d38119b6839046775608
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index df57bd3..7eb08b2 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -777,6 +777,40 @@
fdt_err(ret)
}
+ /// Returns the first subnode of this
+ pub fn first_subnode(&'a mut self) -> Result<Option<Self>> {
+ // SAFETY: Accesses (read-only) are constrained to the DT totalsize.
+ let ret = unsafe { libfdt_bindgen::fdt_first_subnode(self.fdt.as_ptr(), self.offset) };
+
+ Ok(fdt_err_or_option(ret)?.map(|offset| Self { fdt: self.fdt, offset }))
+ }
+
+ /// Returns the next subnode that shares the same parent with this
+ pub fn next_subnode(self) -> Result<Option<Self>> {
+ // SAFETY: Accesses (read-only) are constrained to the DT totalsize.
+ let ret = unsafe { libfdt_bindgen::fdt_next_subnode(self.fdt.as_ptr(), self.offset) };
+
+ Ok(fdt_err_or_option(ret)?.map(|offset| Self { fdt: self.fdt, offset }))
+ }
+
+ /// Deletes the current node and returns the next subnode
+ pub fn delete_and_next_subnode(mut self) -> Result<Option<Self>> {
+ // SAFETY: Accesses (read-only) are constrained to the DT totalsize.
+ let ret = unsafe { libfdt_bindgen::fdt_next_subnode(self.fdt.as_ptr(), self.offset) };
+
+ let next_offset = fdt_err_or_option(ret)?;
+
+ if Some(self.offset) == next_offset {
+ return Err(FdtError::Internal);
+ }
+
+ // SAFETY: nop_self() only touches bytes of the self and its properties and subnodes, and
+ // doesn't alter any other blob in the tree. self.fdt and next_offset would remain valid.
+ unsafe { self.nop_self()? };
+
+ Ok(next_offset.map(|offset| Self { fdt: self.fdt, offset }))
+ }
+
fn parent(&'a self) -> Result<FdtNode<'a>> {
// SAFETY: Accesses (read-only) are constrained to the DT totalsize.
let ret = unsafe { libfdt_bindgen::fdt_parent_offset(self.fdt.as_ptr(), self.offset) };