Skip to content

Add support for riscv,pmu device #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ Cargo.lock

# Visual Studio Code configuration files
.vscode/
*.dts

*.dtb
!examples/*.dtb
10 changes: 4 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,12 @@ edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
serde = { version = "1.0", default-features = false }
erased-serde = "0.4"

[dev-dependencies]
serde_derive = "1.0"
serde = { version = "1.0", default-features = false, features = ["derive"] }
dyn_serde = { version = "1.0.2", default-features = false, optional = true }

[features]
default = ["std"]
default = ["std", "ser"]

ser = ["dep:dyn_serde"]
std = ["serde/std"]
alloc = ["serde/alloc"]
2 changes: 1 addition & 1 deletion examples/hifive-unmatched-a00.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extern crate alloc;

use alloc::collections::BTreeMap;
use serde_derive::Deserialize;
use serde::Deserialize;
use serde_device_tree::Compatible;

#[derive(Debug, Deserialize)]
Expand Down
3 changes: 1 addition & 2 deletions examples/qemu-virt.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! 这是一个 `from_raw_mut` 反序列化设备树的示例。不需要 `alloc`。
// extern crate alloc;

// 在实际使用中,将这里的 `serde_derive::Deserialize` 改为 `serde::Deserialize`。
use serde_derive::Deserialize;
use serde::Deserialize;

// - `DtbPtr`: 验证设备树首部正确性,后续也可借助这个类型传递设备树,多次解析不必重复验证。
// - `Dtb`: 管理反序列化出的类型生命周期。
Expand Down
2 changes: 1 addition & 1 deletion examples/serialize.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use serde_derive::Serialize;
use serde::Serialize;
use std::io::prelude::*;

const MAX_SIZE: usize = 256 + 32;
Expand Down
4 changes: 2 additions & 2 deletions src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use serde::de;
/// # });
/// # aligned_data.data[..BUFFER_SIZE].clone_from_slice(RAW_DEVICE_TREE);
/// # let fdt_ptr = aligned_data.data.as_ptr();
/// use serde_derive::Deserialize;
/// use serde::Deserialize;
///
/// #[derive(Debug, Deserialize)]
/// struct Tree<'a> {
Expand Down Expand Up @@ -516,7 +516,7 @@ mod tests {
#[cfg(feature = "alloc")]
use alloc::format;
#[cfg(any(feature = "std", feature = "alloc"))]
use serde_derive::Deserialize;
use serde::Deserialize;
#[cfg(feature = "std")]
use std::format;

Expand Down
128 changes: 128 additions & 0 deletions src/de_mut/matrix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
use crate::de_mut::ValueCursor;
use serde::{Deserialize, Serialize};

pub struct Matrix<'de, const T: usize> {
data: &'de [u32],
}

pub struct MatrixItem<'de, const T: usize> {
offset: usize,
data: &'de [u32],
}

impl<'de, const T: usize> Matrix<'de, T> {
#[inline(always)]
pub fn get_block_size() -> usize {
// Block size in bytes.
T * 4
}

#[inline(always)]
pub fn iter(&self) -> MatrixItem<'de, T> {
MatrixItem {
offset: 0,
data: self.data,
}
}

#[inline(always)]
pub fn len(&self) -> usize {
self.data.len() / T
}

#[inline(always)]
pub fn is_empty(&self) -> bool {
self.data.len() != 0
}

#[inline(always)]
pub fn get(&self, i: usize) -> &'de [u32] {
&self.data[i * T..(i + 1) * T]
}
}

impl<'de, const T: usize> Iterator for MatrixItem<'de, T> {
type Item = &'de [u32];

#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
if self.data.len() <= self.offset {
return None;
}
let result = &self.data[self.offset..self.offset + T];
self.offset += T;
Some(result)
}
}

impl<'de, const T: usize> Deserialize<'de> for Matrix<'_, T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let value_deserialzer = super::ValueDeserializer::deserialize(deserializer)?;
let data = match value_deserialzer.cursor {
ValueCursor::Prop(_, cursor) => cursor.data_on(value_deserialzer.dtb),
_ => unreachable!(),
};
if data.len() % Self::get_block_size() != 0 {
panic!("unaligned matrix");
}
let (prefix, data, suffix) = unsafe { data.align_to::<u32>() };
if !prefix.is_empty() || !suffix.is_empty() {
panic!("Not support unaligned data");
}

Ok(Self { data })
}
}

impl<const T: usize> Serialize for Matrix<'_, T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeSeq;
let mut seq = serializer.serialize_seq(Some(self.data.len()))?;
for x in self.data {
seq.serialize_element(x)?;
}
seq.end()
}
}

#[cfg(test)]
mod tests {
use super::Matrix;
use crate::{Dtb, DtbPtr, buildin::Node, from_raw_mut};
use serde::Serialize;

const MAX_SIZE: usize = 256;
#[test]
fn base_ser_test() {
#[derive(Serialize)]
struct Base {
pub hello: [u32; 16],
}
let array: [u32; 16] = [0xdeadbeef; 16];
let mut buf1 = [0u8; MAX_SIZE];

{
let base = Base { hello: array };
crate::ser::to_dtb(&base, &[], &mut buf1).unwrap();
}

let ptr = DtbPtr::from_raw(buf1.as_mut_ptr()).unwrap();
let dtb = Dtb::from(ptr).share();
let node: Node = from_raw_mut(&dtb).unwrap();
let matrix = node.get_prop("hello").unwrap().deserialize::<Matrix<4>>();
let mut count = 0;
for x in matrix.iter() {
for y in x {
count += 1;
assert_eq!(u32::from_be(*y), 0xdeadbeef);
}
}
assert_eq!(count, 16);
}
}
5 changes: 3 additions & 2 deletions src/de_mut/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use serde::de;
mod cursor;
mod data;
// mod group;
mod matrix;
pub(crate) mod node;
mod node_seq;
mod reg;
Expand All @@ -18,11 +19,11 @@ mod structs;
const VALUE_DESERIALIZER_NAME: &str = "$serde_device_tree$de_mut$ValueDeserializer";
pub(crate) const NODE_NAME: &str = "$serde_device_tree$de_mut$Node";
pub(crate) const NODE_NODE_ITEM_NAME: &str = "$serde_device_tree$de_mut$Node$NodeItem";
pub(crate) const NODE_PROP_ITEM_NAME: &str = "$serde_device_tree$de_mut$Node$PropItem";
// pub(crate) const NODE_PROP_ITEM_NAME: &str = "$serde_device_tree$de_mut$Node$PropItem";

pub use structs::{Dtb, DtbPtr};
pub mod buildin {
pub use super::{node::Node, node_seq::NodeSeq, reg::Reg, str_seq::StrSeq};
pub use super::{matrix::Matrix, node::Node, node_seq::NodeSeq, reg::Reg, str_seq::StrSeq};
}

use cursor::{BodyCursor, Cursor, MultiNodeCursor, PropCursor};
Expand Down
16 changes: 12 additions & 4 deletions src/de_mut/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,18 @@ pub struct PropItem<'de> {
impl<'de> Node<'de> {
pub fn deserialize<T: Deserialize<'de>>(&self) -> T {
use super::ValueCursor;
let result = match self.cursor.clone().move_on(self.dtb) {
Cursor::Title(c) => {
let (name, _) = c.split_on(self.dtb);
let take_result = c.take_node_on(self.dtb, name);
take_result
}
_ => unreachable!("Node's cursor should on its start"),
};
T::deserialize(&mut ValueDeserializer {
dtb: self.dtb,
reg: self.reg,
cursor: ValueCursor::Body(self.cursor),
cursor: ValueCursor::NodeIn(result),
})
.unwrap()
}
Expand Down Expand Up @@ -302,7 +310,7 @@ impl<'de> PropItem<'de> {
.unwrap()
}
}
impl<'se> Serialize for NodeItem<'se> {
impl Serialize for NodeItem<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
Expand All @@ -311,7 +319,7 @@ impl<'se> Serialize for NodeItem<'se> {
}
}

impl<'se> Serialize for PropItem<'se> {
impl Serialize for PropItem<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
Expand All @@ -320,7 +328,7 @@ impl<'se> Serialize for PropItem<'se> {
}
}

impl<'se> Serialize for Node<'se> {
impl Serialize for Node<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
Expand Down
2 changes: 1 addition & 1 deletion src/de_mut/node_seq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ impl<'de> NodeSeqItem<'de> {
mod tests {
use crate::buildin::{NodeSeq, Reg};
use crate::{Dtb, DtbPtr, from_raw_mut};
use serde_derive::Deserialize;
use serde::Deserialize;

const RAW_DEVICE_TREE: &[u8] = include_bytes!("../../examples/bl808.dtb");
const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len();
Expand Down
2 changes: 1 addition & 1 deletion src/de_mut/reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl Iterator for RegIter<'_> {
}
}

impl<'se> Serialize for Reg<'se> {
impl Serialize for Reg<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
Expand Down
2 changes: 1 addition & 1 deletion src/de_mut/str_seq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl<'de> Iterator for StrSeqIter<'de> {
}
}

impl<'se> Serialize for StrSeq<'se> {
impl Serialize for StrSeq<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ extern crate alloc;

pub mod de;
pub mod error;
#[cfg(feature = "ser")]
pub mod ser;
pub mod utils;
pub mod value;

mod common;
mod de_mut;
mod tag;
mod value;

pub use value::compatible::Compatible;

Expand Down
11 changes: 6 additions & 5 deletions src/ser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,16 @@ where
let writer_len = writer.len();
let (data_block, string_block) = writer.split_at_mut(writer.len() - offset);
let (header, data_block) = data_block.split_at_mut(HEADER_LEN as usize + RSVMAP_LEN);
{
let struct_len = {
let mut patch_list = crate::ser::patch::PatchList::new(list);
let mut block = crate::ser::string_block::StringBlock::new(string_block, &mut offset);
let mut dst = crate::ser::pointer::Pointer::new(Some(data_block));
let mut ser =
crate::ser::serializer::Serializer::new(&mut dst, &mut block, &mut patch_list);
data.serialize(&mut ser)?;
ser.dst.step_by_u32(FDT_END);
}
ser.dst.get_offset()
};
// Make header
{
let header = unsafe { &mut *(header.as_mut_ptr() as *mut Header) };
Expand All @@ -60,7 +61,7 @@ where
header.last_comp_version = u32::from_be(SUPPORTED_VERSION); // TODO: maybe 16
header.boot_cpuid_phys = 0; // TODO: wtf is this prop
header.size_dt_strings = u32::from_be(offset as u32);
header.size_dt_struct = u32::from_be(data_block.len() as u32); // TODO: correct?
header.size_dt_struct = u32::from_be(struct_len as u32);
}
Ok(())
}
Expand All @@ -71,7 +72,7 @@ pub enum Error {
}

impl core::fmt::Display for Error {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(formatter, "{:?}", self)
}
}
Expand All @@ -81,7 +82,7 @@ impl core::error::Error for Error {}
impl serde::ser::Error for Error {
fn custom<T>(_msg: T) -> Self
where
T: std::fmt::Display,
T: core::fmt::Display,
{
Self::Unknown
}
Expand Down
6 changes: 3 additions & 3 deletions src/ser/patch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use core::cell::Cell;
/// Since this crate is mostly work with `noalloc`, we use `Patch` and `PatchList` for change or
/// add on a dtb.
pub struct Patch<'se> {
pub data: &'se dyn erased_serde::Serialize,
pub data: &'se dyn dyn_serde::Serialize,
name: &'se str,

/// This patch match how many item between its path and serializer.
Expand All @@ -15,7 +15,7 @@ pub struct Patch<'se> {

impl<'se> Patch<'se> {
#[inline(always)]
pub fn new(name: &'se str, data: &'se dyn erased_serde::Serialize) -> Patch<'se> {
pub fn new(name: &'se str, data: &'se dyn dyn_serde::Serialize) -> Patch<'se> {
Patch {
name,
data,
Expand Down Expand Up @@ -51,7 +51,7 @@ impl<'se> Patch<'se> {
pub fn serialize(&self, serializer: &mut Serializer<'se>) {
self.parsed.set(true);
self.data
.erased_serialize(&mut <dyn erased_serde::Serializer>::erase(serializer))
.serialize_dyn(&mut <dyn dyn_serde::Serializer>::new(serializer))
.unwrap();
}
}
Expand Down
Loading