1use core::fmt;
2use core::ops::Deref;
3use core::{ffi::CStr, fmt::Debug};
4
5use crate::Fdt;
6use crate::{
7 FdtError, Token,
8 data::{Bytes, Reader},
9};
10
11mod chosen;
12mod memory;
13mod prop;
14
15pub use chosen::Chosen;
16pub use memory::{Memory, MemoryRegion};
17pub use prop::{PropIter, Property, RangeInfo, RegInfo, RegIter, VecRange};
18
19#[derive(Clone)]
21pub(crate) struct NodeContext {
22 pub address_cells: u8,
24 pub size_cells: u8,
26}
27
28impl Default for NodeContext {
29 fn default() -> Self {
30 NodeContext {
31 address_cells: 2,
32 size_cells: 1,
33 }
34 }
35}
36
37#[derive(Clone)]
39pub struct NodeBase<'a> {
40 name: &'a str,
41 data: Bytes<'a>,
42 strings: Bytes<'a>,
43 level: usize,
44 _fdt: Fdt<'a>,
45 pub address_cells: u8,
47 pub size_cells: u8,
49 context: NodeContext,
51}
52
53impl<'a> NodeBase<'a> {
54 pub fn name(&self) -> &'a str {
55 self.name
56 }
57
58 pub fn level(&self) -> usize {
59 self.level
60 }
61
62 pub fn properties(&self) -> PropIter<'a> {
64 PropIter::new(self.data.reader(), self.strings.clone())
65 }
66
67 pub fn find_property(&self, name: &str) -> Option<Property<'a>> {
69 self.properties().find(|p| p.name() == name)
70 }
71
72 pub fn find_property_str(&self, name: &str) -> Option<&'a str> {
74 let prop = self.find_property(name)?;
75
76 prop.as_str()
78 }
79
80 pub fn reg(&self) -> Option<RegIter<'a>> {
82 let prop = self.find_property("reg")?;
83 Some(RegIter::new(
84 prop.data().reader(),
85 self.context.address_cells,
86 self.context.size_cells,
87 ))
88 }
89
90 pub fn reg_array<const N: usize>(&self) -> heapless::Vec<RegInfo, N> {
92 let mut result = heapless::Vec::new();
93 if let Some(reg) = self.reg() {
94 for info in reg {
95 if result.push(info).is_err() {
96 break; }
98 }
99 }
100 result
101 }
102
103 fn is_chosen(&self) -> bool {
105 self.name == "chosen"
106 }
107
108 fn is_memory(&self) -> bool {
110 self.name.starts_with("memory")
111 }
112
113 pub fn ranges(&self) -> Option<VecRange<'a>> {
114 let prop = self.find_property("ranges")?;
115 Some(VecRange::new(
116 self.address_cells as usize,
117 self.context.address_cells as usize,
118 self.context.size_cells as usize,
119 prop.data(),
120 ))
121 }
122
123 pub fn compatibles(&self) -> impl Iterator<Item = &'a str> {
124 self.find_property("compatible")
125 .into_iter()
126 .flat_map(|p| p.as_str_iter())
127 }
128}
129
130fn write_indent(f: &mut fmt::Formatter<'_>, count: usize, ch: &str) -> fmt::Result {
132 for _ in 0..count {
133 write!(f, "{}", ch)?;
134 }
135 Ok(())
136}
137
138impl fmt::Display for NodeBase<'_> {
139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 write_indent(f, self.level, " ")?;
141 let name = if self.name.is_empty() { "/" } else { self.name };
142
143 writeln!(f, "{} {{", name)?;
144 for prop in self.properties() {
145 write_indent(f, self.level + 1, " ")?;
146 writeln!(f, "{};", prop)?;
147 }
148 write_indent(f, self.level, " ")?;
149 write!(f, "}}")
150 }
151}
152
153#[derive(Clone)]
159pub enum Node<'a> {
160 General(NodeBase<'a>),
162 Chosen(Chosen<'a>),
164 Memory(Memory<'a>),
166}
167
168impl<'a> From<NodeBase<'a>> for Node<'a> {
169 fn from(node: NodeBase<'a>) -> Self {
170 if node.is_chosen() {
171 Node::Chosen(Chosen::new(node))
172 } else if node.is_memory() {
173 Node::Memory(Memory::new(node))
174 } else {
175 Node::General(node)
176 }
177 }
178}
179
180impl<'a> Deref for Node<'a> {
181 type Target = NodeBase<'a>;
182
183 fn deref(&self) -> &Self::Target {
184 match self {
185 Node::General(n) => n,
186 Node::Chosen(c) => c.deref(),
187 Node::Memory(m) => m.deref(),
188 }
189 }
190}
191
192impl fmt::Display for Node<'_> {
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 Debug::fmt(self, f)
195 }
196}
197
198impl fmt::Debug for Node<'_> {
199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200 match self {
201 Node::General(n) => f.debug_tuple("General").field(&n.name()).finish(),
202 Node::Chosen(c) => c.fmt(f),
203 Node::Memory(m) => m.fmt(f),
204 }
205 }
206}
207
208#[derive(Debug, Clone, Default)]
210pub(crate) struct ParsedProps {
211 pub address_cells: Option<u8>,
212 pub size_cells: Option<u8>,
213}
214
215#[derive(Debug, Clone, Copy, PartialEq, Eq)]
217pub(crate) enum OneNodeState {
218 Processing,
220 ChildBegin,
222 End,
224}
225
226pub(crate) struct OneNodeIter<'a> {
229 reader: Reader<'a>,
230 strings: Bytes<'a>,
231 state: OneNodeState,
232 level: usize,
233 context: NodeContext,
234 parsed_props: ParsedProps,
235 fdt: Fdt<'a>,
236}
237
238impl<'a> OneNodeIter<'a> {
239 pub fn new(
240 reader: Reader<'a>,
241 strings: Bytes<'a>,
242 level: usize,
243 context: NodeContext,
244 fdt: Fdt<'a>,
245 ) -> Self {
246 Self {
247 reader,
248 strings,
249 state: OneNodeState::Processing,
250 level,
251 context,
252 parsed_props: ParsedProps::default(),
253 fdt,
254 }
255 }
256
257 pub fn reader(&self) -> &Reader<'a> {
258 &self.reader
259 }
260
261 pub fn parsed_props(&self) -> &ParsedProps {
262 &self.parsed_props
263 }
264
265 pub fn read_node_name(&mut self) -> Result<NodeBase<'a>, FdtError> {
267 let name = self.read_cstr()?;
269
270 self.align4();
272
273 let data = self.reader.remain();
274
275 Ok(NodeBase {
276 name,
277 data,
278 strings: self.strings.clone(),
279 level: self.level,
280 address_cells: 2,
282 size_cells: 1,
283 context: self.context.clone(),
284 _fdt: self.fdt.clone(),
285 })
286 }
287
288 fn read_cstr(&mut self) -> Result<&'a str, FdtError> {
289 let bytes = self.reader.remain();
290 let cstr = CStr::from_bytes_until_nul(bytes.as_slice())?;
291 let s = cstr.to_str()?;
292 let _ = self.reader.read_bytes(s.len() + 1);
294 Ok(s)
295 }
296
297 fn align4(&mut self) {
298 let pos = self.reader.position();
299 let aligned = (pos + 3) & !3;
300 let skip = aligned - pos;
301 if skip > 0 {
302 let _ = self.reader.read_bytes(skip);
303 }
304 }
305
306 fn read_prop_name(&self, nameoff: u32) -> Result<&'a str, FdtError> {
308 let bytes = self.strings.slice(nameoff as usize..self.strings.len());
309 let cstr = CStr::from_bytes_until_nul(bytes.as_slice())?;
310 Ok(cstr.to_str()?)
311 }
312
313 fn read_u32_be(data: &[u8], offset: usize) -> u64 {
315 u32::from_be_bytes(data[offset..offset + 4].try_into().unwrap()) as u64
316 }
317
318 pub fn process(&mut self) -> Result<OneNodeState, FdtError> {
320 loop {
321 let token = self.reader.read_token()?;
322 match token {
323 Token::BeginNode => {
324 self.reader.backtrack(4);
326 self.state = OneNodeState::ChildBegin;
327 return Ok(OneNodeState::ChildBegin);
328 }
329 Token::EndNode => {
330 self.state = OneNodeState::End;
331 return Ok(OneNodeState::End);
332 }
333 Token::Prop => {
334 let len = self.reader.read_u32().ok_or(FdtError::BufferTooSmall {
336 pos: self.reader.position(),
337 })? as usize;
338
339 let nameoff = self.reader.read_u32().ok_or(FdtError::BufferTooSmall {
340 pos: self.reader.position(),
341 })?;
342
343 let prop_data = if len > 0 {
345 self.reader
346 .read_bytes(len)
347 .ok_or(FdtError::BufferTooSmall {
348 pos: self.reader.position(),
349 })?
350 } else {
351 Bytes::new(&[])
352 };
353
354 if let Ok(prop_name) = self.read_prop_name(nameoff) {
356 match prop_name {
357 "#address-cells" if len == 4 => {
358 self.parsed_props.address_cells =
359 Some(Self::read_u32_be(&prop_data, 0) as u8);
360 }
361 "#size-cells" if len == 4 => {
362 self.parsed_props.size_cells =
363 Some(Self::read_u32_be(&prop_data, 0) as u8);
364 }
365 _ => {}
366 }
367 }
368
369 self.align4();
371 }
372 Token::Nop => {
373 }
375 Token::End => {
376 self.state = OneNodeState::End;
378 return Ok(OneNodeState::End);
379 }
380 Token::Data(_) => {
381 return Err(FdtError::BufferTooSmall {
383 pos: self.reader.position(),
384 });
385 }
386 }
387 }
388 }
389}