Skip to main content

fdt_edit/prop/
mod.rs

1//! Device tree property representation and manipulation.
2//!
3//! This module provides the `Property` type which represents a mutable device tree
4//! property with a name and data, along with methods for accessing and modifying
5//! various property data formats.
6
7use core::ffi::CStr;
8
9use alloc::{
10    string::{String, ToString},
11    vec::Vec,
12};
13
14use fdt_raw::data::{Bytes, StrIter, U32Iter};
15// Re-export from fdt_raw
16use crate::Reader;
17
18/// A mutable device tree property.
19///
20/// Represents a property with a name and raw data. Provides methods for
21/// accessing and modifying the data in various formats (u32, u64, strings, etc.).
22#[derive(Clone)]
23pub struct Property {
24    /// Property name
25    pub name: String,
26    /// Raw property data
27    pub data: Vec<u8>,
28}
29
30impl Property {
31    /// Creates a new property with the given name and data.
32    pub fn new(name: &str, data: Vec<u8>) -> Self {
33        Self {
34            name: name.to_string(),
35            data,
36        }
37    }
38
39    /// Returns the property name.
40    pub fn name(&self) -> &str {
41        &self.name
42    }
43
44    /// Returns the property data as a big-endian u32.
45    ///
46    /// Returns None if the data is not exactly 4 bytes.
47    pub fn get_u32(&self) -> Option<u32> {
48        if self.data.len() != 4 {
49            return None;
50        }
51        Some(u32::from_be_bytes([
52            self.data[0],
53            self.data[1],
54            self.data[2],
55            self.data[3],
56        ]))
57    }
58
59    /// Sets the property data from a list of u32 values (as big-endian).
60    pub fn set_u32_ls(&mut self, values: &[u32]) {
61        self.data.clear();
62        for &value in values {
63            self.data.extend_from_slice(&value.to_be_bytes());
64        }
65    }
66
67    /// Returns an iterator over u32 values in the property data.
68    pub fn get_u32_iter(&self) -> U32Iter<'_> {
69        Bytes::new(&self.data).as_u32_iter()
70    }
71
72    /// Returns the property data as a big-endian u64.
73    ///
74    /// Returns None if the data is not exactly 8 bytes.
75    pub fn get_u64(&self) -> Option<u64> {
76        if self.data.len() != 8 {
77            return None;
78        }
79        Some(u64::from_be_bytes([
80            self.data[0],
81            self.data[1],
82            self.data[2],
83            self.data[3],
84            self.data[4],
85            self.data[5],
86            self.data[6],
87            self.data[7],
88        ]))
89    }
90
91    /// Sets the property data from a u64 value (as big-endian).
92    pub fn set_u64(&mut self, value: u64) {
93        self.data = value.to_be_bytes().to_vec();
94    }
95
96    /// Returns the property data as a null-terminated string.
97    ///
98    /// Returns None if the data is not a valid null-terminated UTF-8 string.
99    pub fn as_str(&self) -> Option<&str> {
100        CStr::from_bytes_with_nul(&self.data)
101            .ok()
102            .and_then(|cstr| cstr.to_str().ok())
103    }
104
105    /// Sets the property data from a string value.
106    ///
107    /// The string will be null-terminated.
108    pub fn set_string(&mut self, value: &str) {
109        let mut bytes = value.as_bytes().to_vec();
110        bytes.push(0); // Null-terminate
111        self.data = bytes;
112    }
113
114    /// Returns an iterator over null-terminated strings in the property data.
115    pub fn as_str_iter(&self) -> StrIter<'_> {
116        Bytes::new(&self.data).as_str_iter()
117    }
118
119    /// Sets the property data from a list of string values.
120    ///
121    /// Each string will be null-terminated.
122    pub fn set_string_ls(&mut self, values: &[&str]) {
123        self.data.clear();
124        for &value in values {
125            self.data.extend_from_slice(value.as_bytes());
126            self.data.push(0); // Null-terminate each string
127        }
128    }
129
130    /// Returns a reader for accessing the property data.
131    pub fn as_reader(&self) -> Reader<'_> {
132        Bytes::new(&self.data).reader()
133    }
134}
135
136impl From<&fdt_raw::Property<'_>> for Property {
137    fn from(value: &fdt_raw::Property<'_>) -> Self {
138        Self {
139            name: value.name().to_string(),
140            data: value.as_slice().to_vec(),
141        }
142    }
143}
144
145/// Ranges entry information for address translation.
146///
147/// Represents a single entry in a `ranges` property, mapping a child bus
148/// address range to a parent bus address range.
149#[derive(Debug, Clone, Copy, PartialEq, Eq)]
150pub struct RangesEntry {
151    /// Child bus address
152    pub child_bus_address: u64,
153    /// Parent bus address
154    pub parent_bus_address: u64,
155    /// Length of the region
156    pub length: u64,
157}