mod chosen;
mod cpus;
mod memory;
mod ranges;
mod reg;
mod status;
pub use self::chosen::Chosen;
pub use self::cpus::{Cpu, Cpus};
pub use self::memory::{InitialMappedArea, Memory, ReservedMemory};
pub use self::ranges::Range;
pub use self::reg::Reg;
pub use self::status::Status;
use crate::error::{PropertyError, StandardError};
use crate::fdt::FdtNode;
use crate::{Node, Property};
pub(crate) const DEFAULT_ADDRESS_CELLS: u32 = 2;
pub(crate) const DEFAULT_SIZE_CELLS: u32 = 1;
pub trait NodeStandard<'a>: Node<'a> {
#[must_use]
fn compatible(&self) -> Option<impl Iterator<Item = &'a str> + use<'a, Self>> {
self.property("compatible")
.map(|property| property.as_str_list())
}
#[must_use]
fn is_compatible(&self, compatible_filter: &str) -> bool {
if let Some(mut compatible) = self.compatible() {
compatible.any(|c| c == compatible_filter)
} else {
false
}
}
fn find_compatible<'f>(
&self,
compatible_filter: &'f str,
) -> impl Iterator<Item = Self> + use<'a, 'f, Self> {
self.children()
.filter(move |child| child.is_compatible(compatible_filter))
}
fn model(&self) -> Result<Option<&'a str>, PropertyError> {
if let Some(model) = self.property("model") {
Ok(Some(model.as_str()?))
} else {
Ok(None)
}
}
fn phandle(&self) -> Result<Option<u32>, PropertyError> {
if let Some(property) = self.property("phandle") {
Ok(Some(property.as_u32()?))
} else {
Ok(None)
}
}
fn status(&self) -> Result<Status, StandardError> {
if let Some(status) = self.property("status") {
Ok(status.as_str()?.parse()?)
} else {
Ok(Status::Okay)
}
}
fn address_cells(&self) -> Result<u32, PropertyError> {
if let Some(property) = self.property("#address-cells") {
Ok(property.as_u32()?)
} else {
Ok(DEFAULT_ADDRESS_CELLS)
}
}
fn size_cells(&self) -> Result<u32, PropertyError> {
if let Some(model) = self.property("#size-cells") {
Ok(model.as_u32()?)
} else {
Ok(DEFAULT_SIZE_CELLS)
}
}
#[must_use]
fn address_space(&self) -> AddressSpaceProperties {
AddressSpaceProperties {
address_cells: self.address_cells().unwrap_or(DEFAULT_ADDRESS_CELLS),
size_cells: self.size_cells().unwrap_or(DEFAULT_SIZE_CELLS),
}
}
fn virtual_reg(&self) -> Result<Option<u32>, PropertyError> {
if let Some(property) = self.property("virtual-reg") {
Ok(Some(property.as_u32()?))
} else {
Ok(None)
}
}
#[must_use]
fn dma_coherent(&self) -> bool {
self.property("dma-coherent").is_some()
}
}
impl<'a, T: Node<'a>> NodeStandard<'a> for T {}
impl<'a> FdtNode<'a> {
pub fn reg(&self) -> Result<Option<impl Iterator<Item = Reg<'a>> + use<'a>>, PropertyError> {
let address_cells = self.parent_address_space.address_cells as usize;
let size_cells = self.parent_address_space.size_cells as usize;
if let Some(property) = self.property("reg") {
Ok(Some(
property
.as_prop_encoded_array([address_cells, size_cells])?
.map(Reg::from_cells),
))
} else {
Ok(None)
}
}
pub fn ranges(
&self,
) -> Result<Option<impl Iterator<Item = Range<'a>> + use<'a>>, PropertyError> {
if let Some(property) = self.property("ranges") {
Ok(Some(
property
.as_prop_encoded_array([
self.address_cells().unwrap_or(DEFAULT_ADDRESS_CELLS) as usize,
self.parent_address_space.address_cells as usize,
self.size_cells().unwrap_or(DEFAULT_SIZE_CELLS) as usize,
])?
.map(Range::from_cells),
))
} else {
Ok(None)
}
}
pub fn dma_ranges(
&self,
) -> Result<Option<impl Iterator<Item = Range<'a>> + use<'a>>, PropertyError> {
if let Some(property) = self.property("dma-ranges") {
Ok(Some(
property
.as_prop_encoded_array([
self.address_cells().unwrap_or(DEFAULT_ADDRESS_CELLS) as usize,
self.parent_address_space.address_cells as usize,
self.size_cells().unwrap_or(DEFAULT_SIZE_CELLS) as usize,
])?
.map(Range::from_cells),
))
} else {
Ok(None)
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct AddressSpaceProperties {
pub address_cells: u32,
pub size_cells: u32,
}
impl Default for AddressSpaceProperties {
fn default() -> Self {
Self {
address_cells: DEFAULT_ADDRESS_CELLS,
size_cells: DEFAULT_SIZE_CELLS,
}
}
}