libfdt: Rework APIs for getting subnode

Existing FdtNodeMut::subnode_with_name_len() has following issues:
  - Requires mutability although it's unnecessary.
  - Doesn't work with raw bytes if it isn't nul-terminating.

This adds following APIs to replace old API.
  - FdtNode::subnode(&self, name: &CStr)
  - FdtNode::subnode_with_name_bytes(&self, name: &[u8])

Bug: 277993056
Test: atest liblibfdt.integration_test
Change-Id: I60b10eefb5855571020e67b45aef017a859319cf
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index aae75f7..df57bd3 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -527,6 +527,32 @@
             Ok(None)
         }
     }
+
+    /// Returns the subnode of the given name. The name doesn't need to be nul-terminated.
+    pub fn subnode(&self, name: &CStr) -> Result<Option<Self>> {
+        let offset = self.subnode_offset(name.to_bytes())?;
+        Ok(offset.map(|offset| Self { fdt: self.fdt, offset }))
+    }
+
+    /// Returns the subnode of the given name bytes
+    pub fn subnode_with_name_bytes(&self, name: &[u8]) -> Result<Option<Self>> {
+        let offset = self.subnode_offset(name)?;
+        Ok(offset.map(|offset| Self { fdt: self.fdt, offset }))
+    }
+
+    fn subnode_offset(&self, name: &[u8]) -> Result<Option<c_int>> {
+        let namelen = name.len().try_into().unwrap();
+        // SAFETY: Accesses are constrained to the DT totalsize (validated by ctor).
+        let ret = unsafe {
+            libfdt_bindgen::fdt_subnode_offset_namelen(
+                self.fdt.as_ptr(),
+                self.offset,
+                name.as_ptr().cast::<_>(),
+                namelen,
+            )
+        };
+        fdt_err_or_option(ret)
+    }
 }
 
 impl<'a> PartialEq for FdtNode<'a> {
@@ -751,26 +777,6 @@
         fdt_err(ret)
     }
 
-    /// Returns the subnode of the given name with len.
-    pub fn subnode_with_namelen(&'a mut self, name: &CStr, namelen: usize) -> Result<Option<Self>> {
-        let offset = self.subnode_offset(&name.to_bytes()[..namelen])?;
-        Ok(offset.map(|offset| Self { fdt: self.fdt, offset }))
-    }
-
-    fn subnode_offset(&self, name: &[u8]) -> Result<Option<c_int>> {
-        let namelen = name.len().try_into().unwrap();
-        // SAFETY: Accesses are constrained to the DT totalsize (validated by ctor).
-        let ret = unsafe {
-            libfdt_bindgen::fdt_subnode_offset_namelen(
-                self.fdt.as_ptr(),
-                self.offset,
-                name.as_ptr().cast::<_>(),
-                namelen,
-            )
-        };
-        fdt_err_or_option(ret)
-    }
-
     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) };
diff --git a/libs/libfdt/tests/api_test.rs b/libs/libfdt/tests/api_test.rs
index d5d6ece..0102f9a 100644
--- a/libs/libfdt/tests/api_test.rs
+++ b/libs/libfdt/tests/api_test.rs
@@ -262,14 +262,15 @@
     let subnode_name = cstr!("123456789");
 
     for len in 0..subnode_name.to_bytes().len() {
-        let mut node = fdt.node_mut(node_path).unwrap().unwrap();
-        assert!(node.subnode_with_namelen(subnode_name, len).unwrap().is_none());
+        let name = &subnode_name.to_bytes()[0..len];
+        let node = fdt.node(node_path).unwrap().unwrap();
+        assert_eq!(Ok(None), node.subnode_with_name_bytes(name));
 
         let mut node = fdt.node_mut(node_path).unwrap().unwrap();
         node.add_subnode_with_namelen(subnode_name, len).unwrap();
 
-        let mut node = fdt.node_mut(node_path).unwrap().unwrap();
-        assert!(node.subnode_with_namelen(subnode_name, len).unwrap().is_some());
+        let node = fdt.node(node_path).unwrap().unwrap();
+        assert_ne!(Ok(None), node.subnode_with_name_bytes(name));
     }
 
     let node_path = node_path.to_str().unwrap();
@@ -283,6 +284,48 @@
 }
 
 #[test]
+fn node_subnode() {
+    let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
+    let fdt = Fdt::from_slice(&data).unwrap();
+
+    let name = cstr!("node_a");
+    let root = fdt.root().unwrap();
+    let node = root.subnode(name).unwrap();
+    assert_ne!(None, node);
+    let node = node.unwrap();
+
+    assert_eq!(Ok(name), node.name());
+}
+
+#[test]
+fn node_subnode_with_name_bytes() {
+    let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
+    let fdt = Fdt::from_slice(&data).unwrap();
+
+    let name = b"node_aaaaa";
+    let root = fdt.root().unwrap();
+    let node = root.subnode_with_name_bytes(&name[0..6]).unwrap();
+    assert_ne!(None, node);
+    let node = node.unwrap();
+
+    assert_eq!(Ok(cstr!("node_a")), node.name());
+}
+
+#[test]
+fn node_subnode_borrow_checker() {
+    let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
+    let fdt = Fdt::from_slice(&data).unwrap();
+
+    let name = cstr!("node_a");
+    let node = {
+        let root = fdt.root().unwrap();
+        root.subnode(name).unwrap().unwrap()
+    };
+
+    assert_eq!(Ok(name), node.name());
+}
+
+#[test]
 fn fdt_symbols() {
     let mut data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
     let fdt = Fdt::from_mut_slice(&mut data).unwrap();