From af86aa2bcd4909fc498578388feb8b10eded1195 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Thu, 27 Feb 2025 12:01:24 +0800 Subject: [PATCH 1/8] feat: add `matrix` in `de_mut` Signed-off-by: Woshiluo Luo --- .gitignore | 4 +- src/de_mut/matrix.rs | 110 +++++++++++++++++++++++++++++++++++++++++++ src/de_mut/mod.rs | 5 +- src/ser/mod.rs | 4 +- 4 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 src/de_mut/matrix.rs diff --git a/.gitignore b/.gitignore index c994933..fa5fb3f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ Cargo.lock # Visual Studio Code configuration files .vscode/ -*.dts + +*.dtb +!examples/*.dtb diff --git a/src/de_mut/matrix.rs b/src/de_mut/matrix.rs new file mode 100644 index 0000000..0de549d --- /dev/null +++ b/src/de_mut/matrix.rs @@ -0,0 +1,110 @@ +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> { + // Block size in bytes. + pub fn get_block_size() -> usize { + T * 4 + } + + pub fn iter(&self) -> MatrixItem<'de, T> { + MatrixItem { + offset: 0, + data: self.data, + } + } +} + +impl<'de, const T: usize> Iterator for MatrixItem<'de, T> { + type Item = &'de [u32]; + + fn next(&mut self) -> Option { + 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<'de, T> { + fn deserialize(deserializer: D) -> Result + 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::() }; + if prefix.len() != 0 || suffix.len() != 0 { + panic!("Not support unaligned data"); + } + + Ok(Self { data }) + } +} + +impl<'se, const T: usize> Serialize for Matrix<'se, T> { + fn serialize(&self, serializer: S) -> Result + 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_derive::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::>(); + 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); + } +} diff --git a/src/de_mut/mod.rs b/src/de_mut/mod.rs index e3c7641..3afaeb5 100644 --- a/src/de_mut/mod.rs +++ b/src/de_mut/mod.rs @@ -7,6 +7,7 @@ use serde::de; mod cursor; mod data; // mod group; +mod matrix; pub(crate) mod node; mod node_seq; mod reg; @@ -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}; diff --git a/src/ser/mod.rs b/src/ser/mod.rs index e54bca3..95e8681 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -39,6 +39,7 @@ 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); @@ -47,6 +48,7 @@ where crate::ser::serializer::Serializer::new(&mut dst, &mut block, &mut patch_list); data.serialize(&mut ser)?; ser.dst.step_by_u32(FDT_END); + struct_len = ser.dst.get_offset(); } // Make header { @@ -60,7 +62,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(()) } From ba8f0e5ba547f8ba670cd602069306b0f03abf79 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Thu, 27 Feb 2025 13:40:32 +0800 Subject: [PATCH 2/8] feat: add riscv_pmu value Signed-off-by: Woshiluo Luo --- Cargo.toml | 2 -- src/de_mut/matrix.rs | 24 ++++++++++++-- src/de_mut/node.rs | 6 ++-- src/de_mut/reg.rs | 2 +- src/de_mut/str_seq.rs | 2 +- src/lib.rs | 2 +- src/ser/serializer.rs | 4 +-- src/value/mod.rs | 1 + src/value/riscv_pmu.rs | 72 ++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 src/value/riscv_pmu.rs diff --git a/Cargo.toml b/Cargo.toml index aa63f25..37bdd39 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,8 +16,6 @@ edition = "2024" [dependencies] serde = { version = "1.0", default-features = false } erased-serde = "0.4" - -[dev-dependencies] serde_derive = "1.0" [features] diff --git a/src/de_mut/matrix.rs b/src/de_mut/matrix.rs index 0de549d..5755427 100644 --- a/src/de_mut/matrix.rs +++ b/src/de_mut/matrix.rs @@ -11,22 +11,40 @@ pub struct MatrixItem<'de, const T: usize> { } impl<'de, const T: usize> Matrix<'de, T> { - // Block size in bytes. + #[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 { if self.data.len() <= self.offset { return None; @@ -51,7 +69,7 @@ impl<'de, const T: usize> Deserialize<'de> for Matrix<'de, T> { panic!("unaligned matrix"); } let (prefix, data, suffix) = unsafe { data.align_to::() }; - if prefix.len() != 0 || suffix.len() != 0 { + if !prefix.is_empty() || !suffix.is_empty() { panic!("Not support unaligned data"); } @@ -59,7 +77,7 @@ impl<'de, const T: usize> Deserialize<'de> for Matrix<'de, T> { } } -impl<'se, const T: usize> Serialize for Matrix<'se, T> { +impl Serialize for Matrix<'_, T> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, diff --git a/src/de_mut/node.rs b/src/de_mut/node.rs index 7ff6e48..9cf5774 100644 --- a/src/de_mut/node.rs +++ b/src/de_mut/node.rs @@ -302,7 +302,7 @@ impl<'de> PropItem<'de> { .unwrap() } } -impl<'se> Serialize for NodeItem<'se> { +impl Serialize for NodeItem<'_> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -311,7 +311,7 @@ impl<'se> Serialize for NodeItem<'se> { } } -impl<'se> Serialize for PropItem<'se> { +impl Serialize for PropItem<'_> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -320,7 +320,7 @@ impl<'se> Serialize for PropItem<'se> { } } -impl<'se> Serialize for Node<'se> { +impl Serialize for Node<'_> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, diff --git a/src/de_mut/reg.rs b/src/de_mut/reg.rs index 2d1106a..eb5504d 100644 --- a/src/de_mut/reg.rs +++ b/src/de_mut/reg.rs @@ -117,7 +117,7 @@ impl Iterator for RegIter<'_> { } } -impl<'se> Serialize for Reg<'se> { +impl Serialize for Reg<'_> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, diff --git a/src/de_mut/str_seq.rs b/src/de_mut/str_seq.rs index d0a4c48..9cc4f29 100644 --- a/src/de_mut/str_seq.rs +++ b/src/de_mut/str_seq.rs @@ -91,7 +91,7 @@ impl<'de> Iterator for StrSeqIter<'de> { } } -impl<'se> Serialize for StrSeq<'se> { +impl Serialize for StrSeq<'_> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, diff --git a/src/lib.rs b/src/lib.rs index b7aeadc..e297b86 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,11 +22,11 @@ pub mod de; pub mod error; pub mod ser; pub mod utils; +pub mod value; mod common; mod de_mut; mod tag; -mod value; pub use value::compatible::Compatible; diff --git a/src/ser/serializer.rs b/src/ser/serializer.rs index 88bd22b..aa12d5e 100644 --- a/src/ser/serializer.rs +++ b/src/ser/serializer.rs @@ -530,7 +530,7 @@ mod tests { hello: 0xdeedbeef, base1: ["Hello", "World!", "Again"], }; - crate::ser::to_dtb(&base, &mut [], &mut buf1).unwrap(); + crate::ser::to_dtb(&base, &[], &mut buf1).unwrap(); } // TODO: check buf1 buf2 // println!("{:x?} {:x?}", buf1, buf2); @@ -560,7 +560,7 @@ mod tests { hello2: 0x11223344, base2: Base1 { hello: "Roger" }, }; - crate::ser::to_dtb(&base, &mut [], &mut buf1).unwrap(); + crate::ser::to_dtb(&base, &[], &mut buf1).unwrap(); } // TODO: check buf1 buf2 // println!("{:x?} {:x?}", buf1, buf2); diff --git a/src/value/mod.rs b/src/value/mod.rs index cc61a97..31699d4 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -1,3 +1,4 @@ pub mod compatible; pub mod cpu; +pub mod riscv_pmu; mod tree; diff --git a/src/value/riscv_pmu.rs b/src/value/riscv_pmu.rs new file mode 100644 index 0000000..d474913 --- /dev/null +++ b/src/value/riscv_pmu.rs @@ -0,0 +1,72 @@ +use crate::buildin::Matrix; + +use serde_derive::Serialize; + +use core::ops::RangeInclusive; + +#[repr(transparent)] +#[derive(Serialize)] +#[serde(transparent)] +pub struct EventToMhpmevent<'de>(Matrix<'de, 3>); + +#[repr(transparent)] +#[derive(Serialize)] +#[serde(transparent)] +pub struct EventToMhpmcounters<'de>(Matrix<'de, 3>); + +#[repr(transparent)] +#[derive(Serialize)] +#[serde(transparent)] +pub struct RawEventToMhpcounters<'de>(Matrix<'de, 5>); + +impl EventToMhpmevent<'_> { + pub fn get_len(&self) -> usize { + self.0.len() + } + + pub fn get_event_id(&self, i: usize) -> u32 { + u32::from_be(self.0.get(i)[0]) + } + + pub fn get_selector_value(&self, i: usize) -> u64 { + let current = self.0.get(i); + ((u32::from_be(current[1]) as u64) << 32) | (u32::from_be(current[0]) as u64) + } +} + +impl EventToMhpmcounters<'_> { + pub fn get_len(&self) -> usize { + self.0.len() + } + + pub fn get_event_idx_range(&self, i: usize) -> RangeInclusive { + let current = self.0.get(i); + u32::from_be(current[0])..=u32::from_be(current[1]) + } + + pub fn get_counter_bitmap(&self, i: usize) -> u32 { + let current = self.0.get(i); + u32::from_be(current[2]) + } +} + +impl RawEventToMhpcounters<'_> { + pub fn get_len(&self) -> usize { + self.0.len() + } + + pub fn get_event_idx_base(&self, i: usize) -> u64 { + let current = self.0.get(i); + ((u32::from_be(current[0]) as u64) << 32) | (u32::from_be(current[1]) as u64) + } + + pub fn get_event_idx_mask(&self, i: usize) -> u64 { + let current = self.0.get(i); + ((u32::from_be(current[2]) as u64) << 32) | (u32::from_be(current[3]) as u64) + } + + pub fn get_counter_bitmap(&self, i: usize) -> u32 { + let current = self.0.get(i); + u32::from_be(current[4]) + } +} From 59c1de56fba618827d46f85048ad333a56b33ade Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Thu, 27 Feb 2025 14:20:38 +0800 Subject: [PATCH 3/8] feat: optional "ser" to make no_std work Signed-off-by: Woshiluo Luo --- Cargo.toml | 5 +++-- src/lib.rs | 1 + src/ser/mod.rs | 4 ++-- src/ser/serializer.rs | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 37bdd39..00aeb55 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,11 +15,12 @@ edition = "2024" [dependencies] serde = { version = "1.0", default-features = false } -erased-serde = "0.4" serde_derive = "1.0" +erased-serde = { version = "0.4", optional = true } [features] -default = ["std"] +default = ["std", "ser"] +ser = ["dep:erased-serde"] std = ["serde/std"] alloc = ["serde/alloc"] diff --git a/src/lib.rs b/src/lib.rs index e297b86..c8d4452 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ extern crate alloc; pub mod de; pub mod error; +#[cfg(feature = "ser")] pub mod ser; pub mod utils; pub mod value; diff --git a/src/ser/mod.rs b/src/ser/mod.rs index 95e8681..70314c8 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -73,7 +73,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) } } @@ -83,7 +83,7 @@ impl core::error::Error for Error {} impl serde::ser::Error for Error { fn custom(_msg: T) -> Self where - T: std::fmt::Display, + T: core::fmt::Display, { Self::Unknown } diff --git a/src/ser/serializer.rs b/src/ser/serializer.rs index aa12d5e..6c5f859 100644 --- a/src/ser/serializer.rs +++ b/src/ser/serializer.rs @@ -1,8 +1,8 @@ -use super::Error; use super::patch::PatchList; use super::pointer::Pointer; use super::string_block::StringBlock; use crate::common::*; +use crate::ser::Error; #[derive(Clone, Copy)] // The enum for current parsing type. From 4255b6536e1dfa8497a69ed08d1b27ef1c68a52d Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Thu, 27 Feb 2025 14:58:47 +0800 Subject: [PATCH 4/8] fix: Node deserialize use NodeIn instead Signed-off-by: Woshiluo Luo --- src/de_mut/node.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/de_mut/node.rs b/src/de_mut/node.rs index 9cf5774..0b1ee11 100644 --- a/src/de_mut/node.rs +++ b/src/de_mut/node.rs @@ -54,10 +54,18 @@ pub struct PropItem<'de> { impl<'de> Node<'de> { pub fn deserialize>(&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() } From aff691e25a5aa975efc85c4af77725f4d6299399 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Thu, 27 Feb 2025 15:08:11 +0800 Subject: [PATCH 5/8] fix: typo Signed-off-by: Woshiluo Luo --- src/value/riscv_pmu.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/value/riscv_pmu.rs b/src/value/riscv_pmu.rs index d474913..e42da06 100644 --- a/src/value/riscv_pmu.rs +++ b/src/value/riscv_pmu.rs @@ -30,7 +30,7 @@ impl EventToMhpmevent<'_> { pub fn get_selector_value(&self, i: usize) -> u64 { let current = self.0.get(i); - ((u32::from_be(current[1]) as u64) << 32) | (u32::from_be(current[0]) as u64) + ((u32::from_be(current[1]) as u64) << 32) | (u32::from_be(current[2]) as u64) } } From 2cb1ea656f1e3bebca378e98c43663e0f7c75ee2 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Thu, 27 Feb 2025 16:26:59 +0800 Subject: [PATCH 6/8] feat: add riscv_pmu test refactor: remove serde_dervier Signed-off-by: Woshiluo Luo --- Cargo.toml | 3 +- examples/hifive-unmatched-a00.rs | 2 +- examples/qemu-virt.rs | 3 +- examples/serialize.rs | 2 +- src/de.rs | 4 +- src/de_mut/matrix.rs | 4 +- src/de_mut/node_seq.rs | 2 +- src/ser/mod.rs | 7 ++-- src/ser/serializer.rs | 2 +- src/value/riscv_pmu.rs | 72 +++++++++++++++++++++++++++----- tests/bl808.rs | 3 +- tests/hifive-unmatched-a00.rs | 2 +- tests/qemu-virt.rs | 3 +- 13 files changed, 77 insertions(+), 32 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 00aeb55..6ae2c49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,7 @@ 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 } -serde_derive = "1.0" +serde = { version = "1.0", default-features = false, features = ["derive"] } erased-serde = { version = "0.4", optional = true } [features] diff --git a/examples/hifive-unmatched-a00.rs b/examples/hifive-unmatched-a00.rs index 01fc38f..b975e47 100644 --- a/examples/hifive-unmatched-a00.rs +++ b/examples/hifive-unmatched-a00.rs @@ -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)] diff --git a/examples/qemu-virt.rs b/examples/qemu-virt.rs index dbfcff1..0156142 100644 --- a/examples/qemu-virt.rs +++ b/examples/qemu-virt.rs @@ -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`: 管理反序列化出的类型生命周期。 diff --git a/examples/serialize.rs b/examples/serialize.rs index d046307..ccf9352 100644 --- a/examples/serialize.rs +++ b/examples/serialize.rs @@ -1,4 +1,4 @@ -use serde_derive::Serialize; +use serde::Serialize; use std::io::prelude::*; const MAX_SIZE: usize = 256 + 32; diff --git a/src/de.rs b/src/de.rs index 3efd43d..2998e4b 100644 --- a/src/de.rs +++ b/src/de.rs @@ -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> { @@ -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; diff --git a/src/de_mut/matrix.rs b/src/de_mut/matrix.rs index 5755427..24e8b63 100644 --- a/src/de_mut/matrix.rs +++ b/src/de_mut/matrix.rs @@ -55,7 +55,7 @@ impl<'de, const T: usize> Iterator for MatrixItem<'de, T> { } } -impl<'de, const T: usize> Deserialize<'de> for Matrix<'de, T> { +impl<'de, const T: usize> Deserialize<'de> for Matrix<'_, T> { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, @@ -95,7 +95,7 @@ impl Serialize for Matrix<'_, T> { mod tests { use super::Matrix; use crate::{Dtb, DtbPtr, buildin::Node, from_raw_mut}; - use serde_derive::Serialize; + use serde::Serialize; const MAX_SIZE: usize = 256; #[test] diff --git a/src/de_mut/node_seq.rs b/src/de_mut/node_seq.rs index a7b2331..0e003a8 100644 --- a/src/de_mut/node_seq.rs +++ b/src/de_mut/node_seq.rs @@ -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(); diff --git a/src/ser/mod.rs b/src/ser/mod.rs index 70314c8..6ba133e 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -39,8 +39,7 @@ 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 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)); @@ -48,8 +47,8 @@ where crate::ser::serializer::Serializer::new(&mut dst, &mut block, &mut patch_list); data.serialize(&mut ser)?; ser.dst.step_by_u32(FDT_END); - struct_len = ser.dst.get_offset(); - } + ser.dst.get_offset() + }; // Make header { let header = unsafe { &mut *(header.as_mut_ptr() as *mut Header) }; diff --git a/src/ser/serializer.rs b/src/ser/serializer.rs index 6c5f859..3757980 100644 --- a/src/ser/serializer.rs +++ b/src/ser/serializer.rs @@ -450,7 +450,7 @@ impl<'se> serde::ser::Serializer for &mut Serializer<'se> { #[cfg(test)] mod tests { - use serde_derive::Serialize; + use serde::Serialize; const MAX_SIZE: usize = 256 + 32; #[test] fn base_ser_test() { diff --git a/src/value/riscv_pmu.rs b/src/value/riscv_pmu.rs index e42da06..5ebb874 100644 --- a/src/value/riscv_pmu.rs +++ b/src/value/riscv_pmu.rs @@ -1,29 +1,33 @@ -use crate::buildin::Matrix; +use crate::buildin::*; -use serde_derive::Serialize; +use serde::{Deserialize, Serialize}; use core::ops::RangeInclusive; #[repr(transparent)] -#[derive(Serialize)] +#[derive(Deserialize, Serialize)] #[serde(transparent)] -pub struct EventToMhpmevent<'de>(Matrix<'de, 3>); +pub struct EventToMhpmevent<'a>(Matrix<'a, 3>); #[repr(transparent)] -#[derive(Serialize)] +#[derive(Deserialize, Serialize)] #[serde(transparent)] -pub struct EventToMhpmcounters<'de>(Matrix<'de, 3>); +pub struct EventToMhpmcounters<'a>(Matrix<'a, 3>); #[repr(transparent)] -#[derive(Serialize)] +#[derive(Deserialize, Serialize)] #[serde(transparent)] -pub struct RawEventToMhpcounters<'de>(Matrix<'de, 5>); +pub struct RawEventToMhpcounters<'a>(Matrix<'a, 5>); impl EventToMhpmevent<'_> { - pub fn get_len(&self) -> usize { + pub fn len(&self) -> usize { self.0.len() } + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + pub fn get_event_id(&self, i: usize) -> u32 { u32::from_be(self.0.get(i)[0]) } @@ -35,10 +39,14 @@ impl EventToMhpmevent<'_> { } impl EventToMhpmcounters<'_> { - pub fn get_len(&self) -> usize { + pub fn len(&self) -> usize { self.0.len() } + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + pub fn get_event_idx_range(&self, i: usize) -> RangeInclusive { let current = self.0.get(i); u32::from_be(current[0])..=u32::from_be(current[1]) @@ -51,10 +59,14 @@ impl EventToMhpmcounters<'_> { } impl RawEventToMhpcounters<'_> { - pub fn get_len(&self) -> usize { + pub fn len(&self) -> usize { self.0.len() } + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + pub fn get_event_idx_base(&self, i: usize) -> u64 { let current = self.0.get(i); ((u32::from_be(current[0]) as u64) << 32) | (u32::from_be(current[1]) as u64) @@ -70,3 +82,41 @@ impl RawEventToMhpcounters<'_> { u32::from_be(current[4]) } } + +#[cfg(test)] +mod tests { + use super::EventToMhpmcounters; + use crate::{Dtb, DtbPtr, buildin::Node, from_raw_mut}; + + const RAW_DEVICE_TREE: &[u8] = include_bytes!("../../examples/qemu-virt.dtb"); + const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len(); + #[test] + fn test_chosen_stdout() { + #[repr(align(8))] + struct AlignedBuffer { + pub data: [u8; RAW_DEVICE_TREE.len()], + } + let mut aligned_data: Box = Box::new(AlignedBuffer { + data: [0; BUFFER_SIZE], + }); + aligned_data.data[..BUFFER_SIZE].clone_from_slice(RAW_DEVICE_TREE); + let mut slice = aligned_data.data.to_vec(); + let ptr = DtbPtr::from_raw(slice.as_mut_ptr()).unwrap(); + let dtb = Dtb::from(ptr).share(); + + let node: Node = from_raw_mut(&dtb).unwrap(); + let result = node + .find("/pmu") + .unwrap() + .get_prop("riscv,event-to-mhpmcounters") + .unwrap() + .deserialize::(); + assert_eq!(result.len(), 5); + assert_eq!(result.get_event_idx_range(0), 1..=1); + assert_eq!(result.get_counter_bitmap(0), 0x7fff9); + assert_eq!(result.get_event_idx_range(1), 2..=2); + assert_eq!(result.get_counter_bitmap(1), 0x7fffc); + assert_eq!(result.get_event_idx_range(2), 0x10019..=0x10019); + assert_eq!(result.get_counter_bitmap(2), 0x7fff8); + } +} diff --git a/tests/bl808.rs b/tests/bl808.rs index 33afb63..0e016af 100644 --- a/tests/bl808.rs +++ b/tests/bl808.rs @@ -1,5 +1,4 @@ -// 在实际使用中,将这里的 `serde_derive::Deserialize` 改为 `serde::Deserialize`。 -use serde_derive::Deserialize; +use serde::Deserialize; use serde_device_tree::{Dtb, DtbPtr, buildin::NodeSeq, error::Error, from_raw_mut}; diff --git a/tests/hifive-unmatched-a00.rs b/tests/hifive-unmatched-a00.rs index e01238a..9c8ce51 100644 --- a/tests/hifive-unmatched-a00.rs +++ b/tests/hifive-unmatched-a00.rs @@ -1,4 +1,4 @@ -use serde_derive::Deserialize; +use serde::Deserialize; use serde_device_tree::Compatible; #[derive(Debug, Deserialize)] diff --git a/tests/qemu-virt.rs b/tests/qemu-virt.rs index 43c15b3..fa2e35b 100644 --- a/tests/qemu-virt.rs +++ b/tests/qemu-virt.rs @@ -1,5 +1,4 @@ -// 在实际使用中,将这里的 `serde_derive::Deserialize` 改为 `serde::Deserialize`。 -use serde_derive::Deserialize; +use serde::Deserialize; use serde_device_tree::{ Dtb, DtbPtr, From 4d22c454c40fd20c9e6c4dc9c8e2dd5be1e15bb7 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Thu, 27 Feb 2025 16:38:52 +0800 Subject: [PATCH 7/8] feat: add no_std support for ser Signed-off-by: Woshiluo Luo --- Cargo.toml | 4 ++-- src/ser/patch.rs | 6 +++--- src/ser/serializer.rs | 8 ++++++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6ae2c49..b73c02f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,11 +15,11 @@ edition = "2024" [dependencies] serde = { version = "1.0", default-features = false, features = ["derive"] } -erased-serde = { version = "0.4", optional = true } +dyn_serde = { version = "1.0.2", default-features = false, optional = true } [features] default = ["std", "ser"] -ser = ["dep:erased-serde"] +ser = ["dep:dyn_serde"] std = ["serde/std"] alloc = ["serde/alloc"] diff --git a/src/ser/patch.rs b/src/ser/patch.rs index 8210180..2a31881 100644 --- a/src/ser/patch.rs +++ b/src/ser/patch.rs @@ -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. @@ -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, @@ -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 ::erase(serializer)) + .serialize_dyn(&mut ::new(serializer)) .unwrap(); } } diff --git a/src/ser/serializer.rs b/src/ser/serializer.rs index 3757980..27c5da5 100644 --- a/src/ser/serializer.rs +++ b/src/ser/serializer.rs @@ -446,6 +446,14 @@ impl<'se> serde::ser::Serializer for &mut Serializer<'se> { ) -> Result { todo!("struct variant"); } + + #[cfg(not(feature = "std"))] + fn collect_str(self, _value: &T) -> Result + where + T: ?Sized + core::fmt::Display, + { + todo!() + } } #[cfg(test)] From 3320bf112f13a36ec94a67f233e3b1281559f96c Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Thu, 27 Feb 2025 22:36:20 +0800 Subject: [PATCH 8/8] fix: add inline hint Signed-off-by: Woshiluo Luo --- src/value/riscv_pmu.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/value/riscv_pmu.rs b/src/value/riscv_pmu.rs index 5ebb874..6548acb 100644 --- a/src/value/riscv_pmu.rs +++ b/src/value/riscv_pmu.rs @@ -1,3 +1,5 @@ +/// This module implement prop value described in +/// https://www.kernel.org/doc/Documentation/devicetree/bindings/perf/riscv%2Cpmu.yaml use crate::buildin::*; use serde::{Deserialize, Serialize}; @@ -20,18 +22,22 @@ pub struct EventToMhpmcounters<'a>(Matrix<'a, 3>); pub struct RawEventToMhpcounters<'a>(Matrix<'a, 5>); impl EventToMhpmevent<'_> { + #[inline(always)] pub fn len(&self) -> usize { self.0.len() } + #[inline(always)] pub fn is_empty(&self) -> bool { self.0.is_empty() } + #[inline(always)] pub fn get_event_id(&self, i: usize) -> u32 { u32::from_be(self.0.get(i)[0]) } + #[inline(always)] pub fn get_selector_value(&self, i: usize) -> u64 { let current = self.0.get(i); ((u32::from_be(current[1]) as u64) << 32) | (u32::from_be(current[2]) as u64) @@ -39,19 +45,23 @@ impl EventToMhpmevent<'_> { } impl EventToMhpmcounters<'_> { + #[inline(always)] pub fn len(&self) -> usize { self.0.len() } + #[inline(always)] pub fn is_empty(&self) -> bool { self.0.is_empty() } + #[inline(always)] pub fn get_event_idx_range(&self, i: usize) -> RangeInclusive { let current = self.0.get(i); u32::from_be(current[0])..=u32::from_be(current[1]) } + #[inline(always)] pub fn get_counter_bitmap(&self, i: usize) -> u32 { let current = self.0.get(i); u32::from_be(current[2]) @@ -59,24 +69,29 @@ impl EventToMhpmcounters<'_> { } impl RawEventToMhpcounters<'_> { + #[inline(always)] pub fn len(&self) -> usize { self.0.len() } + #[inline(always)] pub fn is_empty(&self) -> bool { self.0.is_empty() } + #[inline(always)] pub fn get_event_idx_base(&self, i: usize) -> u64 { let current = self.0.get(i); ((u32::from_be(current[0]) as u64) << 32) | (u32::from_be(current[1]) as u64) } + #[inline(always)] pub fn get_event_idx_mask(&self, i: usize) -> u64 { let current = self.0.get(i); ((u32::from_be(current[2]) as u64) << 32) | (u32::from_be(current[3]) as u64) } + #[inline(always)] pub fn get_counter_bitmap(&self, i: usize) -> u32 { let current = self.0.get(i); u32::from_be(current[4])