Skip to content
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
7 changes: 7 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ pub(crate) const FDT_NOP: u32 = 0x4;
pub(crate) const FDT_END: u32 = 0x9;
pub(crate) const SUPPORTED_VERSION: u32 = 17;

// In spec 5.6:
// Specifically, the memory reservation block shall
// be aligned to an 8-byte boundary and the structure
// block to a 4-byte boundary.
pub(crate) const OFFSET_ALIGN: u32 = 64;
pub(crate) const HEADER_PADDING_LEN: u32 = HEADER_LEN.div_ceil(OFFSET_ALIGN) * OFFSET_ALIGN;

impl Header {
pub fn verify(&self) -> Result<(), Error> {
let header_base = self as *const _ as usize;
Expand Down
69 changes: 45 additions & 24 deletions src/ser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,49 +19,70 @@ where
{
writer.iter_mut().for_each(|x| *x = 0);

let mut offset: usize = 0;
{
let mut dst = crate::ser::pointer::Pointer::new(None);
let mut patch_list = crate::ser::patch::PatchList::new(list);
let mut block = crate::ser::string_block::StringBlock::new(writer, &mut offset);
let mut ser =
crate::ser::serializer::SerializerInner::new(&mut dst, &mut block, &mut patch_list);
let ser = crate::ser::serializer::Serializer::new(&mut ser);
data.serialize(ser)?;
let string_block_length = {
let mut offset: usize = 0;
{
let mut dst = crate::ser::pointer::Pointer::new(None);
let mut patch_list = crate::ser::patch::PatchList::new(list);
let mut block = crate::ser::string_block::StringBlock::new(writer, &mut offset);
let mut ser =
crate::ser::serializer::SerializerInner::new(&mut dst, &mut block, &mut patch_list);
let ser = crate::ser::serializer::Serializer::new(&mut ser);
data.serialize(ser)?;
offset
};
{
let mut block = crate::ser::string_block::StringBlock::new(writer, &mut offset);
block.align();
};
offset
};
list.iter().for_each(|patch| patch.init());
// Write from bottom to top, to avoid overlap.
for i in (0..offset).rev() {
writer[writer.len() - offset + i] = writer[i];
for i in (0..string_block_length).rev() {
writer[writer.len() - string_block_length + i] = writer[i];
writer[i] = 0;
}
// TODO: make sure no out of bound.

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 (data_block, string_block) = writer.split_at_mut(writer.len() - string_block_length);
let (_, data_block) = data_block.split_at_mut(HEADER_PADDING_LEN as usize + RSVMAP_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 temp_length = string_block_length;
let mut block = crate::ser::string_block::StringBlock::new(string_block, &mut temp_length);
let mut dst = crate::ser::pointer::Pointer::new(Some(data_block));
let mut ser =
crate::ser::serializer::SerializerInner::new(&mut dst, &mut block, &mut patch_list);
let ser = crate::ser::serializer::Serializer::new(&mut ser);
data.serialize(ser)?
let struct_len = data.serialize(ser)?.1;
assert_eq!(struct_len % 4, 0); // As spec, structure block align with 4 bytes.
assert_eq!(temp_length, string_block_length); // StringBlock should be same with first run.
struct_len
};

// Align to 8-bytes.
for i in 0..string_block_length {
writer[HEADER_PADDING_LEN as usize + RSVMAP_LEN + struct_len + i] =
writer[writer.len() - string_block_length + i];
writer[writer.len() - string_block_length + i] = 0;
}
.1;

// Make header
{
let (header, _) = writer.split_at_mut(HEADER_LEN as usize);
let header = unsafe { &mut *(header.as_mut_ptr() as *mut Header) };
header.magic = u32::from_be(DEVICE_TREE_MAGIC);
header.total_size = u32::from_be(writer_len as u32);
header.off_dt_struct = u32::from_be(HEADER_LEN + RSVMAP_LEN as u32);
header.off_dt_strings = u32::from_be((writer_len - offset) as u32);
header.off_mem_rsvmap = u32::from_be(HEADER_LEN);
header.total_size = u32::from_be(
HEADER_PADDING_LEN + (RSVMAP_LEN + struct_len + string_block_length) as u32,
);
assert_eq!(header.total_size % 8, 0);
header.off_dt_struct = u32::from_be(HEADER_PADDING_LEN + RSVMAP_LEN as u32);
header.off_dt_strings = u32::from_be(HEADER_PADDING_LEN + (RSVMAP_LEN + struct_len) as u32);
header.off_mem_rsvmap = u32::from_be(HEADER_PADDING_LEN);
header.version = u32::from_be(SUPPORTED_VERSION);
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.boot_cpuid_phys = 0; // TODO
header.size_dt_strings = u32::from_be(string_block_length as u32);
header.size_dt_struct = u32::from_be(struct_len as u32);
}
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion src/ser/serializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ impl<'se> serde::ser::Serializer for Serializer<'_, 'se> {
#[cfg(test)]
mod tests {
use serde::Serialize;
const MAX_SIZE: usize = 256 + 32;
const MAX_SIZE: usize = 256 + 128;
#[test]
fn base_ser_test() {
#[derive(Serialize)]
Expand Down
9 changes: 9 additions & 0 deletions src/ser/string_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ impl<'se> StringBlock<'se> {
result
}

/// Align string block size to 8 bytes
#[inline(always)]
pub fn align(&mut self) {
while (*self.end & 0b111) != 0 {
self.data[*self.end] = 0;
*self.end += 1;
}
}

/// Find a string. If not found, insert it.
#[inline(always)]
pub fn find_or_insert(&mut self, name: &str) -> usize {
Expand Down