dtb_parser/
device_tree.rs

1#[cfg(not(feature = "std"))]
2use alloc::{collections::VecDeque, string::String, vec, vec::Vec};
3#[cfg(not(feature = "std"))]
4use core::fmt::{Display, Formatter};
5#[cfg(feature = "std")]
6use std::fmt::{Display, Formatter};
7#[cfg(feature = "std")]
8use std::{collections::VecDeque, string::String, vec, vec::Vec};
9
10use crate::error::{DeviceTreeError, Result};
11use crate::header::DeviceTreeHeader;
12use crate::node::DeviceTreeNode;
13use crate::traits::HasNamedChildNode;
14
15/// The tree structure
16/// Reads data from a slice of bytes and parses into [DeviceTree]
17/// Indexed by nodes and properties' names or by path for the whole tree
18pub struct DeviceTree {
19    header: DeviceTreeHeader,
20    root: DeviceTreeNode,
21}
22
23impl DeviceTree {
24    /// Parses a slice of bytes and constructs [DeviceTree]
25    /// The structure should live as long as the `data`
26    pub fn from_bytes(data: &[u8]) -> Result<Self> {
27        let magic = &data[0..4];
28        if magic != [0xd0, 0x0d, 0xfe, 0xed] {
29            return Err(DeviceTreeError::InvalidMagicNumber);
30        }
31
32        let header = DeviceTreeHeader::from_bytes(data)?;
33
34        let root = DeviceTreeNode::from_bytes(
35            data,
36            &header,
37            header.off_dt_struct as usize,
38            InheritedValues::new(),
39        )?;
40
41        Ok(Self { header, root })
42    }
43
44    #[cfg(not(feature = "std"))]
45    /// Parses from address where a device tree blob is located at
46    pub fn from_address(addr: usize) -> Result<Self> {
47        let header_bytes = unsafe { core::slice::from_raw_parts(addr as *const u8, 40) };
48        let magic = &header_bytes[0..4];
49        if magic != [0xd0, 0x0d, 0xfe, 0xed] {
50            return Err(DeviceTreeError::InvalidMagicNumber);
51        }
52        let header = DeviceTreeHeader::from_bytes(header_bytes)?;
53        let data =
54            unsafe { core::slice::from_raw_parts(addr as *const u8, header.total_size as usize) };
55        Self::from_bytes(data)
56    }
57
58    /// Its magic number extracted from the header
59    pub fn magic(&self) -> usize {
60        self.header.magic as usize
61    }
62
63    /// Its total size extracted from the header
64    pub fn total_size(&self) -> usize {
65        self.header.total_size as usize
66    }
67
68    /// Its offset of the struct region extracted from the header
69    pub fn off_dt_struct(&self) -> usize {
70        self.header.off_dt_struct as usize
71    }
72
73    /// Its offset of the strings region extracted from the header
74    pub fn off_dt_strings(&self) -> usize {
75        self.header.off_dt_strings as usize
76    }
77
78    /// Its offset of the reserved memory region extracted from the header
79    pub fn off_mem_reserved(&self) -> usize {
80        self.header.off_mem_reserved as usize
81    }
82
83    /// Its version extracted from the header
84    pub fn version(&self) -> usize {
85        self.header.version as usize
86    }
87
88    /// Its last compatible version extracted from the header
89    pub fn last_comp_version(&self) -> usize {
90        self.header.last_comp_version as usize
91    }
92
93    /// Its boot cpu id extracted from the header
94    pub fn boot_cpu_id(&self) -> usize {
95        self.header.boot_cpu_id as usize
96    }
97
98    /// Its size of the strings region extracted from the header
99    pub fn size_dt_strings(&self) -> usize {
100        self.header.size_dt_strings as usize
101    }
102
103    /// Its size of the struct region extracted from the header
104    pub fn size_dt_struct(&self) -> usize {
105        self.header.size_dt_struct as usize
106    }
107
108    /// Get a reference of the root node
109    pub fn root(&self) -> &DeviceTreeNode {
110        &self.root
111    }
112
113    /// Find the node by given node path
114    pub fn find_node(&self, path: &str) -> Option<&DeviceTreeNode> {
115        let mut slices = path.split('/');
116        if let Some("") = slices.next() {
117            let mut first = &self.root;
118            for i in slices {
119                if let Some(node) = first.find_child(i) {
120                    first = node;
121                } else {
122                    return None;
123                }
124            }
125            Some(first)
126        } else {
127            None
128        }
129    }
130
131    /// Find the node by given node path with all the nodes traveled
132    pub fn find_along_path(&self, path: &str) -> Option<Vec<&DeviceTreeNode>> {
133        let mut slices: Vec<&str> = path.split('/').collect();
134        let mut container = Vec::<&DeviceTreeNode>::new();
135        if slices.len() > 0 && self.root.name() == slices[0] {
136            container.push(&self.root);
137            if Self::find_along_path_internal(&self.root, &mut slices, 1, &mut container) {
138                Some(container)
139            } else {
140                None
141            }
142        } else {
143            None
144        }
145    }
146
147    fn find_along_path_internal<'tree>(
148        node: &'tree DeviceTreeNode,
149        slices: &mut [&str],
150        index: usize,
151        container: &mut Vec<&'tree DeviceTreeNode>,
152    ) -> bool {
153        if index == slices.len() {
154            return true;
155        }
156        let name = slices[index];
157        for node in node.nodes() {
158            if node.name() == name {
159                container.push(node);
160                return Self::find_along_path_internal(node, slices, index + 1, container);
161            }
162        }
163        return false;
164    }
165}
166
167/// Iterator for all the tree nodes
168pub struct DeviceTreeNodeIter<'a> {
169    queue: VecDeque<&'a DeviceTreeNode>,
170}
171
172impl<'a> Iterator for DeviceTreeNodeIter<'a> {
173    type Item = &'a DeviceTreeNode;
174
175    fn next(&mut self) -> Option<Self::Item> {
176        let res = self.queue.pop_front();
177        match res {
178            Some(node) if node.has_children() => {
179                for i in node.nodes() {
180                    self.queue.push_back(i);
181                }
182            }
183            _ => {}
184        }
185        res
186    }
187}
188
189impl Display for DeviceTree {
190    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
191        writeln!(f, "{}", self.root)
192    }
193}
194
195impl<'a> IntoIterator for &'a DeviceTree {
196    type Item = &'a DeviceTreeNode;
197    type IntoIter = DeviceTreeNodeIter<'a>;
198
199    fn into_iter(self) -> Self::IntoIter {
200        DeviceTreeNodeIter {
201            queue: VecDeque::from([self.root()]),
202        }
203    }
204}
205
206#[derive(Clone)]
207pub(crate) struct InheritedValues(Vec<(String, u64)>);
208
209impl InheritedValues {
210    pub const fn new() -> Self {
211        InheritedValues(vec![])
212    }
213
214    pub fn find(&self, name: &str) -> Option<u64> {
215        for i in &self.0 {
216            if i.0.as_str() == name {
217                return Some(i.1);
218            }
219        }
220        None
221    }
222
223    pub fn insert(&mut self, name: String, value: u64) {
224        self.0.push((name, value));
225    }
226}