11pub mod patch;
22pub mod pointer;
33pub mod serializer;
4+
45pub mod string_block;
56
67use crate :: common:: * ;
@@ -9,14 +10,26 @@ use crate::ser::patch::Patch;
910// TODO: set reverse map
1011const RSVMAP_LEN : usize = 16 ;
1112
13+ #[ inline( always) ]
14+ fn get_structure_padding ( length : usize ) -> usize {
15+ let rem = length & ( ALIGN - 1 ) ;
16+ ALIGN - rem
17+ }
18+
1219/// Make dtb header with structure block and string block length.
13- fn make_header < ' se > ( writer : & ' se mut [ u8 ] , structure_length : u32 , string_block_length : u32 ) {
20+ fn make_header < ' se > (
21+ writer : & ' se mut [ u8 ] ,
22+ structure_length : u32 ,
23+ string_block_length : u32 ,
24+ ) -> usize {
1425 let ( header, _) = writer. split_at_mut ( HEADER_LEN as usize ) ;
1526 let header = unsafe { & mut * ( header. as_mut_ptr ( ) as * mut Header ) } ;
27+ let total_size =
28+ HEADER_PADDING_LEN + RSVMAP_LEN as u32 + structure_length + string_block_length;
29+ let padding = get_structure_padding ( total_size as usize ) ;
30+ let total_size = total_size + padding as u32 ;
1631 header. magic = u32:: from_be ( DEVICE_TREE_MAGIC ) ;
17- header. total_size = u32:: from_be (
18- HEADER_PADDING_LEN + RSVMAP_LEN as u32 + structure_length + string_block_length,
19- ) ;
32+ header. total_size = u32:: from_be ( total_size) ;
2033 assert_eq ! ( header. total_size % 8 , 0 ) ;
2134 header. off_dt_struct = u32:: from_be ( HEADER_PADDING_LEN + RSVMAP_LEN as u32 ) ;
2235 header. off_dt_strings = u32:: from_be ( HEADER_PADDING_LEN + RSVMAP_LEN as u32 + structure_length) ;
@@ -26,80 +39,83 @@ fn make_header<'se>(writer: &'se mut [u8], structure_length: u32, string_block_l
2639 header. boot_cpuid_phys = 0 ; // TODO
2740 header. size_dt_strings = u32:: from_be ( string_block_length as u32 ) ;
2841 header. size_dt_struct = u32:: from_be ( structure_length as u32 ) ;
42+
43+ total_size as usize
2944}
3045
3146/// Serialize the data to dtb, with a list fof Patch, write to the `writer`.
3247///
3348/// We do run-twice on convert, first time to generate string block, second time todo real
3449/// structure.
35- pub fn to_dtb < ' se , T > ( data : & T , list : & ' se [ Patch < ' se > ] , writer : & ' se mut [ u8 ] ) -> Result < ( ) , Error >
50+ pub fn to_dtb < ' se , T > (
51+ data : & T ,
52+ list : & ' se [ Patch < ' se > ] ,
53+ writer : & ' se mut [ u8 ] ,
54+ ) -> Result < usize , Error >
3655where
3756 T : serde:: ser:: Serialize ,
3857{
39- writer. iter_mut ( ) . for_each ( |x| * x = 0 ) ;
58+ writer. fill ( 0 ) ;
4059
41- let string_block_length = {
60+ let ( string_block_length, structure_length ) = {
4261 let mut offset: usize = 0 ;
43- {
44- let mut dst = crate :: ser:: pointer:: Pointer :: new ( None ) ;
45- let mut patch_list = crate :: ser:: patch:: PatchList :: new ( list) ;
46- let mut block = crate :: ser:: string_block:: StringBlock :: new ( writer, & mut offset) ;
47- let mut ser =
48- crate :: ser:: serializer:: SerializerInner :: new ( & mut dst, & mut block, & mut patch_list) ;
49- let ser = crate :: ser:: serializer:: Serializer :: new ( & mut ser) ;
50- data. serialize ( ser) ?;
51- offset
52- } ;
53- {
54- let mut block = crate :: ser:: string_block:: StringBlock :: new ( writer, & mut offset) ;
55- block. align ( ) ;
56- } ;
57- offset
62+ let mut block = crate :: ser:: string_block:: StringBlock :: new ( Some ( writer) , & mut offset) ;
63+ let mut dst = crate :: ser:: pointer:: Pointer :: new ( None ) ;
64+ let mut patch_list = crate :: ser:: patch:: PatchList :: new ( list) ;
65+ let mut ser =
66+ crate :: ser:: serializer:: SerializerInner :: new ( & mut dst, & mut block, & mut patch_list) ;
67+ let ser = crate :: ser:: serializer:: Serializer :: new ( & mut ser) ;
68+ let structure_length = data. serialize ( ser) ?. 1 ;
69+ ( offset, structure_length)
5870 } ;
5971
60- list. iter ( ) . for_each ( |patch| patch. init ( ) ) ;
61- let bottom_string_block_start = writer. len ( ) - string_block_length;
62- // Write to bottom, avoid overlap.
63- unsafe {
64- core:: ptr:: copy (
65- core:: ptr:: addr_of!( writer[ 0 ] ) ,
66- core:: ptr:: addr_of_mut!( writer[ bottom_string_block_start] ) ,
67- string_block_length,
68- ) ;
69- }
72+ // Clear string block
7073 writer[ 0 ..string_block_length] . fill ( 0 ) ;
74+ list. iter ( ) . for_each ( |patch| patch. init ( ) ) ;
75+ let string_block_start = HEADER_PADDING_LEN as usize + RSVMAP_LEN + structure_length;
7176
72- let structure_length = {
73- let ( data_block, string_block) = writer. split_at_mut ( writer . len ( ) - string_block_length ) ;
77+ {
78+ let ( data_block, string_block) = writer. split_at_mut ( string_block_start ) ;
7479 let ( _, data_block) = data_block. split_at_mut ( HEADER_PADDING_LEN as usize + RSVMAP_LEN ) ;
7580
7681 let mut patch_list = crate :: ser:: patch:: PatchList :: new ( list) ;
77- let mut temp_length = string_block_length;
78- let mut block = crate :: ser:: string_block:: StringBlock :: new ( string_block, & mut temp_length) ;
82+ let mut temp_length = 0 ;
83+ let mut block =
84+ crate :: ser:: string_block:: StringBlock :: new ( Some ( string_block) , & mut temp_length) ;
7985 let mut dst = crate :: ser:: pointer:: Pointer :: new ( Some ( data_block) ) ;
8086 let mut ser =
8187 crate :: ser:: serializer:: SerializerInner :: new ( & mut dst, & mut block, & mut patch_list) ;
8288 let ser = crate :: ser:: serializer:: Serializer :: new ( & mut ser) ;
8389 let struct_len = data. serialize ( ser) ?. 1 ;
84- assert_eq ! ( struct_len % 4 , 0 ) ; // As spec, structure block align with 4 bytes.
8590 assert_eq ! ( temp_length, string_block_length) ; // StringBlock should be same with first run.
8691 struct_len
8792 } ;
8893
89- unsafe {
90- core:: ptr:: copy (
91- core:: ptr:: addr_of!( writer[ writer. len( ) - string_block_length] ) ,
92- core:: ptr:: addr_of_mut!(
93- writer[ HEADER_PADDING_LEN as usize + RSVMAP_LEN + structure_length]
94- ) ,
95- string_block_length,
96- ) ;
97- }
98- writer[ bottom_string_block_start..] . fill ( 0 ) ;
94+ let result = make_header ( writer, structure_length as u32 , string_block_length as u32 ) ;
95+
96+ Ok ( result)
97+ }
9998
100- make_header ( writer, structure_length as u32 , string_block_length as u32 ) ;
99+ #[ cfg( feature = "alloc" ) ]
100+ pub fn probe_dtb_length < ' se , T > ( data : & T , list : & ' se [ Patch < ' se > ] ) -> Result < usize , Error >
101+ where
102+ T : serde:: ser:: Serialize ,
103+ {
104+ let mut offset: usize = 0 ;
105+ let structure_length = {
106+ let mut dst = crate :: ser:: pointer:: Pointer :: new ( None ) ;
107+ let mut patch_list = crate :: ser:: patch:: PatchList :: new ( list) ;
108+ let mut block = crate :: ser:: string_block:: StringBlock :: new ( None , & mut offset) ;
109+ let mut ser =
110+ crate :: ser:: serializer:: SerializerInner :: new ( & mut dst, & mut block, & mut patch_list) ;
111+ let ser = crate :: ser:: serializer:: Serializer :: new ( & mut ser) ;
112+ data. serialize ( ser) ?. 1
113+ } ;
101114
102- Ok ( ( ) )
115+ let total_size = HEADER_PADDING_LEN as usize + RSVMAP_LEN + structure_length + offset;
116+ let padding = get_structure_padding ( total_size) ;
117+ let total_size = total_size + padding;
118+ Ok ( total_size)
103119}
104120
105121#[ derive( Debug ) ]
0 commit comments