1use core::fmt::{Debug, Display};
2
3use alloc::{collections::btree_map::BTreeMap, string::String, vec::Vec};
4use fdt_raw::{Phandle, Status};
5
6use crate::{NodeId, Property, RangesEntry};
7
8pub(crate) mod view;
9
10#[derive(Clone)]
16pub struct Node {
17 pub name: String,
19 properties: Vec<Property>,
21 prop_cache: BTreeMap<String, usize>,
23 children: Vec<NodeId>,
25 name_cache: BTreeMap<String, usize>,
28}
29
30impl Node {
31 pub fn new(name: &str) -> Self {
33 Self {
34 name: name.into(),
35 properties: Vec::new(),
36 prop_cache: BTreeMap::new(),
37 children: Vec::new(),
38 name_cache: BTreeMap::new(),
39 }
40 }
41
42 pub fn name(&self) -> &str {
44 &self.name
45 }
46
47 pub fn properties(&self) -> &[Property] {
49 &self.properties
50 }
51
52 pub fn children(&self) -> &[NodeId] {
54 &self.children
55 }
56
57 pub fn add_child(&mut self, name: &str, id: NodeId) {
61 let index = self.children.len();
62 self.name_cache.insert(name.into(), index);
63 self.children.push(id);
64 }
65
66 pub fn add_property(&mut self, prop: Property) {
70 let name = prop.name.clone();
71 let index = self.properties.len();
72 self.prop_cache.insert(name, index);
73 self.properties.push(prop);
74 }
75
76 pub fn get_child(&self, name: &str) -> Option<NodeId> {
80 self.name_cache
81 .get(name)
82 .and_then(|&idx| self.children.get(idx).copied())
83 }
84
85 pub fn remove_child(&mut self, name: &str) -> Option<NodeId> {
89 let &idx = self.name_cache.get(name)?;
90 if idx >= self.children.len() {
91 return None;
92 }
93 let removed = self.children.remove(idx);
94 self.rebuild_name_cache_from(name);
95 Some(removed)
96 }
97
98 pub(crate) fn rebuild_name_cache_from(&mut self, _removed_name: &str) {
101 self.name_cache.remove(_removed_name);
104 self.name_cache.clear();
107 }
108
109 pub(crate) fn rebuild_name_cache_with_names(&mut self, names: &[(String, usize)]) {
111 self.name_cache.clear();
112 for (name, idx) in names {
113 self.name_cache.insert(name.clone(), *idx);
114 }
115 }
116
117 pub fn set_property(&mut self, prop: Property) {
119 let name = prop.name.clone();
120 if let Some(&idx) = self.prop_cache.get(&name) {
121 self.properties[idx] = prop;
123 } else {
124 let idx = self.properties.len();
126 self.prop_cache.insert(name, idx);
127 self.properties.push(prop);
128 }
129 }
130
131 pub fn get_property(&self, name: &str) -> Option<&Property> {
133 self.prop_cache.get(name).map(|&idx| &self.properties[idx])
134 }
135
136 pub fn get_property_mut(&mut self, name: &str) -> Option<&mut Property> {
138 self.prop_cache
139 .get(name)
140 .map(|&idx| &mut self.properties[idx])
141 }
142
143 fn rebuild_prop_cache(&mut self) {
144 self.prop_cache.clear();
145 for (idx, prop) in self.properties.iter().enumerate() {
146 self.prop_cache.insert(prop.name.clone(), idx);
147 }
148 }
149
150 pub fn remove_property(&mut self, name: &str) -> Option<Property> {
154 if let Some(&idx) = self.prop_cache.get(name) {
155 let prop = self.properties.remove(idx);
156 self.rebuild_prop_cache();
157 Some(prop)
158 } else {
159 None
160 }
161 }
162
163 pub fn address_cells(&self) -> Option<u32> {
165 self.get_property("#address-cells")
166 .and_then(|prop| prop.get_u32())
167 }
168
169 pub fn size_cells(&self) -> Option<u32> {
171 self.get_property("#size-cells")
172 .and_then(|prop| prop.get_u32())
173 }
174
175 pub fn phandle(&self) -> Option<Phandle> {
177 self.get_property("phandle")
178 .and_then(|prop| prop.get_u32())
179 .map(Phandle::from)
180 }
181
182 pub fn interrupt_parent(&self) -> Option<Phandle> {
184 self.get_property("interrupt-parent")
185 .and_then(|prop| prop.get_u32())
186 .map(Phandle::from)
187 }
188
189 pub fn status(&self) -> Option<Status> {
191 let prop = self.get_property("status")?;
192 let s = prop.as_str()?;
193 match s {
194 "okay" => Some(Status::Okay),
195 "disabled" => Some(Status::Disabled),
196 _ => None,
197 }
198 }
199
200 pub fn ranges(&self, parent_address_cells: u32) -> Option<Vec<RangesEntry>> {
204 let prop = self.get_property("ranges")?;
205 let mut entries = Vec::new();
206 let mut reader = prop.as_reader();
207
208 let child_address_cells = self.address_cells().unwrap_or(2) as usize;
209 let parent_addr_cells = parent_address_cells as usize;
210 let size_cells = self.size_cells().unwrap_or(1) as usize;
211
212 while let (Some(child_addr), Some(parent_addr), Some(size)) = (
213 reader.read_cells(child_address_cells),
214 reader.read_cells(parent_addr_cells),
215 reader.read_cells(size_cells),
216 ) {
217 entries.push(RangesEntry {
218 child_bus_address: child_addr,
219 parent_bus_address: parent_addr,
220 length: size,
221 });
222 }
223
224 Some(entries)
225 }
226
227 pub fn compatible(&self) -> Option<impl Iterator<Item = &str>> {
229 let prop = self.get_property("compatible")?;
230 Some(prop.as_str_iter())
231 }
232
233 pub fn compatibles(&self) -> impl Iterator<Item = &str> {
235 self.get_property("compatible")
236 .map(|prop| prop.as_str_iter())
237 .into_iter()
238 .flatten()
239 }
240
241 pub fn device_type(&self) -> Option<&str> {
243 let prop = self.get_property("device_type")?;
244 prop.as_str()
245 }
246
247 pub fn is_memory(&self) -> bool {
249 if let Some(dt) = self.device_type()
250 && dt == "memory"
251 {
252 return true;
253 }
254 self.name.starts_with("memory")
255 }
256
257 pub fn is_interrupt_controller(&self) -> bool {
259 self.name.starts_with("interrupt-controller")
260 || self.get_property("interrupt-controller").is_some()
261 }
262
263 pub fn interrupt_cells(&self) -> Option<u32> {
265 self.get_property("#interrupt-cells")
266 .and_then(|prop| prop.get_u32())
267 }
268
269 pub fn is_clock(&self) -> bool {
271 self.get_property("#clock-cells").is_some()
272 }
273
274 pub fn is_pci(&self) -> bool {
276 self.device_type() == Some("pci")
277 }
278}
279
280impl From<&fdt_raw::Node<'_>> for Node {
281 fn from(raw: &fdt_raw::Node<'_>) -> Self {
282 let mut new_node = Node::new(raw.name());
283 for raw_prop in raw.properties() {
285 let prop = Property::from(&raw_prop);
286 new_node.set_property(prop);
287 }
288 new_node
289 }
290}
291
292impl Display for Node {
293 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
294 write!(f, "Node(name: {})", self.name)
295 }
296}
297
298impl Debug for Node {
299 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
300 write!(
301 f,
302 "Node {{ name: {}, properties: {}, children: {} }}",
303 self.name,
304 self.properties.len(),
305 self.children.len()
306 )
307 }
308}