11pub mod patch;
22pub mod pointer;
33pub mod serializer;
4+
45pub mod string_block;
56
67use crate :: common:: * ;
@@ -9,83 +10,112 @@ 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+
19+ /// Make dtb header with structure block and string block length.
20+ fn make_header < ' se > (
21+ writer : & ' se mut [ u8 ] ,
22+ structure_length : u32 ,
23+ string_block_length : u32 ,
24+ ) -> usize {
25+ let ( header, _) = writer. split_at_mut ( HEADER_LEN as usize ) ;
26+ 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 ;
31+ header. magic = u32:: from_be ( DEVICE_TREE_MAGIC ) ;
32+ header. total_size = u32:: from_be ( total_size) ;
33+ assert_eq ! ( header. total_size % 8 , 0 ) ;
34+ header. off_dt_struct = u32:: from_be ( HEADER_PADDING_LEN + RSVMAP_LEN as u32 ) ;
35+ header. off_dt_strings = u32:: from_be ( HEADER_PADDING_LEN + RSVMAP_LEN as u32 + structure_length) ;
36+ header. off_mem_rsvmap = u32:: from_be ( HEADER_PADDING_LEN ) ;
37+ header. version = u32:: from_be ( SUPPORTED_VERSION ) ;
38+ header. last_comp_version = u32:: from_be ( SUPPORTED_VERSION ) ; // TODO: maybe 16
39+ header. boot_cpuid_phys = 0 ; // TODO
40+ header. size_dt_strings = u32:: from_be ( string_block_length as u32 ) ;
41+ header. size_dt_struct = u32:: from_be ( structure_length as u32 ) ;
42+
43+ total_size as usize
44+ }
45+
1246/// Serialize the data to dtb, with a list fof Patch, write to the `writer`.
1347///
1448/// We do run-twice on convert, first time to generate string block, second time todo real
1549/// structure.
16- 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 >
1755where
1856 T : serde:: ser:: Serialize ,
1957{
20- writer. iter_mut ( ) . for_each ( |x| * x = 0 ) ;
58+ writer. fill ( 0 ) ;
2159
22- let string_block_length = {
60+ let ( string_block_length, structure_length ) = {
2361 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
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)
3970 } ;
71+
72+ // Clear string block
73+ writer[ 0 ..string_block_length] . fill ( 0 ) ;
4074 list. iter ( ) . for_each ( |patch| patch. init ( ) ) ;
41- // Write from bottom to top, to avoid overlap.
42- for i in ( 0 ..string_block_length) . rev ( ) {
43- writer[ writer. len ( ) - string_block_length + i] = writer[ i] ;
44- writer[ i] = 0 ;
45- }
75+ let string_block_start = HEADER_PADDING_LEN as usize + RSVMAP_LEN + structure_length;
4676
47- let struct_len = {
48- 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 ) ;
4979 let ( _, data_block) = data_block. split_at_mut ( HEADER_PADDING_LEN as usize + RSVMAP_LEN ) ;
80+
5081 let mut patch_list = crate :: ser:: patch:: PatchList :: new ( list) ;
51- let mut temp_length = string_block_length;
52- 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) ;
5385 let mut dst = crate :: ser:: pointer:: Pointer :: new ( Some ( data_block) ) ;
5486 let mut ser =
5587 crate :: ser:: serializer:: SerializerInner :: new ( & mut dst, & mut block, & mut patch_list) ;
5688 let ser = crate :: ser:: serializer:: Serializer :: new ( & mut ser) ;
5789 let struct_len = data. serialize ( ser) ?. 1 ;
58- assert_eq ! ( struct_len % 4 , 0 ) ; // As spec, structure block align with 4 bytes.
5990 assert_eq ! ( temp_length, string_block_length) ; // StringBlock should be same with first run.
6091 struct_len
6192 } ;
6293
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 ;
68- }
94+ let result = make_header ( writer, structure_length as u32 , string_block_length as u32 ) ;
6995
70- // Make header
71- {
72- let ( header, _) = writer. split_at_mut ( HEADER_LEN as usize ) ;
73- let header = unsafe { & mut * ( header. as_mut_ptr ( ) as * mut Header ) } ;
74- header. magic = u32:: from_be ( DEVICE_TREE_MAGIC ) ;
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 ) ;
82- header. version = u32:: from_be ( SUPPORTED_VERSION ) ;
83- header. last_comp_version = u32:: from_be ( SUPPORTED_VERSION ) ; // TODO: maybe 16
84- header. boot_cpuid_phys = 0 ; // TODO
85- header. size_dt_strings = u32:: from_be ( string_block_length as u32 ) ;
86- header. size_dt_struct = u32:: from_be ( struct_len as u32 ) ;
87- }
88- Ok ( ( ) )
96+ Ok ( result)
97+ }
98+
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+ } ;
114+
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)
89119}
90120
91121#[ derive( Debug ) ]
0 commit comments