1use core::fmt;
2
3use crate::{
4 Chosen, FdtError, Memory, MemoryReservation, Node, data::Bytes, header::Header, iter::FdtIter,
5};
6
7pub struct MemoryReservationIter<'a> {
9 data: &'a [u8],
10 offset: usize,
11}
12
13impl<'a> Iterator for MemoryReservationIter<'a> {
14 type Item = MemoryReservation;
15
16 fn next(&mut self) -> Option<Self::Item> {
17 if self.offset + 16 > self.data.len() {
19 return None;
20 }
21
22 let address_bytes = &self.data[self.offset..self.offset + 8];
24 let address = u64::from_be_bytes(address_bytes.try_into().unwrap());
25 self.offset += 8;
26
27 let size_bytes = &self.data[self.offset..self.offset + 8];
29 let size = u64::from_be_bytes(size_bytes.try_into().unwrap());
30 self.offset += 8;
31
32 if address == 0 && size == 0 {
34 return None;
35 }
36
37 Some(MemoryReservation { address, size })
38 }
39}
40
41fn write_indent(f: &mut fmt::Formatter<'_>, count: usize, ch: &str) -> fmt::Result {
43 for _ in 0..count {
44 write!(f, "{}", ch)?;
45 }
46 Ok(())
47}
48
49#[derive(Clone)]
50pub struct Fdt<'a> {
51 header: Header,
52 pub(crate) data: Bytes<'a>,
53}
54
55impl<'a> Fdt<'a> {
56 pub fn from_bytes(data: &'a [u8]) -> Result<Fdt<'a>, FdtError> {
58 let header = Header::from_bytes(data)?;
59 if data.len() < header.totalsize as usize {
60 return Err(FdtError::BufferTooSmall {
61 pos: header.totalsize as usize,
62 });
63 }
64 let buffer = Bytes::new(data);
65
66 Ok(Fdt {
67 header,
68 data: buffer,
69 })
70 }
71
72 pub unsafe fn from_ptr(ptr: *mut u8) -> Result<Fdt<'a>, FdtError> {
80 let header = unsafe { Header::from_ptr(ptr)? };
81
82 let data_slice = unsafe { core::slice::from_raw_parts(ptr, header.totalsize as _) };
83 let data = Bytes::new(data_slice);
84
85 Ok(Fdt { header, data })
86 }
87
88 pub fn header(&self) -> &Header {
89 &self.header
90 }
91
92 pub fn as_slice(&self) -> &'a [u8] {
93 self.data.as_slice()
94 }
95
96 pub fn all_nodes(&self) -> FdtIter<'a> {
97 FdtIter::new(self.clone())
98 }
99
100 pub fn find_by_path(&self, path: &str) -> Option<Node<'a>> {
101 let path = self.normalize_path(path)?;
102 let split = path.trim_matches('/').split('/');
103
104 let mut current_iter = self.all_nodes();
105 let mut found_node: Option<Node<'a>> = None;
106
107 for part in split {
108 let mut found = false;
109 for node in current_iter.by_ref() {
110 let node_name = node.name();
111 if node_name == part {
112 found = true;
113 found_node = Some(node);
114 break;
115 }
116 }
117 if !found {
118 return None;
119 }
120 }
121
122 found_node
123 }
124
125 fn resolve_alias(&self, alias: &str) -> Option<&'a str> {
126 let aliases_node = self.find_by_path("/aliases")?;
127 aliases_node.find_property_str(alias)
128 }
129
130 fn normalize_path(&self, path: &'a str) -> Option<&'a str> {
131 if path.starts_with('/') {
132 Some(path)
133 } else {
134 self.resolve_alias(path)
135 }
136 }
137
138 pub fn translate_address(&self, path: &'a str, address: u64) -> u64 {
152 let path = match self.normalize_path(path) {
153 Some(p) => p,
154 None => return address,
155 };
156
157 let path_parts: heapless::Vec<&str, 16> = path
159 .trim_matches('/')
160 .split('/')
161 .filter(|s| !s.is_empty())
162 .collect();
163
164 if path_parts.is_empty() {
165 return address;
166 }
167
168 let mut current_address = address;
169
170 for depth in (0..path_parts.len()).rev() {
173 let parent_parts = &path_parts[..depth];
175 if parent_parts.is_empty() {
176 break;
178 }
179
180 let mut parent_path = heapless::String::<256>::new();
182 parent_path.push('/').ok();
183 for (i, part) in parent_parts.iter().enumerate() {
184 if i > 0 {
185 parent_path.push('/').ok();
186 }
187 parent_path.push_str(part).ok();
188 }
189
190 let parent_node = match self.find_by_path(parent_path.as_str()) {
191 Some(node) => node,
192 None => continue,
193 };
194
195 let ranges = match parent_node.ranges() {
197 Some(r) => r,
198 None => {
199 break;
201 }
202 };
203
204 let mut found = false;
206 for range in ranges.iter() {
207 if current_address >= range.child_address
209 && current_address < range.child_address + range.length
210 {
211 let offset = current_address - range.child_address;
213 current_address = range.parent_address + offset;
215 found = true;
216 break;
217 }
218 }
219
220 if !found {
221 }
224 }
225
226 current_address
227 }
228
229 pub fn memory_reservations(&self) -> MemoryReservationIter<'a> {
231 MemoryReservationIter {
232 data: self.data.as_slice(),
233 offset: self.header.off_mem_rsvmap as usize,
234 }
235 }
236
237 pub fn chosen(&self) -> Option<Chosen<'a>> {
238 for node in self.all_nodes() {
239 if let Node::Chosen(c) = node {
240 return Some(c);
241 }
242 }
243 None
244 }
245
246 pub fn memory(&self) -> impl Iterator<Item = Memory<'a>> + 'a {
247 self.all_nodes().filter_map(|node| {
248 if let Node::Memory(mem) = node {
249 Some(mem)
250 } else {
251 None
252 }
253 })
254 }
255
256 pub fn reserved_memory(&self) -> impl Iterator<Item = Node<'a>> + 'a {
257 ReservedMemoryIter {
258 node_iter: self.all_nodes(),
259 in_reserved_memory: false,
260 reserved_level: 0,
261 }
262 }
263}
264
265struct ReservedMemoryIter<'a> {
266 node_iter: FdtIter<'a>,
267 in_reserved_memory: bool,
268 reserved_level: usize,
269}
270
271impl<'a> Iterator for ReservedMemoryIter<'a> {
272 type Item = Node<'a>;
273
274 fn next(&mut self) -> Option<Self::Item> {
275 while let Some(node) = self.node_iter.next() {
276 if node.name() == "reserved-memory" {
277 self.in_reserved_memory = true;
278 self.reserved_level = node.level();
279 continue;
280 }
281
282 if self.in_reserved_memory {
283 if node.level() <= self.reserved_level {
284 self.in_reserved_memory = false;
286 return None;
287 } else {
288 return Some(node);
289 }
290 }
291 }
292 None
293 }
294}
295
296impl fmt::Display for Fdt<'_> {
297 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
298 writeln!(f, "/dts-v1/;")?;
299 writeln!(f)?;
300
301 let mut prev_level = 0;
302
303 for node in self.all_nodes() {
304 let level = node.level();
305
306 while prev_level > level {
308 prev_level -= 1;
309 write_indent(f, prev_level, " ")?;
310 writeln!(f, "}};\n")?;
311 }
312
313 write_indent(f, level, " ")?;
314 let name = if node.name().is_empty() {
315 "/"
316 } else {
317 node.name()
318 };
319
320 writeln!(f, "{} {{", name)?;
322
323 for prop in node.properties() {
325 write_indent(f, level + 1, " ")?;
326 writeln!(f, "{};", prop)?;
327 }
328
329 prev_level = level + 1;
330 }
331
332 while prev_level > 0 {
334 prev_level -= 1;
335 write_indent(f, prev_level, " ")?;
336 writeln!(f, "}};\n")?;
337 }
338
339 Ok(())
340 }
341}
342
343impl fmt::Debug for Fdt<'_> {
344 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
345 writeln!(f, "Fdt {{")?;
346 writeln!(f, "\theader: {:?}", self.header)?;
347 writeln!(f, "\tnodes:")?;
348
349 for node in self.all_nodes() {
350 let level = node.level();
351 write_indent(f, level + 2, "\t")?;
353
354 let name = if node.name().is_empty() {
355 "/"
356 } else {
357 node.name()
358 };
359
360 writeln!(
362 f,
363 "[{}] address_cells={}, size_cells={}",
364 name, node.address_cells, node.size_cells
365 )?;
366
367 for prop in node.properties() {
369 write_indent(f, level + 3, "\t")?;
370 if let Some(v) = prop.as_address_cells() {
371 writeln!(f, "#address-cells: {}", v)?;
372 } else if let Some(v) = prop.as_size_cells() {
373 writeln!(f, "#size-cells: {}", v)?;
374 } else if let Some(v) = prop.as_interrupt_cells() {
375 writeln!(f, "#interrupt-cells: {}", v)?;
376 } else if let Some(s) = prop.as_status() {
377 writeln!(f, "status: {:?}", s)?;
378 } else if let Some(p) = prop.as_phandle() {
379 writeln!(f, "phandle: {}", p)?;
380 } else {
381 if prop.is_empty() {
383 writeln!(f, "{}", prop.name())?;
384 } else if let Some(s) = prop.as_str() {
385 writeln!(f, "{}: \"{}\"", prop.name(), s)?;
386 } else if prop.len() == 4 {
387 let v = u32::from_be_bytes(prop.data().as_slice().try_into().unwrap());
388 writeln!(f, "{}: {:#x}", prop.name(), v)?;
389 } else {
390 writeln!(f, "{}: <{} bytes>", prop.name(), prop.len())?;
391 }
392 }
393 }
394 }
395
396 writeln!(f, "}}")
397 }
398}
399
400#[cfg(test)]
401mod tests {
402 use super::*;
403 use heapless::Vec;
404
405 #[test]
406 fn test_memory_reservation_iterator() {
407 let mut test_data = [0u8; 32];
409
410 test_data[0..8].copy_from_slice(&0x80000000u64.to_be_bytes());
412 test_data[8..16].copy_from_slice(&0x10000000u64.to_be_bytes());
413 test_data[16..24].copy_from_slice(&0u64.to_be_bytes());
415 test_data[24..32].copy_from_slice(&0u64.to_be_bytes());
416
417 let iter = MemoryReservationIter {
418 data: &test_data,
419 offset: 0,
420 };
421
422 let reservations: Vec<MemoryReservation, 4> = iter.collect();
423 assert_eq!(reservations.len(), 1);
424 assert_eq!(reservations[0].address, 0x80000000);
425 assert_eq!(reservations[0].size, 0x10000000);
426 }
427
428 #[test]
429 fn test_empty_memory_reservation_iterator() {
430 let mut test_data = [0u8; 16];
432 test_data[0..8].copy_from_slice(&0u64.to_be_bytes());
433 test_data[8..16].copy_from_slice(&0u64.to_be_bytes());
434
435 let iter = MemoryReservationIter {
436 data: &test_data,
437 offset: 0,
438 };
439
440 let reservations: Vec<MemoryReservation, 4> = iter.collect();
441 assert_eq!(reservations.len(), 0);
442 }
443}