libfdt: Move phandle functions and 0-cost Phandle

Move Phandle to its own module, intended to contain all the zero-cost
abstractions used by our Rust-safe wrapper around libfdt in place of the
c_ints expected by the C code.

Move the functions dealing with phandles to the LibFdt* traits.

Reduce the unsafe blocks to the strict minimum (i.e. the FFI calls).

Test: m pvmfw
Test: atest liblibfdt.integration_test
Change-Id: I548c7436f94bd7a902943eaea5bf1f0195e52366
diff --git a/libs/libfdt/src/ctypes.rs b/libs/libfdt/src/ctypes.rs
new file mode 100644
index 0000000..640d447
--- /dev/null
+++ b/libs/libfdt/src/ctypes.rs
@@ -0,0 +1,52 @@
+// Copyright 2024, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Safe zero-cost wrappers around integer values used by libfdt.
+
+use crate::{FdtError, Result};
+
+/// Wrapper guaranteed to contain a valid phandle.
+#[repr(transparent)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+pub struct Phandle(u32);
+
+impl Phandle {
+    /// Minimum valid value for device tree phandles.
+    pub const MIN: Self = Self(1);
+    /// Maximum valid value for device tree phandles.
+    pub const MAX: Self = Self(libfdt_bindgen::FDT_MAX_PHANDLE);
+
+    /// Creates a new Phandle
+    pub const fn new(value: u32) -> Option<Self> {
+        if Self::MIN.0 <= value && value <= Self::MAX.0 {
+            Some(Self(value))
+        } else {
+            None
+        }
+    }
+}
+
+impl From<Phandle> for u32 {
+    fn from(phandle: Phandle) -> u32 {
+        phandle.0
+    }
+}
+
+impl TryFrom<u32> for Phandle {
+    type Error = FdtError;
+
+    fn try_from(value: u32) -> Result<Self> {
+        Self::new(value).ok_or(FdtError::BadPhandle)
+    }
+}
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index 0249d0d..d5013ca 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -17,10 +17,12 @@
 
 #![no_std]
 
+mod ctypes;
 mod iterators;
 mod libfdt;
 mod result;
 
+pub use ctypes::Phandle;
 pub use iterators::{
     AddressRange, CellIterator, CompatibleIterator, DescendantsIterator, MemRegIterator,
     PropertyIterator, RangesIterator, Reg, RegIterator, SubnodeIterator,
@@ -410,41 +412,6 @@
     }
 }
 
-/// Phandle of a FDT node
-#[repr(transparent)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
-pub struct Phandle(u32);
-
-impl Phandle {
-    /// Minimum valid value for device tree phandles.
-    pub const MIN: Self = Self(1);
-    /// Maximum valid value for device tree phandles.
-    pub const MAX: Self = Self(libfdt_bindgen::FDT_MAX_PHANDLE);
-
-    /// Creates a new Phandle
-    pub const fn new(value: u32) -> Option<Self> {
-        if Self::MIN.0 <= value && value <= Self::MAX.0 {
-            Some(Self(value))
-        } else {
-            None
-        }
-    }
-}
-
-impl From<Phandle> for u32 {
-    fn from(phandle: Phandle) -> u32 {
-        phandle.0
-    }
-}
-
-impl TryFrom<u32> for Phandle {
-    type Error = FdtError;
-
-    fn try_from(value: u32) -> Result<Self> {
-        Self::new(value).ok_or(FdtError::BadPhandle)
-    }
-}
-
 /// Mutable FDT node.
 #[derive(Debug)]
 pub struct FdtNodeMut<'a> {
@@ -896,30 +863,21 @@
 
     /// Returns max phandle in the tree.
     pub fn max_phandle(&self) -> Result<Phandle> {
-        let mut phandle: u32 = 0;
-        // SAFETY: Accesses (read-only) are constrained to the DT totalsize.
-        let ret = unsafe { libfdt_bindgen::fdt_find_max_phandle(self.as_ptr(), &mut phandle) };
-
-        fdt_err_expect_zero(ret)?;
-        phandle.try_into()
+        self.find_max_phandle()
     }
 
     /// Returns a node with the phandle
     pub fn node_with_phandle(&self, phandle: Phandle) -> Result<Option<FdtNode>> {
-        let offset = self.node_offset_with_phandle(phandle)?;
+        let offset = self.node_offset_by_phandle(phandle)?;
+
         Ok(offset.map(|offset| FdtNode { fdt: self, offset }))
     }
 
     /// Returns a mutable node with the phandle
     pub fn node_mut_with_phandle(&mut self, phandle: Phandle) -> Result<Option<FdtNodeMut>> {
-        let offset = self.node_offset_with_phandle(phandle)?;
-        Ok(offset.map(|offset| FdtNodeMut { fdt: self, offset }))
-    }
+        let offset = self.node_offset_by_phandle(phandle)?;
 
-    fn node_offset_with_phandle(&self, phandle: Phandle) -> Result<Option<c_int>> {
-        // SAFETY: Accesses are constrained to the DT totalsize.
-        let ret = unsafe { libfdt_bindgen::fdt_node_offset_by_phandle(self.as_ptr(), phandle.0) };
-        fdt_err_or_option(ret)
+        Ok(offset.map(|offset| FdtNodeMut { fdt: self, offset }))
     }
 
     /// Returns the mutable root node of the tree.
diff --git a/libs/libfdt/src/libfdt.rs b/libs/libfdt/src/libfdt.rs
index 7e3b65a..0614a5e 100644
--- a/libs/libfdt/src/libfdt.rs
+++ b/libs/libfdt/src/libfdt.rs
@@ -21,7 +21,7 @@
 use core::ffi::{c_int, CStr};
 use core::ptr;
 
-use crate::{fdt_err, fdt_err_expect_zero, fdt_err_or_option, FdtError, Result};
+use crate::{fdt_err, fdt_err_expect_zero, fdt_err_or_option, FdtError, Phandle, Result};
 
 // Function names are the C function names without the `fdt_` prefix.
 
@@ -78,6 +78,16 @@
         fdt_err_or_option(ret)
     }
 
+    /// Safe wrapper around `fdt_node_offset_by_phandle()` (C function).
+    fn node_offset_by_phandle(&self, phandle: Phandle) -> Result<Option<c_int>> {
+        let fdt = self.as_fdt_slice().as_ptr().cast();
+        let phandle = phandle.into();
+        // SAFETY: Accesses are constrained to the DT totalsize.
+        let ret = unsafe { libfdt_bindgen::fdt_node_offset_by_phandle(fdt, phandle) };
+
+        fdt_err_or_option(ret)
+    }
+
     /// Safe wrapper around `fdt_node_offset_by_compatible()` (C function).
     fn node_offset_by_compatible(&self, prev: c_int, compatible: &CStr) -> Result<Option<c_int>> {
         let fdt = self.as_fdt_slice().as_ptr().cast();
@@ -175,6 +185,18 @@
 
         Ok(fdt_err(ret)?.try_into().unwrap())
     }
+
+    /// Safe wrapper around `fdt_find_max_phandle()` (C function).
+    fn find_max_phandle(&self) -> Result<Phandle> {
+        let fdt = self.as_fdt_slice().as_ptr().cast();
+        let mut phandle = 0;
+        // SAFETY: Accesses (read-only) are constrained to the DT totalsize.
+        let ret = unsafe { libfdt_bindgen::fdt_find_max_phandle(fdt, &mut phandle) };
+
+        fdt_err_expect_zero(ret)?;
+
+        phandle.try_into()
+    }
 }
 
 /// Wrapper for the read-write libfdt.h functions.