44
55use std:: {
66 fs,
7+ io:: Write ,
78 path:: { Path , PathBuf } ,
89} ;
910
@@ -101,6 +102,9 @@ pub fn save_elf_as_image(
101102 flash_mode : Option < FlashMode > ,
102103 flash_size : Option < FlashSize > ,
103104 flash_freq : Option < FlashFrequency > ,
105+ merge : bool ,
106+ bootloader_path : Option < PathBuf > ,
107+ partition_table_path : Option < PathBuf > ,
104108) -> Result < ( ) > {
105109 let image = FirmwareImageBuilder :: new ( elf_data)
106110 . flash_mode ( flash_mode)
@@ -112,7 +116,7 @@ pub fn save_elf_as_image(
112116 let parts: Vec < _ > = flash_image. ota_segments ( ) . collect ( ) ;
113117
114118 match parts. as_slice ( ) {
115- [ single] => fs:: write ( path, & single. data ) . into_diagnostic ( ) ?,
119+ [ single] => fs:: write ( & path, & single. data ) . into_diagnostic ( ) ?,
116120 parts => {
117121 for part in parts {
118122 let part_path = format ! ( "{:#x}_{}" , part. addr, path. display( ) ) ;
@@ -121,6 +125,77 @@ pub fn save_elf_as_image(
121125 }
122126 }
123127
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." ) ;
124199 Ok ( ( ) )
125200}
126201
0 commit comments