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.