Skip to content

Commit

Permalink
add model
Browse files Browse the repository at this point in the history
  • Loading branch information
kadiwa4 committed Oct 3, 2023
1 parent d7a1f76 commit 6798f10
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 13 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ zerocopy = { version = "0.7.0", features = ["derive"] }
[features]
alloc = ["fallible-iterator/alloc"]
derive = ["devicetree_derive"]
model = []
std = ["alloc", "fallible-iterator/std"]
6 changes: 3 additions & 3 deletions src/blob/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use crate::{
/// It contains [`Property`]s and child nodes.
#[derive(Clone, Debug)]
pub struct Node<'dtb> {
pub(super) dt: &'dtb Devicetree,
pub(super) name: &'dtb [u8],
pub(super) contents: Cursor,
pub(crate) dt: &'dtb Devicetree,
pub(crate) name: &'dtb [u8],
pub(crate) contents: Cursor,
}

impl<'dtb> Node<'dtb> {
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ extern crate alloc as std_alloc;
#[cfg(feature = "alloc")]
pub mod alloc;
pub mod blob;
#[cfg(feature = "model")]
pub mod model;
pub mod prop_value;

#[cfg(feature = "derive")]
Expand Down
128 changes: 128 additions & 0 deletions src/model.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//! Higher level of abstraction.
use crate::{
blob::{self, Cursor, Devicetree},
prop_value::{self, RangesIter},
Cells, DeserializeNode, DeserializeProperty, Error, NodeContext, Result,
};

/// A devicetree node representing some sort of device, meaning it has a
/// `compatible` property.
#[derive(Clone, Debug)]
pub struct Device<'dtb> {
node_name: &'dtb str,
content_cursor: Cursor,
parent_address_cells: Cells,
parent_size_cells: Cells,
address_cells: Cells,
size_cells: Cells,
phandle: Option<u32>,
compatible: prop_value::Strings<'dtb>,
status: prop_value::Status<'dtb>,
reg: Option<&'dtb [u32]>,
ranges: Option<&'dtb [u32]>,
}

impl<'dtb> Device<'dtb> {
pub fn node_name(&self) -> &'dtb str {
self.node_name
}

pub fn content_cursor(&self) -> Cursor {
self.content_cursor
}

pub fn blob_node(&self, dt: &'dtb Devicetree) -> blob::Node<'dtb> {
blob::Node {
dt,
name: self.node_name.as_bytes(),
contents: self.content_cursor,
}
}

pub fn address_cells(&self) -> Cells {
self.address_cells
}

pub fn size_cells(&self) -> Cells {
self.size_cells
}

pub fn phandle(&self) -> Option<u32> {
self.phandle
}

pub fn compatible(&self) -> prop_value::Strings<'dtb> {
self.compatible.clone()
}

pub fn status(&self) -> prop_value::Status<'dtb> {
self.status
}

pub fn reg(&self) -> Option<prop_value::Reg<'dtb>> {
self.reg.map(|value| prop_value::Reg {
value,
address_cells: self.parent_address_cells,
size_cells: self.parent_size_cells,
})
}

pub fn ranges(&self) -> Option<RangesIter<'dtb>> {
self.ranges.map(|value| RangesIter {
value,
child_address_cells: self.address_cells,
address_cells: self.parent_address_cells,
child_size_cells: self.size_cells,
})
}
}

impl<'dtb> DeserializeNode<'dtb> for Device<'dtb> {
fn deserialize(blob_node: &blob::Node<'dtb>, cx: NodeContext<'_>) -> Result<(Self, Cursor)> {
let mut this = Self {
node_name: blob_node.name()?,
content_cursor: blob_node.contents,
parent_address_cells: cx.address_cells,
parent_size_cells: cx.size_cells,
address_cells: 0,
size_cells: 0,
phandle: None,
compatible: prop_value::Strings::EMPTY,
status: prop_value::Status::Ok,
reg: None,
ranges: None,
};
let mut compatible = None;
let (child_cx, cursor) = cx.deserialize_node(
blob_node,
|name, prop| {
match name {
"phandle" => this.phandle = Some(u32::deserialize(prop, cx)?),
"compatible" => compatible = Some(prop_value::Strings::deserialize(prop, cx)?),
"status" => this.status = prop_value::Status::deserialize(prop, cx)?,
"reg" => this.reg = Some(prop_value::Reg::deserialize(prop, cx)?.value),
"ranges" => this.reg = Some(<&[u32]>::deserialize(prop, cx)?),
_ => (),
};
Ok(())
},
|node, _, cursor| {
*cursor = node.end_cursor()?;
Ok(())
},
)?;
this.compatible = compatible.ok_or(Error::UnsuitableNode)?;
if let Some(value) = this.ranges {
RangesIter::new(
value,
child_cx.address_cells,
cx.address_cells,
child_cx.size_cells,
)?;
}
this.address_cells = child_cx.address_cells;
this.size_cells = child_cx.size_cells;
Ok((this, cursor))
}
}
52 changes: 42 additions & 10 deletions src/prop_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use crate::{blob::Property, util, Cells, DeserializeProperty, Error, NodeContext, Result};
use core::{
fmt::{Display, Formatter},
fmt::{self, Display, Formatter},
iter::FusedIterator,
};

Expand Down Expand Up @@ -88,7 +88,7 @@ impl<'a> TryFrom<&'a str> for Status<'a> {
}

impl Display for Status<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match *self {
Self::Ok => f.write_str("okay"),
Self::Disabled => f.write_str("disabled"),
Expand Down Expand Up @@ -160,7 +160,7 @@ impl<'a> DoubleEndedFallibleIterator for Strings<'a> {
}
}

impl<'a> Default for Strings<'a> {
impl Default for Strings<'_> {
fn default() -> Self {
Self::EMPTY
}
Expand All @@ -169,9 +169,9 @@ impl<'a> Default for Strings<'a> {
/// Iterator over the _(address, length)_ pairs of `reg`'s value.
#[derive(Clone, Debug, Default)]
pub struct Reg<'dtb> {
value: &'dtb [u32],
address_cells: Cells,
size_cells: Cells,
pub(crate) value: &'dtb [u32],
pub(crate) address_cells: Cells,
pub(crate) size_cells: Cells,
}

impl<'dtb> Reg<'dtb> {
Expand Down Expand Up @@ -309,10 +309,10 @@ impl<'dtb> DeserializeProperty<'dtb> for Ranges<'dtb> {
/// ```
#[derive(Clone, Debug)]
pub struct RangesIter<'dtb> {
value: &'dtb [u32],
child_address_cells: Cells,
address_cells: Cells,
child_size_cells: Cells,
pub(crate) value: &'dtb [u32],
pub(crate) child_address_cells: Cells,
pub(crate) address_cells: Cells,
pub(crate) child_size_cells: Cells,
}

impl<'dtb> RangesIter<'dtb> {
Expand Down Expand Up @@ -406,6 +406,38 @@ impl RangesBlock {
let length = util::parse_cells(bytes, child_size_cells)?;
Some(Self(child_bus_address, parent_bus_address, length))
}

/// Maps a child address to the parent address.
///
/// The address at the end of the range is not considered part of the range.
///
/// # Examples
/// ```
/// # use devicetree::prop_value::RangesBlock;
/// let ranges = RangesBlock(0x1000, 0x4000, 0x0800);
/// assert_eq!(ranges.map_to_parent(0x1234), Some(0x4234));
/// assert_eq!(ranges.map_to_parent(0x1800), None);
/// ```
pub fn map_to_parent(self, child_address: u128) -> Option<u128> {
let offset = u128::checked_sub(child_address, self.0);
offset.filter(|&o| o < self.2).map(|o| self.1 + o)
}

/// Maps a parent address to the child address.
///
/// The address at the end of the range is not considered part of the range.
///
/// # Examples
/// ```
/// # use devicetree::prop_value::RangesBlock;
/// let ranges = RangesBlock(0x1000, 0x4000, 0x0800);
/// assert_eq!(ranges.map_to_child(0x4321), Some(0x1321));
/// assert_eq!(ranges.map_to_child(0x4800), None);
/// ```
pub fn map_to_child(self, parent_address: u128) -> Option<u128> {
let offset = u128::checked_sub(parent_address, self.1);
offset.filter(|&o| o < self.2).map(|o| self.0 + o)
}
}

/// Value of `initial-mapped-area` property.
Expand Down

0 comments on commit 6798f10

Please sign in to comment.