Skip to content

Commit d658f0e

Browse files
committed
feat(ser): now ser will not use full buffer
fix(ser): some align issue Signed-off-by: Woshiluo Luo <[email protected]>
1 parent 7c57ba6 commit d658f0e

File tree

3 files changed

+61
-24
lines changed

3 files changed

+61
-24
lines changed

src/common.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ pub(crate) const FDT_NOP: u32 = 0x4;
2727
pub(crate) const FDT_END: u32 = 0x9;
2828
pub(crate) const SUPPORTED_VERSION: u32 = 17;
2929

30+
// In spec 5.6:
31+
// Specifically, the memory reservation block shall
32+
// be aligned to an 8-byte boundary and the structure
33+
// block to a 4-byte boundary.
34+
pub(crate) const OFFSET_ALIGN: u32 = 64;
35+
pub(crate) const HEADER_PADDING_LEN: u32 = HEADER_LEN.div_ceil(OFFSET_ALIGN) * OFFSET_ALIGN;
36+
3037
impl Header {
3138
pub fn verify(&self) -> Result<(), Error> {
3239
let header_base = self as *const _ as usize;

src/ser/mod.rs

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,49 +19,70 @@ where
1919
{
2020
writer.iter_mut().for_each(|x| *x = 0);
2121

22-
let mut offset: usize = 0;
23-
{
24-
let mut dst = crate::ser::pointer::Pointer::new(None);
25-
let mut patch_list = crate::ser::patch::PatchList::new(list);
26-
let mut block = crate::ser::string_block::StringBlock::new(writer, &mut offset);
27-
let mut ser =
28-
crate::ser::serializer::SerializerInner::new(&mut dst, &mut block, &mut patch_list);
29-
let ser = crate::ser::serializer::Serializer::new(&mut ser);
30-
data.serialize(ser)?;
22+
let string_block_length = {
23+
let mut offset: usize = 0;
24+
{
25+
let mut dst = crate::ser::pointer::Pointer::new(None);
26+
let mut patch_list = crate::ser::patch::PatchList::new(list);
27+
let mut block = crate::ser::string_block::StringBlock::new(writer, &mut offset);
28+
let mut ser =
29+
crate::ser::serializer::SerializerInner::new(&mut dst, &mut block, &mut patch_list);
30+
let ser = crate::ser::serializer::Serializer::new(&mut ser);
31+
data.serialize(ser)?;
32+
offset
33+
};
34+
{
35+
let mut block = crate::ser::string_block::StringBlock::new(writer, &mut offset);
36+
block.align();
37+
};
38+
offset
3139
};
3240
list.iter().for_each(|patch| patch.init());
3341
// Write from bottom to top, to avoid overlap.
34-
for i in (0..offset).rev() {
35-
writer[writer.len() - offset + i] = writer[i];
42+
for i in (0..string_block_length).rev() {
43+
writer[writer.len() - string_block_length + i] = writer[i];
3644
writer[i] = 0;
3745
}
38-
// TODO: make sure no out of bound.
3946

40-
let writer_len = writer.len();
41-
let (data_block, string_block) = writer.split_at_mut(writer.len() - offset);
42-
let (header, data_block) = data_block.split_at_mut(HEADER_LEN as usize + RSVMAP_LEN);
4347
let struct_len = {
48+
let (data_block, string_block) = writer.split_at_mut(writer.len() - string_block_length);
49+
let (_, data_block) = data_block.split_at_mut(HEADER_PADDING_LEN as usize + RSVMAP_LEN);
4450
let mut patch_list = crate::ser::patch::PatchList::new(list);
45-
let mut block = crate::ser::string_block::StringBlock::new(string_block, &mut offset);
51+
let mut temp_length = string_block_length;
52+
let mut block = crate::ser::string_block::StringBlock::new(string_block, &mut temp_length);
4653
let mut dst = crate::ser::pointer::Pointer::new(Some(data_block));
4754
let mut ser =
4855
crate::ser::serializer::SerializerInner::new(&mut dst, &mut block, &mut patch_list);
4956
let ser = crate::ser::serializer::Serializer::new(&mut ser);
50-
data.serialize(ser)?
57+
let struct_len = data.serialize(ser)?.1;
58+
assert_eq!(struct_len % 4, 0); // As spec, structure block align with 4 bytes.
59+
assert_eq!(temp_length, string_block_length); // StringBlock should be same with first run.
60+
struct_len
61+
};
62+
63+
// Align to 8-bytes.
64+
for i in 0..string_block_length {
65+
writer[HEADER_PADDING_LEN as usize + RSVMAP_LEN + struct_len + i] =
66+
writer[writer.len() - string_block_length + i];
67+
writer[writer.len() - string_block_length + i] = 0;
5168
}
52-
.1;
69+
5370
// Make header
5471
{
72+
let (header, _) = writer.split_at_mut(HEADER_LEN as usize);
5573
let header = unsafe { &mut *(header.as_mut_ptr() as *mut Header) };
5674
header.magic = u32::from_be(DEVICE_TREE_MAGIC);
57-
header.total_size = u32::from_be(writer_len as u32);
58-
header.off_dt_struct = u32::from_be(HEADER_LEN + RSVMAP_LEN as u32);
59-
header.off_dt_strings = u32::from_be((writer_len - offset) as u32);
60-
header.off_mem_rsvmap = u32::from_be(HEADER_LEN);
75+
header.total_size = u32::from_be(
76+
HEADER_PADDING_LEN + (RSVMAP_LEN + struct_len + string_block_length) as u32,
77+
);
78+
assert_eq!(header.total_size % 8, 0);
79+
header.off_dt_struct = u32::from_be(HEADER_PADDING_LEN + RSVMAP_LEN as u32);
80+
header.off_dt_strings = u32::from_be(HEADER_PADDING_LEN + (RSVMAP_LEN + struct_len) as u32);
81+
header.off_mem_rsvmap = u32::from_be(HEADER_PADDING_LEN);
6182
header.version = u32::from_be(SUPPORTED_VERSION);
6283
header.last_comp_version = u32::from_be(SUPPORTED_VERSION); // TODO: maybe 16
63-
header.boot_cpuid_phys = 0; // TODO: wtf is this prop
64-
header.size_dt_strings = u32::from_be(offset as u32);
84+
header.boot_cpuid_phys = 0; // TODO
85+
header.size_dt_strings = u32::from_be(string_block_length as u32);
6586
header.size_dt_struct = u32::from_be(struct_len as u32);
6687
}
6788
Ok(())

src/ser/string_block.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ impl<'se> StringBlock<'se> {
5151
result
5252
}
5353

54+
/// Align string block size to 8 bytes
55+
#[inline(always)]
56+
pub fn align(&mut self) {
57+
while (*self.end & 0b111) != 0 {
58+
self.data[*self.end] = 0;
59+
*self.end += 1;
60+
}
61+
}
62+
5463
/// Find a string. If not found, insert it.
5564
#[inline(always)]
5665
pub fn find_or_insert(&mut self, name: &str) -> usize {

0 commit comments

Comments
 (0)