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