1use core::ffi::CStr;
2use core::fmt;
3use core::ops::Deref;
4
5use crate::{
6 FdtError, Token,
7 data::{Bytes, Reader},
8};
9
10mod chosen;
11mod memory;
12mod prop;
13
14pub use chosen::Chosen;
15pub use memory::{Memory, MemoryRegion};
16pub use prop::{PropIter, Property, RegInfo, RegIter};
17
18#[derive(Debug, Clone)]
20pub struct NodeContext {
21 pub parent_address_cells: u8,
23 pub parent_size_cells: u8,
25}
26
27impl Default for NodeContext {
28 fn default() -> Self {
29 Self {
30 parent_address_cells: 2,
32 parent_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 pub address_cells: u8,
46 pub size_cells: u8,
48 pub context: NodeContext,
50}
51
52impl<'a> NodeBase<'a> {
53 pub fn name(&self) -> &'a str {
54 self.name
55 }
56
57 pub fn level(&self) -> usize {
58 self.level
59 }
60
61 pub(crate) fn create_child_context(&self) -> NodeContext {
63 NodeContext {
64 parent_address_cells: self.address_cells,
65 parent_size_cells: self.size_cells,
66 }
67 }
68
69 pub fn properties(&self) -> PropIter<'a> {
71 PropIter::new(self.data.reader(), self.strings.clone())
72 }
73
74 pub fn find_property(&self, name: &str) -> Option<Property<'a>> {
76 self.properties().find(|p| p.name() == name)
77 }
78
79 pub fn find_property_str(&self, name: &str) -> Option<&'a str> {
81 let prop = self.find_property(name)?;
82
83 prop.as_str()
85 }
86
87 pub fn reg(&self) -> Option<RegIter<'a>> {
89 let prop = self.find_property("reg")?;
90 Some(RegIter::new(
91 prop.data().reader(),
92 self.context.parent_address_cells,
93 self.context.parent_size_cells,
94 ))
95 }
96
97 pub fn reg_array<const N: usize>(&self) -> heapless::Vec<RegInfo, N> {
99 let mut result = heapless::Vec::new();
100 if let Some(reg) = self.reg() {
101 for info in reg {
102 if result.push(info).is_err() {
103 break; }
105 }
106 }
107 result
108 }
109
110 fn is_chosen(&self) -> bool {
112 self.name == "chosen"
113 }
114
115 fn is_memory(&self) -> bool {
117 self.name.starts_with("memory")
118 }
119}
120
121fn write_indent(f: &mut fmt::Formatter<'_>, count: usize, ch: &str) -> fmt::Result {
123 for _ in 0..count {
124 write!(f, "{}", ch)?;
125 }
126 Ok(())
127}
128
129impl fmt::Display for NodeBase<'_> {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 write_indent(f, self.level, " ")?;
132 let name = if self.name.is_empty() { "/" } else { self.name };
133
134 writeln!(f, "{} {{", name)?;
135 for prop in self.properties() {
136 write_indent(f, self.level + 1, " ")?;
137 writeln!(f, "{};", prop)?;
138 }
139 write_indent(f, self.level, " ")?;
140 write!(f, "}}")
141 }
142}
143
144#[derive(Clone)]
150pub enum Node<'a> {
151 General(NodeBase<'a>),
153 Chosen(Chosen<'a>),
155 Memory(Memory<'a>),
157}
158
159impl<'a> Node<'a> {
160 pub fn as_base(&self) -> &NodeBase<'a> {
162 self.deref()
163 }
164
165 pub fn as_chosen(&self) -> Option<&Chosen<'a>> {
167 if let Node::Chosen(c) = self {
168 Some(c)
169 } else {
170 None
171 }
172 }
173
174 pub fn as_memory(&self) -> Option<&Memory<'a>> {
176 if let Node::Memory(m) = self {
177 Some(m)
178 } else {
179 None
180 }
181 }
182}
183
184impl<'a> From<NodeBase<'a>> for Node<'a> {
185 fn from(node: NodeBase<'a>) -> Self {
186 if node.is_chosen() {
187 Node::Chosen(Chosen::new(node))
188 } else if node.is_memory() {
189 Node::Memory(Memory::new(node))
190 } else {
191 Node::General(node)
192 }
193 }
194}
195
196impl<'a> Deref for Node<'a> {
197 type Target = NodeBase<'a>;
198
199 fn deref(&self) -> &Self::Target {
200 match self {
201 Node::General(n) => n,
202 Node::Chosen(c) => c.deref(),
203 Node::Memory(m) => m.deref(),
204 }
205 }
206}
207
208impl fmt::Display for Node<'_> {
209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210 self.as_base().fmt(f)
211 }
212}
213
214impl fmt::Debug for Node<'_> {
215 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216 match self {
217 Node::General(n) => f.debug_tuple("General").field(&n.name()).finish(),
218 Node::Chosen(c) => c.fmt(f),
219 Node::Memory(m) => m.fmt(f),
220 }
221 }
222}
223
224#[derive(Debug, Clone, Default)]
226pub(crate) struct ParsedProps {
227 pub address_cells: Option<u8>,
228 pub size_cells: Option<u8>,
229}
230
231#[derive(Debug, Clone, Copy, PartialEq, Eq)]
233pub(crate) enum OneNodeState {
234 Processing,
236 ChildBegin,
238 End,
240}
241
242pub(crate) struct OneNodeIter<'a> {
245 reader: Reader<'a>,
246 strings: Bytes<'a>,
247 state: OneNodeState,
248 level: usize,
249 context: NodeContext,
250 parsed_props: ParsedProps,
251}
252
253impl<'a> OneNodeIter<'a> {
254 pub fn new(reader: Reader<'a>, strings: Bytes<'a>, level: usize, context: NodeContext) -> Self {
255 Self {
256 reader,
257 strings,
258 state: OneNodeState::Processing,
259 level,
260 context,
261 parsed_props: ParsedProps::default(),
262 }
263 }
264
265 pub fn reader(&self) -> &Reader<'a> {
266 &self.reader
267 }
268
269 pub fn parsed_props(&self) -> &ParsedProps {
270 &self.parsed_props
271 }
272
273 pub fn read_node_name(&mut self) -> Result<NodeBase<'a>, FdtError> {
275 let name = self.read_cstr()?;
277
278 self.align4();
280
281 let data = self.reader.remain();
282
283 Ok(NodeBase {
284 name,
285 data,
286 strings: self.strings.clone(),
287 level: self.level,
288 address_cells: 2,
290 size_cells: 1,
291 context: self.context.clone(),
292 })
293 }
294
295 fn read_cstr(&mut self) -> Result<&'a str, FdtError> {
296 let bytes = self.reader.remain();
297 let cstr = CStr::from_bytes_until_nul(bytes.as_slice())?;
298 let s = cstr.to_str()?;
299 let _ = self.reader.read_bytes(s.len() + 1);
301 Ok(s)
302 }
303
304 fn align4(&mut self) {
305 let pos = self.reader.position();
306 let aligned = (pos + 3) & !3;
307 let skip = aligned - pos;
308 if skip > 0 {
309 let _ = self.reader.read_bytes(skip);
310 }
311 }
312
313 fn read_prop_name(&self, nameoff: u32) -> Result<&'a str, FdtError> {
315 let bytes = self.strings.slice(nameoff as usize..self.strings.len());
316 let cstr = CStr::from_bytes_until_nul(bytes.as_slice())?;
317 Ok(cstr.to_str()?)
318 }
319
320 fn read_u32_be(data: &[u8], offset: usize) -> u64 {
322 u32::from_be_bytes(data[offset..offset + 4].try_into().unwrap()) as u64
323 }
324
325 pub fn process(&mut self) -> Result<OneNodeState, FdtError> {
327 loop {
328 let token = self.reader.read_token()?;
329 match token {
330 Token::BeginNode => {
331 self.reader.backtrack(4);
333 self.state = OneNodeState::ChildBegin;
334 return Ok(OneNodeState::ChildBegin);
335 }
336 Token::EndNode => {
337 self.state = OneNodeState::End;
338 return Ok(OneNodeState::End);
339 }
340 Token::Prop => {
341 let len = self.reader.read_u32().ok_or(FdtError::BufferTooSmall {
343 pos: self.reader.position(),
344 })? as usize;
345
346 let nameoff = self.reader.read_u32().ok_or(FdtError::BufferTooSmall {
347 pos: self.reader.position(),
348 })?;
349
350 let prop_data = if len > 0 {
352 self.reader
353 .read_bytes(len)
354 .ok_or(FdtError::BufferTooSmall {
355 pos: self.reader.position(),
356 })?
357 } else {
358 Bytes::new(&[])
359 };
360
361 if let Ok(prop_name) = self.read_prop_name(nameoff) {
363 match prop_name {
364 "#address-cells" if len == 4 => {
365 self.parsed_props.address_cells =
366 Some(Self::read_u32_be(&prop_data, 0) as u8);
367 }
368 "#size-cells" if len == 4 => {
369 self.parsed_props.size_cells =
370 Some(Self::read_u32_be(&prop_data, 0) as u8);
371 }
372 _ => {}
373 }
374 }
375
376 self.align4();
378 }
379 Token::Nop => {
380 }
382 Token::End => {
383 self.state = OneNodeState::End;
385 return Ok(OneNodeState::End);
386 }
387 Token::Data(_) => {
388 return Err(FdtError::BufferTooSmall {
390 pos: self.reader.position(),
391 });
392 }
393 }
394 }
395 }
396}