aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsander <[email protected]>2023-04-11 13:49:32 +0200
committersander <[email protected]>2023-04-11 13:49:32 +0200
commitf51cbebffd8a2c7a66888b5cbd288a6eb912a784 (patch)
tree91d041a84f4d6fc01c2d925c3a5b72ade445a43f
parentc309797488a4f33dfab659fdb2908eff76e16e40 (diff)
embassy-boot: add nightly feature gates
-rw-r--r--embassy-boot/boot/Cargo.toml2
-rw-r--r--embassy-boot/boot/src/firmware_updater.rs128
-rw-r--r--embassy-boot/boot/src/mem_flash.rs3
-rw-r--r--embassy-boot/boot/src/partition.rs48
4 files changed, 98 insertions, 83 deletions
diff --git a/embassy-boot/boot/Cargo.toml b/embassy-boot/boot/Cargo.toml
index 39f501570..7434dce85 100644
--- a/embassy-boot/boot/Cargo.toml
+++ b/embassy-boot/boot/Cargo.toml
@@ -45,7 +45,7 @@ default_features = false
45features = ["rand", "std", "u32_backend"] 45features = ["rand", "std", "u32_backend"]
46 46
47[features] 47[features]
48default = ["nightly"] 48#default = ["nightly"]
49ed25519-dalek = ["dep:ed25519-dalek", "_verify"] 49ed25519-dalek = ["dep:ed25519-dalek", "_verify"]
50ed25519-salty = ["dep:salty", "_verify"] 50ed25519-salty = ["dep:salty", "_verify"]
51 51
diff --git a/embassy-boot/boot/src/firmware_updater.rs b/embassy-boot/boot/src/firmware_updater.rs
index a2f822f4a..f3d76a56c 100644
--- a/embassy-boot/boot/src/firmware_updater.rs
+++ b/embassy-boot/boot/src/firmware_updater.rs
@@ -1,5 +1,6 @@
1use digest::Digest; 1use digest::Digest;
2use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind}; 2use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind};
3#[cfg(feature = "nightly")]
3use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash; 4use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash;
4 5
5use crate::{Partition, State, BOOT_MAGIC, SWAP_MAGIC}; 6use crate::{Partition, State, BOOT_MAGIC, SWAP_MAGIC};
@@ -73,17 +74,21 @@ impl FirmwareUpdater {
73 Self { dfu, state } 74 Self { dfu, state }
74 } 75 }
75 76
77 //
78 // Blocking API
79 //
80
76 /// Obtain the current state. 81 /// Obtain the current state.
77 /// 82 ///
78 /// This is useful to check if the bootloader has just done a swap, in order 83 /// This is useful to check if the bootloader has just done a swap, in order
79 /// to do verifications and self-tests of the new image before calling 84 /// to do verifications and self-tests of the new image before calling
80 /// `mark_booted`. 85 /// `mark_booted`.
81 pub async fn get_state<F: AsyncNorFlash>( 86 pub fn get_state_blocking<F: NorFlash>(
82 &mut self, 87 &mut self,
83 state_flash: &mut F, 88 state_flash: &mut F,
84 aligned: &mut [u8], 89 aligned: &mut [u8],
85 ) -> Result<State, FirmwareUpdaterError> { 90 ) -> Result<State, FirmwareUpdaterError> {
86 self.state.read(state_flash, 0, aligned).await?; 91 self.state.read_blocking(state_flash, 0, aligned)?;
87 92
88 if !aligned.iter().any(|&b| b != SWAP_MAGIC) { 93 if !aligned.iter().any(|&b| b != SWAP_MAGIC) {
89 Ok(State::Swap) 94 Ok(State::Swap)
@@ -109,7 +114,7 @@ impl FirmwareUpdater {
109 /// The `_aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being read from 114 /// The `_aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being read from
110 /// and written to. 115 /// and written to.
111 #[cfg(feature = "_verify")] 116 #[cfg(feature = "_verify")]
112 pub async fn verify_and_mark_updated<F: AsyncNorFlash>( 117 pub fn verify_and_mark_updated_blocking<F: NorFlash>(
113 &mut self, 118 &mut self,
114 _state_and_dfu_flash: &mut F, 119 _state_and_dfu_flash: &mut F,
115 _public_key: &[u8], 120 _public_key: &[u8],
@@ -132,8 +137,7 @@ impl FirmwareUpdater {
132 let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; 137 let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?;
133 138
134 let mut message = [0; 64]; 139 let mut message = [0; 64];
135 self.hash::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message) 140 self.hash_blocking::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message)?;
136 .await?;
137 141
138 public_key.verify(&message, &signature).map_err(into_signature_error)? 142 public_key.verify(&message, &signature).map_err(into_signature_error)?
139 } 143 }
@@ -154,8 +158,7 @@ impl FirmwareUpdater {
154 let signature = Signature::try_from(&signature).map_err(into_signature_error)?; 158 let signature = Signature::try_from(&signature).map_err(into_signature_error)?;
155 159
156 let mut message = [0; 64]; 160 let mut message = [0; 64];
157 self.hash::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message) 161 self.hash_blocking::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message)?;
158 .await?;
159 162
160 let r = public_key.verify(&message, &signature); 163 let r = public_key.verify(&message, &signature);
161 trace!( 164 trace!(
@@ -168,11 +171,11 @@ impl FirmwareUpdater {
168 r.map_err(into_signature_error)? 171 r.map_err(into_signature_error)?
169 } 172 }
170 173
171 self.set_magic(_aligned, SWAP_MAGIC, _state_and_dfu_flash).await 174 self.set_magic_blocking(_aligned, SWAP_MAGIC, _state_and_dfu_flash)
172 } 175 }
173 176
174 /// Verify the update in DFU with any digest. 177 /// Verify the update in DFU with any digest.
175 pub async fn hash<F: AsyncNorFlash, D: Digest>( 178 pub fn hash_blocking<F: NorFlash, D: Digest>(
176 &mut self, 179 &mut self,
177 dfu_flash: &mut F, 180 dfu_flash: &mut F,
178 update_len: u32, 181 update_len: u32,
@@ -181,7 +184,7 @@ impl FirmwareUpdater {
181 ) -> Result<(), FirmwareUpdaterError> { 184 ) -> Result<(), FirmwareUpdaterError> {
182 let mut digest = D::new(); 185 let mut digest = D::new();
183 for offset in (0..update_len).step_by(chunk_buf.len()) { 186 for offset in (0..update_len).step_by(chunk_buf.len()) {
184 self.dfu.read(dfu_flash, offset, chunk_buf).await?; 187 self.dfu.read_blocking(dfu_flash, offset, chunk_buf)?;
185 let len = core::cmp::min((update_len - offset) as usize, chunk_buf.len()); 188 let len = core::cmp::min((update_len - offset) as usize, chunk_buf.len());
186 digest.update(&chunk_buf[..len]); 189 digest.update(&chunk_buf[..len]);
187 } 190 }
@@ -195,13 +198,13 @@ impl FirmwareUpdater {
195 /// 198 ///
196 /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. 199 /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to.
197 #[cfg(not(feature = "_verify"))] 200 #[cfg(not(feature = "_verify"))]
198 pub async fn mark_updated<F: AsyncNorFlash>( 201 pub fn mark_updated_blocking<F: NorFlash>(
199 &mut self, 202 &mut self,
200 state_flash: &mut F, 203 state_flash: &mut F,
201 aligned: &mut [u8], 204 aligned: &mut [u8],
202 ) -> Result<(), FirmwareUpdaterError> { 205 ) -> Result<(), FirmwareUpdaterError> {
203 assert_eq!(aligned.len(), F::WRITE_SIZE); 206 assert_eq!(aligned.len(), F::WRITE_SIZE);
204 self.set_magic(aligned, SWAP_MAGIC, state_flash).await 207 self.set_magic_blocking(aligned, SWAP_MAGIC, state_flash)
205 } 208 }
206 209
207 /// Mark firmware boot successful and stop rollback on reset. 210 /// Mark firmware boot successful and stop rollback on reset.
@@ -209,26 +212,26 @@ impl FirmwareUpdater {
209 /// # Safety 212 /// # Safety
210 /// 213 ///
211 /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. 214 /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to.
212 pub async fn mark_booted<F: AsyncNorFlash>( 215 pub fn mark_booted_blocking<F: NorFlash>(
213 &mut self, 216 &mut self,
214 state_flash: &mut F, 217 state_flash: &mut F,
215 aligned: &mut [u8], 218 aligned: &mut [u8],
216 ) -> Result<(), FirmwareUpdaterError> { 219 ) -> Result<(), FirmwareUpdaterError> {
217 assert_eq!(aligned.len(), F::WRITE_SIZE); 220 assert_eq!(aligned.len(), F::WRITE_SIZE);
218 self.set_magic(aligned, BOOT_MAGIC, state_flash).await 221 self.set_magic_blocking(aligned, BOOT_MAGIC, state_flash)
219 } 222 }
220 223
221 async fn set_magic<F: AsyncNorFlash>( 224 fn set_magic_blocking<F: NorFlash>(
222 &mut self, 225 &mut self,
223 aligned: &mut [u8], 226 aligned: &mut [u8],
224 magic: u8, 227 magic: u8,
225 state_flash: &mut F, 228 state_flash: &mut F,
226 ) -> Result<(), FirmwareUpdaterError> { 229 ) -> Result<(), FirmwareUpdaterError> {
227 self.state.read(state_flash, 0, aligned).await?; 230 self.state.read_blocking(state_flash, 0, aligned)?;
228 231
229 if aligned.iter().any(|&b| b != magic) { 232 if aligned.iter().any(|&b| b != magic) {
230 // Read progress validity 233 // Read progress validity
231 self.state.read(state_flash, F::WRITE_SIZE as u32, aligned).await?; 234 self.state.read_blocking(state_flash, F::WRITE_SIZE as u32, aligned)?;
232 235
233 // FIXME: Do not make this assumption. 236 // FIXME: Do not make this assumption.
234 const STATE_ERASE_VALUE: u8 = 0xFF; 237 const STATE_ERASE_VALUE: u8 = 0xFF;
@@ -238,15 +241,15 @@ impl FirmwareUpdater {
238 } else { 241 } else {
239 // Invalidate progress 242 // Invalidate progress
240 aligned.fill(!STATE_ERASE_VALUE); 243 aligned.fill(!STATE_ERASE_VALUE);
241 self.state.write(state_flash, F::WRITE_SIZE as u32, aligned).await?; 244 self.state.write_blocking(state_flash, F::WRITE_SIZE as u32, aligned)?;
242 } 245 }
243 246
244 // Clear magic and progress 247 // Clear magic and progress
245 self.state.wipe(state_flash).await?; 248 self.state.wipe_blocking(state_flash)?;
246 249
247 // Set magic 250 // Set magic
248 aligned.fill(magic); 251 aligned.fill(magic);
249 self.state.write(state_flash, 0, aligned).await?; 252 self.state.write_blocking(state_flash, 0, aligned)?;
250 } 253 }
251 Ok(()) 254 Ok(())
252 } 255 }
@@ -258,7 +261,7 @@ impl FirmwareUpdater {
258 /// # Safety 261 /// # Safety
259 /// 262 ///
260 /// Failing to meet alignment and size requirements may result in a panic. 263 /// Failing to meet alignment and size requirements may result in a panic.
261 pub async fn write_firmware<F: AsyncNorFlash>( 264 pub fn write_firmware_blocking<F: NorFlash>(
262 &mut self, 265 &mut self,
263 offset: usize, 266 offset: usize,
264 data: &[u8], 267 data: &[u8],
@@ -267,10 +270,9 @@ impl FirmwareUpdater {
267 assert!(data.len() >= F::ERASE_SIZE); 270 assert!(data.len() >= F::ERASE_SIZE);
268 271
269 self.dfu 272 self.dfu
270 .erase(dfu_flash, offset as u32, (offset + data.len()) as u32) 273 .erase_blocking(dfu_flash, offset as u32, (offset + data.len()) as u32)?;
271 .await?;
272 274
273 self.dfu.write(dfu_flash, offset as u32, data).await?; 275 self.dfu.write_blocking(dfu_flash, offset as u32, data)?;
274 276
275 Ok(()) 277 Ok(())
276 } 278 }
@@ -278,32 +280,29 @@ impl FirmwareUpdater {
278 /// Prepare for an incoming DFU update by erasing the entire DFU area and 280 /// Prepare for an incoming DFU update by erasing the entire DFU area and
279 /// returning its `Partition`. 281 /// returning its `Partition`.
280 /// 282 ///
281 /// Using this instead of `write_firmware` allows for an optimized API in 283 /// Using this instead of `write_firmware_blocking` allows for an optimized
282 /// exchange for added complexity. 284 /// API in exchange for added complexity.
283 pub async fn prepare_update<F: AsyncNorFlash>( 285 pub fn prepare_update_blocking<F: NorFlash>(&mut self, flash: &mut F) -> Result<Partition, FirmwareUpdaterError> {
284 &mut self, 286 self.dfu.wipe_blocking(flash)?;
285 dfu_flash: &mut F,
286 ) -> Result<Partition, FirmwareUpdaterError> {
287 self.dfu.wipe(dfu_flash).await?;
288 287
289 Ok(self.dfu) 288 Ok(self.dfu)
290 } 289 }
290}
291 291
292 // 292// Async API
293 // Blocking API 293#[cfg(feature = "nightly")]
294 // 294impl FirmwareUpdater {
295
296 /// Obtain the current state. 295 /// Obtain the current state.
297 /// 296 ///
298 /// This is useful to check if the bootloader has just done a swap, in order 297 /// This is useful to check if the bootloader has just done a swap, in order
299 /// to do verifications and self-tests of the new image before calling 298 /// to do verifications and self-tests of the new image before calling
300 /// `mark_booted`. 299 /// `mark_booted`.
301 pub fn get_state_blocking<F: NorFlash>( 300 pub async fn get_state<F: AsyncNorFlash>(
302 &mut self, 301 &mut self,
303 state_flash: &mut F, 302 state_flash: &mut F,
304 aligned: &mut [u8], 303 aligned: &mut [u8],
305 ) -> Result<State, FirmwareUpdaterError> { 304 ) -> Result<State, FirmwareUpdaterError> {
306 self.state.read_blocking(state_flash, 0, aligned)?; 305 self.state.read(state_flash, 0, aligned).await?;
307 306
308 if !aligned.iter().any(|&b| b != SWAP_MAGIC) { 307 if !aligned.iter().any(|&b| b != SWAP_MAGIC) {
309 Ok(State::Swap) 308 Ok(State::Swap)
@@ -329,7 +328,7 @@ impl FirmwareUpdater {
329 /// The `_aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being read from 328 /// The `_aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being read from
330 /// and written to. 329 /// and written to.
331 #[cfg(feature = "_verify")] 330 #[cfg(feature = "_verify")]
332 pub fn verify_and_mark_updated_blocking<F: NorFlash>( 331 pub async fn verify_and_mark_updated<F: AsyncNorFlash>(
333 &mut self, 332 &mut self,
334 _state_and_dfu_flash: &mut F, 333 _state_and_dfu_flash: &mut F,
335 _public_key: &[u8], 334 _public_key: &[u8],
@@ -352,7 +351,8 @@ impl FirmwareUpdater {
352 let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; 351 let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?;
353 352
354 let mut message = [0; 64]; 353 let mut message = [0; 64];
355 self.hash_blocking::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message)?; 354 self.hash::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message)
355 .await?;
356 356
357 public_key.verify(&message, &signature).map_err(into_signature_error)? 357 public_key.verify(&message, &signature).map_err(into_signature_error)?
358 } 358 }
@@ -373,7 +373,8 @@ impl FirmwareUpdater {
373 let signature = Signature::try_from(&signature).map_err(into_signature_error)?; 373 let signature = Signature::try_from(&signature).map_err(into_signature_error)?;
374 374
375 let mut message = [0; 64]; 375 let mut message = [0; 64];
376 self.hash_blocking::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message)?; 376 self.hash::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message)
377 .await?;
377 378
378 let r = public_key.verify(&message, &signature); 379 let r = public_key.verify(&message, &signature);
379 trace!( 380 trace!(
@@ -386,11 +387,11 @@ impl FirmwareUpdater {
386 r.map_err(into_signature_error)? 387 r.map_err(into_signature_error)?
387 } 388 }
388 389
389 self.set_magic_blocking(_aligned, SWAP_MAGIC, _state_and_dfu_flash) 390 self.set_magic(_aligned, SWAP_MAGIC, _state_and_dfu_flash).await
390 } 391 }
391 392
392 /// Verify the update in DFU with any digest. 393 /// Verify the update in DFU with any digest.
393 pub fn hash_blocking<F: NorFlash, D: Digest>( 394 pub async fn hash<F: AsyncNorFlash, D: Digest>(
394 &mut self, 395 &mut self,
395 dfu_flash: &mut F, 396 dfu_flash: &mut F,
396 update_len: u32, 397 update_len: u32,
@@ -399,7 +400,7 @@ impl FirmwareUpdater {
399 ) -> Result<(), FirmwareUpdaterError> { 400 ) -> Result<(), FirmwareUpdaterError> {
400 let mut digest = D::new(); 401 let mut digest = D::new();
401 for offset in (0..update_len).step_by(chunk_buf.len()) { 402 for offset in (0..update_len).step_by(chunk_buf.len()) {
402 self.dfu.read_blocking(dfu_flash, offset, chunk_buf)?; 403 self.dfu.read(dfu_flash, offset, chunk_buf).await?;
403 let len = core::cmp::min((update_len - offset) as usize, chunk_buf.len()); 404 let len = core::cmp::min((update_len - offset) as usize, chunk_buf.len());
404 digest.update(&chunk_buf[..len]); 405 digest.update(&chunk_buf[..len]);
405 } 406 }
@@ -413,13 +414,13 @@ impl FirmwareUpdater {
413 /// 414 ///
414 /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. 415 /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to.
415 #[cfg(not(feature = "_verify"))] 416 #[cfg(not(feature = "_verify"))]
416 pub fn mark_updated_blocking<F: NorFlash>( 417 pub async fn mark_updated<F: AsyncNorFlash>(
417 &mut self, 418 &mut self,
418 state_flash: &mut F, 419 state_flash: &mut F,
419 aligned: &mut [u8], 420 aligned: &mut [u8],
420 ) -> Result<(), FirmwareUpdaterError> { 421 ) -> Result<(), FirmwareUpdaterError> {
421 assert_eq!(aligned.len(), F::WRITE_SIZE); 422 assert_eq!(aligned.len(), F::WRITE_SIZE);
422 self.set_magic_blocking(aligned, SWAP_MAGIC, state_flash) 423 self.set_magic(aligned, SWAP_MAGIC, state_flash).await
423 } 424 }
424 425
425 /// Mark firmware boot successful and stop rollback on reset. 426 /// Mark firmware boot successful and stop rollback on reset.
@@ -427,26 +428,26 @@ impl FirmwareUpdater {
427 /// # Safety 428 /// # Safety
428 /// 429 ///
429 /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. 430 /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to.
430 pub fn mark_booted_blocking<F: NorFlash>( 431 pub async fn mark_booted<F: AsyncNorFlash>(
431 &mut self, 432 &mut self,
432 state_flash: &mut F, 433 state_flash: &mut F,
433 aligned: &mut [u8], 434 aligned: &mut [u8],
434 ) -> Result<(), FirmwareUpdaterError> { 435 ) -> Result<(), FirmwareUpdaterError> {
435 assert_eq!(aligned.len(), F::WRITE_SIZE); 436 assert_eq!(aligned.len(), F::WRITE_SIZE);
436 self.set_magic_blocking(aligned, BOOT_MAGIC, state_flash) 437 self.set_magic(aligned, BOOT_MAGIC, state_flash).await
437 } 438 }
438 439
439 fn set_magic_blocking<F: NorFlash>( 440 async fn set_magic<F: AsyncNorFlash>(
440 &mut self, 441 &mut self,
441 aligned: &mut [u8], 442 aligned: &mut [u8],
442 magic: u8, 443 magic: u8,
443 state_flash: &mut F, 444 state_flash: &mut F,
444 ) -> Result<(), FirmwareUpdaterError> { 445 ) -> Result<(), FirmwareUpdaterError> {
445 self.state.read_blocking(state_flash, 0, aligned)?; 446 self.state.read(state_flash, 0, aligned).await?;
446 447
447 if aligned.iter().any(|&b| b != magic) { 448 if aligned.iter().any(|&b| b != magic) {
448 // Read progress validity 449 // Read progress validity
449 self.state.read_blocking(state_flash, F::WRITE_SIZE as u32, aligned)?; 450 self.state.read(state_flash, F::WRITE_SIZE as u32, aligned).await?;
450 451
451 // FIXME: Do not make this assumption. 452 // FIXME: Do not make this assumption.
452 const STATE_ERASE_VALUE: u8 = 0xFF; 453 const STATE_ERASE_VALUE: u8 = 0xFF;
@@ -456,15 +457,15 @@ impl FirmwareUpdater {
456 } else { 457 } else {
457 // Invalidate progress 458 // Invalidate progress
458 aligned.fill(!STATE_ERASE_VALUE); 459 aligned.fill(!STATE_ERASE_VALUE);
459 self.state.write_blocking(state_flash, F::WRITE_SIZE as u32, aligned)?; 460 self.state.write(state_flash, F::WRITE_SIZE as u32, aligned).await?;
460 } 461 }
461 462
462 // Clear magic and progress 463 // Clear magic and progress
463 self.state.wipe_blocking(state_flash)?; 464 self.state.wipe(state_flash).await?;
464 465
465 // Set magic 466 // Set magic
466 aligned.fill(magic); 467 aligned.fill(magic);
467 self.state.write_blocking(state_flash, 0, aligned)?; 468 self.state.write(state_flash, 0, aligned).await?;
468 } 469 }
469 Ok(()) 470 Ok(())
470 } 471 }
@@ -476,7 +477,7 @@ impl FirmwareUpdater {
476 /// # Safety 477 /// # Safety
477 /// 478 ///
478 /// Failing to meet alignment and size requirements may result in a panic. 479 /// Failing to meet alignment and size requirements may result in a panic.
479 pub fn write_firmware_blocking<F: NorFlash>( 480 pub async fn write_firmware<F: AsyncNorFlash>(
480 &mut self, 481 &mut self,
481 offset: usize, 482 offset: usize,
482 data: &[u8], 483 data: &[u8],
@@ -485,9 +486,10 @@ impl FirmwareUpdater {
485 assert!(data.len() >= F::ERASE_SIZE); 486 assert!(data.len() >= F::ERASE_SIZE);
486 487
487 self.dfu 488 self.dfu
488 .erase_blocking(dfu_flash, offset as u32, (offset + data.len()) as u32)?; 489 .erase(dfu_flash, offset as u32, (offset + data.len()) as u32)
490 .await?;
489 491
490 self.dfu.write_blocking(dfu_flash, offset as u32, data)?; 492 self.dfu.write(dfu_flash, offset as u32, data).await?;
491 493
492 Ok(()) 494 Ok(())
493 } 495 }
@@ -495,16 +497,20 @@ impl FirmwareUpdater {
495 /// Prepare for an incoming DFU update by erasing the entire DFU area and 497 /// Prepare for an incoming DFU update by erasing the entire DFU area and
496 /// returning its `Partition`. 498 /// returning its `Partition`.
497 /// 499 ///
498 /// Using this instead of `write_firmware_blocking` allows for an optimized 500 /// Using this instead of `write_firmware` allows for an optimized API in
499 /// API in exchange for added complexity. 501 /// exchange for added complexity.
500 pub fn prepare_update_blocking<F: NorFlash>(&mut self, flash: &mut F) -> Result<Partition, FirmwareUpdaterError> { 502 pub async fn prepare_update<F: AsyncNorFlash>(
501 self.dfu.wipe_blocking(flash)?; 503 &mut self,
504 dfu_flash: &mut F,
505 ) -> Result<Partition, FirmwareUpdaterError> {
506 self.dfu.wipe(dfu_flash).await?;
502 507
503 Ok(self.dfu) 508 Ok(self.dfu)
504 } 509 }
505} 510}
506 511
507#[cfg(test)] 512
513 #[cfg(test)]
508mod tests { 514mod tests {
509 use futures::executor::block_on; 515 use futures::executor::block_on;
510 use sha1::{Digest, Sha1}; 516 use sha1::{Digest, Sha1};
diff --git a/embassy-boot/boot/src/mem_flash.rs b/embassy-boot/boot/src/mem_flash.rs
index c62379b24..3ba84a92c 100644
--- a/embassy-boot/boot/src/mem_flash.rs
+++ b/embassy-boot/boot/src/mem_flash.rs
@@ -3,6 +3,7 @@
3use core::ops::{Bound, Range, RangeBounds}; 3use core::ops::{Bound, Range, RangeBounds};
4 4
5use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; 5use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash};
6#[cfg(feature = "nightly")]
6use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash}; 7use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash};
7 8
8pub struct MemFlash<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> { 9pub struct MemFlash<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> {
@@ -134,6 +135,7 @@ impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> NorFla
134 } 135 }
135} 136}
136 137
138#[cfg(feature = "nightly")]
137impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> AsyncReadNorFlash 139impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> AsyncReadNorFlash
138 for MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE> 140 for MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE>
139{ 141{
@@ -148,6 +150,7 @@ impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> AsyncR
148 } 150 }
149} 151}
150 152
153#[cfg(feature = "nightly")]
151impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> AsyncNorFlash 154impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> AsyncNorFlash
152 for MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE> 155 for MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE>
153{ 156{
diff --git a/embassy-boot/boot/src/partition.rs b/embassy-boot/boot/src/partition.rs
index 7529059b6..67bd7abba 100644
--- a/embassy-boot/boot/src/partition.rs
+++ b/embassy-boot/boot/src/partition.rs
@@ -1,4 +1,5 @@
1use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; 1use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
2#[cfg(feature = "nightly")]
2use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash}; 3use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash};
3 4
4/// A region in flash used by the bootloader. 5/// A region in flash used by the bootloader.
@@ -23,70 +24,75 @@ impl Partition {
23 } 24 }
24 25
25 /// Read from the partition on the provided flash 26 /// Read from the partition on the provided flash
26 pub async fn read<F: AsyncReadNorFlash>( 27 pub fn read_blocking<F: ReadNorFlash>(&self, flash: &mut F, offset: u32, bytes: &mut [u8]) -> Result<(), F::Error> {
27 &self,
28 flash: &mut F,
29 offset: u32,
30 bytes: &mut [u8],
31 ) -> Result<(), F::Error> {
32 let offset = self.from as u32 + offset; 28 let offset = self.from as u32 + offset;
33 flash.read(offset, bytes).await 29 flash.read(offset, bytes)
34 } 30 }
35 31
36 /// Write to the partition on the provided flash 32 /// Write to the partition on the provided flash
37 pub async fn write<F: AsyncNorFlash>(&self, flash: &mut F, offset: u32, bytes: &[u8]) -> Result<(), F::Error> { 33 pub fn write_blocking<F: NorFlash>(&self, flash: &mut F, offset: u32, bytes: &[u8]) -> Result<(), F::Error> {
38 let offset = self.from as u32 + offset; 34 let offset = self.from as u32 + offset;
39 flash.write(offset, bytes).await?; 35 flash.write(offset, bytes)?;
40 trace!("Wrote from 0x{:x} len {}", offset, bytes.len()); 36 trace!("Wrote from 0x{:x} len {}", offset, bytes.len());
41 Ok(()) 37 Ok(())
42 } 38 }
43 39
44 /// Erase part of the partition on the provided flash 40 /// Erase part of the partition on the provided flash
45 pub async fn erase<F: AsyncNorFlash>(&self, flash: &mut F, from: u32, to: u32) -> Result<(), F::Error> { 41 pub fn erase_blocking<F: NorFlash>(&self, flash: &mut F, from: u32, to: u32) -> Result<(), F::Error> {
46 let from = self.from as u32 + from; 42 let from = self.from as u32 + from;
47 let to = self.from as u32 + to; 43 let to = self.from as u32 + to;
48 flash.erase(from, to).await?; 44 flash.erase(from, to)?;
49 trace!("Erased from 0x{:x} to 0x{:x}", from, to); 45 trace!("Erased from 0x{:x} to 0x{:x}", from, to);
50 Ok(()) 46 Ok(())
51 } 47 }
52 48
53 /// Erase the entire partition 49 /// Erase the entire partition
54 pub(crate) async fn wipe<F: AsyncNorFlash>(&self, flash: &mut F) -> Result<(), F::Error> { 50 pub(crate) fn wipe_blocking<F: NorFlash>(&self, flash: &mut F) -> Result<(), F::Error> {
55 let from = self.from as u32; 51 let from = self.from as u32;
56 let to = self.to as u32; 52 let to = self.to as u32;
57 flash.erase(from, to).await?; 53 flash.erase(from, to)?;
58 trace!("Wiped from 0x{:x} to 0x{:x}", from, to); 54 trace!("Wiped from 0x{:x} to 0x{:x}", from, to);
59 Ok(()) 55 Ok(())
60 } 56 }
57}
58
59// Async API
60#[cfg(feature = "nightly")]
61impl Partition {
61 62
62 /// Read from the partition on the provided flash 63 /// Read from the partition on the provided flash
63 pub fn read_blocking<F: ReadNorFlash>(&self, flash: &mut F, offset: u32, bytes: &mut [u8]) -> Result<(), F::Error> { 64 pub async fn read<F: AsyncReadNorFlash>(
65 &self,
66 flash: &mut F,
67 offset: u32,
68 bytes: &mut [u8],
69 ) -> Result<(), F::Error> {
64 let offset = self.from as u32 + offset; 70 let offset = self.from as u32 + offset;
65 flash.read(offset, bytes) 71 flash.read(offset, bytes).await
66 } 72 }
67 73
68 /// Write to the partition on the provided flash 74 /// Write to the partition on the provided flash
69 pub fn write_blocking<F: NorFlash>(&self, flash: &mut F, offset: u32, bytes: &[u8]) -> Result<(), F::Error> { 75 pub async fn write<F: AsyncNorFlash>(&self, flash: &mut F, offset: u32, bytes: &[u8]) -> Result<(), F::Error> {
70 let offset = self.from as u32 + offset; 76 let offset = self.from as u32 + offset;
71 flash.write(offset, bytes)?; 77 flash.write(offset, bytes).await?;
72 trace!("Wrote from 0x{:x} len {}", offset, bytes.len()); 78 trace!("Wrote from 0x{:x} len {}", offset, bytes.len());
73 Ok(()) 79 Ok(())
74 } 80 }
75 81
76 /// Erase part of the partition on the provided flash 82 /// Erase part of the partition on the provided flash
77 pub fn erase_blocking<F: NorFlash>(&self, flash: &mut F, from: u32, to: u32) -> Result<(), F::Error> { 83 pub async fn erase<F: AsyncNorFlash>(&self, flash: &mut F, from: u32, to: u32) -> Result<(), F::Error> {
78 let from = self.from as u32 + from; 84 let from = self.from as u32 + from;
79 let to = self.from as u32 + to; 85 let to = self.from as u32 + to;
80 flash.erase(from, to)?; 86 flash.erase(from, to).await?;
81 trace!("Erased from 0x{:x} to 0x{:x}", from, to); 87 trace!("Erased from 0x{:x} to 0x{:x}", from, to);
82 Ok(()) 88 Ok(())
83 } 89 }
84 90
85 /// Erase the entire partition 91 /// Erase the entire partition
86 pub(crate) fn wipe_blocking<F: NorFlash>(&self, flash: &mut F) -> Result<(), F::Error> { 92 pub(crate) async fn wipe<F: AsyncNorFlash>(&self, flash: &mut F) -> Result<(), F::Error> {
87 let from = self.from as u32; 93 let from = self.from as u32;
88 let to = self.to as u32; 94 let to = self.to as u32;
89 flash.erase(from, to)?; 95 flash.erase(from, to).await?;
90 trace!("Wiped from 0x{:x} to 0x{:x}", from, to); 96 trace!("Wiped from 0x{:x} to 0x{:x}", from, to);
91 Ok(()) 97 Ok(())
92 } 98 }