Skip to content

Commit e388a59

Browse files
committed
feat: add support for serialize
Signed-off-by: Woshiluo Luo <[email protected]>
1 parent c69ea21 commit e388a59

File tree

4 files changed

+75
-17
lines changed

4 files changed

+75
-17
lines changed

examples/serialize.rs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use serde_derive::Serialize;
2+
use std::io::prelude::*;
3+
4+
const MAX_SIZE: usize = 256 + 32;
5+
6+
fn main() {
7+
#[derive(Serialize)]
8+
struct Base {
9+
pub hello: u32,
10+
pub base1: Base1,
11+
pub hello2: u32,
12+
pub base2: Base1,
13+
}
14+
#[derive(Serialize)]
15+
struct Base1 {
16+
pub hello: &'static str,
17+
}
18+
let mut buf1 = [0u8; MAX_SIZE];
19+
20+
{
21+
let new_base = Base1 { hello: "added" };
22+
let patch = serde_device_tree::ser::patch::Patch::new("/base3", &new_base as _);
23+
let mut list = [patch];
24+
let base = Base {
25+
hello: 0xdeedbeef,
26+
base1: Base1 {
27+
hello: "Hello, World!",
28+
},
29+
hello2: 0x11223344,
30+
base2: Base1 { hello: "Roger" },
31+
};
32+
serde_device_tree::ser::to_dtb(&base, &mut list, &mut buf1).unwrap();
33+
}
34+
let mut file = std::fs::File::create("gen.dtb").unwrap();
35+
file.write_all(&buf1).unwrap();
36+
}

src/common.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub(crate) struct Header {
1515
pub size_dt_struct: u32,
1616
}
1717

18-
const DEVICE_TREE_MAGIC: u32 = 0xD00DFEED;
18+
pub const DEVICE_TREE_MAGIC: u32 = 0xD00DFEED;
1919
const U32_LEN: u32 = core::mem::size_of::<u32>() as _;
2020

2121
pub(crate) const ALIGN: usize = core::mem::align_of::<usize>();

src/ser/mod.rs

+28-11
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@ pub mod string_block;
66
use crate::common::*;
77
use crate::ser::patch::Patch;
88

9+
const RSVMAP_LEN: usize = 16;
10+
911
/// We do run-twice on convert, first time to generate string block, second time todo real
1012
/// structure.
1113
pub fn to_dtb<'se, T>(data: &T, list: &'se [Patch<'se>], writer: &'se mut [u8]) -> Result<(), Error>
1214
where
1315
T: serde::ser::Serialize,
1416
{
17+
writer.iter_mut().for_each(|x| *x = 0);
18+
1519
let mut offset: usize = 0;
1620
{
1721
let mut dst = crate::ser::pointer::Pointer::new(None);
@@ -22,24 +26,37 @@ where
2226
data.serialize(&mut ser)?;
2327
};
2428
list.iter().for_each(|patch| patch.init());
25-
{
26-
// Write from bottom to top, to avoid overlap.
27-
for i in (0..offset).rev() {
28-
writer[writer.len() - offset + i] = writer[i];
29-
writer[i] = 0;
30-
}
31-
// TODO: make sure no out of bound.
29+
// Write from bottom to top, to avoid overlap.
30+
for i in (0..offset).rev() {
31+
writer[writer.len() - offset + i] = writer[i];
32+
writer[i] = 0;
33+
}
34+
// TODO: make sure no out of bound.
3235

33-
// -1 for end zero.
34-
let (data_block, string_block) = writer.split_at_mut(writer.len() - offset);
35-
let (_, data_block) = data_block.split_at_mut(size_of::<crate::common::Header>());
36+
let writer_len = writer.len();
37+
let (data_block, string_block) = writer.split_at_mut(writer.len() - offset);
38+
let (header, data_block) = data_block.split_at_mut(HEADER_LEN as usize + RSVMAP_LEN);
39+
{
3640
let mut patch_list = crate::ser::patch::PatchList::new(list);
3741
let mut block = crate::ser::string_block::StringBlock::new(string_block, &mut offset);
3842
let mut dst = crate::ser::pointer::Pointer::new(Some(data_block));
3943
let mut ser =
4044
crate::ser::serializer::Serializer::new(&mut dst, &mut block, &mut patch_list);
41-
ser.dst.step_by_u32(FDT_END);
4245
data.serialize(&mut ser)?;
46+
ser.dst.step_by_u32(FDT_END);
47+
}
48+
{
49+
let header = unsafe { &mut *(header.as_mut_ptr() as *mut Header) };
50+
header.magic = u32::from_be(DEVICE_TREE_MAGIC);
51+
header.total_size = u32::from_be(writer_len as u32);
52+
header.off_dt_struct = u32::from_be(HEADER_LEN + RSVMAP_LEN as u32);
53+
header.off_dt_strings = u32::from_be((writer_len - offset) as u32);
54+
header.off_mem_rsvmap = u32::from_be(HEADER_LEN);
55+
header.version = u32::from_be(SUPPORTED_VERSION);
56+
header.last_comp_version = u32::from_be(SUPPORTED_VERSION); // TODO: maybe 16
57+
header.boot_cpuid_phys = 0; // TODO: wtf is this prop
58+
header.size_dt_strings = u32::from_be(offset as u32);
59+
header.size_dt_struct = u32::from_be(data_block.len() as u32); // TODO: correct?
4360
}
4461
Ok(())
4562
}

src/ser/serializer.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub struct Serializer<'se> {
1414
pub dst: &'se mut Pointer<'se>,
1515
string_block: &'se mut StringBlock<'se>,
1616
value_type: ValueType,
17+
current_name: &'se str,
1718
current_dep: usize,
1819
patch_list: &'se mut PatchList<'se>,
1920
}
@@ -28,6 +29,7 @@ impl<'se> Serializer<'se> {
2829
dst,
2930
string_block: cache,
3031
current_dep: 0,
32+
current_name: "",
3133
value_type: ValueType::Node,
3234
patch_list,
3335
}
@@ -46,8 +48,10 @@ impl<'a, 'se> SerializeDynamicField<'se> for &'a mut Serializer<'se> {
4648
T: serde::ser::Serialize + ?Sized,
4749
{
4850
let prop_header_offset = self.dst.step_by_prop();
49-
let old_value_type = self.value_type;
51+
let prev_type = self.value_type;
52+
let prev_name = self.current_name;
5053
self.current_dep += 1;
54+
self.current_name = key;
5155
let matched_patch = self.patch_list.step_forward(key, self.current_dep);
5256

5357
match matched_patch {
@@ -75,7 +79,8 @@ impl<'a, 'se> SerializeDynamicField<'se> for &'a mut Serializer<'se> {
7579
);
7680
}
7781

78-
self.value_type = old_value_type;
82+
self.value_type = prev_type;
83+
self.current_name = prev_name;
7984
self.dst.step_align();
8085
self.patch_list.step_back(self.current_dep);
8186
self.current_dep -= 1;
@@ -373,15 +378,15 @@ impl<'a, 'se> serde::ser::Serializer for &'a mut Serializer<'se> {
373378

374379
fn serialize_struct(
375380
self,
376-
name: &'static str,
381+
_name: &'static str,
377382
_len: usize,
378383
) -> Result<Self::SerializeStruct, Self::Error> {
379384
self.dst.step_by_u32(FDT_BEGIN_NODE);
380385
if self.current_dep == 0 {
381386
// The name of root node should be empty.
382387
self.dst.step_by_u32(0);
383388
} else {
384-
self.dst.step_by_name(name);
389+
self.dst.step_by_name(self.current_name);
385390
}
386391
self.value_type = ValueType::Node;
387392
Ok(self)
@@ -401,7 +406,7 @@ impl<'a, 'se> serde::ser::Serializer for &'a mut Serializer<'se> {
401406
#[cfg(test)]
402407
mod tests {
403408
use serde_derive::Serialize;
404-
const MAX_SIZE: usize = 256;
409+
const MAX_SIZE: usize = 256 + 32;
405410
#[test]
406411
fn base_ser_test() {
407412
#[derive(Serialize)]

0 commit comments

Comments
 (0)