1use core::fmt;
2use core::ops::Deref;
3use core::{ffi::CStr, fmt::Debug};
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> From<NodeBase<'a>> for Node<'a> {
160 fn from(node: NodeBase<'a>) -> Self {
161 if node.is_chosen() {
162 Node::Chosen(Chosen::new(node))
163 } else if node.is_memory() {
164 Node::Memory(Memory::new(node))
165 } else {
166 Node::General(node)
167 }
168 }
169}
170
171impl<'a> Deref for Node<'a> {
172 type Target = NodeBase<'a>;
173
174 fn deref(&self) -> &Self::Target {
175 match self {
176 Node::General(n) => n,
177 Node::Chosen(c) => c.deref(),
178 Node::Memory(m) => m.deref(),
179 }
180 }
181}
182
183impl fmt::Display for Node<'_> {
184 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185 Debug::fmt(self, f)
186 }
187}
188
189impl fmt::Debug for Node<'_> {
190 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191 match self {
192 Node::General(n) => f.debug_tuple("General").field(&n.name()).finish(),
193 Node::Chosen(c) => c.fmt(f),
194 Node::Memory(m) => m.fmt(f),
195 }
196 }
197}
198
199#[derive(Debug, Clone, Default)]
201pub(crate) struct ParsedProps {
202 pub address_cells: Option<u8>,
203 pub size_cells: Option<u8>,
204}
205
206#[derive(Debug, Clone, Copy, PartialEq, Eq)]
208pub(crate) enum OneNodeState {
209 Processing,
211 ChildBegin,
213 End,
215}
216
217pub(crate) struct OneNodeIter<'a> {
220 reader: Reader<'a>,
221 strings: Bytes<'a>,
222 state: OneNodeState,
223 level: usize,
224 context: NodeContext,
225 parsed_props: ParsedProps,
226}
227
228impl<'a> OneNodeIter<'a> {
229 pub fn new(reader: Reader<'a>, strings: Bytes<'a>, level: usize, context: NodeContext) -> Self {
230 Self {
231 reader,
232 strings,
233 state: OneNodeState::Processing,
234 level,
235 context,
236 parsed_props: ParsedProps::default(),
237 }
238 }
239
240 pub fn reader(&self) -> &Reader<'a> {
241 &self.reader
242 }
243
244 pub fn parsed_props(&self) -> &ParsedProps {
245 &self.parsed_props
246 }
247
248 pub fn read_node_name(&mut self) -> Result<NodeBase<'a>, FdtError> {
250 let name = self.read_cstr()?;
252
253 self.align4();
255
256 let data = self.reader.remain();
257
258 Ok(NodeBase {
259 name,
260 data,
261 strings: self.strings.clone(),
262 level: self.level,
263 address_cells: 2,
265 size_cells: 1,
266 context: self.context.clone(),
267 })
268 }
269
270 fn read_cstr(&mut self) -> Result<&'a str, FdtError> {
271 let bytes = self.reader.remain();
272 let cstr = CStr::from_bytes_until_nul(bytes.as_slice())?;
273 let s = cstr.to_str()?;
274 let _ = self.reader.read_bytes(s.len() + 1);
276 Ok(s)
277 }
278
279 fn align4(&mut self) {
280 let pos = self.reader.position();
281 let aligned = (pos + 3) & !3;
282 let skip = aligned - pos;
283 if skip > 0 {
284 let _ = self.reader.read_bytes(skip);
285 }
286 }
287
288 fn read_prop_name(&self, nameoff: u32) -> Result<&'a str, FdtError> {
290 let bytes = self.strings.slice(nameoff as usize..self.strings.len());
291 let cstr = CStr::from_bytes_until_nul(bytes.as_slice())?;
292 Ok(cstr.to_str()?)
293 }
294
295 fn read_u32_be(data: &[u8], offset: usize) -> u64 {
297 u32::from_be_bytes(data[offset..offset + 4].try_into().unwrap()) as u64
298 }
299
300 pub fn process(&mut self) -> Result<OneNodeState, FdtError> {
302 loop {
303 let token = self.reader.read_token()?;
304 match token {
305 Token::BeginNode => {
306 self.reader.backtrack(4);
308 self.state = OneNodeState::ChildBegin;
309 return Ok(OneNodeState::ChildBegin);
310 }
311 Token::EndNode => {
312 self.state = OneNodeState::End;
313 return Ok(OneNodeState::End);
314 }
315 Token::Prop => {
316 let len = self.reader.read_u32().ok_or(FdtError::BufferTooSmall {
318 pos: self.reader.position(),
319 })? as usize;
320
321 let nameoff = self.reader.read_u32().ok_or(FdtError::BufferTooSmall {
322 pos: self.reader.position(),
323 })?;
324
325 let prop_data = if len > 0 {
327 self.reader
328 .read_bytes(len)
329 .ok_or(FdtError::BufferTooSmall {
330 pos: self.reader.position(),
331 })?
332 } else {
333 Bytes::new(&[])
334 };
335
336 if let Ok(prop_name) = self.read_prop_name(nameoff) {
338 match prop_name {
339 "#address-cells" if len == 4 => {
340 self.parsed_props.address_cells =
341 Some(Self::read_u32_be(&prop_data, 0) as u8);
342 }
343 "#size-cells" if len == 4 => {
344 self.parsed_props.size_cells =
345 Some(Self::read_u32_be(&prop_data, 0) as u8);
346 }
347 _ => {}
348 }
349 }
350
351 self.align4();
353 }
354 Token::Nop => {
355 }
357 Token::End => {
358 self.state = OneNodeState::End;
360 return Ok(OneNodeState::End);
361 }
362 Token::Data(_) => {
363 return Err(FdtError::BufferTooSmall {
365 pos: self.reader.position(),
366 });
367 }
368 }
369 }
370 }
371}