33//! This module defines the traits and types used for flashing operations on a
44//! target device's flash memory.
55
6- use std:: io:: Write ;
6+ use std:: { io:: Write , iter :: repeat_n } ;
77
88use flate2:: {
99 Compression ,
@@ -34,7 +34,7 @@ pub struct Esp32Target {
3434 use_stub : bool ,
3535 verify : bool ,
3636 skip : bool ,
37- need_deflate_end : bool ,
37+ need_flash_end : bool ,
3838}
3939
4040impl Esp32Target {
@@ -52,7 +52,7 @@ impl Esp32Target {
5252 use_stub,
5353 verify,
5454 skip,
55- need_deflate_end : false ,
55+ need_flash_end : false ,
5656 }
5757 }
5858}
@@ -79,7 +79,10 @@ impl FlashTarget for Esp32Target {
7979 //
8080 // TODO: the stub doesn't appear to disable the watchdog on ESP32-S3, so we
8181 // explicitly disable the watchdog here.
82- if connection. is_using_usb_serial_jtag ( ) {
82+ //
83+ // NOTE: In Secure Download Mode, WRITE_REG commands are not allowed, so we
84+ // must skip the watchdog disable.
85+ if connection. is_using_usb_serial_jtag ( ) && !connection. secure_download_mode {
8386 if let ( Some ( wdt_wprotect) , Some ( wdt_config0) ) =
8487 ( self . chip . wdt_wprotect ( ) , self . chip . wdt_config0 ( ) )
8588 {
@@ -116,22 +119,15 @@ impl FlashTarget for Esp32Target {
116119 md5_hasher. update ( & segment. data ) ;
117120 let checksum_md5 = md5_hasher. finalize ( ) ;
118121
119- let mut encoder = ZlibEncoder :: new ( Vec :: new ( ) , Compression :: best ( ) ) ;
120- encoder. write_all ( & segment. data ) ?;
121- let compressed = encoder. finish ( ) ?;
122+ // use compression only when stub is loaded.
123+ let use_compression = self . use_stub ;
122124
123125 let flash_write_size = self . chip . flash_write_size ( ) ;
124- let block_count = compressed. len ( ) . div_ceil ( flash_write_size) ;
125126 let erase_count = segment. data . len ( ) . div_ceil ( FLASH_SECTOR_SIZE ) ;
126127
127128 // round up to sector size
128129 let erase_size = ( erase_count * FLASH_SECTOR_SIZE ) as u32 ;
129130
130- let chunks = compressed. chunks ( flash_write_size) ;
131- let num_chunks = chunks. len ( ) ;
132-
133- progress. init ( addr, num_chunks) ;
134-
135131 if self . skip {
136132 let flash_checksum_md5: u128 = connection. with_timeout (
137133 CommandType :: FlashMd5 . timeout_for_size ( segment. data . len ( ) as u32 ) ,
@@ -153,43 +149,91 @@ impl FlashTarget for Esp32Target {
153149 }
154150 }
155151
156- connection. with_timeout (
157- CommandType :: FlashDeflBegin . timeout_for_size ( erase_size) ,
158- |connection| {
159- connection. command ( Command :: FlashDeflBegin {
160- size : segment. data . len ( ) as u32 ,
161- blocks : block_count as u32 ,
162- block_size : flash_write_size as u32 ,
163- offset : addr,
164- supports_encryption : self . chip != Chip :: Esp32 && !self . use_stub ,
165- } ) ?;
166- Ok ( ( ) )
167- } ,
168- ) ?;
169- self . need_deflate_end = true ;
152+ let data = if use_compression {
153+ let mut encoder = ZlibEncoder :: new ( Vec :: new ( ) , Compression :: best ( ) ) ;
154+ encoder. write_all ( & segment. data ) ?;
155+ encoder. finish ( ) ?
156+ } else {
157+ let mut data = segment. data . to_vec ( ) ;
158+ let padding = ( flash_write_size - ( data. len ( ) % flash_write_size) ) % flash_write_size;
159+ data. extend ( repeat_n ( 0xff , padding) ) ;
160+ data
161+ } ;
170162
171- // decode the chunks to see how much data the device will have to save
172- let mut decoder = ZlibDecoder :: new ( Vec :: new ( ) ) ;
173- let mut decoded_size = 0 ;
163+ let block_count = data. len ( ) . div_ceil ( flash_write_size ) ;
164+ let chunks = data . chunks ( flash_write_size ) ;
165+ let num_chunks = chunks . len ( ) ;
174166
175- for ( i, block) in chunks. enumerate ( ) {
176- decoder. write_all ( block) ?;
177- decoder. flush ( ) ?;
178- let size = decoder. get_ref ( ) . len ( ) - decoded_size;
179- decoded_size = decoder. get_ref ( ) . len ( ) ;
167+ progress. init ( addr, num_chunks) ;
180168
169+ if use_compression {
170+ connection. with_timeout (
171+ CommandType :: FlashDeflBegin . timeout_for_size ( erase_size) ,
172+ |connection| {
173+ connection. command ( Command :: FlashDeflBegin {
174+ size : segment. data . len ( ) as u32 ,
175+ blocks : block_count as u32 ,
176+ block_size : flash_write_size as u32 ,
177+ offset : addr,
178+ supports_encryption : self . chip != Chip :: Esp32 && !self . use_stub ,
179+ } ) ?;
180+ Ok ( ( ) )
181+ } ,
182+ ) ?;
183+ self . need_flash_end = true ;
184+ } else {
181185 connection. with_timeout (
182- CommandType :: FlashDeflData . timeout_for_size ( size as u32 ) ,
186+ CommandType :: FlashBegin . timeout_for_size ( erase_size ) ,
183187 |connection| {
184- connection. command ( Command :: FlashDeflData {
185- sequence : i as u32 ,
186- pad_to : 0 ,
187- pad_byte : 0xff ,
188- data : block,
188+ connection. command ( Command :: FlashBegin {
189+ size : erase_size,
190+ blocks : block_count as u32 ,
191+ block_size : flash_write_size as u32 ,
192+ offset : addr,
193+ supports_encryption : self . chip != Chip :: Esp32 ,
189194 } ) ?;
190195 Ok ( ( ) )
191196 } ,
192197 ) ?;
198+ }
199+
200+ // decode the chunks to see how much data the device will have to save
201+ let mut decoder = ZlibDecoder :: new ( Vec :: new ( ) ) ;
202+ let mut decoded_size = 0 ;
203+
204+ for ( i, block) in chunks. enumerate ( ) {
205+ if use_compression {
206+ decoder. write_all ( block) ?;
207+ decoder. flush ( ) ?;
208+ let size = decoder. get_ref ( ) . len ( ) - decoded_size;
209+ decoded_size = decoder. get_ref ( ) . len ( ) ;
210+
211+ connection. with_timeout (
212+ CommandType :: FlashDeflData . timeout_for_size ( size as u32 ) ,
213+ |connection| {
214+ connection. command ( Command :: FlashDeflData {
215+ sequence : i as u32 ,
216+ pad_to : 0 ,
217+ pad_byte : 0xff ,
218+ data : block,
219+ } ) ?;
220+ Ok ( ( ) )
221+ } ,
222+ ) ?;
223+ } else {
224+ connection. with_timeout (
225+ CommandType :: FlashData . timeout_for_size ( block. len ( ) as u32 ) ,
226+ |connection| {
227+ connection. command ( Command :: FlashData {
228+ sequence : i as u32 ,
229+ pad_to : flash_write_size,
230+ pad_byte : 0xff ,
231+ data : block,
232+ } ) ?;
233+ Ok ( ( ) )
234+ } ,
235+ ) ?;
236+ }
193237
194238 progress. update ( i + 1 )
195239 }
@@ -220,10 +264,16 @@ impl FlashTarget for Esp32Target {
220264 }
221265
222266 fn finish ( & mut self , connection : & mut Connection , reboot : bool ) -> Result < ( ) , Error > {
223- if self . need_deflate_end {
224- connection. with_timeout ( CommandType :: FlashDeflEnd . timeout ( ) , |connection| {
225- connection. command ( Command :: FlashDeflEnd { reboot : false } )
226- } ) ?;
267+ if self . need_flash_end {
268+ if self . use_stub {
269+ connection. with_timeout ( CommandType :: FlashDeflEnd . timeout ( ) , |connection| {
270+ connection. command ( Command :: FlashDeflEnd { reboot : false } )
271+ } ) ?;
272+ } else {
273+ connection. with_timeout ( CommandType :: FlashEnd . timeout ( ) , |connection| {
274+ connection. command ( Command :: FlashEnd { reboot : false } )
275+ } ) ?;
276+ }
227277 }
228278
229279 if reboot {
0 commit comments