Andrew Walbran | 55ad01b | 2022-12-05 17:00:40 +0000 | [diff] [blame] | 1 | // 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 Kim | fe06c85 | 2023-10-05 23:40:06 +0900 | [diff] [blame] | 17 | use crate::Fdt; |
Alice Wang | 474c0ee | 2023-09-14 12:52:33 +0000 | [diff] [blame] | 18 | use crate::FdtError; |
Jaewan Kim | fe06c85 | 2023-10-05 23:40:06 +0900 | [diff] [blame] | 19 | use crate::FdtNode; |
Jaewan Kim | 72d1090 | 2023-10-12 21:59:26 +0900 | [diff] [blame] | 20 | use crate::FdtProperty; |
Andrew Walbran | 55ad01b | 2022-12-05 17:00:40 +0000 | [diff] [blame] | 21 | use crate::{AddrCells, SizeCells}; |
Jaewan Kim | fe06c85 | 2023-10-05 23:40:06 +0900 | [diff] [blame] | 22 | use core::ffi::CStr; |
Andrew Walbran | b39e692 | 2022-12-05 17:01:20 +0000 | [diff] [blame] | 23 | use core::marker::PhantomData; |
Andrew Walbran | 55ad01b | 2022-12-05 17:00:40 +0000 | [diff] [blame] | 24 | use core::{mem::size_of, ops::Range, slice::ChunksExact}; |
| 25 | |
Pierre-Clément Tosi | df3037f | 2024-01-22 15:41:43 +0000 | [diff] [blame] | 26 | use zerocopy::transmute; |
| 27 | |
Jaewan Kim | fe06c85 | 2023-10-05 23:40:06 +0900 | [diff] [blame] | 28 | /// Iterator over nodes sharing a same compatible string. |
| 29 | pub struct CompatibleIterator<'a> { |
| 30 | node: FdtNode<'a>, |
| 31 | compatible: &'a CStr, |
| 32 | } |
| 33 | |
| 34 | impl<'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 | |
| 41 | impl<'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 Walbran | 55ad01b | 2022-12-05 17:00:40 +0000 | [diff] [blame] | 55 | /// Iterator over cells of a DT property. |
| 56 | #[derive(Debug)] |
| 57 | pub struct CellIterator<'a> { |
| 58 | chunks: ChunksExact<'a, u8>, |
| 59 | } |
| 60 | |
| 61 | impl<'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 | |
| 69 | impl<'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)] |
| 79 | pub 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)] |
| 89 | pub 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 Wang | 474c0ee | 2023-09-14 12:52:33 +0000 | [diff] [blame] | 96 | impl<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 | |
| 107 | fn to_usize<T: TryInto<usize>>(num: T) -> Result<usize, FdtError> { |
| 108 | num.try_into().map_err(|_| FdtError::BadValue) |
| 109 | } |
| 110 | |
Andrew Walbran | 55ad01b | 2022-12-05 17:00:40 +0000 | [diff] [blame] | 111 | impl<'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 | |
| 121 | impl<'a> Iterator for RegIterator<'a> { |
| 122 | type Item = Reg<u64>; |
| 123 | |
| 124 | fn next(&mut self) -> Option<Self::Item> { |
Andrew Walbran | b39e692 | 2022-12-05 17:01:20 +0000 | [diff] [blame] | 125 | let addr = FromAddrCells::from_addr_cells(&mut self.cells, self.addr_cells)?; |
Andrew Walbran | 55ad01b | 2022-12-05 17:00:40 +0000 | [diff] [blame] | 126 | // If the parent node specifies a value of 0 for #size-cells, 'size' shall be omitted. |
Andrew Walbran | b39e692 | 2022-12-05 17:01:20 +0000 | [diff] [blame] | 127 | 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 Walbran | 55ad01b | 2022-12-05 17:00:40 +0000 | [diff] [blame] | 131 | }; |
| 132 | |
| 133 | Some(Self::Item { addr, size }) |
| 134 | } |
| 135 | } |
| 136 | |
Jiyong Park | 9c63cd1 | 2023-03-21 17:53:07 +0900 | [diff] [blame] | 137 | impl 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 Tosi | df3037f | 2024-01-22 15:41:43 +0000 | [diff] [blame] | 144 | 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 Park | 9c63cd1 | 2023-03-21 17:53:07 +0900 | [diff] [blame] | 148 | (addr, size) |
| 149 | } |
| 150 | } |
| 151 | |
Andrew Walbran | 55ad01b | 2022-12-05 17:00:40 +0000 | [diff] [blame] | 152 | /// Iterator over the address ranges defined by the /memory/ node. |
| 153 | #[derive(Debug)] |
| 154 | pub struct MemRegIterator<'a> { |
| 155 | reg: RegIterator<'a>, |
| 156 | } |
| 157 | |
| 158 | impl<'a> MemRegIterator<'a> { |
| 159 | pub(crate) fn new(reg: RegIterator<'a>) -> Self { |
| 160 | Self { reg } |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | impl<'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 Walbran | b39e692 | 2022-12-05 17:01:20 +0000 | [diff] [blame] | 175 | |
| 176 | /// Iterator over the 'ranges' property of a DT node. |
| 177 | #[derive(Debug)] |
| 178 | pub 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 Park | 6a8789a | 2023-03-21 14:50:59 +0900 | [diff] [blame] | 189 | #[derive(Clone, Debug, Default)] |
Andrew Walbran | b39e692 | 2022-12-05 17:01:20 +0000 | [diff] [blame] | 190 | pub 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 | |
| 199 | impl<'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 | |
| 218 | impl<'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 | |
| 231 | trait FromAddrCells: Sized { |
| 232 | fn from_addr_cells(cells: &mut CellIterator, cell_count: AddrCells) -> Option<Self>; |
| 233 | } |
| 234 | |
| 235 | impl 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 Walbran | 0d8b54d | 2022-12-08 16:32:33 +0000 | [diff] [blame] | 245 | impl FromAddrCells for (u32, u64) { |
Andrew Walbran | b39e692 | 2022-12-05 17:01:20 +0000 | [diff] [blame] | 246 | fn from_addr_cells(cells: &mut CellIterator, cell_count: AddrCells) -> Option<Self> { |
| 247 | Some(match cell_count { |
Andrew Walbran | b39e692 | 2022-12-05 17:01:20 +0000 | [diff] [blame] | 248 | AddrCells::Triple => { |
Andrew Walbran | 0d8b54d | 2022-12-08 16:32:33 +0000 | [diff] [blame] | 249 | (cells.next()?, (cells.next()? as u64) << 32 | cells.next()? as u64) |
Andrew Walbran | b39e692 | 2022-12-05 17:01:20 +0000 | [diff] [blame] | 250 | } |
Andrew Walbran | 0d8b54d | 2022-12-08 16:32:33 +0000 | [diff] [blame] | 251 | _ => panic!("Invalid addr_cells {:?} for (u32, u64)", cell_count), |
Andrew Walbran | b39e692 | 2022-12-05 17:01:20 +0000 | [diff] [blame] | 252 | }) |
| 253 | } |
| 254 | } |
| 255 | |
| 256 | trait FromSizeCells: Sized { |
| 257 | fn from_size_cells(cells: &mut CellIterator, cell_count: SizeCells) -> Option<Self>; |
| 258 | } |
| 259 | |
| 260 | impl 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 Park | 9c63cd1 | 2023-03-21 17:53:07 +0900 | [diff] [blame] | 269 | |
| 270 | impl 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 Tosi | df3037f | 2024-01-22 15:41:43 +0000 | [diff] [blame] | 283 | |
| 284 | transmute!(buf) |
Jiyong Park | 9c63cd1 | 2023-03-21 17:53:07 +0900 | [diff] [blame] | 285 | } |
| 286 | } |
Jaewan Kim | bc828d7 | 2023-09-19 15:52:08 +0900 | [diff] [blame] | 287 | |
| 288 | /// Iterator over subnodes |
| 289 | #[derive(Debug)] |
| 290 | pub struct SubnodeIterator<'a> { |
| 291 | subnode: Option<FdtNode<'a>>, |
| 292 | } |
| 293 | |
| 294 | impl<'a> SubnodeIterator<'a> { |
Jaewan Kim | 4a34b0d | 2024-01-19 13:17:47 +0900 | [diff] [blame] | 295 | pub(crate) fn new(node: &FdtNode<'a>) -> Result<Self, FdtError> { |
Jaewan Kim | bc828d7 | 2023-09-19 15:52:08 +0900 | [diff] [blame] | 296 | let subnode = node.first_subnode()?; |
| 297 | |
| 298 | Ok(Self { subnode }) |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | impl<'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 Kim | 72d1090 | 2023-10-12 21:59:26 +0900 | [diff] [blame] | 313 | |
Jaewan Kim | c9e1411 | 2023-12-04 17:05:27 +0900 | [diff] [blame] | 314 | /// Iterator over descendants |
| 315 | #[derive(Debug)] |
| 316 | pub struct DescendantsIterator<'a> { |
| 317 | node: Option<(FdtNode<'a>, usize)>, |
| 318 | } |
| 319 | |
| 320 | impl<'a> DescendantsIterator<'a> { |
Jaewan Kim | 1eab723 | 2024-01-04 09:46:16 +0900 | [diff] [blame] | 321 | pub(crate) fn new(node: &FdtNode<'a>) -> Self { |
Jaewan Kim | c9e1411 | 2023-12-04 17:05:27 +0900 | [diff] [blame] | 322 | Self { node: Some((*node, 0)) } |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | impl<'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 Kim | 72d1090 | 2023-10-12 21:59:26 +0900 | [diff] [blame] | 337 | /// Iterator over properties |
| 338 | #[derive(Debug)] |
| 339 | pub struct PropertyIterator<'a> { |
| 340 | prop: Option<FdtProperty<'a>>, |
| 341 | } |
| 342 | |
| 343 | impl<'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 | |
| 351 | impl<'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 | } |