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
124fn write_indent(f: &mut fmt::Formatter<'_>, count: usize, ch: &str) -> fmt::Result {
126 for _ in 0..count {
127 write!(f, "{}", ch)?;
128 }
129 Ok(())
130}
131
132impl fmt::Display for NodeBase<'_> {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 write_indent(f, self.level, " ")?;
135 let name = if self.name.is_empty() { "/" } else { self.name };
136
137 writeln!(f, "{} {{", name)?;
138 for prop in self.properties() {
139 write_indent(f, self.level + 1, " ")?;
140 writeln!(f, "{};", prop)?;
141 }
142 write_indent(f, self.level, " ")?;
143 write!(f, "}}")
144 }
145}
146
147#[derive(Clone)]
153pub enum Node<'a> {
154 General(NodeBase<'a>),
156 Chosen(Chosen<'a>),
158 Memory(Memory<'a>),
160}
161
162impl<'a> From<NodeBase<'a>> for Node<'a> {
163 fn from(node: NodeBase<'a>) -> Self {
164 if node.is_chosen() {
165 Node::Chosen(Chosen::new(node))
166 } else if node.is_memory() {
167 Node::Memory(Memory::new(node))
168 } else {
169 Node::General(node)
170 }
171 }
172}
173
174impl<'a> Deref for Node<'a> {
175 type Target = NodeBase<'a>;
176
177 fn deref(&self) -> &Self::Target {
178 match self {
179 Node::General(n) => n,
180 Node::Chosen(c) => c.deref(),
181 Node::Memory(m) => m.deref(),
182 }
183 }
184}
185
186impl fmt::Display for Node<'_> {
187 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188 Debug::fmt(self, f)
189 }
190}
191
192impl fmt::Debug for Node<'_> {
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 match self {
195 Node::General(n) => f.debug_tuple("General").field(&n.name()).finish(),
196 Node::Chosen(c) => c.fmt(f),
197 Node::Memory(m) => m.fmt(f),
198 }
199 }
200}
201
202#[derive(Debug, Clone, Default)]
204pub(crate) struct ParsedProps {
205 pub address_cells: Option<u8>,
206 pub size_cells: Option<u8>,
207}
208
209#[derive(Debug, Clone, Copy, PartialEq, Eq)]
211pub(crate) enum OneNodeState {
212 Processing,
214 ChildBegin,
216 End,
218}
219
220pub(crate) struct OneNodeIter<'a> {
223 reader: Reader<'a>,
224 strings: Bytes<'a>,
225 state: OneNodeState,
226 level: usize,
227 context: NodeContext,
228 parsed_props: ParsedProps,
229 fdt: Fdt<'a>,
230}
231
232impl<'a> OneNodeIter<'a> {
233 pub fn new(
234 reader: Reader<'a>,
235 strings: Bytes<'a>,
236 level: usize,
237 context: NodeContext,
238 fdt: Fdt<'a>,
239 ) -> Self {
240 Self {
241 reader,
242 strings,
243 state: OneNodeState::Processing,
244 level,
245 context,
246 parsed_props: ParsedProps::default(),
247 fdt,
248 }
249 }
250
251 pub fn reader(&self) -> &Reader<'a> {
252 &self.reader
253 }
254
255 pub fn parsed_props(&self) -> &ParsedProps {
256 &self.parsed_props
257 }
258
259 pub fn read_node_name(&mut self) -> Result<NodeBase<'a>, FdtError> {
261 let name = self.read_cstr()?;
263
264 self.align4();
266
267 let data = self.reader.remain();
268
269 Ok(NodeBase {
270 name,
271 data,
272 strings: self.strings.clone(),
273 level: self.level,
274 address_cells: 2,
276 size_cells: 1,
277 context: self.context.clone(),
278 _fdt: self.fdt.clone(),
279 })
280 }
281
282 fn read_cstr(&mut self) -> Result<&'a str, FdtError> {
283 let bytes = self.reader.remain();
284 let cstr = CStr::from_bytes_until_nul(bytes.as_slice())?;
285 let s = cstr.to_str()?;
286 let _ = self.reader.read_bytes(s.len() + 1);
288 Ok(s)
289 }
290
291 fn align4(&mut self) {
292 let pos = self.reader.position();
293 let aligned = (pos + 3) & !3;
294 let skip = aligned - pos;
295 if skip > 0 {
296 let _ = self.reader.read_bytes(skip);
297 }
298 }
299
300 fn read_prop_name(&self, nameoff: u32) -> Result<&'a str, FdtError> {
302 let bytes = self.strings.slice(nameoff as usize..self.strings.len());
303 let cstr = CStr::from_bytes_until_nul(bytes.as_slice())?;
304 Ok(cstr.to_str()?)
305 }
306
307 fn read_u32_be(data: &[u8], offset: usize) -> u64 {
309 u32::from_be_bytes(data[offset..offset + 4].try_into().unwrap()) as u64
310 }
311
312 pub fn process(&mut self) -> Result<OneNodeState, FdtError> {
314 loop {
315 let token = self.reader.read_token()?;
316 match token {
317 Token::BeginNode => {
318 self.reader.backtrack(4);
320 self.state = OneNodeState::ChildBegin;
321 return Ok(OneNodeState::ChildBegin);
322 }
323 Token::EndNode => {
324 self.state = OneNodeState::End;
325 return Ok(OneNodeState::End);
326 }
327 Token::Prop => {
328 let len = self.reader.read_u32().ok_or(FdtError::BufferTooSmall {
330 pos: self.reader.position(),
331 })? as usize;
332
333 let nameoff = self.reader.read_u32().ok_or(FdtError::BufferTooSmall {
334 pos: self.reader.position(),
335 })?;
336
337 let prop_data = if len > 0 {
339 self.reader
340 .read_bytes(len)
341 .ok_or(FdtError::BufferTooSmall {
342 pos: self.reader.position(),
343 })?
344 } else {
345 Bytes::new(&[])
346 };
347
348 if let Ok(prop_name) = self.read_prop_name(nameoff) {
350 match prop_name {
351 "#address-cells" if len == 4 => {
352 self.parsed_props.address_cells =
353 Some(Self::read_u32_be(&prop_data, 0) as u8);
354 }
355 "#size-cells" if len == 4 => {
356 self.parsed_props.size_cells =
357 Some(Self::read_u32_be(&prop_data, 0) as u8);
358 }
359 _ => {}
360 }
361 }
362
363 self.align4();
365 }
366 Token::Nop => {
367 }
369 Token::End => {
370 self.state = OneNodeState::End;
372 return Ok(OneNodeState::End);
373 }
374 Token::Data(_) => {
375 return Err(FdtError::BufferTooSmall {
377 pos: self.reader.position(),
378 });
379 }
380 }
381 }
382 }
383}