libfdt: Add FdtNode::get_phandle()

This doesn't directly use fdt_get_phandle() because the API doesn't
return error code.

Bug: 277993056
Test: atest libpvmfw.device_assignment.test, launch protected VM
Change-Id: I822116f51bc5e21e5c0aa5e8adab938b69e1634e
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index b811730..cab9713 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -504,6 +504,18 @@
 
         fdt_err_or_option(ret)?.map(|offset| FdtProperty::new(self.fdt, offset)).transpose()
     }
+
+    /// Returns the phandle
+    pub fn get_phandle(&self) -> Result<Option<Phandle>> {
+        // This rewrites the fdt_get_phandle() because it doesn't return error code.
+        if let Some(prop) = self.getprop_u32(cstr!("phandle"))? {
+            Ok(Some(prop.try_into()?))
+        } else if let Some(prop) = self.getprop_u32(cstr!("linux,phandle"))? {
+            Ok(Some(prop.try_into()?))
+        } else {
+            Ok(None)
+        }
+    }
 }
 
 impl<'a> PartialEq for FdtNode<'a> {
diff --git a/libs/libfdt/tests/api_test.rs b/libs/libfdt/tests/api_test.rs
index bc306ad..68b95cc 100644
--- a/libs/libfdt/tests/api_test.rs
+++ b/libs/libfdt/tests/api_test.rs
@@ -200,6 +200,24 @@
 }
 
 #[test]
+fn node_get_phandle() {
+    let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
+    let fdt = Fdt::from_slice(&data).unwrap();
+
+    // Test linux,phandle
+    let node = fdt.node(cstr!("/node_z/node_zz")).unwrap().unwrap();
+    assert_eq!(node.get_phandle(), Ok(Phandle::new(0xFF)));
+
+    // Test phandle
+    let node = fdt.node(cstr!("/node_a/node_ab/node_abc")).unwrap().unwrap();
+    assert_eq!(node.get_phandle(), Ok(Phandle::new(0x22)));
+
+    // Test no phandle
+    let node = fdt.node(cstr!("/node_b")).unwrap().unwrap();
+    assert_eq!(node.get_phandle(), Ok(None));
+}
+
+#[test]
 fn node_nop() {
     let mut data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
     let fdt = Fdt::from_mut_slice(&mut data).unwrap();