pub mod cells;
pub mod interrupts;
pub mod ranges;
pub mod reg;
pub mod values;
use crate::{
helpers::{FallibleNode, FallibleRoot},
parsing::{BigEndianU32, ParserWithMode},
FdtError,
};
pub trait Property<'a, P: ParserWithMode<'a>>: Sized {
fn parse(node: FallibleNode<'a, P>, root: FallibleRoot<'a, P>) -> Result<Option<Self>, FdtError>;
}
#[derive(Debug, Clone, Copy)]
pub struct Compatible<'a> {
string: &'a str,
}
impl<'a, P: ParserWithMode<'a>> Property<'a, P> for Compatible<'a> {
fn parse(node: FallibleNode<'a, P>, _: FallibleRoot<'a, P>) -> Result<Option<Self>, FdtError> {
let property = node.properties()?.find("compatible")?;
match property {
Some(prop) => Ok(Some(Self { string: prop.as_value()? })),
None => Ok(None),
}
}
}
impl<'a> Compatible<'a> {
pub fn first(self) -> &'a str {
self.string.split('\0').next().unwrap_or(self.string)
}
pub fn all(self) -> CompatibleIter<'a> {
CompatibleIter { iter: self.string.split('\0') }
}
pub fn compatible_with(self, value: &str) -> bool {
self.all().any(|c| c == value)
}
}
impl<'a> IntoIterator for Compatible<'a> {
type IntoIter = CompatibleIter<'a>;
type Item = &'a str;
fn into_iter(self) -> Self::IntoIter {
self.all()
}
}
pub struct CompatibleIter<'a> {
iter: core::str::Split<'a, char>,
}
impl<'a> Iterator for CompatibleIter<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Model<'a>(&'a str);
impl<'a, P: ParserWithMode<'a>> Property<'a, P> for Model<'a> {
fn parse(node: FallibleNode<'a, P>, _: FallibleRoot<'a, P>) -> Result<Option<Self>, FdtError> {
match node.properties()?.find("model")? {
Some(model) => Ok(Some(Self(model.as_value()?))),
None => Ok(None),
}
}
}
impl<'a> core::ops::Deref for Model<'a> {
type Target = str;
fn deref(&self) -> &Self::Target {
self.0
}
}
impl<'a> AsRef<str> for Model<'a> {
fn as_ref(&self) -> &str {
self.0
}
}
impl<'a> core::cmp::PartialEq<str> for Model<'a> {
fn eq(&self, other: &str) -> bool {
self.0.eq(other)
}
}
impl<'a> core::cmp::PartialEq<Model<'a>> for str {
fn eq(&self, other: &Model<'a>) -> bool {
self.eq(other.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PHandle(BigEndianU32);
impl PHandle {
pub fn new(handle: u32) -> Self {
Self(BigEndianU32::from_ne(handle))
}
pub fn as_u32(self) -> u32 {
self.0.to_ne()
}
}
impl<'a, P: ParserWithMode<'a>> Property<'a, P> for PHandle {
fn parse(node: FallibleNode<'a, P>, _: FallibleRoot<'a, P>) -> Result<Option<Self>, FdtError> {
let Some(phandle) = node.properties()?.find("phandle")? else {
return Ok(None);
};
Ok(Some(PHandle(phandle.as_value()?)))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Status<'a>(&'a str);
impl<'a> Status<'a> {
#[allow(missing_docs)]
pub const OKAY: Self = Self("okay");
#[allow(missing_docs)]
pub const DISABLED: Self = Self("disabled");
#[allow(missing_docs)]
pub const RESERVED: Self = Self("reserved");
#[allow(missing_docs)]
pub const FAIL: Self = Self("fail");
#[inline]
pub fn is_okay(self) -> bool {
self == Self::OKAY
}
#[inline]
pub fn is_disabled(self) -> bool {
self == Self::DISABLED
}
#[inline]
pub fn is_reserved(self) -> bool {
self == Self::RESERVED
}
#[inline]
pub fn is_failed(self) -> bool {
self == Self::FAIL || self.0.starts_with("fail-")
}
pub fn failed_status_code(self) -> Option<&'a str> {
match self.0.starts_with("fail-") {
true => Some(self.0.trim_start_matches("fail-")),
false => None,
}
}
}
impl<'a, P: ParserWithMode<'a>> Property<'a, P> for Status<'a> {
fn parse(node: FallibleNode<'a, P>, _: FallibleRoot<'a, P>) -> Result<Option<Self>, FdtError> {
match node.properties()?.find("status")? {
Some(model) => Ok(Some(Self(model.as_value()?))),
None => Ok(None),
}
}
}
impl<'a> core::ops::Deref for Status<'a> {
type Target = str;
fn deref(&self) -> &Self::Target {
self.0
}
}
impl<'a> core::cmp::PartialEq<str> for Status<'a> {
fn eq(&self, other: &str) -> bool {
self.0.eq(other)
}
}
impl<'a> core::cmp::PartialEq<Status<'a>> for str {
fn eq(&self, other: &Status<'a>) -> bool {
self.eq(other.0)
}
}
pub struct DmaCoherent;
impl<'a, P: ParserWithMode<'a>> Property<'a, P> for DmaCoherent {
fn parse(node: FallibleNode<'a, P>, _: FallibleRoot<'a, P>) -> Result<Option<Self>, FdtError> {
match node.properties()?.find("dma-coherent")? {
Some(_) => Ok(Some(Self)),
None => Ok(None),
}
}
}