Skip to content

Commit 4e25df1

Browse files
authored
feat: getters and types for standard reg, ranges and dma-ranges props (#19)
* Pass Fdt by value rather than reference. It is Copy and only contains a single reference, so there's no point passing it by reference. This also means that the lifetimes of things returned from getters are only tied to the underlying slice, not the Fdt itself, which may be more convenient. * Add getter for standard `reg` property. This requires keeping track of the #address-cells and #size-cells of the parent node. * Factor out Cells type for Reg. * Make as_prop_encoded_array return array of Cells. This saves work splitting the result in the caller. * Add type and getters for standard ranges and dma-ranges properties. * Fix test build for Rust 1.88. * Fixes from code review.
1 parent 3fd1f18 commit 4e25df1

File tree

12 files changed

+514
-67
lines changed

12 files changed

+514
-67
lines changed

src/error.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ pub enum FdtError {
3535
/// The number of 4 byte cells expected in each element of the array.
3636
chunk: usize,
3737
},
38+
/// Tried to convert part of a prop-encoded-array property to a type which
39+
/// was too small.
40+
#[error("prop-encoded-array field too big for chosen type ({cells} cells)")]
41+
TooManyCells {
42+
/// The number of (32-bit) cells in the field.
43+
cells: usize,
44+
},
3845
}
3946

4047
/// An error that can occur when parsing a device tree.

src/fdt/mod.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use zerocopy::byteorder::big_endian;
2626
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
2727

2828
pub use self::node::FdtNode;
29-
pub use self::property::FdtProperty;
29+
pub use self::property::{Cells, FdtProperty};
3030
use crate::error::{FdtErrorKind, FdtParseError};
3131
use crate::memreserve::MemoryReservation;
3232

@@ -240,7 +240,7 @@ impl<'a> Fdt<'a> {
240240
Fdt::new(slice)
241241
}
242242

243-
fn validate_header(&self) -> Result<(), FdtParseError> {
243+
fn validate_header(self) -> Result<(), FdtParseError> {
244244
let header = self.header();
245245
let data = &self.data;
246246

@@ -291,40 +291,40 @@ impl<'a> Fdt<'a> {
291291
}
292292

293293
/// Returns the header of the device tree.
294-
pub(crate) fn header(&self) -> &FdtHeader {
294+
pub(crate) fn header(self) -> &'a FdtHeader {
295295
let (header, _remaining_bytes) = FdtHeader::ref_from_prefix(self.data)
296296
.expect("new() checks if the slice is at least as big as the header");
297297
header
298298
}
299299

300300
/// Returns the underlying data slice of the FDT.
301301
#[must_use]
302-
pub fn data(&self) -> &'a [u8] {
302+
pub fn data(self) -> &'a [u8] {
303303
self.data
304304
}
305305

306306
/// Returns the version of the FDT.
307307
#[must_use]
308-
pub fn version(&self) -> u32 {
308+
pub fn version(self) -> u32 {
309309
self.header().version()
310310
}
311311

312312
/// Returns the last compatible version of the FDT.
313313
#[must_use]
314-
pub fn last_comp_version(&self) -> u32 {
314+
pub fn last_comp_version(self) -> u32 {
315315
self.header().last_comp_version()
316316
}
317317

318318
/// Returns the physical ID of the boot CPU.
319319
#[must_use]
320-
pub fn boot_cpuid_phys(&self) -> u32 {
320+
pub fn boot_cpuid_phys(self) -> u32 {
321321
self.header().boot_cpuid_phys()
322322
}
323323

324324
/// Returns an iterator over the memory reservation block.
325325
pub fn memory_reservations(
326-
&self,
327-
) -> impl Iterator<Item = Result<MemoryReservation, FdtParseError>> + '_ {
326+
self,
327+
) -> impl Iterator<Item = Result<MemoryReservation, FdtParseError>> + 'a {
328328
let mut offset = self.header().off_mem_rsvmap() as usize;
329329
core::iter::from_fn(move || {
330330
if offset >= self.header().off_dt_struct() as usize {
@@ -366,7 +366,7 @@ impl<'a> Fdt<'a> {
366366
/// let root = fdt.root().unwrap();
367367
/// assert_eq!(root.name().unwrap(), "");
368368
/// ```
369-
pub fn root(&self) -> Result<FdtNode<'_>, FdtParseError> {
369+
pub fn root(self) -> Result<FdtNode<'a>, FdtParseError> {
370370
let offset = self.header().off_dt_struct() as usize;
371371
let token = self.read_token(offset)?;
372372
if token != FdtToken::BeginNode {
@@ -375,7 +375,7 @@ impl<'a> Fdt<'a> {
375375
offset,
376376
));
377377
}
378-
Ok(FdtNode { fdt: self, offset })
378+
Ok(FdtNode::new(self, offset))
379379
}
380380

381381
/// Finds a node by its path.
@@ -424,7 +424,7 @@ impl<'a> Fdt<'a> {
424424
/// let node = fdt.find_node("/child2@42").unwrap().unwrap();
425425
/// assert_eq!(node.name().unwrap(), "child2@42");
426426
/// ```
427-
pub fn find_node(&self, path: &str) -> Result<Option<FdtNode<'_>>, FdtParseError> {
427+
pub fn find_node(self, path: &str) -> Result<Option<FdtNode<'a>>, FdtParseError> {
428428
if !path.starts_with('/') {
429429
return Ok(None);
430430
}
@@ -441,15 +441,15 @@ impl<'a> Fdt<'a> {
441441
Ok(Some(current_node))
442442
}
443443

444-
pub(crate) fn read_token(&self, offset: usize) -> Result<FdtToken, FdtParseError> {
444+
pub(crate) fn read_token(self, offset: usize) -> Result<FdtToken, FdtParseError> {
445445
let val = big_endian::U32::ref_from_prefix(&self.data[offset..])
446446
.map(|(val, _)| val.get())
447447
.map_err(|_e| FdtParseError::new(FdtErrorKind::InvalidLength, offset))?;
448448
FdtToken::try_from(val).map_err(|t| FdtParseError::new(FdtErrorKind::BadToken(t), offset))
449449
}
450450

451451
/// Returns a string from the string block.
452-
pub(crate) fn string(&self, string_block_offset: usize) -> Result<&'a str, FdtParseError> {
452+
pub(crate) fn string(self, string_block_offset: usize) -> Result<&'a str, FdtParseError> {
453453
let header = self.header();
454454
let str_block_start = header.off_dt_strings() as usize;
455455
let str_block_size = header.size_dt_strings() as usize;
@@ -465,7 +465,7 @@ impl<'a> Fdt<'a> {
465465

466466
/// Returns a NUL-terminated string from a given offset.
467467
pub(crate) fn string_at_offset(
468-
&self,
468+
self,
469469
offset: usize,
470470
end: Option<usize>,
471471
) -> Result<&'a str, FdtParseError> {
@@ -481,7 +481,7 @@ impl<'a> Fdt<'a> {
481481
}
482482
}
483483

484-
pub(crate) fn find_string_end(&self, start: usize) -> Result<usize, FdtParseError> {
484+
pub(crate) fn find_string_end(self, start: usize) -> Result<usize, FdtParseError> {
485485
let mut offset = start;
486486
loop {
487487
match self.data.get(offset) {
@@ -493,7 +493,7 @@ impl<'a> Fdt<'a> {
493493
}
494494
}
495495

496-
pub(crate) fn next_sibling_offset(&self, mut offset: usize) -> Result<usize, FdtParseError> {
496+
pub(crate) fn next_sibling_offset(self, mut offset: usize) -> Result<usize, FdtParseError> {
497497
offset += FDT_TAGSIZE; // Skip FDT_BEGIN_NODE
498498

499499
// Skip node name
@@ -532,7 +532,7 @@ impl<'a> Fdt<'a> {
532532
Ok(offset)
533533
}
534534

535-
pub(crate) fn next_property_offset(&self, mut offset: usize) -> Result<usize, FdtParseError> {
535+
pub(crate) fn next_property_offset(self, mut offset: usize) -> Result<usize, FdtParseError> {
536536
let len = big_endian::U32::ref_from_prefix(&self.data[offset..])
537537
.map(|(val, _)| val.get())
538538
.map_err(|_e| FdtParseError::new(FdtErrorKind::InvalidLength, offset))?

src/fdt/node.rs

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,27 @@ use core::fmt;
1313
use super::{FDT_TAGSIZE, Fdt, FdtToken};
1414
use crate::error::FdtParseError;
1515
use crate::fdt::property::{FdtPropIter, FdtProperty};
16+
use crate::standard::AddressSpaceProperties;
1617

1718
/// A node in a flattened device tree.
1819
#[derive(Debug, Clone, Copy)]
1920
pub struct FdtNode<'a> {
20-
pub(crate) fdt: &'a Fdt<'a>,
21+
pub(crate) fdt: Fdt<'a>,
2122
pub(crate) offset: usize,
23+
/// The `#address-cells` and `#size-cells` properties of this node's parent
24+
/// node.
25+
pub(crate) parent_address_space: AddressSpaceProperties,
2226
}
2327

2428
impl<'a> FdtNode<'a> {
29+
pub(crate) fn new(fdt: Fdt<'a>, offset: usize) -> Self {
30+
Self {
31+
fdt,
32+
offset,
33+
parent_address_space: AddressSpaceProperties::default(),
34+
}
35+
}
36+
2537
/// Returns the name of this node.
2638
///
2739
/// # Errors
@@ -196,10 +208,7 @@ impl<'a> FdtNode<'a> {
196208
/// assert!(children.next().is_none());
197209
/// ```
198210
pub fn children(&self) -> impl Iterator<Item = Result<FdtNode<'a>, FdtParseError>> + use<'a> {
199-
FdtChildIter::Start {
200-
fdt: self.fdt,
201-
offset: self.offset,
202-
}
211+
FdtChildIter::Start { node: *self }
203212
}
204213

205214
pub(crate) fn fmt_recursive(&self, f: &mut fmt::Formatter<'_>, indent: usize) -> fmt::Result {
@@ -242,8 +251,14 @@ impl<'a> FdtNode<'a> {
242251

243252
/// An iterator over the children of a device tree node.
244253
enum FdtChildIter<'a> {
245-
Start { fdt: &'a Fdt<'a>, offset: usize },
246-
Running { fdt: &'a Fdt<'a>, offset: usize },
254+
Start {
255+
node: FdtNode<'a>,
256+
},
257+
Running {
258+
fdt: Fdt<'a>,
259+
offset: usize,
260+
address_space: AddressSpaceProperties,
261+
},
247262
Error,
248263
}
249264

@@ -252,21 +267,33 @@ impl<'a> Iterator for FdtChildIter<'a> {
252267

253268
fn next(&mut self) -> Option<Self::Item> {
254269
match self {
255-
Self::Start { fdt, offset } => {
256-
let mut offset = *offset;
270+
Self::Start { node } => {
271+
let address_space = match node.address_space() {
272+
Ok(value) => value,
273+
Err(e) => return Some(Err(e)),
274+
};
275+
let mut offset = node.offset;
257276
offset += FDT_TAGSIZE; // Skip FDT_BEGIN_NODE
258-
offset = match fdt.find_string_end(offset) {
277+
offset = match node.fdt.find_string_end(offset) {
259278
Ok(offset) => offset,
260279
Err(e) => {
261280
*self = Self::Error;
262281
return Some(Err(e));
263282
}
264283
};
265284
offset = Fdt::align_tag_offset(offset);
266-
*self = Self::Running { fdt, offset };
285+
*self = Self::Running {
286+
fdt: node.fdt,
287+
offset,
288+
address_space,
289+
};
267290
self.next()
268291
}
269-
Self::Running { fdt, offset } => match Self::try_next(fdt, offset) {
292+
Self::Running {
293+
fdt,
294+
offset,
295+
address_space,
296+
} => match Self::try_next(*fdt, offset, *address_space) {
270297
Some(Ok(val)) => Some(Ok(val)),
271298
Some(Err(e)) => {
272299
*self = Self::Error;
@@ -281,8 +308,9 @@ impl<'a> Iterator for FdtChildIter<'a> {
281308

282309
impl<'a> FdtChildIter<'a> {
283310
fn try_next(
284-
fdt: &'a Fdt<'a>,
311+
fdt: Fdt<'a>,
285312
offset: &mut usize,
313+
parent_address_space: AddressSpaceProperties,
286314
) -> Option<Result<FdtNode<'a>, FdtParseError>> {
287315
loop {
288316
let token = match fdt.read_token(*offset) {
@@ -299,6 +327,7 @@ impl<'a> FdtChildIter<'a> {
299327
return Some(Ok(FdtNode {
300328
fdt,
301329
offset: node_offset,
330+
parent_address_space,
302331
}));
303332
}
304333
FdtToken::Prop => {

0 commit comments

Comments
 (0)