blob: a80aa1b198d87ae77c4f65c88e5fc1a1ba2476d0 [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
17use crate::{AddrCells, SizeCells};
18use core::{mem::size_of, ops::Range, slice::ChunksExact};
19
20/// Iterator over cells of a DT property.
21#[derive(Debug)]
22pub struct CellIterator<'a> {
23 chunks: ChunksExact<'a, u8>,
24}
25
26impl<'a> CellIterator<'a> {
27 pub(crate) fn new(bytes: &'a [u8]) -> Self {
28 const CHUNK_SIZE: usize = size_of::<<CellIterator as Iterator>::Item>();
29
30 Self { chunks: bytes.chunks_exact(CHUNK_SIZE) }
31 }
32}
33
34impl<'a> Iterator for CellIterator<'a> {
35 type Item = u32;
36
37 fn next(&mut self) -> Option<Self::Item> {
38 Some(Self::Item::from_be_bytes(self.chunks.next()?.try_into().ok()?))
39 }
40}
41
42/// Iterator over a 'reg' property of a DT node.
43#[derive(Debug)]
44pub struct RegIterator<'a> {
45 cells: CellIterator<'a>,
46 addr_cells: AddrCells,
47 size_cells: SizeCells,
48}
49
50/// Represents a contiguous region within the address space defined by the parent bus.
51/// Commonly means the offsets and lengths of MMIO blocks, but may have a different meaning on some
52/// bus types. Addresses in the address space defined by the root node are CPU real addresses.
53#[derive(Copy, Clone, Debug)]
54pub struct Reg<T> {
55 /// Base address of the region.
56 pub addr: T,
57 /// Size of the region (optional).
58 pub size: Option<T>,
59}
60
61impl<'a> RegIterator<'a> {
62 pub(crate) fn new(
63 cells: CellIterator<'a>,
64 addr_cells: AddrCells,
65 size_cells: SizeCells,
66 ) -> Self {
67 Self { cells, addr_cells, size_cells }
68 }
69}
70
71impl<'a> Iterator for RegIterator<'a> {
72 type Item = Reg<u64>;
73
74 fn next(&mut self) -> Option<Self::Item> {
75 let make_double = |a, b| (u64::from(a) << 32) | u64::from(b);
76
77 let addr = match self.addr_cells {
78 AddrCells::Single => self.cells.next()?.into(),
79 AddrCells::Double => make_double(self.cells.next()?, self.cells.next()?),
80 };
81 // If the parent node specifies a value of 0 for #size-cells, 'size' shall be omitted.
82 let size = match self.size_cells {
83 SizeCells::None => None,
84 SizeCells::Single => Some(self.cells.next()?.into()),
85 SizeCells::Double => Some(make_double(self.cells.next()?, self.cells.next()?)),
86 };
87
88 Some(Self::Item { addr, size })
89 }
90}
91
92/// Iterator over the address ranges defined by the /memory/ node.
93#[derive(Debug)]
94pub struct MemRegIterator<'a> {
95 reg: RegIterator<'a>,
96}
97
98impl<'a> MemRegIterator<'a> {
99 pub(crate) fn new(reg: RegIterator<'a>) -> Self {
100 Self { reg }
101 }
102}
103
104impl<'a> Iterator for MemRegIterator<'a> {
105 type Item = Range<usize>;
106
107 fn next(&mut self) -> Option<Self::Item> {
108 let next = self.reg.next()?;
109 let addr = usize::try_from(next.addr).ok()?;
110 let size = usize::try_from(next.size?).ok()?;
111
112 Some(addr..addr.checked_add(size)?)
113 }
114}