libfdt: Move FFI for DT properties to Libfdt*

Move all the functions dealing with DT properties to the new traits.

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

Test: m pvmfw
Test: atest liblibfdt.integration_test
Change-Id: I98698a7ae9b6874c329c8a7bf902b33c7e7a453d
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index 299b1d3..ab3c83f 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -95,17 +95,7 @@
 
 impl FdtPropertyStruct {
     fn from_offset(fdt: &Fdt, offset: c_int) -> Result<&Self> {
-        let mut len = 0;
-        let prop =
-            // SAFETY: Accesses (read-only) are constrained to the DT totalsize.
-            unsafe { libfdt_bindgen::fdt_get_property_by_offset(fdt.as_ptr(), offset, &mut len) };
-        if prop.is_null() {
-            fdt_err(len)?;
-            return Err(FdtError::Internal); // shouldn't happen.
-        }
-        // SAFETY: prop is only returned when it points to valid libfdt_bindgen.
-        let prop = unsafe { &*prop };
-        Ok(prop.as_ref())
+        Ok(fdt.get_property_by_offset(offset)?.as_ref())
     }
 
     fn name_offset(&self) -> c_int {
@@ -146,11 +136,7 @@
     }
 
     fn next_property(&self) -> Result<Option<Self>> {
-        let ret =
-            // SAFETY: Accesses (read-only) are constrained to the DT totalsize.
-            unsafe { libfdt_bindgen::fdt_next_property_offset(self.fdt.as_ptr(), self.offset) };
-
-        if let Some(offset) = fdt_err_or_option(ret)? {
+        if let Some(offset) = self.fdt.next_property_offset(self.offset)? {
             Ok(Some(Self::new(self.fdt, offset)?))
         } else {
             Ok(None)
@@ -261,44 +247,7 @@
 
     /// Returns the value of a given property.
     pub fn getprop(&self, name: &CStr) -> Result<Option<&'a [u8]>> {
-        if let Some((prop, len)) = Self::getprop_internal(self.fdt, self.offset, name)? {
-            Ok(Some(self.fdt.get_from_ptr(prop, len)?))
-        } else {
-            Ok(None)
-        }
-    }
-
-    /// Returns the pointer and size of the property named `name`, in a node at offset `offset`, in
-    /// a device tree `fdt`. The pointer is guaranteed to be non-null, in which case error returns.
-    fn getprop_internal(
-        fdt: &'a Fdt,
-        offset: c_int,
-        name: &CStr,
-    ) -> Result<Option<(*const c_void, usize)>> {
-        let mut len: i32 = 0;
-        // SAFETY: Accesses are constrained to the DT totalsize (validated by ctor) and the
-        // function respects the passed number of characters.
-        let prop = unsafe {
-            libfdt_bindgen::fdt_getprop_namelen(
-                fdt.as_ptr(),
-                offset,
-                name.as_ptr(),
-                // *_namelen functions don't include the trailing nul terminator in 'len'.
-                name.to_bytes().len().try_into().map_err(|_| FdtError::BadPath)?,
-                &mut len as *mut i32,
-            )
-        } as *const u8;
-
-        let Some(len) = fdt_err_or_option(len)? else {
-            return Ok(None); // Property was not found.
-        };
-        let len = usize::try_from(len).unwrap();
-
-        if prop.is_null() {
-            // We expected an error code in len but still received a valid value?!
-            return Err(FdtError::Internal);
-        }
-        Ok(Some((prop.cast::<c_void>(), len)))
+        self.fdt.getprop_namelen(self.offset, name.to_bytes())
     }
 
     /// Returns reference to the containing device tree.
@@ -362,11 +311,7 @@
     }
 
     fn first_property(&self) -> Result<Option<FdtProperty<'a>>> {
-        let ret =
-            // SAFETY: Accesses (read-only) are constrained to the DT totalsize.
-            unsafe { libfdt_bindgen::fdt_first_property_offset(self.fdt.as_ptr(), self.offset) };
-
-        if let Some(offset) = fdt_err_or_option(ret)? {
+        if let Some(offset) = self.fdt.first_property_offset(self.offset)? {
             Ok(Some(FdtProperty::new(self.fdt, offset)?))
         } else {
             Ok(None)
@@ -417,54 +362,20 @@
 impl<'a> FdtNodeMut<'a> {
     /// Appends a property name-value (possibly empty) pair to the given node.
     pub fn appendprop<T: AsRef<[u8]>>(&mut self, name: &CStr, value: &T) -> Result<()> {
-        // SAFETY: Accesses are constrained to the DT totalsize (validated by ctor).
-        let ret = unsafe {
-            libfdt_bindgen::fdt_appendprop(
-                self.fdt.as_mut_ptr(),
-                self.offset,
-                name.as_ptr(),
-                value.as_ref().as_ptr().cast::<c_void>(),
-                value.as_ref().len().try_into().map_err(|_| FdtError::BadValue)?,
-            )
-        };
-
-        fdt_err_expect_zero(ret)
+        self.fdt.appendprop(self.offset, name, value.as_ref())
     }
 
     /// Appends a (address, size) pair property to the given node.
     pub fn appendprop_addrrange(&mut self, name: &CStr, addr: u64, size: u64) -> Result<()> {
-        // SAFETY: Accesses are constrained to the DT totalsize (validated by ctor).
-        let ret = unsafe {
-            libfdt_bindgen::fdt_appendprop_addrrange(
-                self.fdt.as_mut_ptr(),
-                self.parent()?.offset,
-                self.offset,
-                name.as_ptr(),
-                addr,
-                size,
-            )
-        };
-
-        fdt_err_expect_zero(ret)
+        let parent = self.parent()?.offset;
+        self.fdt.appendprop_addrrange(parent, self.offset, name, addr, size)
     }
 
     /// Sets a property name-value pair to the given node.
     ///
     /// This may create a new prop or replace existing value.
     pub fn setprop(&mut self, name: &CStr, value: &[u8]) -> Result<()> {
-        // SAFETY: New value size is constrained to the DT totalsize
-        //          (validated by underlying libfdt).
-        let ret = unsafe {
-            libfdt_bindgen::fdt_setprop(
-                self.fdt.as_mut_ptr(),
-                self.offset,
-                name.as_ptr(),
-                value.as_ptr().cast::<c_void>(),
-                value.len().try_into().map_err(|_| FdtError::BadValue)?,
-            )
-        };
-
-        fdt_err_expect_zero(ret)
+        self.fdt.setprop(self.offset, name, value)
     }
 
     /// Sets the value of the given property with the given value, and ensure that the given
@@ -472,18 +383,7 @@
     ///
     /// This can only be used to replace existing value.
     pub fn setprop_inplace(&mut self, name: &CStr, value: &[u8]) -> Result<()> {
-        // SAFETY: fdt size is not altered
-        let ret = unsafe {
-            libfdt_bindgen::fdt_setprop_inplace(
-                self.fdt.as_mut_ptr(),
-                self.offset,
-                name.as_ptr(),
-                value.as_ptr().cast::<c_void>(),
-                value.len().try_into().map_err(|_| FdtError::BadValue)?,
-            )
-        };
-
-        fdt_err_expect_zero(ret)
+        self.fdt.setprop_inplace(self.offset, name, value)
     }
 
     /// Sets the value of the given (address, size) pair property with the given value, and
@@ -492,38 +392,24 @@
     /// This can only be used to replace existing value.
     pub fn setprop_addrrange_inplace(&mut self, name: &CStr, addr: u64, size: u64) -> Result<()> {
         let pair = [addr.to_be(), size.to_be()];
-        self.setprop_inplace(name, pair.as_bytes())
+        self.fdt.setprop_inplace(self.offset, name, pair.as_bytes())
     }
 
     /// Sets a flag-like empty property.
     ///
     /// This may create a new prop or replace existing value.
     pub fn setprop_empty(&mut self, name: &CStr) -> Result<()> {
-        self.setprop(name, &[])
+        self.fdt.setprop(self.offset, name, &[])
     }
 
     /// Deletes the given property.
     pub fn delprop(&mut self, name: &CStr) -> Result<()> {
-        // SAFETY: Accesses are constrained to the DT totalsize (validated by ctor) when the
-        // library locates the node's property. Removing the property may shift the offsets of
-        // other nodes and properties but the borrow checker should prevent this function from
-        // being called when FdtNode instances are in use.
-        let ret = unsafe {
-            libfdt_bindgen::fdt_delprop(self.fdt.as_mut_ptr(), self.offset, name.as_ptr())
-        };
-
-        fdt_err_expect_zero(ret)
+        self.fdt.delprop(self.offset, name)
     }
 
     /// Deletes the given property effectively from DT, by setting it with FDT_NOP.
     pub fn nop_property(&mut self, name: &CStr) -> Result<()> {
-        // SAFETY: Accesses are constrained to the DT totalsize (validated by ctor) when the
-        // library locates the node's property.
-        let ret = unsafe {
-            libfdt_bindgen::fdt_nop_property(self.fdt.as_mut_ptr(), self.offset, name.as_ptr())
-        };
-
-        fdt_err_expect_zero(ret)
+        self.fdt.nop_property(self.offset, name)
     }
 
     /// Trims the size of the given property to new_size.