diff options
| author | Ulf Lilleengen <[email protected]> | 2023-08-03 20:56:04 +0200 |
|---|---|---|
| committer | Ulf Lilleengen <[email protected]> | 2023-08-06 19:46:53 +0200 |
| commit | a34331ae5fbf76a61bb2f65dbb13af4d34fcb176 (patch) | |
| tree | eddfa2b200b206923a91b9aae1474156c04e40fa | |
| parent | a40daa923ba031b543ce402f8bd83c2ec41329d8 (diff) | |
Refactor firmware updater
* Allow manipulating state without accessing DFU partition.
* Provide aligned buffer when creating updater to reduce potential wrong parameters passed.
| -rw-r--r-- | embassy-boot/boot/src/firmware_updater/asynch.rs | 188 | ||||
| -rw-r--r-- | embassy-boot/boot/src/firmware_updater/blocking.rs | 196 | ||||
| -rw-r--r-- | embassy-boot/boot/src/firmware_updater/mod.rs | 4 | ||||
| -rw-r--r-- | embassy-boot/boot/src/lib.rs | 79 | ||||
| -rw-r--r-- | embassy-boot/nrf/src/lib.rs | 6 | ||||
| -rw-r--r-- | embassy-boot/rp/src/lib.rs | 6 | ||||
| -rw-r--r-- | embassy-boot/stm32/src/lib.rs | 6 | ||||
| -rw-r--r-- | examples/boot/application/nrf/src/bin/a.rs | 8 | ||||
| -rw-r--r-- | examples/boot/application/rp/src/bin/a.rs | 7 | ||||
| -rw-r--r-- | examples/boot/application/stm32f3/src/bin/a.rs | 8 | ||||
| -rw-r--r-- | examples/boot/application/stm32f7/src/bin/a.rs | 6 | ||||
| -rw-r--r-- | examples/boot/application/stm32h7/src/bin/a.rs | 6 | ||||
| -rw-r--r-- | examples/boot/application/stm32l0/src/bin/a.rs | 8 | ||||
| -rw-r--r-- | examples/boot/application/stm32l1/src/bin/a.rs | 8 | ||||
| -rw-r--r-- | examples/boot/application/stm32l4/src/bin/a.rs | 8 | ||||
| -rw-r--r-- | examples/boot/application/stm32wl/src/bin/a.rs | 8 |
16 files changed, 302 insertions, 250 deletions
diff --git a/embassy-boot/boot/src/firmware_updater/asynch.rs b/embassy-boot/boot/src/firmware_updater/asynch.rs index 20731ee0a..ae713bb6f 100644 --- a/embassy-boot/boot/src/firmware_updater/asynch.rs +++ b/embassy-boot/boot/src/firmware_updater/asynch.rs | |||
| @@ -10,9 +10,9 @@ use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAG | |||
| 10 | 10 | ||
| 11 | /// FirmwareUpdater is an application API for interacting with the BootLoader without the ability to | 11 | /// FirmwareUpdater is an application API for interacting with the BootLoader without the ability to |
| 12 | /// 'mess up' the internal bootloader state | 12 | /// 'mess up' the internal bootloader state |
| 13 | pub struct FirmwareUpdater<DFU: NorFlash, STATE: NorFlash> { | 13 | pub struct FirmwareUpdater<'d, DFU: NorFlash, STATE: NorFlash> { |
| 14 | dfu: DFU, | 14 | dfu: DFU, |
| 15 | state: STATE, | 15 | state: FirmwareState<'d, STATE>, |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | #[cfg(target_os = "none")] | 18 | #[cfg(target_os = "none")] |
| @@ -47,22 +47,12 @@ impl<'a, FLASH: NorFlash> | |||
| 47 | } | 47 | } |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> { | 50 | impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> { |
| 51 | /// Create a firmware updater instance with partition ranges for the update and state partitions. | 51 | /// Create a firmware updater instance with partition ranges for the update and state partitions. |
| 52 | pub fn new(config: FirmwareUpdaterConfig<DFU, STATE>) -> Self { | 52 | pub fn new(config: FirmwareUpdaterConfig<DFU, STATE>, aligned: &'d mut [u8]) -> Self { |
| 53 | Self { | 53 | Self { |
| 54 | dfu: config.dfu, | 54 | dfu: config.dfu, |
| 55 | state: config.state, | 55 | state: FirmwareState::new(config.state, aligned), |
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | // Make sure we are running a booted firmware to avoid reverting to a bad state. | ||
| 60 | async fn verify_booted(&mut self, aligned: &mut [u8]) -> Result<(), FirmwareUpdaterError> { | ||
| 61 | assert_eq!(aligned.len(), STATE::WRITE_SIZE); | ||
| 62 | if self.get_state(aligned).await? == State::Boot { | ||
| 63 | Ok(()) | ||
| 64 | } else { | ||
| 65 | Err(FirmwareUpdaterError::BadState) | ||
| 66 | } | 56 | } |
| 67 | } | 57 | } |
| 68 | 58 | ||
| @@ -71,14 +61,8 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> { | |||
| 71 | /// This is useful to check if the bootloader has just done a swap, in order | 61 | /// This is useful to check if the bootloader has just done a swap, in order |
| 72 | /// to do verifications and self-tests of the new image before calling | 62 | /// to do verifications and self-tests of the new image before calling |
| 73 | /// `mark_booted`. | 63 | /// `mark_booted`. |
| 74 | pub async fn get_state(&mut self, aligned: &mut [u8]) -> Result<State, FirmwareUpdaterError> { | 64 | pub async fn get_state(&mut self) -> Result<State, FirmwareUpdaterError> { |
| 75 | self.state.read(0, aligned).await?; | 65 | self.state.get_state().await |
| 76 | |||
| 77 | if !aligned.iter().any(|&b| b != SWAP_MAGIC) { | ||
| 78 | Ok(State::Swap) | ||
| 79 | } else { | ||
| 80 | Ok(State::Boot) | ||
| 81 | } | ||
| 82 | } | 66 | } |
| 83 | 67 | ||
| 84 | /// Verify the DFU given a public key. If there is an error then DO NOT | 68 | /// Verify the DFU given a public key. If there is an error then DO NOT |
| @@ -92,23 +76,16 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> { | |||
| 92 | /// | 76 | /// |
| 93 | /// If no signature feature is set then this method will always return a | 77 | /// If no signature feature is set then this method will always return a |
| 94 | /// signature error. | 78 | /// signature error. |
| 95 | /// | ||
| 96 | /// # Safety | ||
| 97 | /// | ||
| 98 | /// The `_aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being read from | ||
| 99 | /// and written to. | ||
| 100 | #[cfg(feature = "_verify")] | 79 | #[cfg(feature = "_verify")] |
| 101 | pub async fn verify_and_mark_updated( | 80 | pub async fn verify_and_mark_updated( |
| 102 | &mut self, | 81 | &mut self, |
| 103 | _public_key: &[u8], | 82 | _public_key: &[u8], |
| 104 | _signature: &[u8], | 83 | _signature: &[u8], |
| 105 | _update_len: u32, | 84 | _update_len: u32, |
| 106 | _aligned: &mut [u8], | ||
| 107 | ) -> Result<(), FirmwareUpdaterError> { | 85 | ) -> Result<(), FirmwareUpdaterError> { |
| 108 | assert_eq!(_aligned.len(), STATE::WRITE_SIZE); | ||
| 109 | assert!(_update_len <= self.dfu.capacity() as u32); | 86 | assert!(_update_len <= self.dfu.capacity() as u32); |
| 110 | 87 | ||
| 111 | self.verify_booted(_aligned).await?; | 88 | self.state.verify_booted().await?; |
| 112 | 89 | ||
| 113 | #[cfg(feature = "ed25519-dalek")] | 90 | #[cfg(feature = "ed25519-dalek")] |
| 114 | { | 91 | { |
| @@ -121,8 +98,9 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> { | |||
| 121 | let public_key = PublicKey::from_bytes(_public_key).map_err(into_signature_error)?; | 98 | let public_key = PublicKey::from_bytes(_public_key).map_err(into_signature_error)?; |
| 122 | let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; | 99 | let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; |
| 123 | 100 | ||
| 101 | let mut chunk_buf = [0; 2]; | ||
| 124 | let mut message = [0; 64]; | 102 | let mut message = [0; 64]; |
| 125 | self.hash::<Sha512>(_update_len, _aligned, &mut message).await?; | 103 | self.hash::<Sha512>(_update_len, &mut chunk_buf, &mut message).await?; |
| 126 | 104 | ||
| 127 | public_key.verify(&message, &signature).map_err(into_signature_error)? | 105 | public_key.verify(&message, &signature).map_err(into_signature_error)? |
| 128 | } | 106 | } |
| @@ -143,7 +121,8 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> { | |||
| 143 | let signature = Signature::try_from(&signature).map_err(into_signature_error)?; | 121 | let signature = Signature::try_from(&signature).map_err(into_signature_error)?; |
| 144 | 122 | ||
| 145 | let mut message = [0; 64]; | 123 | let mut message = [0; 64]; |
| 146 | self.hash::<Sha512>(_update_len, _aligned, &mut message).await?; | 124 | let mut chunk_buf = [0; 2]; |
| 125 | self.hash::<Sha512>(_update_len, &mut chunk_buf, &mut message).await?; | ||
| 147 | 126 | ||
| 148 | let r = public_key.verify(&message, &signature); | 127 | let r = public_key.verify(&message, &signature); |
| 149 | trace!( | 128 | trace!( |
| @@ -156,7 +135,7 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> { | |||
| 156 | r.map_err(into_signature_error)? | 135 | r.map_err(into_signature_error)? |
| 157 | } | 136 | } |
| 158 | 137 | ||
| 159 | self.set_magic(_aligned, SWAP_MAGIC).await | 138 | self.state.mark_updated().await |
| 160 | } | 139 | } |
| 161 | 140 | ||
| 162 | /// Verify the update in DFU with any digest. | 141 | /// Verify the update in DFU with any digest. |
| @@ -177,49 +156,14 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> { | |||
| 177 | } | 156 | } |
| 178 | 157 | ||
| 179 | /// Mark to trigger firmware swap on next boot. | 158 | /// Mark to trigger firmware swap on next boot. |
| 180 | /// | ||
| 181 | /// # Safety | ||
| 182 | /// | ||
| 183 | /// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being written to. | ||
| 184 | #[cfg(not(feature = "_verify"))] | 159 | #[cfg(not(feature = "_verify"))] |
| 185 | pub async fn mark_updated(&mut self, aligned: &mut [u8]) -> Result<(), FirmwareUpdaterError> { | 160 | pub async fn mark_updated(&mut self) -> Result<(), FirmwareUpdaterError> { |
| 186 | assert_eq!(aligned.len(), STATE::WRITE_SIZE); | 161 | self.state.mark_updated().await |
| 187 | self.set_magic(aligned, SWAP_MAGIC).await | ||
| 188 | } | 162 | } |
| 189 | 163 | ||
| 190 | /// Mark firmware boot successful and stop rollback on reset. | 164 | /// Mark firmware boot successful and stop rollback on reset. |
| 191 | /// | 165 | pub async fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> { |
| 192 | /// # Safety | 166 | self.state.mark_booted().await |
| 193 | /// | ||
| 194 | /// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being written to. | ||
| 195 | pub async fn mark_booted(&mut self, aligned: &mut [u8]) -> Result<(), FirmwareUpdaterError> { | ||
| 196 | assert_eq!(aligned.len(), STATE::WRITE_SIZE); | ||
| 197 | self.set_magic(aligned, BOOT_MAGIC).await | ||
| 198 | } | ||
| 199 | |||
| 200 | async fn set_magic(&mut self, aligned: &mut [u8], magic: u8) -> Result<(), FirmwareUpdaterError> { | ||
| 201 | self.state.read(0, aligned).await?; | ||
| 202 | |||
| 203 | if aligned.iter().any(|&b| b != magic) { | ||
| 204 | // Read progress validity | ||
| 205 | self.state.read(STATE::WRITE_SIZE as u32, aligned).await?; | ||
| 206 | |||
| 207 | if aligned.iter().any(|&b| b != STATE_ERASE_VALUE) { | ||
| 208 | // The current progress validity marker is invalid | ||
| 209 | } else { | ||
| 210 | // Invalidate progress | ||
| 211 | aligned.fill(!STATE_ERASE_VALUE); | ||
| 212 | self.state.write(STATE::WRITE_SIZE as u32, aligned).await?; | ||
| 213 | } | ||
| 214 | |||
| 215 | // Clear magic and progress | ||
| 216 | self.state.erase(0, self.state.capacity() as u32).await?; | ||
| 217 | |||
| 218 | // Set magic | ||
| 219 | aligned.fill(magic); | ||
| 220 | self.state.write(0, aligned).await?; | ||
| 221 | } | ||
| 222 | Ok(()) | ||
| 223 | } | 167 | } |
| 224 | 168 | ||
| 225 | /// Write data to a flash page. | 169 | /// Write data to a flash page. |
| @@ -229,16 +173,10 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> { | |||
| 229 | /// # Safety | 173 | /// # Safety |
| 230 | /// | 174 | /// |
| 231 | /// Failing to meet alignment and size requirements may result in a panic. | 175 | /// Failing to meet alignment and size requirements may result in a panic. |
| 232 | pub async fn write_firmware( | 176 | pub async fn write_firmware(&mut self, offset: usize, data: &[u8]) -> Result<(), FirmwareUpdaterError> { |
| 233 | &mut self, | ||
| 234 | aligned: &mut [u8], | ||
| 235 | offset: usize, | ||
| 236 | data: &[u8], | ||
| 237 | ) -> Result<(), FirmwareUpdaterError> { | ||
| 238 | assert!(data.len() >= DFU::ERASE_SIZE); | 177 | assert!(data.len() >= DFU::ERASE_SIZE); |
| 239 | assert_eq!(aligned.len(), STATE::WRITE_SIZE); | ||
| 240 | 178 | ||
| 241 | self.verify_booted(aligned).await?; | 179 | self.state.verify_booted().await?; |
| 242 | 180 | ||
| 243 | self.dfu.erase(offset as u32, (offset + data.len()) as u32).await?; | 181 | self.dfu.erase(offset as u32, (offset + data.len()) as u32).await?; |
| 244 | 182 | ||
| @@ -252,17 +190,91 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> { | |||
| 252 | /// | 190 | /// |
| 253 | /// Using this instead of `write_firmware` allows for an optimized API in | 191 | /// Using this instead of `write_firmware` allows for an optimized API in |
| 254 | /// exchange for added complexity. | 192 | /// exchange for added complexity. |
| 193 | pub async fn prepare_update(&mut self) -> Result<&mut DFU, FirmwareUpdaterError> { | ||
| 194 | self.state.verify_booted().await?; | ||
| 195 | self.dfu.erase(0, self.dfu.capacity() as u32).await?; | ||
| 196 | |||
| 197 | Ok(&mut self.dfu) | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | /// Manages the state partition of the firmware update. | ||
| 202 | /// | ||
| 203 | /// Can be used standalone for more fine grained control, or as part of the updater. | ||
| 204 | pub struct FirmwareState<'d, STATE> { | ||
| 205 | state: STATE, | ||
| 206 | aligned: &'d mut [u8], | ||
| 207 | } | ||
| 208 | |||
| 209 | impl<'d, STATE: NorFlash> FirmwareState<'d, STATE> { | ||
| 210 | /// Create a firmware state instance with a buffer for magic content and state partition. | ||
| 255 | /// | 211 | /// |
| 256 | /// # Safety | 212 | /// # Safety |
| 257 | /// | 213 | /// |
| 258 | /// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being written to. | 214 | /// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being read from |
| 259 | pub async fn prepare_update(&mut self, aligned: &mut [u8]) -> Result<&mut DFU, FirmwareUpdaterError> { | 215 | /// and written to. |
| 216 | pub fn new(state: STATE, aligned: &'d mut [u8]) -> Self { | ||
| 260 | assert_eq!(aligned.len(), STATE::WRITE_SIZE); | 217 | assert_eq!(aligned.len(), STATE::WRITE_SIZE); |
| 261 | self.verify_booted(aligned).await?; | 218 | Self { state, aligned } |
| 219 | } | ||
| 262 | 220 | ||
| 263 | self.dfu.erase(0, self.dfu.capacity() as u32).await?; | 221 | // Make sure we are running a booted firmware to avoid reverting to a bad state. |
| 222 | async fn verify_booted(&mut self) -> Result<(), FirmwareUpdaterError> { | ||
| 223 | if self.get_state().await? == State::Boot { | ||
| 224 | Ok(()) | ||
| 225 | } else { | ||
| 226 | Err(FirmwareUpdaterError::BadState) | ||
| 227 | } | ||
| 228 | } | ||
| 264 | 229 | ||
| 265 | Ok(&mut self.dfu) | 230 | /// Obtain the current state. |
| 231 | /// | ||
| 232 | /// This is useful to check if the bootloader has just done a swap, in order | ||
| 233 | /// to do verifications and self-tests of the new image before calling | ||
| 234 | /// `mark_booted`. | ||
| 235 | pub async fn get_state(&mut self) -> Result<State, FirmwareUpdaterError> { | ||
| 236 | self.state.read(0, &mut self.aligned).await?; | ||
| 237 | |||
| 238 | if !self.aligned.iter().any(|&b| b != SWAP_MAGIC) { | ||
| 239 | Ok(State::Swap) | ||
| 240 | } else { | ||
| 241 | Ok(State::Boot) | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | /// Mark to trigger firmware swap on next boot. | ||
| 246 | pub async fn mark_updated(&mut self) -> Result<(), FirmwareUpdaterError> { | ||
| 247 | self.set_magic(SWAP_MAGIC).await | ||
| 248 | } | ||
| 249 | |||
| 250 | /// Mark firmware boot successful and stop rollback on reset. | ||
| 251 | pub async fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> { | ||
| 252 | self.set_magic(BOOT_MAGIC).await | ||
| 253 | } | ||
| 254 | |||
| 255 | async fn set_magic(&mut self, magic: u8) -> Result<(), FirmwareUpdaterError> { | ||
| 256 | self.state.read(0, &mut self.aligned).await?; | ||
| 257 | |||
| 258 | if self.aligned.iter().any(|&b| b != magic) { | ||
| 259 | // Read progress validity | ||
| 260 | self.state.read(STATE::WRITE_SIZE as u32, &mut self.aligned).await?; | ||
| 261 | |||
| 262 | if self.aligned.iter().any(|&b| b != STATE_ERASE_VALUE) { | ||
| 263 | // The current progress validity marker is invalid | ||
| 264 | } else { | ||
| 265 | // Invalidate progress | ||
| 266 | self.aligned.fill(!STATE_ERASE_VALUE); | ||
| 267 | self.state.write(STATE::WRITE_SIZE as u32, &self.aligned).await?; | ||
| 268 | } | ||
| 269 | |||
| 270 | // Clear magic and progress | ||
| 271 | self.state.erase(0, self.state.capacity() as u32).await?; | ||
| 272 | |||
| 273 | // Set magic | ||
| 274 | self.aligned.fill(magic); | ||
| 275 | self.state.write(0, &self.aligned).await?; | ||
| 276 | } | ||
| 277 | Ok(()) | ||
| 266 | } | 278 | } |
| 267 | } | 279 | } |
| 268 | 280 | ||
| @@ -288,8 +300,8 @@ mod tests { | |||
| 288 | let mut to_write = [0; 4096]; | 300 | let mut to_write = [0; 4096]; |
| 289 | to_write[..7].copy_from_slice(update.as_slice()); | 301 | to_write[..7].copy_from_slice(update.as_slice()); |
| 290 | 302 | ||
| 291 | let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig { dfu, state }); | 303 | let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig { dfu, state }, &mut aligned); |
| 292 | block_on(updater.write_firmware(&mut aligned, 0, to_write.as_slice())).unwrap(); | 304 | block_on(updater.write_firmware(0, to_write.as_slice())).unwrap(); |
| 293 | let mut chunk_buf = [0; 2]; | 305 | let mut chunk_buf = [0; 2]; |
| 294 | let mut hash = [0; 20]; | 306 | let mut hash = [0; 20]; |
| 295 | block_on(updater.hash::<Sha1>(update.len() as u32, &mut chunk_buf, &mut hash)).unwrap(); | 307 | block_on(updater.hash::<Sha1>(update.len() as u32, &mut chunk_buf, &mut hash)).unwrap(); |
diff --git a/embassy-boot/boot/src/firmware_updater/blocking.rs b/embassy-boot/boot/src/firmware_updater/blocking.rs index f03f53e4d..76e4264a0 100644 --- a/embassy-boot/boot/src/firmware_updater/blocking.rs +++ b/embassy-boot/boot/src/firmware_updater/blocking.rs | |||
| @@ -10,9 +10,9 @@ use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAG | |||
| 10 | 10 | ||
| 11 | /// Blocking FirmwareUpdater is an application API for interacting with the BootLoader without the ability to | 11 | /// Blocking FirmwareUpdater is an application API for interacting with the BootLoader without the ability to |
| 12 | /// 'mess up' the internal bootloader state | 12 | /// 'mess up' the internal bootloader state |
| 13 | pub struct BlockingFirmwareUpdater<DFU: NorFlash, STATE: NorFlash> { | 13 | pub struct BlockingFirmwareUpdater<'d, DFU: NorFlash, STATE: NorFlash> { |
| 14 | dfu: DFU, | 14 | dfu: DFU, |
| 15 | state: STATE, | 15 | state: BlockingFirmwareState<'d, STATE>, |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | #[cfg(target_os = "none")] | 18 | #[cfg(target_os = "none")] |
| @@ -49,22 +49,17 @@ impl<'a, FLASH: NorFlash> | |||
| 49 | } | 49 | } |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> { | 52 | impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE> { |
| 53 | /// Create a firmware updater instance with partition ranges for the update and state partitions. | 53 | /// Create a firmware updater instance with partition ranges for the update and state partitions. |
| 54 | pub fn new(config: FirmwareUpdaterConfig<DFU, STATE>) -> Self { | 54 | /// |
| 55 | /// # Safety | ||
| 56 | /// | ||
| 57 | /// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being read from | ||
| 58 | /// and written to. | ||
| 59 | pub fn new(config: FirmwareUpdaterConfig<DFU, STATE>, aligned: &'d mut [u8]) -> Self { | ||
| 55 | Self { | 60 | Self { |
| 56 | dfu: config.dfu, | 61 | dfu: config.dfu, |
| 57 | state: config.state, | 62 | state: BlockingFirmwareState::new(config.state, aligned), |
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | // Make sure we are running a booted firmware to avoid reverting to a bad state. | ||
| 62 | fn verify_booted(&mut self, aligned: &mut [u8]) -> Result<(), FirmwareUpdaterError> { | ||
| 63 | assert_eq!(aligned.len(), STATE::WRITE_SIZE); | ||
| 64 | if self.get_state(aligned)? == State::Boot { | ||
| 65 | Ok(()) | ||
| 66 | } else { | ||
| 67 | Err(FirmwareUpdaterError::BadState) | ||
| 68 | } | 63 | } |
| 69 | } | 64 | } |
| 70 | 65 | ||
| @@ -73,14 +68,8 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> { | |||
| 73 | /// This is useful to check if the bootloader has just done a swap, in order | 68 | /// This is useful to check if the bootloader has just done a swap, in order |
| 74 | /// to do verifications and self-tests of the new image before calling | 69 | /// to do verifications and self-tests of the new image before calling |
| 75 | /// `mark_booted`. | 70 | /// `mark_booted`. |
| 76 | pub fn get_state(&mut self, aligned: &mut [u8]) -> Result<State, FirmwareUpdaterError> { | 71 | pub fn get_state(&mut self) -> Result<State, FirmwareUpdaterError> { |
| 77 | self.state.read(0, aligned)?; | 72 | self.state.get_state() |
| 78 | |||
| 79 | if !aligned.iter().any(|&b| b != SWAP_MAGIC) { | ||
| 80 | Ok(State::Swap) | ||
| 81 | } else { | ||
| 82 | Ok(State::Boot) | ||
| 83 | } | ||
| 84 | } | 73 | } |
| 85 | 74 | ||
| 86 | /// Verify the DFU given a public key. If there is an error then DO NOT | 75 | /// Verify the DFU given a public key. If there is an error then DO NOT |
| @@ -94,23 +83,16 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> { | |||
| 94 | /// | 83 | /// |
| 95 | /// If no signature feature is set then this method will always return a | 84 | /// If no signature feature is set then this method will always return a |
| 96 | /// signature error. | 85 | /// signature error. |
| 97 | /// | ||
| 98 | /// # Safety | ||
| 99 | /// | ||
| 100 | /// The `_aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being read from | ||
| 101 | /// and written to. | ||
| 102 | #[cfg(feature = "_verify")] | 86 | #[cfg(feature = "_verify")] |
| 103 | pub fn verify_and_mark_updated( | 87 | pub fn verify_and_mark_updated( |
| 104 | &mut self, | 88 | &mut self, |
| 105 | _public_key: &[u8], | 89 | _public_key: &[u8], |
| 106 | _signature: &[u8], | 90 | _signature: &[u8], |
| 107 | _update_len: u32, | 91 | _update_len: u32, |
| 108 | _aligned: &mut [u8], | ||
| 109 | ) -> Result<(), FirmwareUpdaterError> { | 92 | ) -> Result<(), FirmwareUpdaterError> { |
| 110 | assert_eq!(_aligned.len(), STATE::WRITE_SIZE); | ||
| 111 | assert!(_update_len <= self.dfu.capacity() as u32); | 93 | assert!(_update_len <= self.dfu.capacity() as u32); |
| 112 | 94 | ||
| 113 | self.verify_booted(_aligned)?; | 95 | self.state.verify_booted()?; |
| 114 | 96 | ||
| 115 | #[cfg(feature = "ed25519-dalek")] | 97 | #[cfg(feature = "ed25519-dalek")] |
| 116 | { | 98 | { |
| @@ -124,7 +106,8 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> { | |||
| 124 | let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; | 106 | let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; |
| 125 | 107 | ||
| 126 | let mut message = [0; 64]; | 108 | let mut message = [0; 64]; |
| 127 | self.hash::<Sha512>(_update_len, _aligned, &mut message)?; | 109 | let mut chunk_buf = [0; 2]; |
| 110 | self.hash::<Sha512>(_update_len, &mut chunk_buf, &mut message)?; | ||
| 128 | 111 | ||
| 129 | public_key.verify(&message, &signature).map_err(into_signature_error)? | 112 | public_key.verify(&message, &signature).map_err(into_signature_error)? |
| 130 | } | 113 | } |
| @@ -145,7 +128,8 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> { | |||
| 145 | let signature = Signature::try_from(&signature).map_err(into_signature_error)?; | 128 | let signature = Signature::try_from(&signature).map_err(into_signature_error)?; |
| 146 | 129 | ||
| 147 | let mut message = [0; 64]; | 130 | let mut message = [0; 64]; |
| 148 | self.hash::<Sha512>(_update_len, _aligned, &mut message)?; | 131 | let mut chunk_buf = [0; 2]; |
| 132 | self.hash::<Sha512>(_update_len, &mut chunk_buf, &mut message)?; | ||
| 149 | 133 | ||
| 150 | let r = public_key.verify(&message, &signature); | 134 | let r = public_key.verify(&message, &signature); |
| 151 | trace!( | 135 | trace!( |
| @@ -158,7 +142,7 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> { | |||
| 158 | r.map_err(into_signature_error)? | 142 | r.map_err(into_signature_error)? |
| 159 | } | 143 | } |
| 160 | 144 | ||
| 161 | self.set_magic(_aligned, SWAP_MAGIC) | 145 | self.state.mark_updated() |
| 162 | } | 146 | } |
| 163 | 147 | ||
| 164 | /// Verify the update in DFU with any digest. | 148 | /// Verify the update in DFU with any digest. |
| @@ -179,49 +163,14 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> { | |||
| 179 | } | 163 | } |
| 180 | 164 | ||
| 181 | /// Mark to trigger firmware swap on next boot. | 165 | /// Mark to trigger firmware swap on next boot. |
| 182 | /// | ||
| 183 | /// # Safety | ||
| 184 | /// | ||
| 185 | /// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being written to. | ||
| 186 | #[cfg(not(feature = "_verify"))] | 166 | #[cfg(not(feature = "_verify"))] |
| 187 | pub fn mark_updated(&mut self, aligned: &mut [u8]) -> Result<(), FirmwareUpdaterError> { | 167 | pub fn mark_updated(&mut self) -> Result<(), FirmwareUpdaterError> { |
| 188 | assert_eq!(aligned.len(), STATE::WRITE_SIZE); | 168 | self.state.mark_updated() |
| 189 | self.set_magic(aligned, SWAP_MAGIC) | ||
| 190 | } | 169 | } |
| 191 | 170 | ||
| 192 | /// Mark firmware boot successful and stop rollback on reset. | 171 | /// Mark firmware boot successful and stop rollback on reset. |
| 193 | /// | 172 | pub fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> { |
| 194 | /// # Safety | 173 | self.state.mark_booted() |
| 195 | /// | ||
| 196 | /// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being written to. | ||
| 197 | pub fn mark_booted(&mut self, aligned: &mut [u8]) -> Result<(), FirmwareUpdaterError> { | ||
| 198 | assert_eq!(aligned.len(), STATE::WRITE_SIZE); | ||
| 199 | self.set_magic(aligned, BOOT_MAGIC) | ||
| 200 | } | ||
| 201 | |||
| 202 | fn set_magic(&mut self, aligned: &mut [u8], magic: u8) -> Result<(), FirmwareUpdaterError> { | ||
| 203 | self.state.read(0, aligned)?; | ||
| 204 | |||
| 205 | if aligned.iter().any(|&b| b != magic) { | ||
| 206 | // Read progress validity | ||
| 207 | self.state.read(STATE::WRITE_SIZE as u32, aligned)?; | ||
| 208 | |||
| 209 | if aligned.iter().any(|&b| b != STATE_ERASE_VALUE) { | ||
| 210 | // The current progress validity marker is invalid | ||
| 211 | } else { | ||
| 212 | // Invalidate progress | ||
| 213 | aligned.fill(!STATE_ERASE_VALUE); | ||
| 214 | self.state.write(STATE::WRITE_SIZE as u32, aligned)?; | ||
| 215 | } | ||
| 216 | |||
| 217 | // Clear magic and progress | ||
| 218 | self.state.erase(0, self.state.capacity() as u32)?; | ||
| 219 | |||
| 220 | // Set magic | ||
| 221 | aligned.fill(magic); | ||
| 222 | self.state.write(0, aligned)?; | ||
| 223 | } | ||
| 224 | Ok(()) | ||
| 225 | } | 174 | } |
| 226 | 175 | ||
| 227 | /// Write data to a flash page. | 176 | /// Write data to a flash page. |
| @@ -231,15 +180,9 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> { | |||
| 231 | /// # Safety | 180 | /// # Safety |
| 232 | /// | 181 | /// |
| 233 | /// Failing to meet alignment and size requirements may result in a panic. | 182 | /// Failing to meet alignment and size requirements may result in a panic. |
| 234 | pub fn write_firmware( | 183 | pub fn write_firmware(&mut self, offset: usize, data: &[u8]) -> Result<(), FirmwareUpdaterError> { |
| 235 | &mut self, | ||
| 236 | aligned: &mut [u8], | ||
| 237 | offset: usize, | ||
| 238 | data: &[u8], | ||
| 239 | ) -> Result<(), FirmwareUpdaterError> { | ||
| 240 | assert!(data.len() >= DFU::ERASE_SIZE); | 184 | assert!(data.len() >= DFU::ERASE_SIZE); |
| 241 | assert_eq!(aligned.len(), STATE::WRITE_SIZE); | 185 | self.state.verify_booted()?; |
| 242 | self.verify_booted(aligned)?; | ||
| 243 | 186 | ||
| 244 | self.dfu.erase(offset as u32, (offset + data.len()) as u32)?; | 187 | self.dfu.erase(offset as u32, (offset + data.len()) as u32)?; |
| 245 | 188 | ||
| @@ -253,16 +196,91 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> { | |||
| 253 | /// | 196 | /// |
| 254 | /// Using this instead of `write_firmware` allows for an optimized API in | 197 | /// Using this instead of `write_firmware` allows for an optimized API in |
| 255 | /// exchange for added complexity. | 198 | /// exchange for added complexity. |
| 199 | pub fn prepare_update(&mut self) -> Result<&mut DFU, FirmwareUpdaterError> { | ||
| 200 | self.state.verify_booted()?; | ||
| 201 | self.dfu.erase(0, self.dfu.capacity() as u32)?; | ||
| 202 | |||
| 203 | Ok(&mut self.dfu) | ||
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | /// Manages the state partition of the firmware update. | ||
| 208 | /// | ||
| 209 | /// Can be used standalone for more fine grained control, or as part of the updater. | ||
| 210 | pub struct BlockingFirmwareState<'d, STATE> { | ||
| 211 | state: STATE, | ||
| 212 | aligned: &'d mut [u8], | ||
| 213 | } | ||
| 214 | |||
| 215 | impl<'d, STATE: NorFlash> BlockingFirmwareState<'d, STATE> { | ||
| 216 | /// Create a firmware state instance with a buffer for magic content and state partition. | ||
| 256 | /// | 217 | /// |
| 257 | /// # Safety | 218 | /// # Safety |
| 258 | /// | 219 | /// |
| 259 | /// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being written to. | 220 | /// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being read from |
| 260 | pub fn prepare_update(&mut self, aligned: &mut [u8]) -> Result<&mut DFU, FirmwareUpdaterError> { | 221 | /// and written to. |
| 222 | pub fn new(state: STATE, aligned: &'d mut [u8]) -> Self { | ||
| 261 | assert_eq!(aligned.len(), STATE::WRITE_SIZE); | 223 | assert_eq!(aligned.len(), STATE::WRITE_SIZE); |
| 262 | self.verify_booted(aligned)?; | 224 | Self { state, aligned } |
| 263 | self.dfu.erase(0, self.dfu.capacity() as u32)?; | 225 | } |
| 264 | 226 | ||
| 265 | Ok(&mut self.dfu) | 227 | // Make sure we are running a booted firmware to avoid reverting to a bad state. |
| 228 | fn verify_booted(&mut self) -> Result<(), FirmwareUpdaterError> { | ||
| 229 | if self.get_state()? == State::Boot { | ||
| 230 | Ok(()) | ||
| 231 | } else { | ||
| 232 | Err(FirmwareUpdaterError::BadState) | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | /// Obtain the current state. | ||
| 237 | /// | ||
| 238 | /// This is useful to check if the bootloader has just done a swap, in order | ||
| 239 | /// to do verifications and self-tests of the new image before calling | ||
| 240 | /// `mark_booted`. | ||
| 241 | pub fn get_state(&mut self) -> Result<State, FirmwareUpdaterError> { | ||
| 242 | self.state.read(0, &mut self.aligned)?; | ||
| 243 | |||
| 244 | if !self.aligned.iter().any(|&b| b != SWAP_MAGIC) { | ||
| 245 | Ok(State::Swap) | ||
| 246 | } else { | ||
| 247 | Ok(State::Boot) | ||
| 248 | } | ||
| 249 | } | ||
| 250 | |||
| 251 | /// Mark to trigger firmware swap on next boot. | ||
| 252 | pub fn mark_updated(&mut self) -> Result<(), FirmwareUpdaterError> { | ||
| 253 | self.set_magic(SWAP_MAGIC) | ||
| 254 | } | ||
| 255 | |||
| 256 | /// Mark firmware boot successful and stop rollback on reset. | ||
| 257 | pub fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> { | ||
| 258 | self.set_magic(BOOT_MAGIC) | ||
| 259 | } | ||
| 260 | |||
| 261 | fn set_magic(&mut self, magic: u8) -> Result<(), FirmwareUpdaterError> { | ||
| 262 | self.state.read(0, &mut self.aligned)?; | ||
| 263 | |||
| 264 | if self.aligned.iter().any(|&b| b != magic) { | ||
| 265 | // Read progress validity | ||
| 266 | self.state.read(STATE::WRITE_SIZE as u32, &mut self.aligned)?; | ||
| 267 | |||
| 268 | if self.aligned.iter().any(|&b| b != STATE_ERASE_VALUE) { | ||
| 269 | // The current progress validity marker is invalid | ||
| 270 | } else { | ||
| 271 | // Invalidate progress | ||
| 272 | self.aligned.fill(!STATE_ERASE_VALUE); | ||
| 273 | self.state.write(STATE::WRITE_SIZE as u32, &self.aligned)?; | ||
| 274 | } | ||
| 275 | |||
| 276 | // Clear magic and progress | ||
| 277 | self.state.erase(0, self.state.capacity() as u32)?; | ||
| 278 | |||
| 279 | // Set magic | ||
| 280 | self.aligned.fill(magic); | ||
| 281 | self.state.write(0, &self.aligned)?; | ||
| 282 | } | ||
| 283 | Ok(()) | ||
| 266 | } | 284 | } |
| 267 | } | 285 | } |
| 268 | 286 | ||
| @@ -283,14 +301,14 @@ mod tests { | |||
| 283 | let flash = Mutex::<NoopRawMutex, _>::new(RefCell::new(MemFlash::<131072, 4096, 8>::default())); | 301 | let flash = Mutex::<NoopRawMutex, _>::new(RefCell::new(MemFlash::<131072, 4096, 8>::default())); |
| 284 | let state = BlockingPartition::new(&flash, 0, 4096); | 302 | let state = BlockingPartition::new(&flash, 0, 4096); |
| 285 | let dfu = BlockingPartition::new(&flash, 65536, 65536); | 303 | let dfu = BlockingPartition::new(&flash, 65536, 65536); |
| 304 | let mut aligned = [0; 8]; | ||
| 286 | 305 | ||
| 287 | let update = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66]; | 306 | let update = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66]; |
| 288 | let mut to_write = [0; 4096]; | 307 | let mut to_write = [0; 4096]; |
| 289 | to_write[..7].copy_from_slice(update.as_slice()); | 308 | to_write[..7].copy_from_slice(update.as_slice()); |
| 290 | 309 | ||
| 291 | let mut updater = BlockingFirmwareUpdater::new(FirmwareUpdaterConfig { dfu, state }); | 310 | let mut updater = BlockingFirmwareUpdater::new(FirmwareUpdaterConfig { dfu, state }, &mut aligned); |
| 292 | let mut aligned = [0; 8]; | 311 | updater.write_firmware(0, to_write.as_slice()).unwrap(); |
| 293 | updater.write_firmware(&mut aligned, 0, to_write.as_slice()).unwrap(); | ||
| 294 | let mut chunk_buf = [0; 2]; | 312 | let mut chunk_buf = [0; 2]; |
| 295 | let mut hash = [0; 20]; | 313 | let mut hash = [0; 20]; |
| 296 | updater | 314 | updater |
diff --git a/embassy-boot/boot/src/firmware_updater/mod.rs b/embassy-boot/boot/src/firmware_updater/mod.rs index 55ce8f363..937ddcc69 100644 --- a/embassy-boot/boot/src/firmware_updater/mod.rs +++ b/embassy-boot/boot/src/firmware_updater/mod.rs | |||
| @@ -3,8 +3,8 @@ mod asynch; | |||
| 3 | mod blocking; | 3 | mod blocking; |
| 4 | 4 | ||
| 5 | #[cfg(feature = "nightly")] | 5 | #[cfg(feature = "nightly")] |
| 6 | pub use asynch::FirmwareUpdater; | 6 | pub use asynch::{FirmwareState, FirmwareUpdater}; |
| 7 | pub use blocking::BlockingFirmwareUpdater; | 7 | pub use blocking::{BlockingFirmwareState, BlockingFirmwareUpdater}; |
| 8 | use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind}; | 8 | use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind}; |
| 9 | 9 | ||
| 10 | /// Firmware updater flash configuration holding the two flashes used by the updater | 10 | /// Firmware updater flash configuration holding the two flashes used by the updater |
diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs index 016362b86..47f7c1797 100644 --- a/embassy-boot/boot/src/lib.rs +++ b/embassy-boot/boot/src/lib.rs | |||
| @@ -16,9 +16,11 @@ mod test_flash; | |||
| 16 | // TODO: Use the value provided by NorFlash when available | 16 | // TODO: Use the value provided by NorFlash when available |
| 17 | pub(crate) const STATE_ERASE_VALUE: u8 = 0xFF; | 17 | pub(crate) const STATE_ERASE_VALUE: u8 = 0xFF; |
| 18 | pub use boot_loader::{BootError, BootLoader, BootLoaderConfig}; | 18 | pub use boot_loader::{BootError, BootLoader, BootLoaderConfig}; |
| 19 | pub use firmware_updater::{ | ||
| 20 | BlockingFirmwareState, BlockingFirmwareUpdater, FirmwareUpdaterConfig, FirmwareUpdaterError, | ||
| 21 | }; | ||
| 19 | #[cfg(feature = "nightly")] | 22 | #[cfg(feature = "nightly")] |
| 20 | pub use firmware_updater::FirmwareUpdater; | 23 | pub use firmware_updater::{FirmwareState, FirmwareUpdater}; |
| 21 | pub use firmware_updater::{BlockingFirmwareUpdater, FirmwareUpdaterConfig, FirmwareUpdaterError}; | ||
| 22 | 24 | ||
| 23 | pub(crate) const BOOT_MAGIC: u8 = 0xD0; | 25 | pub(crate) const BOOT_MAGIC: u8 = 0xD0; |
| 24 | pub(crate) const SWAP_MAGIC: u8 = 0xF0; | 26 | pub(crate) const SWAP_MAGIC: u8 = 0xF0; |
| @@ -118,15 +120,18 @@ mod tests { | |||
| 118 | block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap(); | 120 | block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap(); |
| 119 | block_on(flash.active().write(0, &ORIGINAL)).unwrap(); | 121 | block_on(flash.active().write(0, &ORIGINAL)).unwrap(); |
| 120 | 122 | ||
| 121 | let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig { | 123 | let mut updater = FirmwareUpdater::new( |
| 122 | dfu: flash.dfu(), | 124 | FirmwareUpdaterConfig { |
| 123 | state: flash.state(), | 125 | dfu: flash.dfu(), |
| 124 | }); | 126 | state: flash.state(), |
| 125 | block_on(updater.write_firmware(&mut aligned, 0, &UPDATE)).unwrap(); | 127 | }, |
| 126 | block_on(updater.mark_updated(&mut aligned)).unwrap(); | 128 | &mut aligned, |
| 129 | ); | ||
| 130 | block_on(updater.write_firmware(0, &UPDATE)).unwrap(); | ||
| 131 | block_on(updater.mark_updated()).unwrap(); | ||
| 127 | 132 | ||
| 128 | // Writing after marking updated is not allowed until marked as booted. | 133 | // Writing after marking updated is not allowed until marked as booted. |
| 129 | let res: Result<(), FirmwareUpdaterError> = block_on(updater.write_firmware(&mut aligned, 0, &UPDATE)); | 134 | let res: Result<(), FirmwareUpdaterError> = block_on(updater.write_firmware(0, &UPDATE)); |
| 130 | assert!(matches!(res, Err::<(), _>(FirmwareUpdaterError::BadState))); | 135 | assert!(matches!(res, Err::<(), _>(FirmwareUpdaterError::BadState))); |
| 131 | 136 | ||
| 132 | let flash = flash.into_blocking(); | 137 | let flash = flash.into_blocking(); |
| @@ -158,11 +163,14 @@ mod tests { | |||
| 158 | 163 | ||
| 159 | // Mark as booted | 164 | // Mark as booted |
| 160 | let flash = flash.into_async(); | 165 | let flash = flash.into_async(); |
| 161 | let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig { | 166 | let mut updater = FirmwareUpdater::new( |
| 162 | dfu: flash.dfu(), | 167 | FirmwareUpdaterConfig { |
| 163 | state: flash.state(), | 168 | dfu: flash.dfu(), |
| 164 | }); | 169 | state: flash.state(), |
| 165 | block_on(updater.mark_booted(&mut aligned)).unwrap(); | 170 | }, |
| 171 | &mut aligned, | ||
| 172 | ); | ||
| 173 | block_on(updater.mark_booted()).unwrap(); | ||
| 166 | 174 | ||
| 167 | let flash = flash.into_blocking(); | 175 | let flash = flash.into_blocking(); |
| 168 | let mut bootloader = BootLoader::new(BootLoaderConfig { | 176 | let mut bootloader = BootLoader::new(BootLoaderConfig { |
| @@ -190,12 +198,15 @@ mod tests { | |||
| 190 | block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap(); | 198 | block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap(); |
| 191 | block_on(flash.active().write(0, &ORIGINAL)).unwrap(); | 199 | block_on(flash.active().write(0, &ORIGINAL)).unwrap(); |
| 192 | 200 | ||
| 193 | let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig { | 201 | let mut updater = FirmwareUpdater::new( |
| 194 | dfu: flash.dfu(), | 202 | FirmwareUpdaterConfig { |
| 195 | state: flash.state(), | 203 | dfu: flash.dfu(), |
| 196 | }); | 204 | state: flash.state(), |
| 197 | block_on(updater.write_firmware(&mut aligned, 0, &UPDATE)).unwrap(); | 205 | }, |
| 198 | block_on(updater.mark_updated(&mut aligned)).unwrap(); | 206 | &mut aligned, |
| 207 | ); | ||
| 208 | block_on(updater.write_firmware(0, &UPDATE)).unwrap(); | ||
| 209 | block_on(updater.mark_updated()).unwrap(); | ||
| 199 | 210 | ||
| 200 | let flash = flash.into_blocking(); | 211 | let flash = flash.into_blocking(); |
| 201 | let mut bootloader = BootLoader::new(BootLoaderConfig { | 212 | let mut bootloader = BootLoader::new(BootLoaderConfig { |
| @@ -232,12 +243,15 @@ mod tests { | |||
| 232 | block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap(); | 243 | block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap(); |
| 233 | block_on(flash.active().write(0, &ORIGINAL)).unwrap(); | 244 | block_on(flash.active().write(0, &ORIGINAL)).unwrap(); |
| 234 | 245 | ||
| 235 | let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig { | 246 | let mut updater = FirmwareUpdater::new( |
| 236 | dfu: flash.dfu(), | 247 | FirmwareUpdaterConfig { |
| 237 | state: flash.state(), | 248 | dfu: flash.dfu(), |
| 238 | }); | 249 | state: flash.state(), |
| 239 | block_on(updater.write_firmware(&mut aligned, 0, &UPDATE)).unwrap(); | 250 | }, |
| 240 | block_on(updater.mark_updated(&mut aligned)).unwrap(); | 251 | &mut aligned, |
| 252 | ); | ||
| 253 | block_on(updater.write_firmware(0, &UPDATE)).unwrap(); | ||
| 254 | block_on(updater.mark_updated()).unwrap(); | ||
| 241 | 255 | ||
| 242 | let flash = flash.into_blocking(); | 256 | let flash = flash.into_blocking(); |
| 243 | let mut bootloader = BootLoader::new(BootLoaderConfig { | 257 | let mut bootloader = BootLoader::new(BootLoaderConfig { |
| @@ -293,18 +307,19 @@ mod tests { | |||
| 293 | 307 | ||
| 294 | // On with the test | 308 | // On with the test |
| 295 | let flash = flash.into_async(); | 309 | let flash = flash.into_async(); |
| 296 | let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig { | ||
| 297 | dfu: flash.dfu(), | ||
| 298 | state: flash.state(), | ||
| 299 | }); | ||
| 300 | |||
| 301 | let mut aligned = [0; 4]; | 310 | let mut aligned = [0; 4]; |
| 311 | let mut updater = FirmwareUpdater::new( | ||
| 312 | FirmwareUpdaterConfig { | ||
| 313 | dfu: flash.dfu(), | ||
| 314 | state: flash.state(), | ||
| 315 | }, | ||
| 316 | &mut aligned, | ||
| 317 | ); | ||
| 302 | 318 | ||
| 303 | assert!(block_on(updater.verify_and_mark_updated( | 319 | assert!(block_on(updater.verify_and_mark_updated( |
| 304 | &public_key.to_bytes(), | 320 | &public_key.to_bytes(), |
| 305 | &signature.to_bytes(), | 321 | &signature.to_bytes(), |
| 306 | firmware_len as u32, | 322 | firmware_len as u32, |
| 307 | &mut aligned, | ||
| 308 | )) | 323 | )) |
| 309 | .is_ok()); | 324 | .is_ok()); |
| 310 | } | 325 | } |
diff --git a/embassy-boot/nrf/src/lib.rs b/embassy-boot/nrf/src/lib.rs index 65f57fcd1..df94819fc 100644 --- a/embassy-boot/nrf/src/lib.rs +++ b/embassy-boot/nrf/src/lib.rs | |||
| @@ -3,9 +3,11 @@ | |||
| 3 | #![doc = include_str!("../README.md")] | 3 | #![doc = include_str!("../README.md")] |
| 4 | mod fmt; | 4 | mod fmt; |
| 5 | 5 | ||
| 6 | pub use embassy_boot::{ | ||
| 7 | AlignedBuffer, BlockingFirmwareState, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig, | ||
| 8 | }; | ||
| 6 | #[cfg(feature = "nightly")] | 9 | #[cfg(feature = "nightly")] |
| 7 | pub use embassy_boot::FirmwareUpdater; | 10 | pub use embassy_boot::{FirmwareState, FirmwareUpdater}; |
| 8 | pub use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig}; | ||
| 9 | use embassy_nrf::nvmc::PAGE_SIZE; | 11 | use embassy_nrf::nvmc::PAGE_SIZE; |
| 10 | use embassy_nrf::peripherals::WDT; | 12 | use embassy_nrf::peripherals::WDT; |
| 11 | use embassy_nrf::wdt; | 13 | use embassy_nrf::wdt; |
diff --git a/embassy-boot/rp/src/lib.rs b/embassy-boot/rp/src/lib.rs index 35fc104ec..f5aefa416 100644 --- a/embassy-boot/rp/src/lib.rs +++ b/embassy-boot/rp/src/lib.rs | |||
| @@ -3,9 +3,11 @@ | |||
| 3 | #![doc = include_str!("../README.md")] | 3 | #![doc = include_str!("../README.md")] |
| 4 | mod fmt; | 4 | mod fmt; |
| 5 | 5 | ||
| 6 | pub use embassy_boot::{ | ||
| 7 | AlignedBuffer, BlockingFirmwareState, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig, State, | ||
| 8 | }; | ||
| 6 | #[cfg(feature = "nightly")] | 9 | #[cfg(feature = "nightly")] |
| 7 | pub use embassy_boot::FirmwareUpdater; | 10 | pub use embassy_boot::{FirmwareState, FirmwareUpdater}; |
| 8 | pub use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig, State}; | ||
| 9 | use embassy_rp::flash::{Blocking, Flash, ERASE_SIZE}; | 11 | use embassy_rp::flash::{Blocking, Flash, ERASE_SIZE}; |
| 10 | use embassy_rp::peripherals::{FLASH, WATCHDOG}; | 12 | use embassy_rp::peripherals::{FLASH, WATCHDOG}; |
| 11 | use embassy_rp::watchdog::Watchdog; | 13 | use embassy_rp::watchdog::Watchdog; |
diff --git a/embassy-boot/stm32/src/lib.rs b/embassy-boot/stm32/src/lib.rs index 069de0d1a..25f029423 100644 --- a/embassy-boot/stm32/src/lib.rs +++ b/embassy-boot/stm32/src/lib.rs | |||
| @@ -3,9 +3,11 @@ | |||
| 3 | #![doc = include_str!("../README.md")] | 3 | #![doc = include_str!("../README.md")] |
| 4 | mod fmt; | 4 | mod fmt; |
| 5 | 5 | ||
| 6 | pub use embassy_boot::{ | ||
| 7 | AlignedBuffer, BlockingFirmwareState, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig, State, | ||
| 8 | }; | ||
| 6 | #[cfg(feature = "nightly")] | 9 | #[cfg(feature = "nightly")] |
| 7 | pub use embassy_boot::FirmwareUpdater; | 10 | pub use embassy_boot::{FirmwareState, FirmwareUpdater}; |
| 8 | pub use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig, State}; | ||
| 9 | use embedded_storage::nor_flash::NorFlash; | 11 | use embedded_storage::nor_flash::NorFlash; |
| 10 | 12 | ||
| 11 | /// A bootloader for STM32 devices. | 13 | /// A bootloader for STM32 devices. |
diff --git a/examples/boot/application/nrf/src/bin/a.rs b/examples/boot/application/nrf/src/bin/a.rs index 021d77f3b..8b510ed35 100644 --- a/examples/boot/application/nrf/src/bin/a.rs +++ b/examples/boot/application/nrf/src/bin/a.rs | |||
| @@ -52,20 +52,20 @@ async fn main(_spawner: Spawner) { | |||
| 52 | let nvmc = Mutex::new(BlockingAsync::new(nvmc)); | 52 | let nvmc = Mutex::new(BlockingAsync::new(nvmc)); |
| 53 | 53 | ||
| 54 | let config = FirmwareUpdaterConfig::from_linkerfile(&nvmc); | 54 | let config = FirmwareUpdaterConfig::from_linkerfile(&nvmc); |
| 55 | let mut updater = FirmwareUpdater::new(config); | 55 | let mut magic = [0; 4]; |
| 56 | let mut updater = FirmwareUpdater::new(config, &mut magic); | ||
| 56 | loop { | 57 | loop { |
| 57 | led.set_low(); | 58 | led.set_low(); |
| 58 | button.wait_for_any_edge().await; | 59 | button.wait_for_any_edge().await; |
| 59 | if button.is_low() { | 60 | if button.is_low() { |
| 60 | let mut offset = 0; | 61 | let mut offset = 0; |
| 61 | let mut magic = [0; 4]; | ||
| 62 | for chunk in APP_B.chunks(4096) { | 62 | for chunk in APP_B.chunks(4096) { |
| 63 | let mut buf: [u8; 4096] = [0; 4096]; | 63 | let mut buf: [u8; 4096] = [0; 4096]; |
| 64 | buf[..chunk.len()].copy_from_slice(chunk); | 64 | buf[..chunk.len()].copy_from_slice(chunk); |
| 65 | updater.write_firmware(&mut magic, offset, &buf).await.unwrap(); | 65 | updater.write_firmware(offset, &buf).await.unwrap(); |
| 66 | offset += chunk.len(); | 66 | offset += chunk.len(); |
| 67 | } | 67 | } |
| 68 | updater.mark_updated(&mut magic).await.unwrap(); | 68 | updater.mark_updated().await.unwrap(); |
| 69 | led.set_high(); | 69 | led.set_high(); |
| 70 | cortex_m::peripheral::SCB::sys_reset(); | 70 | cortex_m::peripheral::SCB::sys_reset(); |
| 71 | } | 71 | } |
diff --git a/examples/boot/application/rp/src/bin/a.rs b/examples/boot/application/rp/src/bin/a.rs index b5e1950cc..f0dda39d0 100644 --- a/examples/boot/application/rp/src/bin/a.rs +++ b/examples/boot/application/rp/src/bin/a.rs | |||
| @@ -38,7 +38,8 @@ async fn main(_s: Spawner) { | |||
| 38 | let flash = Mutex::new(RefCell::new(flash)); | 38 | let flash = Mutex::new(RefCell::new(flash)); |
| 39 | 39 | ||
| 40 | let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash); | 40 | let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash); |
| 41 | let mut updater = BlockingFirmwareUpdater::new(config); | 41 | let mut aligned = AlignedBuffer([0; 4]); |
| 42 | let mut updater = BlockingFirmwareUpdater::new(config, &mut aligned.0); | ||
| 42 | 43 | ||
| 43 | Timer::after(Duration::from_secs(5)).await; | 44 | Timer::after(Duration::from_secs(5)).await; |
| 44 | watchdog.feed(); | 45 | watchdog.feed(); |
| @@ -47,7 +48,7 @@ async fn main(_s: Spawner) { | |||
| 47 | let mut buf: AlignedBuffer<4096> = AlignedBuffer([0; 4096]); | 48 | let mut buf: AlignedBuffer<4096> = AlignedBuffer([0; 4096]); |
| 48 | defmt::info!("preparing update"); | 49 | defmt::info!("preparing update"); |
| 49 | let writer = updater | 50 | let writer = updater |
| 50 | .prepare_update(&mut buf.0[..1]) | 51 | .prepare_update() |
| 51 | .map_err(|e| defmt::warn!("E: {:?}", defmt::Debug2Format(&e))) | 52 | .map_err(|e| defmt::warn!("E: {:?}", defmt::Debug2Format(&e))) |
| 52 | .unwrap(); | 53 | .unwrap(); |
| 53 | defmt::info!("writer created, starting write"); | 54 | defmt::info!("writer created, starting write"); |
| @@ -59,7 +60,7 @@ async fn main(_s: Spawner) { | |||
| 59 | } | 60 | } |
| 60 | watchdog.feed(); | 61 | watchdog.feed(); |
| 61 | defmt::info!("firmware written, marking update"); | 62 | defmt::info!("firmware written, marking update"); |
| 62 | updater.mark_updated(&mut buf.0[..1]).unwrap(); | 63 | updater.mark_updated().unwrap(); |
| 63 | Timer::after(Duration::from_secs(2)).await; | 64 | Timer::after(Duration::from_secs(2)).await; |
| 64 | led.set_low(); | 65 | led.set_low(); |
| 65 | defmt::info!("update marked, resetting"); | 66 | defmt::info!("update marked, resetting"); |
diff --git a/examples/boot/application/stm32f3/src/bin/a.rs b/examples/boot/application/stm32f3/src/bin/a.rs index c0a11d699..8be39bfb7 100644 --- a/examples/boot/application/stm32f3/src/bin/a.rs +++ b/examples/boot/application/stm32f3/src/bin/a.rs | |||
| @@ -31,17 +31,17 @@ async fn main(_spawner: Spawner) { | |||
| 31 | led.set_high(); | 31 | led.set_high(); |
| 32 | 32 | ||
| 33 | let config = FirmwareUpdaterConfig::from_linkerfile(&flash); | 33 | let config = FirmwareUpdaterConfig::from_linkerfile(&flash); |
| 34 | let mut updater = FirmwareUpdater::new(config); | 34 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); |
| 35 | let mut updater = FirmwareUpdater::new(config, &mut magic.0); | ||
| 35 | button.wait_for_falling_edge().await; | 36 | button.wait_for_falling_edge().await; |
| 36 | let mut offset = 0; | 37 | let mut offset = 0; |
| 37 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); | ||
| 38 | for chunk in APP_B.chunks(2048) { | 38 | for chunk in APP_B.chunks(2048) { |
| 39 | let mut buf: [u8; 2048] = [0; 2048]; | 39 | let mut buf: [u8; 2048] = [0; 2048]; |
| 40 | buf[..chunk.len()].copy_from_slice(chunk); | 40 | buf[..chunk.len()].copy_from_slice(chunk); |
| 41 | updater.write_firmware(magic.as_mut(), offset, &buf).await.unwrap(); | 41 | updater.write_firmware(offset, &buf).await.unwrap(); |
| 42 | offset += chunk.len(); | 42 | offset += chunk.len(); |
| 43 | } | 43 | } |
| 44 | updater.mark_updated(magic.as_mut()).await.unwrap(); | 44 | updater.mark_updated().await.unwrap(); |
| 45 | led.set_low(); | 45 | led.set_low(); |
| 46 | cortex_m::peripheral::SCB::sys_reset(); | 46 | cortex_m::peripheral::SCB::sys_reset(); |
| 47 | } | 47 | } |
diff --git a/examples/boot/application/stm32f7/src/bin/a.rs b/examples/boot/application/stm32f7/src/bin/a.rs index dea682a96..0c3819bed 100644 --- a/examples/boot/application/stm32f7/src/bin/a.rs +++ b/examples/boot/application/stm32f7/src/bin/a.rs | |||
| @@ -33,9 +33,9 @@ async fn main(_spawner: Spawner) { | |||
| 33 | led.set_high(); | 33 | led.set_high(); |
| 34 | 34 | ||
| 35 | let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash); | 35 | let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash); |
| 36 | let mut updater = BlockingFirmwareUpdater::new(config); | ||
| 37 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); | 36 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); |
| 38 | let writer = updater.prepare_update(magic.as_mut()).unwrap(); | 37 | let mut updater = BlockingFirmwareUpdater::new(config, &mut magic.0); |
| 38 | let writer = updater.prepare_update().unwrap(); | ||
| 39 | button.wait_for_rising_edge().await; | 39 | button.wait_for_rising_edge().await; |
| 40 | let mut offset = 0; | 40 | let mut offset = 0; |
| 41 | let mut buf = AlignedBuffer([0; 4096]); | 41 | let mut buf = AlignedBuffer([0; 4096]); |
| @@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) { | |||
| 44 | writer.write(offset, buf.as_ref()).unwrap(); | 44 | writer.write(offset, buf.as_ref()).unwrap(); |
| 45 | offset += chunk.len() as u32; | 45 | offset += chunk.len() as u32; |
| 46 | } | 46 | } |
| 47 | updater.mark_updated(magic.as_mut()).unwrap(); | 47 | updater.mark_updated().unwrap(); |
| 48 | led.set_low(); | 48 | led.set_low(); |
| 49 | cortex_m::peripheral::SCB::sys_reset(); | 49 | cortex_m::peripheral::SCB::sys_reset(); |
| 50 | } | 50 | } |
diff --git a/examples/boot/application/stm32h7/src/bin/a.rs b/examples/boot/application/stm32h7/src/bin/a.rs index 719176692..f239e3732 100644 --- a/examples/boot/application/stm32h7/src/bin/a.rs +++ b/examples/boot/application/stm32h7/src/bin/a.rs | |||
| @@ -34,8 +34,8 @@ async fn main(_spawner: Spawner) { | |||
| 34 | 34 | ||
| 35 | let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash); | 35 | let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash); |
| 36 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); | 36 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); |
| 37 | let mut updater = BlockingFirmwareUpdater::new(config); | 37 | let mut updater = BlockingFirmwareUpdater::new(config, &mut magic.0); |
| 38 | let writer = updater.prepare_update(magic.as_mut()).unwrap(); | 38 | let writer = updater.prepare_update().unwrap(); |
| 39 | button.wait_for_rising_edge().await; | 39 | button.wait_for_rising_edge().await; |
| 40 | let mut offset = 0; | 40 | let mut offset = 0; |
| 41 | let mut buf = AlignedBuffer([0; 4096]); | 41 | let mut buf = AlignedBuffer([0; 4096]); |
| @@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) { | |||
| 44 | writer.write(offset, buf.as_ref()).unwrap(); | 44 | writer.write(offset, buf.as_ref()).unwrap(); |
| 45 | offset += chunk.len() as u32; | 45 | offset += chunk.len() as u32; |
| 46 | } | 46 | } |
| 47 | updater.mark_updated(magic.as_mut()).unwrap(); | 47 | updater.mark_updated().unwrap(); |
| 48 | led.set_low(); | 48 | led.set_low(); |
| 49 | cortex_m::peripheral::SCB::sys_reset(); | 49 | cortex_m::peripheral::SCB::sys_reset(); |
| 50 | } | 50 | } |
diff --git a/examples/boot/application/stm32l0/src/bin/a.rs b/examples/boot/application/stm32l0/src/bin/a.rs index ce80056e6..b4cdcd44d 100644 --- a/examples/boot/application/stm32l0/src/bin/a.rs +++ b/examples/boot/application/stm32l0/src/bin/a.rs | |||
| @@ -33,18 +33,18 @@ async fn main(_spawner: Spawner) { | |||
| 33 | led.set_high(); | 33 | led.set_high(); |
| 34 | 34 | ||
| 35 | let config = FirmwareUpdaterConfig::from_linkerfile(&flash); | 35 | let config = FirmwareUpdaterConfig::from_linkerfile(&flash); |
| 36 | let mut updater = FirmwareUpdater::new(config); | 36 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); |
| 37 | let mut updater = FirmwareUpdater::new(config, &mut magic.0); | ||
| 37 | button.wait_for_falling_edge().await; | 38 | button.wait_for_falling_edge().await; |
| 38 | let mut offset = 0; | 39 | let mut offset = 0; |
| 39 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); | ||
| 40 | for chunk in APP_B.chunks(128) { | 40 | for chunk in APP_B.chunks(128) { |
| 41 | let mut buf: [u8; 128] = [0; 128]; | 41 | let mut buf: [u8; 128] = [0; 128]; |
| 42 | buf[..chunk.len()].copy_from_slice(chunk); | 42 | buf[..chunk.len()].copy_from_slice(chunk); |
| 43 | updater.write_firmware(magic.as_mut(), offset, &buf).await.unwrap(); | 43 | updater.write_firmware(offset, &buf).await.unwrap(); |
| 44 | offset += chunk.len(); | 44 | offset += chunk.len(); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | updater.mark_updated(magic.as_mut()).await.unwrap(); | 47 | updater.mark_updated().await.unwrap(); |
| 48 | led.set_low(); | 48 | led.set_low(); |
| 49 | Timer::after(Duration::from_secs(1)).await; | 49 | Timer::after(Duration::from_secs(1)).await; |
| 50 | cortex_m::peripheral::SCB::sys_reset(); | 50 | cortex_m::peripheral::SCB::sys_reset(); |
diff --git a/examples/boot/application/stm32l1/src/bin/a.rs b/examples/boot/application/stm32l1/src/bin/a.rs index 1e9bf3cb9..b4cdcd44d 100644 --- a/examples/boot/application/stm32l1/src/bin/a.rs +++ b/examples/boot/application/stm32l1/src/bin/a.rs | |||
| @@ -33,18 +33,18 @@ async fn main(_spawner: Spawner) { | |||
| 33 | led.set_high(); | 33 | led.set_high(); |
| 34 | 34 | ||
| 35 | let config = FirmwareUpdaterConfig::from_linkerfile(&flash); | 35 | let config = FirmwareUpdaterConfig::from_linkerfile(&flash); |
| 36 | let mut updater = FirmwareUpdater::new(config); | ||
| 37 | button.wait_for_falling_edge().await; | ||
| 38 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); | 36 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); |
| 37 | let mut updater = FirmwareUpdater::new(config, &mut magic.0); | ||
| 38 | button.wait_for_falling_edge().await; | ||
| 39 | let mut offset = 0; | 39 | let mut offset = 0; |
| 40 | for chunk in APP_B.chunks(128) { | 40 | for chunk in APP_B.chunks(128) { |
| 41 | let mut buf: [u8; 128] = [0; 128]; | 41 | let mut buf: [u8; 128] = [0; 128]; |
| 42 | buf[..chunk.len()].copy_from_slice(chunk); | 42 | buf[..chunk.len()].copy_from_slice(chunk); |
| 43 | updater.write_firmware(magic.as_mut(), offset, &buf).await.unwrap(); | 43 | updater.write_firmware(offset, &buf).await.unwrap(); |
| 44 | offset += chunk.len(); | 44 | offset += chunk.len(); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | updater.mark_updated(magic.as_mut()).await.unwrap(); | 47 | updater.mark_updated().await.unwrap(); |
| 48 | led.set_low(); | 48 | led.set_low(); |
| 49 | Timer::after(Duration::from_secs(1)).await; | 49 | Timer::after(Duration::from_secs(1)).await; |
| 50 | cortex_m::peripheral::SCB::sys_reset(); | 50 | cortex_m::peripheral::SCB::sys_reset(); |
diff --git a/examples/boot/application/stm32l4/src/bin/a.rs b/examples/boot/application/stm32l4/src/bin/a.rs index a514ab5be..eefa25f75 100644 --- a/examples/boot/application/stm32l4/src/bin/a.rs +++ b/examples/boot/application/stm32l4/src/bin/a.rs | |||
| @@ -31,17 +31,17 @@ async fn main(_spawner: Spawner) { | |||
| 31 | led.set_high(); | 31 | led.set_high(); |
| 32 | 32 | ||
| 33 | let config = FirmwareUpdaterConfig::from_linkerfile(&flash); | 33 | let config = FirmwareUpdaterConfig::from_linkerfile(&flash); |
| 34 | let mut updater = FirmwareUpdater::new(config); | ||
| 35 | button.wait_for_falling_edge().await; | ||
| 36 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); | 34 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); |
| 35 | let mut updater = FirmwareUpdater::new(config, &mut magic.0); | ||
| 36 | button.wait_for_falling_edge().await; | ||
| 37 | let mut offset = 0; | 37 | let mut offset = 0; |
| 38 | for chunk in APP_B.chunks(2048) { | 38 | for chunk in APP_B.chunks(2048) { |
| 39 | let mut buf: [u8; 2048] = [0; 2048]; | 39 | let mut buf: [u8; 2048] = [0; 2048]; |
| 40 | buf[..chunk.len()].copy_from_slice(chunk); | 40 | buf[..chunk.len()].copy_from_slice(chunk); |
| 41 | updater.write_firmware(magic.as_mut(), offset, &buf).await.unwrap(); | 41 | updater.write_firmware(offset, &buf).await.unwrap(); |
| 42 | offset += chunk.len(); | 42 | offset += chunk.len(); |
| 43 | } | 43 | } |
| 44 | updater.mark_updated(magic.as_mut()).await.unwrap(); | 44 | updater.mark_updated().await.unwrap(); |
| 45 | led.set_low(); | 45 | led.set_low(); |
| 46 | cortex_m::peripheral::SCB::sys_reset(); | 46 | cortex_m::peripheral::SCB::sys_reset(); |
| 47 | } | 47 | } |
diff --git a/examples/boot/application/stm32wl/src/bin/a.rs b/examples/boot/application/stm32wl/src/bin/a.rs index 52a197a5c..c837e47b5 100644 --- a/examples/boot/application/stm32wl/src/bin/a.rs +++ b/examples/boot/application/stm32wl/src/bin/a.rs | |||
| @@ -31,19 +31,19 @@ async fn main(_spawner: Spawner) { | |||
| 31 | led.set_high(); | 31 | led.set_high(); |
| 32 | 32 | ||
| 33 | let config = FirmwareUpdaterConfig::from_linkerfile(&flash); | 33 | let config = FirmwareUpdaterConfig::from_linkerfile(&flash); |
| 34 | let mut updater = FirmwareUpdater::new(config); | 34 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); |
| 35 | let mut updater = FirmwareUpdater::new(config, &mut magic.0); | ||
| 35 | button.wait_for_falling_edge().await; | 36 | button.wait_for_falling_edge().await; |
| 36 | //defmt::info!("Starting update"); | 37 | //defmt::info!("Starting update"); |
| 37 | let mut magic = AlignedBuffer([0; WRITE_SIZE]); | ||
| 38 | let mut offset = 0; | 38 | let mut offset = 0; |
| 39 | for chunk in APP_B.chunks(2048) { | 39 | for chunk in APP_B.chunks(2048) { |
| 40 | let mut buf: [u8; 2048] = [0; 2048]; | 40 | let mut buf: [u8; 2048] = [0; 2048]; |
| 41 | buf[..chunk.len()].copy_from_slice(chunk); | 41 | buf[..chunk.len()].copy_from_slice(chunk); |
| 42 | // defmt::info!("Writing chunk at 0x{:x}", offset); | 42 | // defmt::info!("Writing chunk at 0x{:x}", offset); |
| 43 | updater.write_firmware(magic.as_mut(), offset, &buf).await.unwrap(); | 43 | updater.write_firmware(offset, &buf).await.unwrap(); |
| 44 | offset += chunk.len(); | 44 | offset += chunk.len(); |
| 45 | } | 45 | } |
| 46 | updater.mark_updated(magic.as_mut()).await.unwrap(); | 46 | updater.mark_updated().await.unwrap(); |
| 47 | //defmt::info!("Marked as updated"); | 47 | //defmt::info!("Marked as updated"); |
| 48 | led.set_low(); | 48 | led.set_low(); |
| 49 | cortex_m::peripheral::SCB::sys_reset(); | 49 | cortex_m::peripheral::SCB::sys_reset(); |
