1
1
pub mod patch;
2
2
pub mod pointer;
3
3
pub mod serializer;
4
+
4
5
pub mod string_block;
5
6
6
7
use crate :: common:: * ;
@@ -9,83 +10,112 @@ use crate::ser::patch::Patch;
9
10
// TODO: set reverse map
10
11
const RSVMAP_LEN : usize = 16 ;
11
12
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
+
12
46
/// Serialize the data to dtb, with a list fof Patch, write to the `writer`.
13
47
///
14
48
/// We do run-twice on convert, first time to generate string block, second time todo real
15
49
/// 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 >
17
55
where
18
56
T : serde:: ser:: Serialize ,
19
57
{
20
- writer. iter_mut ( ) . for_each ( |x| * x = 0 ) ;
58
+ writer. fill ( 0 ) ;
21
59
22
- let string_block_length = {
60
+ let ( string_block_length, structure_length ) = {
23
61
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)
39
70
} ;
71
+
72
+ // Clear string block
73
+ writer[ 0 ..string_block_length] . fill ( 0 ) ;
40
74
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;
46
76
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 ) ;
49
79
let ( _, data_block) = data_block. split_at_mut ( HEADER_PADDING_LEN as usize + RSVMAP_LEN ) ;
80
+
50
81
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) ;
53
85
let mut dst = crate :: ser:: pointer:: Pointer :: new ( Some ( data_block) ) ;
54
86
let mut ser =
55
87
crate :: ser:: serializer:: SerializerInner :: new ( & mut dst, & mut block, & mut patch_list) ;
56
88
let ser = crate :: ser:: serializer:: Serializer :: new ( & mut ser) ;
57
89
let struct_len = data. serialize ( ser) ?. 1 ;
58
- assert_eq ! ( struct_len % 4 , 0 ) ; // As spec, structure block align with 4 bytes.
59
90
assert_eq ! ( temp_length, string_block_length) ; // StringBlock should be same with first run.
60
91
struct_len
61
92
} ;
62
93
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 ) ;
69
95
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)
89
119
}
90
120
91
121
#[ derive( Debug ) ]
0 commit comments