diff options
| author | klownfish <[email protected]> | 2024-09-24 20:46:04 +0200 |
|---|---|---|
| committer | klownfish <[email protected]> | 2024-09-24 20:46:04 +0200 |
| commit | 60347976b2e56eb8484e10d4aec5fa12534457f7 (patch) | |
| tree | fe1af22314ae008f2a93f34e1bb2b4129d4d85da /embassy-boot/src | |
| parent | fe868fc1948472666b6d8386a3191a074468a34e (diff) | |
| parent | 0ede8479dc4c6a58cfab0a5d4df41c0592405971 (diff) | |
Merge remote-tracking branch 'origin/main' into u5_adc
Diffstat (limited to 'embassy-boot/src')
| -rw-r--r-- | embassy-boot/src/boot_loader.rs | 6 | ||||
| -rw-r--r-- | embassy-boot/src/firmware_updater/asynch.rs | 10 | ||||
| -rw-r--r-- | embassy-boot/src/firmware_updater/blocking.rs | 12 | ||||
| -rw-r--r-- | embassy-boot/src/lib.rs | 24 |
4 files changed, 34 insertions, 18 deletions
diff --git a/embassy-boot/src/boot_loader.rs b/embassy-boot/src/boot_loader.rs index 61d61b96e..5bffdc5ea 100644 --- a/embassy-boot/src/boot_loader.rs +++ b/embassy-boot/src/boot_loader.rs | |||
| @@ -5,7 +5,7 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; | |||
| 5 | use embassy_sync::blocking_mutex::Mutex; | 5 | use embassy_sync::blocking_mutex::Mutex; |
| 6 | use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind}; | 6 | use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind}; |
| 7 | 7 | ||
| 8 | use crate::{State, BOOT_MAGIC, DFU_DETACH_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC}; | 8 | use crate::{State, DFU_DETACH_MAGIC, REVERT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC}; |
| 9 | 9 | ||
| 10 | /// Errors returned by bootloader | 10 | /// Errors returned by bootloader |
| 11 | #[derive(PartialEq, Eq, Debug)] | 11 | #[derive(PartialEq, Eq, Debug)] |
| @@ -276,7 +276,7 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash> BootLoader<ACTIVE, DFU, S | |||
| 276 | self.state.erase(0, self.state.capacity() as u32)?; | 276 | self.state.erase(0, self.state.capacity() as u32)?; |
| 277 | 277 | ||
| 278 | // Set magic | 278 | // Set magic |
| 279 | state_word.fill(BOOT_MAGIC); | 279 | state_word.fill(REVERT_MAGIC); |
| 280 | self.state.write(0, state_word)?; | 280 | self.state.write(0, state_word)?; |
| 281 | } | 281 | } |
| 282 | } | 282 | } |
| @@ -411,6 +411,8 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash> BootLoader<ACTIVE, DFU, S | |||
| 411 | Ok(State::Swap) | 411 | Ok(State::Swap) |
| 412 | } else if !state_word.iter().any(|&b| b != DFU_DETACH_MAGIC) { | 412 | } else if !state_word.iter().any(|&b| b != DFU_DETACH_MAGIC) { |
| 413 | Ok(State::DfuDetach) | 413 | Ok(State::DfuDetach) |
| 414 | } else if !state_word.iter().any(|&b| b != REVERT_MAGIC) { | ||
| 415 | Ok(State::Revert) | ||
| 414 | } else { | 416 | } else { |
| 415 | Ok(State::Boot) | 417 | Ok(State::Boot) |
| 416 | } | 418 | } |
diff --git a/embassy-boot/src/firmware_updater/asynch.rs b/embassy-boot/src/firmware_updater/asynch.rs index 86b441592..d9d15b004 100644 --- a/embassy-boot/src/firmware_updater/asynch.rs +++ b/embassy-boot/src/firmware_updater/asynch.rs | |||
| @@ -289,7 +289,8 @@ impl<'d, STATE: NorFlash> FirmwareState<'d, STATE> { | |||
| 289 | 289 | ||
| 290 | // Make sure we are running a booted firmware to avoid reverting to a bad state. | 290 | // Make sure we are running a booted firmware to avoid reverting to a bad state. |
| 291 | async fn verify_booted(&mut self) -> Result<(), FirmwareUpdaterError> { | 291 | async fn verify_booted(&mut self) -> Result<(), FirmwareUpdaterError> { |
| 292 | if self.get_state().await? == State::Boot { | 292 | let state = self.get_state().await?; |
| 293 | if state == State::Boot || state == State::DfuDetach || state == State::Revert { | ||
| 293 | Ok(()) | 294 | Ok(()) |
| 294 | } else { | 295 | } else { |
| 295 | Err(FirmwareUpdaterError::BadState) | 296 | Err(FirmwareUpdaterError::BadState) |
| @@ -303,12 +304,7 @@ impl<'d, STATE: NorFlash> FirmwareState<'d, STATE> { | |||
| 303 | /// `mark_booted`. | 304 | /// `mark_booted`. |
| 304 | pub async fn get_state(&mut self) -> Result<State, FirmwareUpdaterError> { | 305 | pub async fn get_state(&mut self) -> Result<State, FirmwareUpdaterError> { |
| 305 | self.state.read(0, &mut self.aligned).await?; | 306 | self.state.read(0, &mut self.aligned).await?; |
| 306 | 307 | Ok(State::from(&self.aligned)) | |
| 307 | if !self.aligned.iter().any(|&b| b != SWAP_MAGIC) { | ||
| 308 | Ok(State::Swap) | ||
| 309 | } else { | ||
| 310 | Ok(State::Boot) | ||
| 311 | } | ||
| 312 | } | 308 | } |
| 313 | 309 | ||
| 314 | /// Mark to trigger firmware swap on next boot. | 310 | /// Mark to trigger firmware swap on next boot. |
diff --git a/embassy-boot/src/firmware_updater/blocking.rs b/embassy-boot/src/firmware_updater/blocking.rs index d3c723456..08062b0d0 100644 --- a/embassy-boot/src/firmware_updater/blocking.rs +++ b/embassy-boot/src/firmware_updater/blocking.rs | |||
| @@ -324,7 +324,8 @@ impl<'d, STATE: NorFlash> BlockingFirmwareState<'d, STATE> { | |||
| 324 | 324 | ||
| 325 | // Make sure we are running a booted firmware to avoid reverting to a bad state. | 325 | // Make sure we are running a booted firmware to avoid reverting to a bad state. |
| 326 | fn verify_booted(&mut self) -> Result<(), FirmwareUpdaterError> { | 326 | fn verify_booted(&mut self) -> Result<(), FirmwareUpdaterError> { |
| 327 | if self.get_state()? == State::Boot || self.get_state()? == State::DfuDetach { | 327 | let state = self.get_state()?; |
| 328 | if state == State::Boot || state == State::DfuDetach || state == State::Revert { | ||
| 328 | Ok(()) | 329 | Ok(()) |
| 329 | } else { | 330 | } else { |
| 330 | Err(FirmwareUpdaterError::BadState) | 331 | Err(FirmwareUpdaterError::BadState) |
| @@ -338,14 +339,7 @@ impl<'d, STATE: NorFlash> BlockingFirmwareState<'d, STATE> { | |||
| 338 | /// `mark_booted`. | 339 | /// `mark_booted`. |
| 339 | pub fn get_state(&mut self) -> Result<State, FirmwareUpdaterError> { | 340 | pub fn get_state(&mut self) -> Result<State, FirmwareUpdaterError> { |
| 340 | self.state.read(0, &mut self.aligned)?; | 341 | self.state.read(0, &mut self.aligned)?; |
| 341 | 342 | Ok(State::from(&self.aligned)) | |
| 342 | if !self.aligned.iter().any(|&b| b != SWAP_MAGIC) { | ||
| 343 | Ok(State::Swap) | ||
| 344 | } else if !self.aligned.iter().any(|&b| b != DFU_DETACH_MAGIC) { | ||
| 345 | Ok(State::DfuDetach) | ||
| 346 | } else { | ||
| 347 | Ok(State::Boot) | ||
| 348 | } | ||
| 349 | } | 343 | } |
| 350 | 344 | ||
| 351 | /// Mark to trigger firmware swap on next boot. | 345 | /// Mark to trigger firmware swap on next boot. |
diff --git a/embassy-boot/src/lib.rs b/embassy-boot/src/lib.rs index 8849055e8..e2c4cf771 100644 --- a/embassy-boot/src/lib.rs +++ b/embassy-boot/src/lib.rs | |||
| @@ -25,6 +25,7 @@ pub use firmware_updater::{ | |||
| 25 | FirmwareUpdaterError, | 25 | FirmwareUpdaterError, |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | pub(crate) const REVERT_MAGIC: u8 = 0xC0; | ||
| 28 | pub(crate) const BOOT_MAGIC: u8 = 0xD0; | 29 | pub(crate) const BOOT_MAGIC: u8 = 0xD0; |
| 29 | pub(crate) const SWAP_MAGIC: u8 = 0xF0; | 30 | pub(crate) const SWAP_MAGIC: u8 = 0xF0; |
| 30 | pub(crate) const DFU_DETACH_MAGIC: u8 = 0xE0; | 31 | pub(crate) const DFU_DETACH_MAGIC: u8 = 0xE0; |
| @@ -37,10 +38,30 @@ pub enum State { | |||
| 37 | Boot, | 38 | Boot, |
| 38 | /// Bootloader has swapped the active partition with the dfu partition and will attempt boot. | 39 | /// Bootloader has swapped the active partition with the dfu partition and will attempt boot. |
| 39 | Swap, | 40 | Swap, |
| 41 | /// Bootloader has reverted the active partition with the dfu partition and will attempt boot. | ||
| 42 | Revert, | ||
| 40 | /// Application has received a request to reboot into DFU mode to apply an update. | 43 | /// Application has received a request to reboot into DFU mode to apply an update. |
| 41 | DfuDetach, | 44 | DfuDetach, |
| 42 | } | 45 | } |
| 43 | 46 | ||
| 47 | impl<T> From<T> for State | ||
| 48 | where | ||
| 49 | T: AsRef<[u8]>, | ||
| 50 | { | ||
| 51 | fn from(magic: T) -> State { | ||
| 52 | let magic = magic.as_ref(); | ||
| 53 | if !magic.iter().any(|&b| b != SWAP_MAGIC) { | ||
| 54 | State::Swap | ||
| 55 | } else if !magic.iter().any(|&b| b != REVERT_MAGIC) { | ||
| 56 | State::Revert | ||
| 57 | } else if !magic.iter().any(|&b| b != DFU_DETACH_MAGIC) { | ||
| 58 | State::DfuDetach | ||
| 59 | } else { | ||
| 60 | State::Boot | ||
| 61 | } | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 44 | /// Buffer aligned to 32 byte boundary, largest known alignment requirement for embassy-boot. | 65 | /// Buffer aligned to 32 byte boundary, largest known alignment requirement for embassy-boot. |
| 45 | #[repr(align(32))] | 66 | #[repr(align(32))] |
| 46 | pub struct AlignedBuffer<const N: usize>(pub [u8; N]); | 67 | pub struct AlignedBuffer<const N: usize>(pub [u8; N]); |
| @@ -157,6 +178,9 @@ mod tests { | |||
| 157 | // Running again should cause a revert | 178 | // Running again should cause a revert |
| 158 | assert_eq!(State::Swap, bootloader.prepare_boot(&mut page).unwrap()); | 179 | assert_eq!(State::Swap, bootloader.prepare_boot(&mut page).unwrap()); |
| 159 | 180 | ||
| 181 | // Next time we know it was reverted | ||
| 182 | assert_eq!(State::Revert, bootloader.prepare_boot(&mut page).unwrap()); | ||
| 183 | |||
| 160 | let mut read_buf = [0; FIRMWARE_SIZE]; | 184 | let mut read_buf = [0; FIRMWARE_SIZE]; |
| 161 | flash.active().read(0, &mut read_buf).unwrap(); | 185 | flash.active().read(0, &mut read_buf).unwrap(); |
| 162 | assert_eq!(ORIGINAL, read_buf); | 186 | assert_eq!(ORIGINAL, read_buf); |
