blob: cb7afda4cea5fe8d4c191c43c2f95bec048ad64d [file] [log] [blame]
Andrew Walbran55ad01b2022-12-05 17:00:40 +00001// Copyright 2022, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Iterators over cells, and various layers on top of them.
16
Jaewan Kimfe06c852023-10-05 23:40:06 +090017use crate::Fdt;
Alice Wang474c0ee2023-09-14 12:52:33 +000018use crate::FdtError;
Jaewan Kimfe06c852023-10-05 23:40:06 +090019use crate::FdtNode;
Jaewan Kim72d10902023-10-12 21:59:26 +090020use crate::FdtProperty;
Andrew Walbran55ad01b2022-12-05 17:00:40 +000021use crate::{AddrCells, SizeCells};
Jaewan Kimfe06c852023-10-05 23:40:06 +090022use core::ffi::CStr;
Andrew Walbranb39e6922022-12-05 17:01:20 +000023use core::marker::PhantomData;
Andrew Walbran55ad01b2022-12-05 17:00:40 +000024use core::{mem::size_of, ops::Range, slice::ChunksExact};
25
Pierre-Clément Tosidf3037f2024-01-22 15:41:43 +000026use zerocopy::transmute;
27
Jaewan Kimfe06c852023-10-05 23:40:06 +090028/// Iterator over nodes sharing a same compatible string.
29pub struct CompatibleIterator<'a> {
30 node: FdtNode<'a>,
31 compatible: &'a CStr,
32}
33
34impl<'a> CompatibleIterator<'a> {
35 pub(crate) fn new(fdt: &'a Fdt, compatible: &'a CStr) -> Result<Self, FdtError> {
36 let node = fdt.root()?;
37 Ok(Self { node, compatible })
38 }
39}
40
41impl<'a> Iterator for CompatibleIterator<'a> {
42 type Item = FdtNode<'a>;
43
44 fn next(&mut self) -> Option<Self::Item> {
45 let next = self.node.next_compatible(self.compatible).ok()?;
46
47 if let Some(node) = next {
48 self.node = node;
49 }
50
51 next
52 }
53}
54
Andrew Walbran55ad01b2022-12-05 17:00:40 +000055/// Iterator over cells of a DT property.
56#[derive(Debug)]
57pub struct CellIterator<'a> {
58 chunks: ChunksExact<'a, u8>,
59}
60
61impl<'a> CellIterator<'a> {
62 pub(crate) fn new(bytes: &'a [u8]) -> Self {
63 const CHUNK_SIZE: usize = size_of::<<CellIterator as Iterator>::Item>();
64
65 Self { chunks: bytes.chunks_exact(CHUNK_SIZE) }
66 }
67}
68
69impl<'a> Iterator for CellIterator<'a> {
70 type Item = u32;
71
72 fn next(&mut self) -> Option<Self::Item> {
73 Some(Self::Item::from_be_bytes(self.chunks.next()?.try_into().ok()?))
74 }
75}
76
77/// Iterator over a 'reg' property of a DT node.
78#[derive(Debug)]
79pub struct RegIterator<'a> {
80 cells: CellIterator<'a>,
81 addr_cells: AddrCells,
82 size_cells: SizeCells,
83}
84
85/// Represents a contiguous region within the address space defined by the parent bus.
86/// Commonly means the offsets and lengths of MMIO blocks, but may have a different meaning on some
87/// bus types. Addresses in the address space defined by the root node are CPU real addresses.
88#[derive(Copy, Clone, Debug)]
89pub struct Reg<T> {
90 /// Base address of the region.
91 pub addr: T,
92 /// Size of the region (optional).
93 pub size: Option<T>,
94}
95
Alice Wang474c0ee2023-09-14 12:52:33 +000096impl<T: TryInto<usize>> TryFrom<Reg<T>> for Range<usize> {
97 type Error = FdtError;
98
99 fn try_from(reg: Reg<T>) -> Result<Self, Self::Error> {
100 let addr = to_usize(reg.addr)?;
101 let size = to_usize(reg.size.ok_or(FdtError::NotFound)?)?;
102 let end = addr.checked_add(size).ok_or(FdtError::BadValue)?;
103 Ok(addr..end)
104 }
105}
106
107fn to_usize<T: TryInto<usize>>(num: T) -> Result<usize, FdtError> {
108 num.try_into().map_err(|_| FdtError::BadValue)
109}
110
Andrew Walbran55ad01b2022-12-05 17:00:40 +0000111impl<'a> RegIterator<'a> {
112 pub(crate) fn new(
113 cells: CellIterator<'a>,
114 addr_cells: AddrCells,
115 size_cells: SizeCells,
116 ) -> Self {
117 Self { cells, addr_cells, size_cells }
118 }
119}
120
121impl<'a> Iterator for RegIterator<'a> {
122 type Item = Reg<u64>;
123
124 fn next(&mut self) -> Option<Self::Item> {
Andrew Walbranb39e6922022-12-05 17:01:20 +0000125 let addr = FromAddrCells::from_addr_cells(&mut self.cells, self.addr_cells)?;
Andrew Walbran55ad01b2022-12-05 17:00:40 +0000126 // If the parent node specifies a value of 0 for #size-cells, 'size' shall be omitted.
Andrew Walbranb39e6922022-12-05 17:01:20 +0000127 let size = if self.size_cells == SizeCells::None {
128 None
129 } else {
130 Some(FromSizeCells::from_size_cells(&mut self.cells, self.size_cells)?)
Andrew Walbran55ad01b2022-12-05 17:00:40 +0000131 };
132
133 Some(Self::Item { addr, size })
134 }
135}
136
Jiyong Park9c63cd12023-03-21 17:53:07 +0900137impl Reg<u64> {
138 const NUM_CELLS: usize = 2;
139 /// Converts addr and (optional) size to the format that is consumable by libfdt.
140 pub fn to_cells(
141 &self,
142 ) -> ([u8; Self::NUM_CELLS * size_of::<u32>()], Option<[u8; Self::NUM_CELLS * size_of::<u32>()]>)
143 {
Pierre-Clément Tosidf3037f2024-01-22 15:41:43 +0000144 let addr = transmute!([((self.addr >> 32) as u32).to_be(), (self.addr as u32).to_be()]);
145 let size =
146 self.size.map(|sz| transmute!([((sz >> 32) as u32).to_be(), (sz as u32).to_be()]));
147
Jiyong Park9c63cd12023-03-21 17:53:07 +0900148 (addr, size)
149 }
150}
151
Andrew Walbran55ad01b2022-12-05 17:00:40 +0000152/// Iterator over the address ranges defined by the /memory/ node.
153#[derive(Debug)]
154pub struct MemRegIterator<'a> {
155 reg: RegIterator<'a>,
156}
157
158impl<'a> MemRegIterator<'a> {
159 pub(crate) fn new(reg: RegIterator<'a>) -> Self {
160 Self { reg }
161 }
162}
163
164impl<'a> Iterator for MemRegIterator<'a> {
165 type Item = Range<usize>;
166
167 fn next(&mut self) -> Option<Self::Item> {
168 let next = self.reg.next()?;
169 let addr = usize::try_from(next.addr).ok()?;
170 let size = usize::try_from(next.size?).ok()?;
171
172 Some(addr..addr.checked_add(size)?)
173 }
174}
Andrew Walbranb39e6922022-12-05 17:01:20 +0000175
176/// Iterator over the 'ranges' property of a DT node.
177#[derive(Debug)]
178pub struct RangesIterator<'a, A, P, S> {
179 cells: CellIterator<'a>,
180 addr_cells: AddrCells,
181 parent_addr_cells: AddrCells,
182 size_cells: SizeCells,
183 _addr: PhantomData<A>,
184 _parent_addr: PhantomData<P>,
185 _size: PhantomData<S>,
186}
187
188/// An address range from the 'ranges' property of a DT node.
Jiyong Park6a8789a2023-03-21 14:50:59 +0900189#[derive(Clone, Debug, Default)]
Andrew Walbranb39e6922022-12-05 17:01:20 +0000190pub struct AddressRange<A, P, S> {
191 /// The physical address of the range within the child bus's address space.
192 pub addr: A,
193 /// The physical address of the range in the parent bus's address space.
194 pub parent_addr: P,
195 /// The size of the range in the child's address space.
196 pub size: S,
197}
198
199impl<'a, A, P, S> RangesIterator<'a, A, P, S> {
200 pub(crate) fn new(
201 cells: CellIterator<'a>,
202 addr_cells: AddrCells,
203 parent_addr_cells: AddrCells,
204 size_cells: SizeCells,
205 ) -> Self {
206 Self {
207 cells,
208 addr_cells,
209 parent_addr_cells,
210 size_cells,
211 _addr: Default::default(),
212 _parent_addr: Default::default(),
213 _size: Default::default(),
214 }
215 }
216}
217
218impl<'a, A: FromAddrCells, P: FromAddrCells, S: FromSizeCells> Iterator
219 for RangesIterator<'a, A, P, S>
220{
221 type Item = AddressRange<A, P, S>;
222
223 fn next(&mut self) -> Option<Self::Item> {
224 let addr = FromAddrCells::from_addr_cells(&mut self.cells, self.addr_cells)?;
225 let parent_addr = FromAddrCells::from_addr_cells(&mut self.cells, self.parent_addr_cells)?;
226 let size = FromSizeCells::from_size_cells(&mut self.cells, self.size_cells)?;
227 Some(AddressRange { addr, parent_addr, size })
228 }
229}
230
231trait FromAddrCells: Sized {
232 fn from_addr_cells(cells: &mut CellIterator, cell_count: AddrCells) -> Option<Self>;
233}
234
235impl FromAddrCells for u64 {
236 fn from_addr_cells(cells: &mut CellIterator, cell_count: AddrCells) -> Option<Self> {
237 Some(match cell_count {
238 AddrCells::Single => cells.next()?.into(),
239 AddrCells::Double => (cells.next()? as Self) << 32 | cells.next()? as Self,
240 _ => panic!("Invalid addr_cells {:?} for u64", cell_count),
241 })
242 }
243}
244
Andrew Walbran0d8b54d2022-12-08 16:32:33 +0000245impl FromAddrCells for (u32, u64) {
Andrew Walbranb39e6922022-12-05 17:01:20 +0000246 fn from_addr_cells(cells: &mut CellIterator, cell_count: AddrCells) -> Option<Self> {
247 Some(match cell_count {
Andrew Walbranb39e6922022-12-05 17:01:20 +0000248 AddrCells::Triple => {
Andrew Walbran0d8b54d2022-12-08 16:32:33 +0000249 (cells.next()?, (cells.next()? as u64) << 32 | cells.next()? as u64)
Andrew Walbranb39e6922022-12-05 17:01:20 +0000250 }
Andrew Walbran0d8b54d2022-12-08 16:32:33 +0000251 _ => panic!("Invalid addr_cells {:?} for (u32, u64)", cell_count),
Andrew Walbranb39e6922022-12-05 17:01:20 +0000252 })
253 }
254}
255
256trait FromSizeCells: Sized {
257 fn from_size_cells(cells: &mut CellIterator, cell_count: SizeCells) -> Option<Self>;
258}
259
260impl FromSizeCells for u64 {
261 fn from_size_cells(cells: &mut CellIterator, cell_count: SizeCells) -> Option<Self> {
262 Some(match cell_count {
263 SizeCells::Single => cells.next()?.into(),
264 SizeCells::Double => (cells.next()? as Self) << 32 | cells.next()? as Self,
265 _ => panic!("Invalid size_cells {:?} for u64", cell_count),
266 })
267 }
268}
Jiyong Park9c63cd12023-03-21 17:53:07 +0900269
270impl AddressRange<(u32, u64), u64, u64> {
271 const SIZE_CELLS: usize = 7;
272 /// Converts to the format that is consumable by libfdt
273 pub fn to_cells(&self) -> [u8; Self::SIZE_CELLS * size_of::<u32>()] {
274 let buf = [
275 self.addr.0.to_be(),
276 ((self.addr.1 >> 32) as u32).to_be(),
277 (self.addr.1 as u32).to_be(),
278 ((self.parent_addr >> 32) as u32).to_be(),
279 (self.parent_addr as u32).to_be(),
280 ((self.size >> 32) as u32).to_be(),
281 (self.size as u32).to_be(),
282 ];
Pierre-Clément Tosidf3037f2024-01-22 15:41:43 +0000283
284 transmute!(buf)
Jiyong Park9c63cd12023-03-21 17:53:07 +0900285 }
286}
Jaewan Kimbc828d72023-09-19 15:52:08 +0900287
288/// Iterator over subnodes
289#[derive(Debug)]
290pub struct SubnodeIterator<'a> {
291 subnode: Option<FdtNode<'a>>,
292}
293
294impl<'a> SubnodeIterator<'a> {
Jaewan Kim4a34b0d2024-01-19 13:17:47 +0900295 pub(crate) fn new(node: &FdtNode<'a>) -> Result<Self, FdtError> {
Jaewan Kimbc828d72023-09-19 15:52:08 +0900296 let subnode = node.first_subnode()?;
297
298 Ok(Self { subnode })
299 }
300}
301
302impl<'a> Iterator for SubnodeIterator<'a> {
303 type Item = FdtNode<'a>;
304
305 fn next(&mut self) -> Option<Self::Item> {
306 let res = self.subnode;
307
308 self.subnode = self.subnode.and_then(|node| node.next_subnode().ok()?);
309
310 res
311 }
312}
Jaewan Kim72d10902023-10-12 21:59:26 +0900313
Jaewan Kimc9e14112023-12-04 17:05:27 +0900314/// Iterator over descendants
315#[derive(Debug)]
316pub struct DescendantsIterator<'a> {
317 node: Option<(FdtNode<'a>, usize)>,
318}
319
320impl<'a> DescendantsIterator<'a> {
Jaewan Kim1eab7232024-01-04 09:46:16 +0900321 pub(crate) fn new(node: &FdtNode<'a>) -> Self {
Jaewan Kimc9e14112023-12-04 17:05:27 +0900322 Self { node: Some((*node, 0)) }
323 }
324}
325
326impl<'a> Iterator for DescendantsIterator<'a> {
327 type Item = (FdtNode<'a>, usize);
328
329 fn next(&mut self) -> Option<Self::Item> {
330 let (node, depth) = self.node?;
331 self.node = node.next_node(depth).ok().flatten().filter(|(_, depth)| *depth > 0);
332
333 self.node
334 }
335}
336
Jaewan Kim72d10902023-10-12 21:59:26 +0900337/// Iterator over properties
338#[derive(Debug)]
339pub struct PropertyIterator<'a> {
340 prop: Option<FdtProperty<'a>>,
341}
342
343impl<'a> PropertyIterator<'a> {
344 pub(crate) fn new(node: &'a FdtNode) -> Result<Self, FdtError> {
345 let prop = node.first_property()?;
346
347 Ok(Self { prop })
348 }
349}
350
351impl<'a> Iterator for PropertyIterator<'a> {
352 type Item = FdtProperty<'a>;
353
354 fn next(&mut self) -> Option<Self::Item> {
355 let res = self.prop;
356
357 self.prop = res?.next_property().ok()?;
358
359 res
360 }
361}