4
4
5
5
use std:: {
6
6
fs,
7
+ io:: Write ,
7
8
path:: { Path , PathBuf } ,
8
9
} ;
9
10
@@ -101,6 +102,9 @@ pub fn save_elf_as_image(
101
102
flash_mode : Option < FlashMode > ,
102
103
flash_size : Option < FlashSize > ,
103
104
flash_freq : Option < FlashFrequency > ,
105
+ merge : bool ,
106
+ bootloader_path : Option < PathBuf > ,
107
+ partition_table_path : Option < PathBuf > ,
104
108
) -> Result < ( ) > {
105
109
let image = FirmwareImageBuilder :: new ( elf_data)
106
110
. flash_mode ( flash_mode)
@@ -112,7 +116,7 @@ pub fn save_elf_as_image(
112
116
let parts: Vec < _ > = flash_image. ota_segments ( ) . collect ( ) ;
113
117
114
118
match parts. as_slice ( ) {
115
- [ single] => fs:: write ( path, & single. data ) . into_diagnostic ( ) ?,
119
+ [ single] => fs:: write ( & path, & single. data ) . into_diagnostic ( ) ?,
116
120
parts => {
117
121
for part in parts {
118
122
let part_path = format ! ( "{:#x}_{}" , part. addr, path. display( ) ) ;
@@ -121,6 +125,77 @@ pub fn save_elf_as_image(
121
125
}
122
126
}
123
127
128
+ // merge_bin is TRUE
129
+ // merge bootloader, partition table and app binaries
130
+ // basic functionality, only merge 3 binaries
131
+ if merge {
132
+ // If the '-B' option is provided, load the bootloader binary file at the
133
+ // specified path.
134
+ let bootloader = if let Some ( bootloader_path) = bootloader_path {
135
+ let path = fs:: canonicalize ( bootloader_path) . into_diagnostic ( ) ?;
136
+ let data = fs:: read ( path) . into_diagnostic ( ) ?;
137
+
138
+ Some ( data)
139
+ } else {
140
+ None
141
+ } ;
142
+
143
+ // If the '-T' option is provided, load the partition table from
144
+ // the CSV at the specified path.
145
+ let partition_table = if let Some ( partition_table_path) = partition_table_path {
146
+ let path = fs:: canonicalize ( partition_table_path) . into_diagnostic ( ) ?;
147
+ let data = fs:: read_to_string ( path)
148
+ . into_diagnostic ( )
149
+ . wrap_err ( "Failed to open partition table" ) ?;
150
+
151
+ let table =
152
+ PartitionTable :: try_from_str ( data) . wrap_err ( "Failed to parse partition table" ) ?;
153
+
154
+ Some ( table)
155
+ } else {
156
+ None
157
+ } ;
158
+
159
+ // To get a chip revision, the connection is needed
160
+ // For simplicity, the revision None is used
161
+ let image =
162
+ chip. get_flash_image ( & image, bootloader, partition_table, image_format, None ) ?;
163
+
164
+ let merged_bin = format ! (
165
+ "merged_{path}" ,
166
+ path = & path. to_str( ) . unwrap_or( "merged_bins.bin" )
167
+ ) ;
168
+
169
+ if Path :: new ( & merged_bin) . exists ( ) {
170
+ fs:: remove_file ( & merged_bin) . into_diagnostic ( ) ?;
171
+ }
172
+
173
+ let mut file = fs:: OpenOptions :: new ( )
174
+ . write ( true )
175
+ . create_new ( true )
176
+ . open ( merged_bin)
177
+ . into_diagnostic ( ) ?;
178
+
179
+ for segment in image. flash_segments ( ) {
180
+ let padding_bytes = vec ! [
181
+ 0xffu8 ;
182
+ segment. addr as usize
183
+ - file. metadata( ) . into_diagnostic( ) ?. len( ) as usize
184
+ ] ;
185
+ file. write_all ( & padding_bytes) . into_diagnostic ( ) ?;
186
+ file. write_all ( & segment. data ) . into_diagnostic ( ) ?;
187
+ }
188
+
189
+ // Take flash_size as input parameter, if None, use default value of 4Mb
190
+ let padding_bytes = vec ! [
191
+ 0xffu8 ;
192
+ flash_size. unwrap_or( FlashSize :: Flash4Mb ) . size( ) as usize
193
+ - file. metadata( ) . into_diagnostic( ) ?. len( ) as usize
194
+ ] ;
195
+ file. write_all ( & padding_bytes) . into_diagnostic ( ) ?;
196
+ }
197
+
198
+ println ! ( "The final merge binary was created successfully." ) ;
124
199
Ok ( ( ) )
125
200
}
126
201
0 commit comments