From ba9afbc26d06ab38065cbff5b17a7f76db297ad4 Mon Sep 17 00:00:00 2001 From: sander Date: Wed, 22 Mar 2023 16:49:49 +0100 Subject: [PATCH 01/10] embassy-boot: add default nightly feature, makes it possible to compile with the stable compiler --- embassy-boot/boot/Cargo.toml | 5 ++++- embassy-boot/boot/src/lib.rs | 11 ++++++++++- embassy-boot/nrf/Cargo.toml | 6 ++++-- embassy-boot/nrf/src/lib.rs | 2 +- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/embassy-boot/boot/Cargo.toml b/embassy-boot/boot/Cargo.toml index 3312c2f9..04409cdc 100644 --- a/embassy-boot/boot/Cargo.toml +++ b/embassy-boot/boot/Cargo.toml @@ -28,7 +28,7 @@ log = { version = "0.4", optional = true } ed25519-dalek = { version = "1.0.1", default_features = false, features = ["u32_backend"], optional = true } embassy-sync = { version = "0.1.0", path = "../../embassy-sync" } embedded-storage = "0.3.0" -embedded-storage-async = "0.4.0" +embedded-storage-async = { version = "0.4.0", optional = true} salty = { git = "https://github.com/ycrypto/salty.git", rev = "a9f17911a5024698406b75c0fac56ab5ccf6a8c7", optional = true } signature = { version = "1.6.4", default-features = false } @@ -43,8 +43,11 @@ default_features = false features = ["rand", "std", "u32_backend"] [features] +default = ["nightly"] ed25519-dalek = ["dep:ed25519-dalek", "_verify"] ed25519-salty = ["dep:salty", "_verify"] +nightly = ["dep:embedded-storage-async"] + #Internal features _verify = [] \ No newline at end of file diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs index 0df44f36..7ce0c664 100644 --- a/embassy-boot/boot/src/lib.rs +++ b/embassy-boot/boot/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(async_fn_in_trait)] +#![cfg_attr(feature = "nightly", feature(async_fn_in_trait))] #![allow(incomplete_features)] #![no_std] #![warn(missing_docs)] @@ -6,6 +6,8 @@ mod fmt; use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; + +#[cfg(feature = "nightly")] use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash; const BOOT_MAGIC: u8 = 0xD0; @@ -647,6 +649,7 @@ impl FirmwareUpdater { /// This is useful to check if the bootloader has just done a swap, in order /// to do verifications and self-tests of the new image before calling /// `mark_booted`. + #[cfg(feature = "nightly")] pub async fn get_state( &mut self, flash: &mut F, @@ -776,6 +779,7 @@ impl FirmwareUpdater { /// /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. #[cfg(not(feature = "_verify"))] + #[cfg(feature = "nightly")] pub async fn mark_updated( &mut self, flash: &mut F, @@ -790,6 +794,7 @@ impl FirmwareUpdater { /// # Safety /// /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. + #[cfg(feature = "nightly")] pub async fn mark_booted( &mut self, flash: &mut F, @@ -799,6 +804,7 @@ impl FirmwareUpdater { self.set_magic(aligned, BOOT_MAGIC, flash).await } + #[cfg(feature = "nightly")] async fn set_magic( &mut self, aligned: &mut [u8], @@ -826,6 +832,7 @@ impl FirmwareUpdater { /// # Safety /// /// Failing to meet alignment and size requirements may result in a panic. + #[cfg(feature = "nightly")] pub async fn write_firmware( &mut self, offset: usize, @@ -860,6 +867,7 @@ impl FirmwareUpdater { /// /// Using this instead of `write_firmware` allows for an optimized API in /// exchange for added complexity. + #[cfg(feature = "nightly")] pub async fn prepare_update( &mut self, flash: &mut F, @@ -1112,6 +1120,7 @@ impl FirmwareWriter { /// # Safety /// /// Failing to meet alignment and size requirements may result in a panic. + #[cfg(feature = "nightly")] pub async fn write_block( &mut self, offset: usize, diff --git a/embassy-boot/nrf/Cargo.toml b/embassy-boot/nrf/Cargo.toml index c1a12751..90a36d01 100644 --- a/embassy-boot/nrf/Cargo.toml +++ b/embassy-boot/nrf/Cargo.toml @@ -17,17 +17,18 @@ target = "thumbv7em-none-eabi" defmt = { version = "0.3", optional = true } embassy-sync = { path = "../../embassy-sync" } -embassy-nrf = { path = "../../embassy-nrf", default-features = false, features = ["nightly"] } +embassy-nrf = { path = "../../embassy-nrf", default-features = false } embassy-boot = { path = "../boot", default-features = false } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.0" -embedded-storage-async = "0.4.0" +embedded-storage-async = { version = "0.4.0", optional = true } cfg-if = "1.0.0" nrf-softdevice-mbr = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-softdevice.git", branch = "master", optional = true } [features] +default = ["nightly"] defmt = [ "dep:defmt", "embassy-boot/defmt", @@ -36,3 +37,4 @@ defmt = [ softdevice = [ "nrf-softdevice-mbr", ] +nightly = ["dep:embedded-storage-async", "embassy-boot/nightly", "embassy-nrf/nightly"] diff --git a/embassy-boot/nrf/src/lib.rs b/embassy-boot/nrf/src/lib.rs index f40ae62d..5cc6ba44 100644 --- a/embassy-boot/nrf/src/lib.rs +++ b/embassy-boot/nrf/src/lib.rs @@ -1,5 +1,5 @@ #![no_std] -#![feature(type_alias_impl_trait)] +#![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] #![warn(missing_docs)] #![doc = include_str!("../README.md")] mod fmt; From f51cbebffd8a2c7a66888b5cbd288a6eb912a784 Mon Sep 17 00:00:00 2001 From: sander Date: Tue, 11 Apr 2023 13:49:32 +0200 Subject: [PATCH 02/10] embassy-boot: add nightly feature gates --- embassy-boot/boot/Cargo.toml | 2 +- embassy-boot/boot/src/firmware_updater.rs | 440 +++++++++++----------- embassy-boot/boot/src/mem_flash.rs | 3 + embassy-boot/boot/src/partition.rs | 70 ++-- 4 files changed, 265 insertions(+), 250 deletions(-) diff --git a/embassy-boot/boot/Cargo.toml b/embassy-boot/boot/Cargo.toml index 39f50157..7434dce8 100644 --- a/embassy-boot/boot/Cargo.toml +++ b/embassy-boot/boot/Cargo.toml @@ -45,7 +45,7 @@ default_features = false features = ["rand", "std", "u32_backend"] [features] -default = ["nightly"] +#default = ["nightly"] ed25519-dalek = ["dep:ed25519-dalek", "_verify"] ed25519-salty = ["dep:salty", "_verify"] diff --git a/embassy-boot/boot/src/firmware_updater.rs b/embassy-boot/boot/src/firmware_updater.rs index a2f822f4..f3d76a56 100644 --- a/embassy-boot/boot/src/firmware_updater.rs +++ b/embassy-boot/boot/src/firmware_updater.rs @@ -1,5 +1,6 @@ use digest::Digest; use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind}; +#[cfg(feature = "nightly")] use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash; use crate::{Partition, State, BOOT_MAGIC, SWAP_MAGIC}; @@ -73,222 +74,6 @@ impl FirmwareUpdater { Self { dfu, state } } - /// Obtain the current state. - /// - /// This is useful to check if the bootloader has just done a swap, in order - /// to do verifications and self-tests of the new image before calling - /// `mark_booted`. - pub async fn get_state( - &mut self, - state_flash: &mut F, - aligned: &mut [u8], - ) -> Result { - self.state.read(state_flash, 0, aligned).await?; - - if !aligned.iter().any(|&b| b != SWAP_MAGIC) { - Ok(State::Swap) - } else { - Ok(State::Boot) - } - } - - /// Verify the DFU given a public key. If there is an error then DO NOT - /// proceed with updating the firmware as it must be signed with a - /// corresponding private key (otherwise it could be malicious firmware). - /// - /// Mark to trigger firmware swap on next boot if verify suceeds. - /// - /// If the "ed25519-salty" feature is set (or another similar feature) then the signature is expected to have - /// been generated from a SHA-512 digest of the firmware bytes. - /// - /// If no signature feature is set then this method will always return a - /// signature error. - /// - /// # Safety - /// - /// The `_aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being read from - /// and written to. - #[cfg(feature = "_verify")] - pub async fn verify_and_mark_updated( - &mut self, - _state_and_dfu_flash: &mut F, - _public_key: &[u8], - _signature: &[u8], - _update_len: u32, - _aligned: &mut [u8], - ) -> Result<(), FirmwareUpdaterError> { - assert_eq!(_aligned.len(), F::WRITE_SIZE); - assert!(_update_len <= self.dfu.size()); - - #[cfg(feature = "ed25519-dalek")] - { - use ed25519_dalek::{PublicKey, Signature, SignatureError, Verifier}; - - use crate::digest_adapters::ed25519_dalek::Sha512; - - let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into()); - - let public_key = PublicKey::from_bytes(_public_key).map_err(into_signature_error)?; - let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; - - let mut message = [0; 64]; - self.hash::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message) - .await?; - - public_key.verify(&message, &signature).map_err(into_signature_error)? - } - #[cfg(feature = "ed25519-salty")] - { - use salty::constants::{PUBLICKEY_SERIALIZED_LENGTH, SIGNATURE_SERIALIZED_LENGTH}; - use salty::{PublicKey, Signature}; - - use crate::digest_adapters::salty::Sha512; - - fn into_signature_error(_: E) -> FirmwareUpdaterError { - FirmwareUpdaterError::Signature(signature::Error::default()) - } - - let public_key: [u8; PUBLICKEY_SERIALIZED_LENGTH] = _public_key.try_into().map_err(into_signature_error)?; - let public_key = PublicKey::try_from(&public_key).map_err(into_signature_error)?; - let signature: [u8; SIGNATURE_SERIALIZED_LENGTH] = _signature.try_into().map_err(into_signature_error)?; - let signature = Signature::try_from(&signature).map_err(into_signature_error)?; - - let mut message = [0; 64]; - self.hash::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message) - .await?; - - let r = public_key.verify(&message, &signature); - trace!( - "Verifying with public key {}, signature {} and message {} yields ok: {}", - public_key.to_bytes(), - signature.to_bytes(), - message, - r.is_ok() - ); - r.map_err(into_signature_error)? - } - - self.set_magic(_aligned, SWAP_MAGIC, _state_and_dfu_flash).await - } - - /// Verify the update in DFU with any digest. - pub async fn hash( - &mut self, - dfu_flash: &mut F, - update_len: u32, - chunk_buf: &mut [u8], - output: &mut [u8], - ) -> Result<(), FirmwareUpdaterError> { - let mut digest = D::new(); - for offset in (0..update_len).step_by(chunk_buf.len()) { - self.dfu.read(dfu_flash, offset, chunk_buf).await?; - let len = core::cmp::min((update_len - offset) as usize, chunk_buf.len()); - digest.update(&chunk_buf[..len]); - } - output.copy_from_slice(digest.finalize().as_slice()); - Ok(()) - } - - /// Mark to trigger firmware swap on next boot. - /// - /// # Safety - /// - /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. - #[cfg(not(feature = "_verify"))] - pub async fn mark_updated( - &mut self, - state_flash: &mut F, - aligned: &mut [u8], - ) -> Result<(), FirmwareUpdaterError> { - assert_eq!(aligned.len(), F::WRITE_SIZE); - self.set_magic(aligned, SWAP_MAGIC, state_flash).await - } - - /// Mark firmware boot successful and stop rollback on reset. - /// - /// # Safety - /// - /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. - pub async fn mark_booted( - &mut self, - state_flash: &mut F, - aligned: &mut [u8], - ) -> Result<(), FirmwareUpdaterError> { - assert_eq!(aligned.len(), F::WRITE_SIZE); - self.set_magic(aligned, BOOT_MAGIC, state_flash).await - } - - async fn set_magic( - &mut self, - aligned: &mut [u8], - magic: u8, - state_flash: &mut F, - ) -> Result<(), FirmwareUpdaterError> { - self.state.read(state_flash, 0, aligned).await?; - - if aligned.iter().any(|&b| b != magic) { - // Read progress validity - self.state.read(state_flash, F::WRITE_SIZE as u32, aligned).await?; - - // FIXME: Do not make this assumption. - const STATE_ERASE_VALUE: u8 = 0xFF; - - if aligned.iter().any(|&b| b != STATE_ERASE_VALUE) { - // The current progress validity marker is invalid - } else { - // Invalidate progress - aligned.fill(!STATE_ERASE_VALUE); - self.state.write(state_flash, F::WRITE_SIZE as u32, aligned).await?; - } - - // Clear magic and progress - self.state.wipe(state_flash).await?; - - // Set magic - aligned.fill(magic); - self.state.write(state_flash, 0, aligned).await?; - } - Ok(()) - } - - /// Write data to a flash page. - /// - /// The buffer must follow alignment requirements of the target flash and a multiple of page size big. - /// - /// # Safety - /// - /// Failing to meet alignment and size requirements may result in a panic. - pub async fn write_firmware( - &mut self, - offset: usize, - data: &[u8], - dfu_flash: &mut F, - ) -> Result<(), FirmwareUpdaterError> { - assert!(data.len() >= F::ERASE_SIZE); - - self.dfu - .erase(dfu_flash, offset as u32, (offset + data.len()) as u32) - .await?; - - self.dfu.write(dfu_flash, offset as u32, data).await?; - - Ok(()) - } - - /// Prepare for an incoming DFU update by erasing the entire DFU area and - /// returning its `Partition`. - /// - /// Using this instead of `write_firmware` allows for an optimized API in - /// exchange for added complexity. - pub async fn prepare_update( - &mut self, - dfu_flash: &mut F, - ) -> Result { - self.dfu.wipe(dfu_flash).await?; - - Ok(self.dfu) - } - // // Blocking API // @@ -504,7 +289,228 @@ impl FirmwareUpdater { } } -#[cfg(test)] +// Async API +#[cfg(feature = "nightly")] +impl FirmwareUpdater { + /// Obtain the current state. + /// + /// This is useful to check if the bootloader has just done a swap, in order + /// to do verifications and self-tests of the new image before calling + /// `mark_booted`. + pub async fn get_state( + &mut self, + state_flash: &mut F, + aligned: &mut [u8], + ) -> Result { + self.state.read(state_flash, 0, aligned).await?; + + if !aligned.iter().any(|&b| b != SWAP_MAGIC) { + Ok(State::Swap) + } else { + Ok(State::Boot) + } + } + + /// Verify the DFU given a public key. If there is an error then DO NOT + /// proceed with updating the firmware as it must be signed with a + /// corresponding private key (otherwise it could be malicious firmware). + /// + /// Mark to trigger firmware swap on next boot if verify suceeds. + /// + /// If the "ed25519-salty" feature is set (or another similar feature) then the signature is expected to have + /// been generated from a SHA-512 digest of the firmware bytes. + /// + /// If no signature feature is set then this method will always return a + /// signature error. + /// + /// # Safety + /// + /// The `_aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being read from + /// and written to. + #[cfg(feature = "_verify")] + pub async fn verify_and_mark_updated( + &mut self, + _state_and_dfu_flash: &mut F, + _public_key: &[u8], + _signature: &[u8], + _update_len: u32, + _aligned: &mut [u8], + ) -> Result<(), FirmwareUpdaterError> { + assert_eq!(_aligned.len(), F::WRITE_SIZE); + assert!(_update_len <= self.dfu.size()); + + #[cfg(feature = "ed25519-dalek")] + { + use ed25519_dalek::{PublicKey, Signature, SignatureError, Verifier}; + + use crate::digest_adapters::ed25519_dalek::Sha512; + + let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into()); + + let public_key = PublicKey::from_bytes(_public_key).map_err(into_signature_error)?; + let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; + + let mut message = [0; 64]; + self.hash::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message) + .await?; + + public_key.verify(&message, &signature).map_err(into_signature_error)? + } + #[cfg(feature = "ed25519-salty")] + { + use salty::constants::{PUBLICKEY_SERIALIZED_LENGTH, SIGNATURE_SERIALIZED_LENGTH}; + use salty::{PublicKey, Signature}; + + use crate::digest_adapters::salty::Sha512; + + fn into_signature_error(_: E) -> FirmwareUpdaterError { + FirmwareUpdaterError::Signature(signature::Error::default()) + } + + let public_key: [u8; PUBLICKEY_SERIALIZED_LENGTH] = _public_key.try_into().map_err(into_signature_error)?; + let public_key = PublicKey::try_from(&public_key).map_err(into_signature_error)?; + let signature: [u8; SIGNATURE_SERIALIZED_LENGTH] = _signature.try_into().map_err(into_signature_error)?; + let signature = Signature::try_from(&signature).map_err(into_signature_error)?; + + let mut message = [0; 64]; + self.hash::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message) + .await?; + + let r = public_key.verify(&message, &signature); + trace!( + "Verifying with public key {}, signature {} and message {} yields ok: {}", + public_key.to_bytes(), + signature.to_bytes(), + message, + r.is_ok() + ); + r.map_err(into_signature_error)? + } + + self.set_magic(_aligned, SWAP_MAGIC, _state_and_dfu_flash).await + } + + /// Verify the update in DFU with any digest. + pub async fn hash( + &mut self, + dfu_flash: &mut F, + update_len: u32, + chunk_buf: &mut [u8], + output: &mut [u8], + ) -> Result<(), FirmwareUpdaterError> { + let mut digest = D::new(); + for offset in (0..update_len).step_by(chunk_buf.len()) { + self.dfu.read(dfu_flash, offset, chunk_buf).await?; + let len = core::cmp::min((update_len - offset) as usize, chunk_buf.len()); + digest.update(&chunk_buf[..len]); + } + output.copy_from_slice(digest.finalize().as_slice()); + Ok(()) + } + + /// Mark to trigger firmware swap on next boot. + /// + /// # Safety + /// + /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. + #[cfg(not(feature = "_verify"))] + pub async fn mark_updated( + &mut self, + state_flash: &mut F, + aligned: &mut [u8], + ) -> Result<(), FirmwareUpdaterError> { + assert_eq!(aligned.len(), F::WRITE_SIZE); + self.set_magic(aligned, SWAP_MAGIC, state_flash).await + } + + /// Mark firmware boot successful and stop rollback on reset. + /// + /// # Safety + /// + /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. + pub async fn mark_booted( + &mut self, + state_flash: &mut F, + aligned: &mut [u8], + ) -> Result<(), FirmwareUpdaterError> { + assert_eq!(aligned.len(), F::WRITE_SIZE); + self.set_magic(aligned, BOOT_MAGIC, state_flash).await + } + + async fn set_magic( + &mut self, + aligned: &mut [u8], + magic: u8, + state_flash: &mut F, + ) -> Result<(), FirmwareUpdaterError> { + self.state.read(state_flash, 0, aligned).await?; + + if aligned.iter().any(|&b| b != magic) { + // Read progress validity + self.state.read(state_flash, F::WRITE_SIZE as u32, aligned).await?; + + // FIXME: Do not make this assumption. + const STATE_ERASE_VALUE: u8 = 0xFF; + + if aligned.iter().any(|&b| b != STATE_ERASE_VALUE) { + // The current progress validity marker is invalid + } else { + // Invalidate progress + aligned.fill(!STATE_ERASE_VALUE); + self.state.write(state_flash, F::WRITE_SIZE as u32, aligned).await?; + } + + // Clear magic and progress + self.state.wipe(state_flash).await?; + + // Set magic + aligned.fill(magic); + self.state.write(state_flash, 0, aligned).await?; + } + Ok(()) + } + + /// Write data to a flash page. + /// + /// The buffer must follow alignment requirements of the target flash and a multiple of page size big. + /// + /// # Safety + /// + /// Failing to meet alignment and size requirements may result in a panic. + pub async fn write_firmware( + &mut self, + offset: usize, + data: &[u8], + dfu_flash: &mut F, + ) -> Result<(), FirmwareUpdaterError> { + assert!(data.len() >= F::ERASE_SIZE); + + self.dfu + .erase(dfu_flash, offset as u32, (offset + data.len()) as u32) + .await?; + + self.dfu.write(dfu_flash, offset as u32, data).await?; + + Ok(()) + } + + /// Prepare for an incoming DFU update by erasing the entire DFU area and + /// returning its `Partition`. + /// + /// Using this instead of `write_firmware` allows for an optimized API in + /// exchange for added complexity. + pub async fn prepare_update( + &mut self, + dfu_flash: &mut F, + ) -> Result { + self.dfu.wipe(dfu_flash).await?; + + Ok(self.dfu) + } +} + + + #[cfg(test)] mod tests { use futures::executor::block_on; use sha1::{Digest, Sha1}; diff --git a/embassy-boot/boot/src/mem_flash.rs b/embassy-boot/boot/src/mem_flash.rs index c62379b2..3ba84a92 100644 --- a/embassy-boot/boot/src/mem_flash.rs +++ b/embassy-boot/boot/src/mem_flash.rs @@ -3,6 +3,7 @@ use core::ops::{Bound, Range, RangeBounds}; use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; +#[cfg(feature = "nightly")] use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash}; pub struct MemFlash { @@ -134,6 +135,7 @@ impl NorFla } } +#[cfg(feature = "nightly")] impl AsyncReadNorFlash for MemFlash { @@ -148,6 +150,7 @@ impl AsyncR } } +#[cfg(feature = "nightly")] impl AsyncNorFlash for MemFlash { diff --git a/embassy-boot/boot/src/partition.rs b/embassy-boot/boot/src/partition.rs index 7529059b..67bd7abb 100644 --- a/embassy-boot/boot/src/partition.rs +++ b/embassy-boot/boot/src/partition.rs @@ -1,4 +1,5 @@ use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; +#[cfg(feature = "nightly")] use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash}; /// A region in flash used by the bootloader. @@ -22,6 +23,43 @@ impl Partition { self.to - self.from } + /// Read from the partition on the provided flash + pub fn read_blocking(&self, flash: &mut F, offset: u32, bytes: &mut [u8]) -> Result<(), F::Error> { + let offset = self.from as u32 + offset; + flash.read(offset, bytes) + } + + /// Write to the partition on the provided flash + pub fn write_blocking(&self, flash: &mut F, offset: u32, bytes: &[u8]) -> Result<(), F::Error> { + let offset = self.from as u32 + offset; + flash.write(offset, bytes)?; + trace!("Wrote from 0x{:x} len {}", offset, bytes.len()); + Ok(()) + } + + /// Erase part of the partition on the provided flash + pub fn erase_blocking(&self, flash: &mut F, from: u32, to: u32) -> Result<(), F::Error> { + let from = self.from as u32 + from; + let to = self.from as u32 + to; + flash.erase(from, to)?; + trace!("Erased from 0x{:x} to 0x{:x}", from, to); + Ok(()) + } + + /// Erase the entire partition + pub(crate) fn wipe_blocking(&self, flash: &mut F) -> Result<(), F::Error> { + let from = self.from as u32; + let to = self.to as u32; + flash.erase(from, to)?; + trace!("Wiped from 0x{:x} to 0x{:x}", from, to); + Ok(()) + } +} + +// Async API +#[cfg(feature = "nightly")] +impl Partition { + /// Read from the partition on the provided flash pub async fn read( &self, @@ -58,38 +96,6 @@ impl Partition { trace!("Wiped from 0x{:x} to 0x{:x}", from, to); Ok(()) } - - /// Read from the partition on the provided flash - pub fn read_blocking(&self, flash: &mut F, offset: u32, bytes: &mut [u8]) -> Result<(), F::Error> { - let offset = self.from as u32 + offset; - flash.read(offset, bytes) - } - - /// Write to the partition on the provided flash - pub fn write_blocking(&self, flash: &mut F, offset: u32, bytes: &[u8]) -> Result<(), F::Error> { - let offset = self.from as u32 + offset; - flash.write(offset, bytes)?; - trace!("Wrote from 0x{:x} len {}", offset, bytes.len()); - Ok(()) - } - - /// Erase part of the partition on the provided flash - pub fn erase_blocking(&self, flash: &mut F, from: u32, to: u32) -> Result<(), F::Error> { - let from = self.from as u32 + from; - let to = self.from as u32 + to; - flash.erase(from, to)?; - trace!("Erased from 0x{:x} to 0x{:x}", from, to); - Ok(()) - } - - /// Erase the entire partition - pub(crate) fn wipe_blocking(&self, flash: &mut F) -> Result<(), F::Error> { - let from = self.from as u32; - let to = self.to as u32; - flash.erase(from, to)?; - trace!("Wiped from 0x{:x} to 0x{:x}", from, to); - Ok(()) - } } #[cfg(test)] From 1b86570cfd480b0821de555780a2dbdaa7ec562d Mon Sep 17 00:00:00 2001 From: sander Date: Tue, 11 Apr 2023 13:55:19 +0200 Subject: [PATCH 03/10] embassy-boot: readd nightly feature as default --- embassy-boot/boot/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-boot/boot/Cargo.toml b/embassy-boot/boot/Cargo.toml index 7434dce8..39f50157 100644 --- a/embassy-boot/boot/Cargo.toml +++ b/embassy-boot/boot/Cargo.toml @@ -45,7 +45,7 @@ default_features = false features = ["rand", "std", "u32_backend"] [features] -#default = ["nightly"] +default = ["nightly"] ed25519-dalek = ["dep:ed25519-dalek", "_verify"] ed25519-salty = ["dep:salty", "_verify"] From 3002ee0dcf0ae186867b2fd869daed609d7a4a23 Mon Sep 17 00:00:00 2001 From: sander Date: Fri, 14 Apr 2023 11:27:23 +0200 Subject: [PATCH 04/10] embassy-boot: add nightly feature gate for async usage --- embassy-boot/boot/src/firmware_updater.rs | 445 +++++++++++----------- embassy-boot/boot/src/partition.rs | 83 ++-- embassy-boot/nrf/Cargo.toml | 6 +- 3 files changed, 269 insertions(+), 265 deletions(-) diff --git a/embassy-boot/boot/src/firmware_updater.rs b/embassy-boot/boot/src/firmware_updater.rs index f3d76a56..1f2a6d24 100644 --- a/embassy-boot/boot/src/firmware_updater.rs +++ b/embassy-boot/boot/src/firmware_updater.rs @@ -74,6 +74,228 @@ impl FirmwareUpdater { Self { dfu, state } } + /// Obtain the current state. + /// + /// This is useful to check if the bootloader has just done a swap, in order + /// to do verifications and self-tests of the new image before calling + /// `mark_booted`. + #[cfg(feature = "nightly")] + pub async fn get_state( + &mut self, + state_flash: &mut F, + aligned: &mut [u8], + ) -> Result { + self.state.read(state_flash, 0, aligned).await?; + + if !aligned.iter().any(|&b| b != SWAP_MAGIC) { + Ok(State::Swap) + } else { + Ok(State::Boot) + } + } + + /// Verify the DFU given a public key. If there is an error then DO NOT + /// proceed with updating the firmware as it must be signed with a + /// corresponding private key (otherwise it could be malicious firmware). + /// + /// Mark to trigger firmware swap on next boot if verify suceeds. + /// + /// If the "ed25519-salty" feature is set (or another similar feature) then the signature is expected to have + /// been generated from a SHA-512 digest of the firmware bytes. + /// + /// If no signature feature is set then this method will always return a + /// signature error. + /// + /// # Safety + /// + /// The `_aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being read from + /// and written to. + #[cfg(all(feature = "_verify", feature = "nightly"))] + pub async fn verify_and_mark_updated( + &mut self, + _state_and_dfu_flash: &mut F, + _public_key: &[u8], + _signature: &[u8], + _update_len: u32, + _aligned: &mut [u8], + ) -> Result<(), FirmwareUpdaterError> { + assert_eq!(_aligned.len(), F::WRITE_SIZE); + assert!(_update_len <= self.dfu.size()); + + #[cfg(feature = "ed25519-dalek")] + { + use ed25519_dalek::{PublicKey, Signature, SignatureError, Verifier}; + + use crate::digest_adapters::ed25519_dalek::Sha512; + + let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into()); + + let public_key = PublicKey::from_bytes(_public_key).map_err(into_signature_error)?; + let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; + + let mut message = [0; 64]; + self.hash::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message) + .await?; + + public_key.verify(&message, &signature).map_err(into_signature_error)? + } + #[cfg(feature = "ed25519-salty")] + { + use salty::constants::{PUBLICKEY_SERIALIZED_LENGTH, SIGNATURE_SERIALIZED_LENGTH}; + use salty::{PublicKey, Signature}; + + use crate::digest_adapters::salty::Sha512; + + fn into_signature_error(_: E) -> FirmwareUpdaterError { + FirmwareUpdaterError::Signature(signature::Error::default()) + } + + let public_key: [u8; PUBLICKEY_SERIALIZED_LENGTH] = _public_key.try_into().map_err(into_signature_error)?; + let public_key = PublicKey::try_from(&public_key).map_err(into_signature_error)?; + let signature: [u8; SIGNATURE_SERIALIZED_LENGTH] = _signature.try_into().map_err(into_signature_error)?; + let signature = Signature::try_from(&signature).map_err(into_signature_error)?; + + let mut message = [0; 64]; + self.hash::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message) + .await?; + + let r = public_key.verify(&message, &signature); + trace!( + "Verifying with public key {}, signature {} and message {} yields ok: {}", + public_key.to_bytes(), + signature.to_bytes(), + message, + r.is_ok() + ); + r.map_err(into_signature_error)? + } + + self.set_magic(_aligned, SWAP_MAGIC, _state_and_dfu_flash).await + } + + /// Verify the update in DFU with any digest. + #[cfg(feature = "nightly")] + pub async fn hash( + &mut self, + dfu_flash: &mut F, + update_len: u32, + chunk_buf: &mut [u8], + output: &mut [u8], + ) -> Result<(), FirmwareUpdaterError> { + let mut digest = D::new(); + for offset in (0..update_len).step_by(chunk_buf.len()) { + self.dfu.read(dfu_flash, offset, chunk_buf).await?; + let len = core::cmp::min((update_len - offset) as usize, chunk_buf.len()); + digest.update(&chunk_buf[..len]); + } + output.copy_from_slice(digest.finalize().as_slice()); + Ok(()) + } + + /// Mark to trigger firmware swap on next boot. + /// + /// # Safety + /// + /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. + #[cfg(all(feature = "nightly", not(feature = "_verify")))] + pub async fn mark_updated( + &mut self, + state_flash: &mut F, + aligned: &mut [u8], + ) -> Result<(), FirmwareUpdaterError> { + assert_eq!(aligned.len(), F::WRITE_SIZE); + self.set_magic(aligned, SWAP_MAGIC, state_flash).await + } + + /// Mark firmware boot successful and stop rollback on reset. + /// + /// # Safety + /// + /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. + #[cfg(feature = "nightly")] + pub async fn mark_booted( + &mut self, + state_flash: &mut F, + aligned: &mut [u8], + ) -> Result<(), FirmwareUpdaterError> { + assert_eq!(aligned.len(), F::WRITE_SIZE); + self.set_magic(aligned, BOOT_MAGIC, state_flash).await + } + + #[cfg(feature = "nightly")] + async fn set_magic( + &mut self, + aligned: &mut [u8], + magic: u8, + state_flash: &mut F, + ) -> Result<(), FirmwareUpdaterError> { + self.state.read(state_flash, 0, aligned).await?; + + if aligned.iter().any(|&b| b != magic) { + // Read progress validity + self.state.read(state_flash, F::WRITE_SIZE as u32, aligned).await?; + + // FIXME: Do not make this assumption. + const STATE_ERASE_VALUE: u8 = 0xFF; + + if aligned.iter().any(|&b| b != STATE_ERASE_VALUE) { + // The current progress validity marker is invalid + } else { + // Invalidate progress + aligned.fill(!STATE_ERASE_VALUE); + self.state.write(state_flash, F::WRITE_SIZE as u32, aligned).await?; + } + + // Clear magic and progress + self.state.wipe(state_flash).await?; + + // Set magic + aligned.fill(magic); + self.state.write(state_flash, 0, aligned).await?; + } + Ok(()) + } + + /// Write data to a flash page. + /// + /// The buffer must follow alignment requirements of the target flash and a multiple of page size big. + /// + /// # Safety + /// + /// Failing to meet alignment and size requirements may result in a panic. + #[cfg(feature = "nightly")] + pub async fn write_firmware( + &mut self, + offset: usize, + data: &[u8], + dfu_flash: &mut F, + ) -> Result<(), FirmwareUpdaterError> { + assert!(data.len() >= F::ERASE_SIZE); + + self.dfu + .erase(dfu_flash, offset as u32, (offset + data.len()) as u32) + .await?; + + self.dfu.write(dfu_flash, offset as u32, data).await?; + + Ok(()) + } + + /// Prepare for an incoming DFU update by erasing the entire DFU area and + /// returning its `Partition`. + /// + /// Using this instead of `write_firmware` allows for an optimized API in + /// exchange for added complexity. + #[cfg(feature = "nightly")] + pub async fn prepare_update( + &mut self, + dfu_flash: &mut F, + ) -> Result { + self.dfu.wipe(dfu_flash).await?; + + Ok(self.dfu) + } + // // Blocking API // @@ -289,228 +511,7 @@ impl FirmwareUpdater { } } -// Async API -#[cfg(feature = "nightly")] -impl FirmwareUpdater { - /// Obtain the current state. - /// - /// This is useful to check if the bootloader has just done a swap, in order - /// to do verifications and self-tests of the new image before calling - /// `mark_booted`. - pub async fn get_state( - &mut self, - state_flash: &mut F, - aligned: &mut [u8], - ) -> Result { - self.state.read(state_flash, 0, aligned).await?; - - if !aligned.iter().any(|&b| b != SWAP_MAGIC) { - Ok(State::Swap) - } else { - Ok(State::Boot) - } - } - - /// Verify the DFU given a public key. If there is an error then DO NOT - /// proceed with updating the firmware as it must be signed with a - /// corresponding private key (otherwise it could be malicious firmware). - /// - /// Mark to trigger firmware swap on next boot if verify suceeds. - /// - /// If the "ed25519-salty" feature is set (or another similar feature) then the signature is expected to have - /// been generated from a SHA-512 digest of the firmware bytes. - /// - /// If no signature feature is set then this method will always return a - /// signature error. - /// - /// # Safety - /// - /// The `_aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being read from - /// and written to. - #[cfg(feature = "_verify")] - pub async fn verify_and_mark_updated( - &mut self, - _state_and_dfu_flash: &mut F, - _public_key: &[u8], - _signature: &[u8], - _update_len: u32, - _aligned: &mut [u8], - ) -> Result<(), FirmwareUpdaterError> { - assert_eq!(_aligned.len(), F::WRITE_SIZE); - assert!(_update_len <= self.dfu.size()); - - #[cfg(feature = "ed25519-dalek")] - { - use ed25519_dalek::{PublicKey, Signature, SignatureError, Verifier}; - - use crate::digest_adapters::ed25519_dalek::Sha512; - - let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into()); - - let public_key = PublicKey::from_bytes(_public_key).map_err(into_signature_error)?; - let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; - - let mut message = [0; 64]; - self.hash::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message) - .await?; - - public_key.verify(&message, &signature).map_err(into_signature_error)? - } - #[cfg(feature = "ed25519-salty")] - { - use salty::constants::{PUBLICKEY_SERIALIZED_LENGTH, SIGNATURE_SERIALIZED_LENGTH}; - use salty::{PublicKey, Signature}; - - use crate::digest_adapters::salty::Sha512; - - fn into_signature_error(_: E) -> FirmwareUpdaterError { - FirmwareUpdaterError::Signature(signature::Error::default()) - } - - let public_key: [u8; PUBLICKEY_SERIALIZED_LENGTH] = _public_key.try_into().map_err(into_signature_error)?; - let public_key = PublicKey::try_from(&public_key).map_err(into_signature_error)?; - let signature: [u8; SIGNATURE_SERIALIZED_LENGTH] = _signature.try_into().map_err(into_signature_error)?; - let signature = Signature::try_from(&signature).map_err(into_signature_error)?; - - let mut message = [0; 64]; - self.hash::<_, Sha512>(_state_and_dfu_flash, _update_len, _aligned, &mut message) - .await?; - - let r = public_key.verify(&message, &signature); - trace!( - "Verifying with public key {}, signature {} and message {} yields ok: {}", - public_key.to_bytes(), - signature.to_bytes(), - message, - r.is_ok() - ); - r.map_err(into_signature_error)? - } - - self.set_magic(_aligned, SWAP_MAGIC, _state_and_dfu_flash).await - } - - /// Verify the update in DFU with any digest. - pub async fn hash( - &mut self, - dfu_flash: &mut F, - update_len: u32, - chunk_buf: &mut [u8], - output: &mut [u8], - ) -> Result<(), FirmwareUpdaterError> { - let mut digest = D::new(); - for offset in (0..update_len).step_by(chunk_buf.len()) { - self.dfu.read(dfu_flash, offset, chunk_buf).await?; - let len = core::cmp::min((update_len - offset) as usize, chunk_buf.len()); - digest.update(&chunk_buf[..len]); - } - output.copy_from_slice(digest.finalize().as_slice()); - Ok(()) - } - - /// Mark to trigger firmware swap on next boot. - /// - /// # Safety - /// - /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. - #[cfg(not(feature = "_verify"))] - pub async fn mark_updated( - &mut self, - state_flash: &mut F, - aligned: &mut [u8], - ) -> Result<(), FirmwareUpdaterError> { - assert_eq!(aligned.len(), F::WRITE_SIZE); - self.set_magic(aligned, SWAP_MAGIC, state_flash).await - } - - /// Mark firmware boot successful and stop rollback on reset. - /// - /// # Safety - /// - /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. - pub async fn mark_booted( - &mut self, - state_flash: &mut F, - aligned: &mut [u8], - ) -> Result<(), FirmwareUpdaterError> { - assert_eq!(aligned.len(), F::WRITE_SIZE); - self.set_magic(aligned, BOOT_MAGIC, state_flash).await - } - - async fn set_magic( - &mut self, - aligned: &mut [u8], - magic: u8, - state_flash: &mut F, - ) -> Result<(), FirmwareUpdaterError> { - self.state.read(state_flash, 0, aligned).await?; - - if aligned.iter().any(|&b| b != magic) { - // Read progress validity - self.state.read(state_flash, F::WRITE_SIZE as u32, aligned).await?; - - // FIXME: Do not make this assumption. - const STATE_ERASE_VALUE: u8 = 0xFF; - - if aligned.iter().any(|&b| b != STATE_ERASE_VALUE) { - // The current progress validity marker is invalid - } else { - // Invalidate progress - aligned.fill(!STATE_ERASE_VALUE); - self.state.write(state_flash, F::WRITE_SIZE as u32, aligned).await?; - } - - // Clear magic and progress - self.state.wipe(state_flash).await?; - - // Set magic - aligned.fill(magic); - self.state.write(state_flash, 0, aligned).await?; - } - Ok(()) - } - - /// Write data to a flash page. - /// - /// The buffer must follow alignment requirements of the target flash and a multiple of page size big. - /// - /// # Safety - /// - /// Failing to meet alignment and size requirements may result in a panic. - pub async fn write_firmware( - &mut self, - offset: usize, - data: &[u8], - dfu_flash: &mut F, - ) -> Result<(), FirmwareUpdaterError> { - assert!(data.len() >= F::ERASE_SIZE); - - self.dfu - .erase(dfu_flash, offset as u32, (offset + data.len()) as u32) - .await?; - - self.dfu.write(dfu_flash, offset as u32, data).await?; - - Ok(()) - } - - /// Prepare for an incoming DFU update by erasing the entire DFU area and - /// returning its `Partition`. - /// - /// Using this instead of `write_firmware` allows for an optimized API in - /// exchange for added complexity. - pub async fn prepare_update( - &mut self, - dfu_flash: &mut F, - ) -> Result { - self.dfu.wipe(dfu_flash).await?; - - Ok(self.dfu) - } -} - - - #[cfg(test)] +#[cfg(test)] mod tests { use futures::executor::block_on; use sha1::{Digest, Sha1}; diff --git a/embassy-boot/boot/src/partition.rs b/embassy-boot/boot/src/partition.rs index 67bd7abb..7b56a824 100644 --- a/embassy-boot/boot/src/partition.rs +++ b/embassy-boot/boot/src/partition.rs @@ -23,6 +23,47 @@ impl Partition { self.to - self.from } + /// Read from the partition on the provided flash + #[cfg(feature = "nightly")] + pub async fn read( + &self, + flash: &mut F, + offset: u32, + bytes: &mut [u8], + ) -> Result<(), F::Error> { + let offset = self.from as u32 + offset; + flash.read(offset, bytes).await + } + + /// Write to the partition on the provided flash + #[cfg(feature = "nightly")] + pub async fn write(&self, flash: &mut F, offset: u32, bytes: &[u8]) -> Result<(), F::Error> { + let offset = self.from as u32 + offset; + flash.write(offset, bytes).await?; + trace!("Wrote from 0x{:x} len {}", offset, bytes.len()); + Ok(()) + } + + /// Erase part of the partition on the provided flash + #[cfg(feature = "nightly")] + pub async fn erase(&self, flash: &mut F, from: u32, to: u32) -> Result<(), F::Error> { + let from = self.from as u32 + from; + let to = self.from as u32 + to; + flash.erase(from, to).await?; + trace!("Erased from 0x{:x} to 0x{:x}", from, to); + Ok(()) + } + + /// Erase the entire partition + #[cfg(feature = "nightly")] + pub(crate) async fn wipe(&self, flash: &mut F) -> Result<(), F::Error> { + let from = self.from as u32; + let to = self.to as u32; + flash.erase(from, to).await?; + trace!("Wiped from 0x{:x} to 0x{:x}", from, to); + Ok(()) + } + /// Read from the partition on the provided flash pub fn read_blocking(&self, flash: &mut F, offset: u32, bytes: &mut [u8]) -> Result<(), F::Error> { let offset = self.from as u32 + offset; @@ -56,48 +97,6 @@ impl Partition { } } -// Async API -#[cfg(feature = "nightly")] -impl Partition { - - /// Read from the partition on the provided flash - pub async fn read( - &self, - flash: &mut F, - offset: u32, - bytes: &mut [u8], - ) -> Result<(), F::Error> { - let offset = self.from as u32 + offset; - flash.read(offset, bytes).await - } - - /// Write to the partition on the provided flash - pub async fn write(&self, flash: &mut F, offset: u32, bytes: &[u8]) -> Result<(), F::Error> { - let offset = self.from as u32 + offset; - flash.write(offset, bytes).await?; - trace!("Wrote from 0x{:x} len {}", offset, bytes.len()); - Ok(()) - } - - /// Erase part of the partition on the provided flash - pub async fn erase(&self, flash: &mut F, from: u32, to: u32) -> Result<(), F::Error> { - let from = self.from as u32 + from; - let to = self.from as u32 + to; - flash.erase(from, to).await?; - trace!("Erased from 0x{:x} to 0x{:x}", from, to); - Ok(()) - } - - /// Erase the entire partition - pub(crate) async fn wipe(&self, flash: &mut F) -> Result<(), F::Error> { - let from = self.from as u32; - let to = self.to as u32; - flash.erase(from, to).await?; - trace!("Wiped from 0x{:x} to 0x{:x}", from, to); - Ok(()) - } -} - #[cfg(test)] mod tests { use crate::mem_flash::MemFlash; diff --git a/embassy-boot/nrf/Cargo.toml b/embassy-boot/nrf/Cargo.toml index 90a36d01..05ab8789 100644 --- a/embassy-boot/nrf/Cargo.toml +++ b/embassy-boot/nrf/Cargo.toml @@ -37,4 +37,8 @@ defmt = [ softdevice = [ "nrf-softdevice-mbr", ] -nightly = ["dep:embedded-storage-async", "embassy-boot/nightly", "embassy-nrf/nightly"] +nightly = [ + "dep:embedded-storage-async", + "embassy-boot/nightly", + "embassy-nrf/nightly" +] From b153a5b0d764c32eea6a3c312781743af98b3a11 Mon Sep 17 00:00:00 2001 From: sander Date: Thu, 20 Apr 2023 10:04:41 +0200 Subject: [PATCH 05/10] embassy-boot: add nightly feature to stm32 and rp as well --- embassy-boot/boot/Cargo.toml | 1 - embassy-boot/nrf/Cargo.toml | 1 - embassy-boot/nrf/src/lib.rs | 1 - embassy-boot/rp/Cargo.toml | 12 +++++++++--- embassy-boot/rp/src/lib.rs | 1 - embassy-boot/stm32/Cargo.toml | 9 +++++++-- embassy-boot/stm32/src/lib.rs | 1 - 7 files changed, 16 insertions(+), 10 deletions(-) diff --git a/embassy-boot/boot/Cargo.toml b/embassy-boot/boot/Cargo.toml index 956b0f98..f641d5e1 100644 --- a/embassy-boot/boot/Cargo.toml +++ b/embassy-boot/boot/Cargo.toml @@ -45,7 +45,6 @@ default_features = false features = ["rand", "std", "u32_backend"] [features] -default = ["nightly"] ed25519-dalek = ["dep:ed25519-dalek", "_verify"] ed25519-salty = ["dep:salty", "_verify"] diff --git a/embassy-boot/nrf/Cargo.toml b/embassy-boot/nrf/Cargo.toml index 05ab8789..e4673688 100644 --- a/embassy-boot/nrf/Cargo.toml +++ b/embassy-boot/nrf/Cargo.toml @@ -28,7 +28,6 @@ cfg-if = "1.0.0" nrf-softdevice-mbr = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-softdevice.git", branch = "master", optional = true } [features] -default = ["nightly"] defmt = [ "dep:defmt", "embassy-boot/defmt", diff --git a/embassy-boot/nrf/src/lib.rs b/embassy-boot/nrf/src/lib.rs index 48bbd7e2..14bea1f7 100644 --- a/embassy-boot/nrf/src/lib.rs +++ b/embassy-boot/nrf/src/lib.rs @@ -1,5 +1,4 @@ #![no_std] -#![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] #![warn(missing_docs)] #![doc = include_str!("../README.md")] mod fmt; diff --git a/embassy-boot/rp/Cargo.toml b/embassy-boot/rp/Cargo.toml index 96024cdd..5147392c 100644 --- a/embassy-boot/rp/Cargo.toml +++ b/embassy-boot/rp/Cargo.toml @@ -18,14 +18,14 @@ defmt-rtt = { version = "0.4", optional = true } log = { version = "0.4", optional = true } embassy-sync = { path = "../../embassy-sync" } -embassy-rp = { path = "../../embassy-rp", default-features = false, features = ["nightly"] } +embassy-rp = { path = "../../embassy-rp", default-features = false } embassy-boot = { path = "../boot", default-features = false } -embassy-time = { path = "../../embassy-time", features = ["nightly"] } +embassy-time = { path = "../../embassy-time" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.0" -embedded-storage-async = "0.4.0" +embedded-storage-async = { version = "0.4.0", optional = true } cfg-if = "1.0.0" [features] @@ -40,6 +40,12 @@ log = [ "embassy-rp/log", ] debug = ["defmt-rtt"] +nightly = [ + "dep:embedded-storage-async", + "embassy-boot/nightly", + "embassy-rp/nightly", + "embassy-time/nightly" +] [profile.dev] debug = 2 diff --git a/embassy-boot/rp/src/lib.rs b/embassy-boot/rp/src/lib.rs index c3cb2229..0d577f08 100644 --- a/embassy-boot/rp/src/lib.rs +++ b/embassy-boot/rp/src/lib.rs @@ -1,5 +1,4 @@ #![no_std] -#![feature(type_alias_impl_trait)] #![warn(missing_docs)] #![doc = include_str!("../README.md")] mod fmt; diff --git a/embassy-boot/stm32/Cargo.toml b/embassy-boot/stm32/Cargo.toml index 7061063b..99a6b8e0 100644 --- a/embassy-boot/stm32/Cargo.toml +++ b/embassy-boot/stm32/Cargo.toml @@ -19,12 +19,12 @@ defmt-rtt = { version = "0.4", optional = true } log = { version = "0.4", optional = true } embassy-sync = { path = "../../embassy-sync" } -embassy-stm32 = { path = "../../embassy-stm32", default-features = false, features = ["nightly"] } +embassy-stm32 = { path = "../../embassy-stm32", default-features = false } embassy-boot = { path = "../boot", default-features = false } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.0" -embedded-storage-async = "0.4.0" +embedded-storage-async = { version = "0.4.0", optional = true } cfg-if = "1.0.0" [features] @@ -39,6 +39,11 @@ log = [ "embassy-stm32/log", ] debug = ["defmt-rtt"] +nightly = [ + "dep:embedded-storage-async", + "embassy-boot/nightly", + "embassy-stm32/nightly" +] [profile.dev] debug = 2 diff --git a/embassy-boot/stm32/src/lib.rs b/embassy-boot/stm32/src/lib.rs index 94404697..88ce1c87 100644 --- a/embassy-boot/stm32/src/lib.rs +++ b/embassy-boot/stm32/src/lib.rs @@ -1,5 +1,4 @@ #![no_std] -#![feature(type_alias_impl_trait)] #![warn(missing_docs)] #![doc = include_str!("../README.md")] mod fmt; From f64d1131b6c57c5bde9c6211d6d465f0bd256066 Mon Sep 17 00:00:00 2001 From: sander Date: Thu, 20 Apr 2023 10:22:44 +0200 Subject: [PATCH 06/10] embassy-boot: update ci and examples to use the nightly flag --- ci.sh | 8 ++++---- ci_stable.sh | 4 ++++ examples/boot/application/nrf/Cargo.toml | 4 ++-- examples/boot/application/rp/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- 11 files changed, 18 insertions(+), 14 deletions(-) diff --git a/ci.sh b/ci.sh index 65797504..4b7d7371 100755 --- a/ci.sh +++ b/ci.sh @@ -69,10 +69,10 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f100c4,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32h503rb,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32h562ag,defmt,exti,time-driver-any,unstable-traits \ - --- build --release --manifest-path embassy-boot/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \ - --- build --release --manifest-path embassy-boot/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns \ - --- build --release --manifest-path embassy-boot/rp/Cargo.toml --target thumbv6m-none-eabi \ - --- build --release --manifest-path embassy-boot/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wl55jc-cm4 \ + --- build --release --manifest-path embassy-boot/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840,nightly \ + --- build --release --manifest-path embassy-boot/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns,nightly \ + --- build --release --manifest-path embassy-boot/rp/Cargo.toml --target thumbv6m-none-eabi --features nightly \ + --- build --release --manifest-path embassy-boot/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wl55jc-cm4,nightly \ --- build --release --manifest-path docs/modules/ROOT/examples/basic/Cargo.toml --target thumbv7em-none-eabi \ --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-pac/Cargo.toml --target thumbv7em-none-eabi \ --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-hal/Cargo.toml --target thumbv7em-none-eabi \ diff --git a/ci_stable.sh b/ci_stable.sh index 18271ee7..55a2f89a 100755 --- a/ci_stable.sh +++ b/ci_stable.sh @@ -9,6 +9,10 @@ export DEFMT_LOG=trace sed -i 's/channel.*/channel = "stable"/g' rust-toolchain.toml cargo batch \ + --- build --release --manifest-path embassy-boot/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \ + --- build --release --manifest-path embassy-boot/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns \ + --- build --release --manifest-path embassy-boot/rp/Cargo.toml --target thumbv6m-none-eabi \ + --- build --release --manifest-path embassy-boot/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wl55jc-cm4 \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features log \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features defmt \ diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index d6a30602..88528e76 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -9,8 +9,8 @@ embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] } embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly"] } -embassy-boot = { version = "0.1.0", path = "../../../../embassy-boot/boot" } -embassy-boot-nrf = { version = "0.1.0", path = "../../../../embassy-boot/nrf" } +embassy-boot = { version = "0.1.0", path = "../../../../embassy-boot/boot", features = ["nightly"] } +embassy-boot-nrf = { version = "0.1.0", path = "../../../../embassy-boot/nrf", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index 62ef42d6..782ccef2 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] } embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", "unstable-traits", "nightly"] } -embassy-boot-rp = { version = "0.1.0", path = "../../../../embassy-boot/rp" } +embassy-boot-rp = { version = "0.1.0", path = "../../../../embassy-boot/rp", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = "0.3" diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index e5fb1b01..88119187 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f303re", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" } +embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index a6ac1cad..21665553 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f767zi", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" } +embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index 5b8ee555..eef8b413 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32h743zi", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" } +embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 05ce5c10..2bcf292b 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] } -embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" } +embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 14af99e9..f452db72 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" } +embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index 90ae9772..2c94ed3e 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" } +embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index 08403a4e..f9dfb7c7 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" } +embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } From 8cd117fd5d692aef695afc46018c6b48f047bcbd Mon Sep 17 00:00:00 2001 From: sander Date: Thu, 20 Apr 2023 10:26:02 +0200 Subject: [PATCH 07/10] embassy-boot: update readme MSRV to stable --- embassy-boot/boot/README.md | 2 +- embassy-boot/nrf/README.md | 2 +- embassy-boot/rp/README.md | 2 +- embassy-boot/stm32/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/embassy-boot/boot/README.md b/embassy-boot/boot/README.md index 41440537..346aa6f5 100644 --- a/embassy-boot/boot/README.md +++ b/embassy-boot/boot/README.md @@ -17,7 +17,7 @@ The bootloader supports different hardware in separate crates: ## Minimum supported Rust version (MSRV) -`embassy-boot` requires Rust nightly to compile as it relies on async traits for interacting with the flash peripherals. +`embassy-boot` is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release. ## License diff --git a/embassy-boot/nrf/README.md b/embassy-boot/nrf/README.md index 02f35c0a..7ce3c702 100644 --- a/embassy-boot/nrf/README.md +++ b/embassy-boot/nrf/README.md @@ -13,7 +13,7 @@ An adaptation of `embassy-boot` for nRF. ## Minimum supported Rust version (MSRV) -`embassy-boot-nrf` requires Rust nightly to compile as it relies on async traits for interacting with the flash peripherals. +`embassy-boot-nrf` is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release. ## License diff --git a/embassy-boot/rp/README.md b/embassy-boot/rp/README.md index c0c2d85f..315d655e 100644 --- a/embassy-boot/rp/README.md +++ b/embassy-boot/rp/README.md @@ -13,7 +13,7 @@ NOTE: The applications using this bootloader should not link with the `link-rp.x ## Minimum supported Rust version (MSRV) -`embassy-boot-rp` requires Rust nightly to compile as it relies on async traits for interacting with the flash peripherals. +`embassy-boot-rp` is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release. ## License diff --git a/embassy-boot/stm32/README.md b/embassy-boot/stm32/README.md index cb134b53..b4d7ba5a 100644 --- a/embassy-boot/stm32/README.md +++ b/embassy-boot/stm32/README.md @@ -11,7 +11,7 @@ An adaptation of `embassy-boot` for STM32. ## Minimum supported Rust version (MSRV) -`embassy-boot-stm32` requires Rust nightly to compile as it relies on async traits for interacting with the flash peripherals. +`embassy-boot-stm32` is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release. ## License From 0e01b28d5ecd56fc2d8b14fa0b90f3ec2b564b0f Mon Sep 17 00:00:00 2001 From: sander Date: Thu, 20 Apr 2023 10:40:40 +0200 Subject: [PATCH 08/10] embassy-boot: resolve conflicts --- embassy-boot/boot/Cargo.toml | 1 - embassy-boot/nrf/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/embassy-boot/boot/Cargo.toml b/embassy-boot/boot/Cargo.toml index 956b0f98..f641d5e1 100644 --- a/embassy-boot/boot/Cargo.toml +++ b/embassy-boot/boot/Cargo.toml @@ -45,7 +45,6 @@ default_features = false features = ["rand", "std", "u32_backend"] [features] -default = ["nightly"] ed25519-dalek = ["dep:ed25519-dalek", "_verify"] ed25519-salty = ["dep:salty", "_verify"] diff --git a/embassy-boot/nrf/Cargo.toml b/embassy-boot/nrf/Cargo.toml index 05ab8789..e4673688 100644 --- a/embassy-boot/nrf/Cargo.toml +++ b/embassy-boot/nrf/Cargo.toml @@ -28,7 +28,6 @@ cfg-if = "1.0.0" nrf-softdevice-mbr = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-softdevice.git", branch = "master", optional = true } [features] -default = ["nightly"] defmt = [ "dep:defmt", "embassy-boot/defmt", From 3bf41e9a06bab1b48b08fbc0b8f10d00b47b936e Mon Sep 17 00:00:00 2001 From: sander Date: Thu, 20 Apr 2023 10:47:40 +0200 Subject: [PATCH 09/10] ci: ad nightly flag to embassy-boot tests --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 3bfe5ef0..b8af7fcc 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -71,7 +71,7 @@ jobs: - name: Test boot working-directory: ./embassy-boot/boot - run: cargo test && cargo test --features "ed25519-dalek" && cargo test --features "ed25519-salty" + run: cargo test --features nightly && cargo test --features "ed25519-dalek,nightly" && cargo test --features "ed25519-salty,nightly" - name: Test sync working-directory: ./embassy-sync From a73f9474a0dc4af1ebfb22d7960e6c4b3aca81bd Mon Sep 17 00:00:00 2001 From: sander Date: Thu, 20 Apr 2023 10:56:59 +0200 Subject: [PATCH 10/10] embassy-boot: ensure tests can run on the stable compiler --- .github/workflows/rust.yml | 2 +- embassy-boot/boot/src/firmware_updater.rs | 1 + embassy-boot/boot/src/lib.rs | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index b8af7fcc..79354fe7 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -71,7 +71,7 @@ jobs: - name: Test boot working-directory: ./embassy-boot/boot - run: cargo test --features nightly && cargo test --features "ed25519-dalek,nightly" && cargo test --features "ed25519-salty,nightly" + run: cargo test && cargo test --features nightly && cargo test --features "ed25519-dalek,nightly" && cargo test --features "ed25519-salty,nightly" - name: Test sync working-directory: ./embassy-sync diff --git a/embassy-boot/boot/src/firmware_updater.rs b/embassy-boot/boot/src/firmware_updater.rs index 1f2a6d24..92987825 100644 --- a/embassy-boot/boot/src/firmware_updater.rs +++ b/embassy-boot/boot/src/firmware_updater.rs @@ -520,6 +520,7 @@ mod tests { use crate::mem_flash::MemFlash; #[test] + #[cfg(feature = "nightly")] fn can_verify_sha1() { const STATE: Partition = Partition::new(0, 4096); const DFU: Partition = Partition::new(65536, 131072); diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs index e268d888..8eb3ba96 100644 --- a/embassy-boot/boot/src/lib.rs +++ b/embassy-boot/boot/src/lib.rs @@ -83,7 +83,7 @@ mod tests { } #[test] - #[cfg(not(feature = "_verify"))] + #[cfg(all(feature = "nightly", not(feature = "_verify")))] fn test_swap_state() { const STATE: Partition = Partition::new(0, 4096); const ACTIVE: Partition = Partition::new(4096, 61440); @@ -136,7 +136,7 @@ mod tests { } #[test] - #[cfg(not(feature = "_verify"))] + #[cfg(all(feature = "nightly", not(feature = "_verify")))] fn test_separate_flash_active_page_biggest() { const STATE: Partition = Partition::new(2048, 4096); const ACTIVE: Partition = Partition::new(4096, 16384); @@ -173,7 +173,7 @@ mod tests { } #[test] - #[cfg(not(feature = "_verify"))] + #[cfg(all(feature = "nightly", not(feature = "_verify")))] fn test_separate_flash_dfu_page_biggest() { const STATE: Partition = Partition::new(2048, 4096); const ACTIVE: Partition = Partition::new(4096, 16384); @@ -212,7 +212,7 @@ mod tests { } #[test] - #[cfg(feature = "_verify")] + #[cfg(all(feature = "nightly", feature = "_verify"))] fn test_verify() { // The following key setup is based on: // https://docs.rs/ed25519-dalek/latest/ed25519_dalek/#example