1use core::marker::PhantomData;
3use core::mem::size_of;
4use core::num::NonZeroUsize;
5use core::str::from_utf8;
6
7use crate::prelude::*;
8
9use crate::base::parse::{next_devtree_token, ParsedTok};
10use crate::base::{DevTree, DevTreeItem, DevTreeNode, DevTreeProp};
11use crate::error::{DevTreeError, Result};
12use crate::spec::fdt_reserve_entry;
13
14pub use super::parse::DevTreeParseIter;
16pub use crate::common::prop::StringPropIter;
17
18use fallible_iterator::FallibleIterator;
19
20#[derive(Clone)]
22pub struct DevTreeReserveEntryIter<'a, 'dt: 'a> {
23 offset: usize,
24 fdt: &'a DevTree<'dt>,
25}
26
27#[repr(transparent)]
28pub struct DevTreeReserveEntryRef<'dt>(*const fdt_reserve_entry, PhantomData<DevTree<'dt>>);
29
30impl<'dt> DevTreeReserveEntryRef<'dt> {
31 unsafe fn read_unaligned(&self) -> fdt_reserve_entry {
32 self.0.read_unaligned()
33 }
34}
35
36impl<'a, 'dt: 'a> DevTreeReserveEntryIter<'a, 'dt> {
37 pub(crate) fn new(fdt: &'a DevTree<'dt>) -> Self {
38 Self {
39 offset: fdt.off_mem_rsvmap(),
40 fdt,
41 }
42 }
43
44 unsafe fn ptr(&'a self) -> Result<DevTreeReserveEntryRef<'dt>> {
46 Ok(DevTreeReserveEntryRef(
47 self.fdt.ptr_at(self.offset)?,
48 PhantomData,
49 ))
50 }
51}
52
53impl<'a, 'dt: 'a> Iterator for DevTreeReserveEntryIter<'a, 'dt> {
54 type Item = DevTreeReserveEntryRef<'dt>;
55 fn next(&mut self) -> Option<Self::Item> {
56 let next_offset = size_of::<fdt_reserve_entry>() + self.offset;
57 if next_offset > self.fdt.totalsize() {
58 None
59 } else {
60 unsafe {
66 let res = self.ptr().unwrap();
67 let data: fdt_reserve_entry = res.read_unaligned();
68 if data.address == 0.into() && data.size == 0.into() {
69 return None;
70 }
71 self.offset = next_offset;
72 Some(res)
73 }
74 }
75 }
76}
77
78#[derive(Clone, PartialEq)]
80pub struct DevTreeIter<'a, 'dt: 'a> {
81 current_prop_parent_off: Option<NonZeroUsize>,
88
89 offset: usize,
91 pub(crate) fdt: &'a DevTree<'dt>,
92}
93
94#[derive(Clone, PartialEq)]
95pub struct DevTreeNodeIter<'a, 'dt: 'a>(pub DevTreeIter<'a, 'dt>);
96impl<'a, 'dt: 'a> FallibleIterator for DevTreeNodeIter<'a, 'dt> {
97 type Item = DevTreeNode<'a, 'dt>;
98 type Error = DevTreeError;
99 fn next(&mut self) -> Result<Option<Self::Item>> {
100 self.0.next_node()
101 }
102}
103
104#[derive(Clone, PartialEq)]
105pub struct DevTreePropIter<'a, 'dt: 'a>(pub DevTreeIter<'a, 'dt>);
106impl<'a, 'dt: 'a> FallibleIterator for DevTreePropIter<'a, 'dt> {
107 type Error = DevTreeError;
108 type Item = DevTreeProp<'a, 'dt>;
109 fn next(&mut self) -> Result<Option<Self::Item>> {
110 self.0.next_prop()
111 }
112}
113
114#[derive(Clone, PartialEq)]
115pub struct DevTreeNodePropIter<'a, 'dt: 'a>(pub DevTreeIter<'a, 'dt>);
116impl<'a, 'dt: 'a> FallibleIterator for DevTreeNodePropIter<'a, 'dt> {
117 type Error = DevTreeError;
118 type Item = DevTreeProp<'a, 'dt>;
119 fn next(&mut self) -> Result<Option<Self::Item>> {
120 self.0.next_node_prop()
121 }
122}
123
124#[derive(Clone, PartialEq)]
125pub struct DevTreeCompatibleNodeIter<'s, 'a, 'dt: 'a> {
126 pub iter: DevTreeIter<'a, 'dt>,
127 pub string: &'s str,
128}
129impl<'s, 'a, 'dt: 'a> FallibleIterator for DevTreeCompatibleNodeIter<'s, 'a, 'dt> {
130 type Error = DevTreeError;
131 type Item = DevTreeNode<'a, 'dt>;
132 fn next(&mut self) -> Result<Option<Self::Item>> {
133 self.iter.next_compatible_node(self.string)
134 }
135}
136
137impl<'a, 'dt: 'a> DevTreeIter<'a, 'dt> {
138 pub fn new(fdt: &'a DevTree<'dt>) -> Self {
139 Self {
140 offset: fdt.off_dt_struct(),
141 current_prop_parent_off: None,
142 fdt,
143 }
144 }
145
146 fn current_node_itr(&self) -> Option<DevTreeIter<'a, 'dt>> {
147 self.current_prop_parent_off.map(|offset| DevTreeIter {
148 fdt: self.fdt,
149 current_prop_parent_off: Some(offset),
150 offset: offset.get(),
151 })
152 }
153
154 pub fn last_node(mut self) -> Option<DevTreeNode<'a, 'dt>> {
155 if let Some(off) = self.current_prop_parent_off.take() {
156 self.offset = off.get();
157 return self.next_node().unwrap();
158 }
159 None
160 }
161
162 pub fn next_item(&mut self) -> Result<Option<DevTreeItem<'a, 'dt>>> {
163 loop {
164 let old_offset = self.offset;
165 let res = unsafe { next_devtree_token(self.fdt.buf(), &mut self.offset)? };
167
168 match res {
169 Some(ParsedTok::BeginNode(node)) => {
170 self.current_prop_parent_off =
171 unsafe { Some(NonZeroUsize::new_unchecked(old_offset)) };
172 return Ok(Some(DevTreeItem::Node(DevTreeNode {
173 parse_iter: self.clone(),
174 name: from_utf8(node.name).map_err(|e| e.into()),
175 })));
176 }
177 Some(ParsedTok::Prop(prop)) => {
178 let prev_node = match self.current_node_itr() {
180 Some(n) => n,
181 None => return Err(DevTreeError::ParseError),
182 };
183
184 return Ok(Some(DevTreeItem::Prop(DevTreeProp::new(
185 prev_node,
186 prop.prop_buf,
187 prop.name_offset,
188 ))));
189 }
190 Some(ParsedTok::EndNode) => {
191 self.current_prop_parent_off = None;
194 }
195 Some(_) => continue,
196 None => return Ok(None),
197 }
198 }
199 }
200
201 pub fn next_prop(&mut self) -> Result<Option<DevTreeProp<'a, 'dt>>> {
202 loop {
203 match self.next() {
204 Ok(Some(DevTreeItem::Prop(p))) => return Ok(Some(p)),
205 Ok(Some(_n)) => continue,
206 Ok(None) => return Ok(None),
207 Err(e) => return Err(e),
208 }
209 }
210 }
211
212 pub fn next_node(&mut self) -> Result<Option<DevTreeNode<'a, 'dt>>> {
213 loop {
214 match self.next() {
215 Ok(Some(DevTreeItem::Node(n))) => return Ok(Some(n)),
216 Ok(Some(_p)) => continue,
217 Ok(None) => return Ok(None),
218 Err(e) => return Err(e),
219 }
220 }
221 }
222
223 pub fn next_node_prop(&mut self) -> Result<Option<DevTreeProp<'a, 'dt>>> {
224 match self.next() {
225 Ok(Some(item)) => Ok(item.prop()),
227 Ok(None) => Ok(None),
228 Err(e) => Err(e),
229 }
230 }
231
232 pub fn next_compatible_node(&mut self, string: &str) -> Result<Option<DevTreeNode<'a, 'dt>>> {
233 self.next_node().and_then(|_| {
235 loop {
238 match self.next_prop() {
239 Ok(Some(prop)) => {
240 if prop.name()? == "compatible" {
241 let mut candidates = prop.iter_str();
242 while let Some(s) = candidates.next()? {
243 if s.eq(string) {
244 return Ok(Some(prop.node()));
245 }
246 }
247 }
248 continue;
249 }
250 Ok(None) => return Ok(None),
251 Err(e) => return Err(e),
252 }
253 }
254 })
255 }
256}
257
258impl<'a, 'dt: 'a> FallibleIterator for DevTreeIter<'a, 'dt> {
259 type Error = DevTreeError;
260 type Item = DevTreeItem<'a, 'dt>;
261
262 fn next(&mut self) -> Result<Option<Self::Item>> {
263 self.next_item()
264 }
265}