diff options
| author | Rasmus Melchior Jacobsen <[email protected]> | 2023-04-05 08:28:31 +0200 |
|---|---|---|
| committer | Rasmus Melchior Jacobsen <[email protected]> | 2023-04-05 08:28:31 +0200 |
| commit | 2deb2c624c78f4ff582441d7d00a654ac3844e33 (patch) | |
| tree | 159614af96d809bab75537400d91d2dda4224432 | |
| parent | 064ec9581e33fdd42f89ff75984254ccfec3f6c2 (diff) | |
Let Partition range be u32 instead of usize
| -rw-r--r-- | embassy-boot/boot/src/boot_loader.rs | 101 | ||||
| -rw-r--r-- | embassy-boot/boot/src/firmware_updater.rs | 17 | ||||
| -rw-r--r-- | embassy-boot/boot/src/lib.rs | 60 | ||||
| -rw-r--r-- | embassy-boot/boot/src/mem_flash.rs | 17 | ||||
| -rw-r--r-- | embassy-boot/boot/src/partition.rs | 9 |
5 files changed, 93 insertions, 111 deletions
diff --git a/embassy-boot/boot/src/boot_loader.rs b/embassy-boot/boot/src/boot_loader.rs index 2412427c0..b959de2c4 100644 --- a/embassy-boot/boot/src/boot_loader.rs +++ b/embassy-boot/boot/src/boot_loader.rs | |||
| @@ -50,13 +50,13 @@ pub trait FlashConfig { | |||
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | trait FlashConfigEx { | 52 | trait FlashConfigEx { |
| 53 | fn page_size() -> usize; | 53 | fn page_size() -> u32; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | impl<T: FlashConfig> FlashConfigEx for T { | 56 | impl<T: FlashConfig> FlashConfigEx for T { |
| 57 | /// Get the page size which is the "unit of operation" within the bootloader. | 57 | /// Get the page size which is the "unit of operation" within the bootloader. |
| 58 | fn page_size() -> usize { | 58 | fn page_size() -> u32 { |
| 59 | core::cmp::max(T::ACTIVE::ERASE_SIZE, T::DFU::ERASE_SIZE) | 59 | core::cmp::max(T::ACTIVE::ERASE_SIZE, T::DFU::ERASE_SIZE) as u32 |
| 60 | } | 60 | } |
| 61 | } | 61 | } |
| 62 | 62 | ||
| @@ -86,7 +86,7 @@ impl BootLoader { | |||
| 86 | 86 | ||
| 87 | /// Return the offset of the active partition into the active flash. | 87 | /// Return the offset of the active partition into the active flash. |
| 88 | pub fn boot_address(&self) -> usize { | 88 | pub fn boot_address(&self) -> usize { |
| 89 | self.active.from | 89 | self.active.from as usize |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | /// Perform necessary boot preparations like swapping images. | 92 | /// Perform necessary boot preparations like swapping images. |
| @@ -177,11 +177,11 @@ impl BootLoader { | |||
| 177 | /// | 177 | /// |
| 178 | pub fn prepare_boot<P: FlashConfig>(&mut self, p: &mut P, aligned_buf: &mut [u8]) -> Result<State, BootError> { | 178 | pub fn prepare_boot<P: FlashConfig>(&mut self, p: &mut P, aligned_buf: &mut [u8]) -> Result<State, BootError> { |
| 179 | // Ensure we have enough progress pages to store copy progress | 179 | // Ensure we have enough progress pages to store copy progress |
| 180 | assert_eq!(0, P::page_size() % aligned_buf.len()); | 180 | assert_eq!(0, P::page_size() % aligned_buf.len() as u32); |
| 181 | assert_eq!(0, P::page_size() % P::ACTIVE::WRITE_SIZE); | 181 | assert_eq!(0, P::page_size() % P::ACTIVE::WRITE_SIZE as u32); |
| 182 | assert_eq!(0, P::page_size() % P::ACTIVE::ERASE_SIZE); | 182 | assert_eq!(0, P::page_size() % P::ACTIVE::ERASE_SIZE as u32); |
| 183 | assert_eq!(0, P::page_size() % P::DFU::WRITE_SIZE); | 183 | assert_eq!(0, P::page_size() % P::DFU::WRITE_SIZE as u32); |
| 184 | assert_eq!(0, P::page_size() % P::DFU::ERASE_SIZE); | 184 | assert_eq!(0, P::page_size() % P::DFU::ERASE_SIZE as u32); |
| 185 | assert!(aligned_buf.len() >= P::STATE::WRITE_SIZE); | 185 | assert!(aligned_buf.len() >= P::STATE::WRITE_SIZE); |
| 186 | assert_eq!(0, aligned_buf.len() % P::ACTIVE::WRITE_SIZE); | 186 | assert_eq!(0, aligned_buf.len() % P::ACTIVE::WRITE_SIZE); |
| 187 | assert_eq!(0, aligned_buf.len() % P::DFU::WRITE_SIZE); | 187 | assert_eq!(0, aligned_buf.len() % P::DFU::WRITE_SIZE); |
| @@ -222,30 +222,27 @@ impl BootLoader { | |||
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | fn is_swapped<P: FlashConfig>(&mut self, p: &mut P, aligned_buf: &mut [u8]) -> Result<bool, BootError> { | 224 | fn is_swapped<P: FlashConfig>(&mut self, p: &mut P, aligned_buf: &mut [u8]) -> Result<bool, BootError> { |
| 225 | let page_count = self.active.len() / P::page_size(); | 225 | let page_count = (self.active.size() / P::page_size()) as usize; |
| 226 | let progress = self.current_progress(p, aligned_buf)?; | 226 | let progress = self.current_progress(p, aligned_buf)?; |
| 227 | 227 | ||
| 228 | Ok(progress >= page_count * 2) | 228 | Ok(progress >= page_count * 2) |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | fn current_progress<P: FlashConfig>(&mut self, config: &mut P, aligned_buf: &mut [u8]) -> Result<usize, BootError> { | 231 | fn current_progress<P: FlashConfig>(&mut self, config: &mut P, aligned_buf: &mut [u8]) -> Result<usize, BootError> { |
| 232 | let max_index = ((self.state.len() - P::STATE::WRITE_SIZE) / P::STATE::WRITE_SIZE) - 2; | 232 | let write_size = P::STATE::WRITE_SIZE as u32; |
| 233 | let max_index = (((self.state.size() - write_size) / write_size) - 2) as usize; | ||
| 233 | let state_flash = config.state(); | 234 | let state_flash = config.state(); |
| 234 | let state_word = &mut aligned_buf[..P::STATE::WRITE_SIZE]; | 235 | let state_word = &mut aligned_buf[..write_size as usize]; |
| 235 | 236 | ||
| 236 | self.state | 237 | self.state.read_blocking(state_flash, write_size, state_word)?; |
| 237 | .read_blocking(state_flash, P::STATE::WRITE_SIZE as u32, state_word)?; | ||
| 238 | if state_word.iter().any(|&b| b != P::STATE_ERASE_VALUE) { | 238 | if state_word.iter().any(|&b| b != P::STATE_ERASE_VALUE) { |
| 239 | // Progress is invalid | 239 | // Progress is invalid |
| 240 | return Ok(max_index); | 240 | return Ok(max_index); |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | for index in 0..max_index { | 243 | for index in 0..max_index { |
| 244 | self.state.read_blocking( | 244 | self.state |
| 245 | state_flash, | 245 | .read_blocking(state_flash, (2 + index) as u32 * write_size, state_word)?; |
| 246 | (2 + index) as u32 * P::STATE::WRITE_SIZE as u32, | ||
| 247 | state_word, | ||
| 248 | )?; | ||
| 249 | 246 | ||
| 250 | if state_word.iter().any(|&b| b == P::STATE_ERASE_VALUE) { | 247 | if state_word.iter().any(|&b| b == P::STATE_ERASE_VALUE) { |
| 251 | return Ok(index); | 248 | return Ok(index); |
| @@ -256,26 +253,29 @@ impl BootLoader { | |||
| 256 | 253 | ||
| 257 | fn update_progress<P: FlashConfig>( | 254 | fn update_progress<P: FlashConfig>( |
| 258 | &mut self, | 255 | &mut self, |
| 259 | index: usize, | 256 | progress_index: usize, |
| 260 | p: &mut P, | 257 | p: &mut P, |
| 261 | aligned_buf: &mut [u8], | 258 | aligned_buf: &mut [u8], |
| 262 | ) -> Result<(), BootError> { | 259 | ) -> Result<(), BootError> { |
| 263 | let state_word = &mut aligned_buf[..P::STATE::WRITE_SIZE]; | 260 | let state_word = &mut aligned_buf[..P::STATE::WRITE_SIZE]; |
| 264 | state_word.fill(!P::STATE_ERASE_VALUE); | 261 | state_word.fill(!P::STATE_ERASE_VALUE); |
| 265 | self.state | 262 | self.state.write_blocking( |
| 266 | .write_blocking(p.state(), (2 + index) as u32 * P::STATE::WRITE_SIZE as u32, state_word)?; | 263 | p.state(), |
| 264 | (2 + progress_index) as u32 * P::STATE::WRITE_SIZE as u32, | ||
| 265 | state_word, | ||
| 266 | )?; | ||
| 267 | Ok(()) | 267 | Ok(()) |
| 268 | } | 268 | } |
| 269 | 269 | ||
| 270 | fn copy_page_once_to_active<P: FlashConfig>( | 270 | fn copy_page_once_to_active<P: FlashConfig>( |
| 271 | &mut self, | 271 | &mut self, |
| 272 | idx: usize, | 272 | progress_index: usize, |
| 273 | from_offset: u32, | 273 | from_offset: u32, |
| 274 | to_offset: u32, | 274 | to_offset: u32, |
| 275 | p: &mut P, | 275 | p: &mut P, |
| 276 | aligned_buf: &mut [u8], | 276 | aligned_buf: &mut [u8], |
| 277 | ) -> Result<(), BootError> { | 277 | ) -> Result<(), BootError> { |
| 278 | if self.current_progress(p, aligned_buf)? <= idx { | 278 | if self.current_progress(p, aligned_buf)? <= progress_index { |
| 279 | let page_size = P::page_size() as u32; | 279 | let page_size = P::page_size() as u32; |
| 280 | 280 | ||
| 281 | self.active | 281 | self.active |
| @@ -288,20 +288,20 @@ impl BootLoader { | |||
| 288 | .write_blocking(p.active(), to_offset + offset_in_page as u32, aligned_buf)?; | 288 | .write_blocking(p.active(), to_offset + offset_in_page as u32, aligned_buf)?; |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | self.update_progress(idx, p, aligned_buf)?; | 291 | self.update_progress(progress_index, p, aligned_buf)?; |
| 292 | } | 292 | } |
| 293 | Ok(()) | 293 | Ok(()) |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | fn copy_page_once_to_dfu<P: FlashConfig>( | 296 | fn copy_page_once_to_dfu<P: FlashConfig>( |
| 297 | &mut self, | 297 | &mut self, |
| 298 | idx: usize, | 298 | progress_index: usize, |
| 299 | from_offset: u32, | 299 | from_offset: u32, |
| 300 | to_offset: u32, | 300 | to_offset: u32, |
| 301 | p: &mut P, | 301 | p: &mut P, |
| 302 | aligned_buf: &mut [u8], | 302 | aligned_buf: &mut [u8], |
| 303 | ) -> Result<(), BootError> { | 303 | ) -> Result<(), BootError> { |
| 304 | if self.current_progress(p, aligned_buf)? <= idx { | 304 | if self.current_progress(p, aligned_buf)? <= progress_index { |
| 305 | let page_size = P::page_size() as u32; | 305 | let page_size = P::page_size() as u32; |
| 306 | 306 | ||
| 307 | self.dfu | 307 | self.dfu |
| @@ -314,31 +314,28 @@ impl BootLoader { | |||
| 314 | .write_blocking(p.dfu(), to_offset + offset_in_page as u32, aligned_buf)?; | 314 | .write_blocking(p.dfu(), to_offset + offset_in_page as u32, aligned_buf)?; |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | self.update_progress(idx, p, aligned_buf)?; | 317 | self.update_progress(progress_index, p, aligned_buf)?; |
| 318 | } | 318 | } |
| 319 | Ok(()) | 319 | Ok(()) |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | fn swap<P: FlashConfig>(&mut self, p: &mut P, aligned_buf: &mut [u8]) -> Result<(), BootError> { | 322 | fn swap<P: FlashConfig>(&mut self, p: &mut P, aligned_buf: &mut [u8]) -> Result<(), BootError> { |
| 323 | let page_size = P::page_size(); | 323 | let page_size = P::page_size(); |
| 324 | let page_count = self.active.len() / page_size; | 324 | let page_count = self.active.size() / page_size; |
| 325 | trace!("Page count: {}", page_count); | ||
| 326 | for page_num in 0..page_count { | 325 | for page_num in 0..page_count { |
| 327 | trace!("COPY PAGE {}", page_num); | 326 | let progress_index = (page_num * 2) as usize; |
| 328 | |||
| 329 | let idx = page_num * 2; | ||
| 330 | 327 | ||
| 331 | // Copy active page to the 'next' DFU page. | 328 | // Copy active page to the 'next' DFU page. |
| 332 | let active_from_offset = ((page_count - 1 - page_num) * page_size) as u32; | 329 | let active_from_offset = (page_count - 1 - page_num) * page_size; |
| 333 | let dfu_to_offset = ((page_count - page_num) * page_size) as u32; | 330 | let dfu_to_offset = (page_count - page_num) * page_size; |
| 334 | //trace!("Copy active {} to dfu {}", active_from_offset, dfu_to_offset); | 331 | //trace!("Copy active {} to dfu {}", active_from_offset, dfu_to_offset); |
| 335 | self.copy_page_once_to_dfu(idx, active_from_offset, dfu_to_offset, p, aligned_buf)?; | 332 | self.copy_page_once_to_dfu(progress_index, active_from_offset, dfu_to_offset, p, aligned_buf)?; |
| 336 | 333 | ||
| 337 | // Copy DFU page to the active page | 334 | // Copy DFU page to the active page |
| 338 | let active_to_offset = ((page_count - 1 - page_num) * page_size) as u32; | 335 | let active_to_offset = (page_count - 1 - page_num) * page_size; |
| 339 | let dfu_from_offset = ((page_count - 1 - page_num) * page_size) as u32; | 336 | let dfu_from_offset = (page_count - 1 - page_num) * page_size; |
| 340 | //trace!("Copy dfy {} to active {}", dfu_from_offset, active_to_offset); | 337 | //trace!("Copy dfy {} to active {}", dfu_from_offset, active_to_offset); |
| 341 | self.copy_page_once_to_active(idx + 1, dfu_from_offset, active_to_offset, p, aligned_buf)?; | 338 | self.copy_page_once_to_active(progress_index + 1, dfu_from_offset, active_to_offset, p, aligned_buf)?; |
| 342 | } | 339 | } |
| 343 | 340 | ||
| 344 | Ok(()) | 341 | Ok(()) |
| @@ -346,19 +343,19 @@ impl BootLoader { | |||
| 346 | 343 | ||
| 347 | fn revert<P: FlashConfig>(&mut self, p: &mut P, aligned_buf: &mut [u8]) -> Result<(), BootError> { | 344 | fn revert<P: FlashConfig>(&mut self, p: &mut P, aligned_buf: &mut [u8]) -> Result<(), BootError> { |
| 348 | let page_size = P::page_size(); | 345 | let page_size = P::page_size(); |
| 349 | let page_count = self.active.len() / page_size; | 346 | let page_count = self.active.size() / page_size; |
| 350 | for page_num in 0..page_count { | 347 | for page_num in 0..page_count { |
| 351 | let idx = page_count * 2 + page_num * 2; | 348 | let progress_index = (page_count * 2 + page_num * 2) as usize; |
| 352 | 349 | ||
| 353 | // Copy the bad active page to the DFU page | 350 | // Copy the bad active page to the DFU page |
| 354 | let active_from_offset = (page_num * page_size) as u32; | 351 | let active_from_offset = page_num * page_size; |
| 355 | let dfu_to_offset = (page_num * page_size) as u32; | 352 | let dfu_to_offset = page_num * page_size; |
| 356 | self.copy_page_once_to_dfu(idx, active_from_offset, dfu_to_offset, p, aligned_buf)?; | 353 | self.copy_page_once_to_dfu(progress_index, active_from_offset, dfu_to_offset, p, aligned_buf)?; |
| 357 | 354 | ||
| 358 | // Copy the DFU page back to the active page | 355 | // Copy the DFU page back to the active page |
| 359 | let active_to_offset = (page_num * page_size) as u32; | 356 | let active_to_offset = page_num * page_size; |
| 360 | let dfu_from_offset = ((page_num + 1) * page_size) as u32; | 357 | let dfu_from_offset = (page_num + 1) * page_size; |
| 361 | self.copy_page_once_to_active(idx + 1, dfu_from_offset, active_to_offset, p, aligned_buf)?; | 358 | self.copy_page_once_to_active(progress_index + 1, dfu_from_offset, active_to_offset, p, aligned_buf)?; |
| 362 | } | 359 | } |
| 363 | 360 | ||
| 364 | Ok(()) | 361 | Ok(()) |
| @@ -376,11 +373,11 @@ impl BootLoader { | |||
| 376 | } | 373 | } |
| 377 | } | 374 | } |
| 378 | 375 | ||
| 379 | fn assert_partitions(active: Partition, dfu: Partition, state: Partition, page_size: usize, write_size: usize) { | 376 | fn assert_partitions(active: Partition, dfu: Partition, state: Partition, page_size: u32, state_write_size: usize) { |
| 380 | assert_eq!(active.len() % page_size, 0); | 377 | assert_eq!(active.size() % page_size, 0); |
| 381 | assert_eq!(dfu.len() % page_size, 0); | 378 | assert_eq!(dfu.size() % page_size, 0); |
| 382 | assert!(dfu.len() - active.len() >= page_size); | 379 | assert!(dfu.size() - active.size() >= page_size); |
| 383 | assert!(2 + 2 * (active.len() / page_size) <= state.len() / write_size); | 380 | assert!(2 + 2 * (active.size() / page_size) <= state.size() / state_write_size as u32); |
| 384 | } | 381 | } |
| 385 | 382 | ||
| 386 | /// A flash wrapper implementing the Flash and embedded_storage traits. | 383 | /// A flash wrapper implementing the Flash and embedded_storage traits. |
diff --git a/embassy-boot/boot/src/firmware_updater.rs b/embassy-boot/boot/src/firmware_updater.rs index 2b5cc72fa..93d4a4c12 100644 --- a/embassy-boot/boot/src/firmware_updater.rs +++ b/embassy-boot/boot/src/firmware_updater.rs | |||
| @@ -49,14 +49,14 @@ impl Default for FirmwareUpdater { | |||
| 49 | 49 | ||
| 50 | let dfu = unsafe { | 50 | let dfu = unsafe { |
| 51 | Partition::new( | 51 | Partition::new( |
| 52 | &__bootloader_dfu_start as *const u32 as usize, | 52 | &__bootloader_dfu_start as *const u32 as u32, |
| 53 | &__bootloader_dfu_end as *const u32 as usize, | 53 | &__bootloader_dfu_end as *const u32 as u32, |
| 54 | ) | 54 | ) |
| 55 | }; | 55 | }; |
| 56 | let state = unsafe { | 56 | let state = unsafe { |
| 57 | Partition::new( | 57 | Partition::new( |
| 58 | &__bootloader_state_start as *const u32 as usize, | 58 | &__bootloader_state_start as *const u32 as u32, |
| 59 | &__bootloader_state_end as *const u32 as usize, | 59 | &__bootloader_state_end as *const u32 as u32, |
| 60 | ) | 60 | ) |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| @@ -121,10 +121,8 @@ impl FirmwareUpdater { | |||
| 121 | _update_len: usize, | 121 | _update_len: usize, |
| 122 | _aligned: &mut [u8], | 122 | _aligned: &mut [u8], |
| 123 | ) -> Result<(), FirmwareUpdaterError> { | 123 | ) -> Result<(), FirmwareUpdaterError> { |
| 124 | let _read_size = _aligned.len(); | ||
| 125 | |||
| 126 | assert_eq!(_aligned.len(), F::WRITE_SIZE); | 124 | assert_eq!(_aligned.len(), F::WRITE_SIZE); |
| 127 | assert!(_update_len <= self.dfu.len()); | 125 | assert!(_update_len as u32 <= self.dfu.size()); |
| 128 | 126 | ||
| 129 | #[cfg(feature = "ed25519-dalek")] | 127 | #[cfg(feature = "ed25519-dalek")] |
| 130 | { | 128 | { |
| @@ -330,11 +328,8 @@ impl FirmwareUpdater { | |||
| 330 | _update_len: usize, | 328 | _update_len: usize, |
| 331 | _aligned: &mut [u8], | 329 | _aligned: &mut [u8], |
| 332 | ) -> Result<(), FirmwareUpdaterError> { | 330 | ) -> Result<(), FirmwareUpdaterError> { |
| 333 | let _end = self.dfu.from + _update_len; | ||
| 334 | let _read_size = _aligned.len(); | ||
| 335 | |||
| 336 | assert_eq!(_aligned.len(), F::WRITE_SIZE); | 331 | assert_eq!(_aligned.len(), F::WRITE_SIZE); |
| 337 | assert!(_end <= self.dfu.to); | 332 | assert!(_update_len as u32 <= self.dfu.size()); |
| 338 | 333 | ||
| 339 | #[cfg(feature = "ed25519-dalek")] | 334 | #[cfg(feature = "ed25519-dalek")] |
| 340 | { | 335 | { |
diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs index 3109f2b47..8b94b6bdc 100644 --- a/embassy-boot/boot/src/lib.rs +++ b/embassy-boot/boot/src/lib.rs | |||
| @@ -89,13 +89,11 @@ mod tests { | |||
| 89 | const DFU: Partition = Partition::new(61440, 122880); | 89 | const DFU: Partition = Partition::new(61440, 122880); |
| 90 | let mut flash = MemFlash::<131072, 4096, 4>::random(); | 90 | let mut flash = MemFlash::<131072, 4096, 4>::random(); |
| 91 | 91 | ||
| 92 | let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()]; | 92 | let original = [rand::random::<u8>(); ACTIVE.size() as usize]; |
| 93 | let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()]; | 93 | let update = [rand::random::<u8>(); ACTIVE.size() as usize]; |
| 94 | let mut aligned = [0; 4]; | 94 | let mut aligned = [0; 4]; |
| 95 | 95 | ||
| 96 | for i in ACTIVE.from..ACTIVE.to { | 96 | flash.program(ACTIVE.from, &original).unwrap(); |
| 97 | flash.mem[i] = original[i - ACTIVE.from]; | ||
| 98 | } | ||
| 99 | 97 | ||
| 100 | let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE); | 98 | let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE); |
| 101 | let mut updater = FirmwareUpdater::new(DFU, STATE); | 99 | let mut updater = FirmwareUpdater::new(DFU, STATE); |
| @@ -110,14 +108,9 @@ mod tests { | |||
| 110 | .unwrap() | 108 | .unwrap() |
| 111 | ); | 109 | ); |
| 112 | 110 | ||
| 113 | for i in ACTIVE.from..ACTIVE.to { | 111 | flash.assert_eq(ACTIVE.from, &update); |
| 114 | assert_eq!(flash.mem[i], update[i - ACTIVE.from], "Index {}", i); | ||
| 115 | } | ||
| 116 | |||
| 117 | // First DFU page is untouched | 112 | // First DFU page is untouched |
| 118 | for i in DFU.from + 4096..DFU.to { | 113 | flash.assert_eq(DFU.from + 4096, &original); |
| 119 | assert_eq!(flash.mem[i], original[i - DFU.from - 4096], "Index {}", i); | ||
| 120 | } | ||
| 121 | 114 | ||
| 122 | // Running again should cause a revert | 115 | // Running again should cause a revert |
| 123 | assert_eq!( | 116 | assert_eq!( |
| @@ -127,14 +120,9 @@ mod tests { | |||
| 127 | .unwrap() | 120 | .unwrap() |
| 128 | ); | 121 | ); |
| 129 | 122 | ||
| 130 | for i in ACTIVE.from..ACTIVE.to { | 123 | flash.assert_eq(ACTIVE.from, &original); |
| 131 | assert_eq!(flash.mem[i], original[i - ACTIVE.from], "Index {}", i); | ||
| 132 | } | ||
| 133 | |||
| 134 | // Last page is untouched | 124 | // Last page is untouched |
| 135 | for i in DFU.from..DFU.to - 4096 { | 125 | flash.assert_eq(DFU.from, &update); |
| 136 | assert_eq!(flash.mem[i], update[i - DFU.from], "Index {}", i); | ||
| 137 | } | ||
| 138 | 126 | ||
| 139 | // Mark as booted | 127 | // Mark as booted |
| 140 | block_on(updater.mark_booted(&mut flash, &mut aligned)).unwrap(); | 128 | block_on(updater.mark_booted(&mut flash, &mut aligned)).unwrap(); |
| @@ -158,12 +146,10 @@ mod tests { | |||
| 158 | let mut state = MemFlash::<4096, 128, 4>::random(); | 146 | let mut state = MemFlash::<4096, 128, 4>::random(); |
| 159 | let mut aligned = [0; 4]; | 147 | let mut aligned = [0; 4]; |
| 160 | 148 | ||
| 161 | let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()]; | 149 | let original = [rand::random::<u8>(); ACTIVE.size() as usize]; |
| 162 | let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()]; | 150 | let update = [rand::random::<u8>(); ACTIVE.size() as usize]; |
| 163 | 151 | ||
| 164 | for i in ACTIVE.from..ACTIVE.to { | 152 | active.program(ACTIVE.from, &original).unwrap(); |
| 165 | active.mem[i] = original[i - ACTIVE.from]; | ||
| 166 | } | ||
| 167 | 153 | ||
| 168 | let mut updater = FirmwareUpdater::new(DFU, STATE); | 154 | let mut updater = FirmwareUpdater::new(DFU, STATE); |
| 169 | 155 | ||
| @@ -180,14 +166,9 @@ mod tests { | |||
| 180 | .unwrap() | 166 | .unwrap() |
| 181 | ); | 167 | ); |
| 182 | 168 | ||
| 183 | for i in ACTIVE.from..ACTIVE.to { | 169 | active.assert_eq(ACTIVE.from, &update); |
| 184 | assert_eq!(active.mem[i], update[i - ACTIVE.from], "Index {}", i); | ||
| 185 | } | ||
| 186 | |||
| 187 | // First DFU page is untouched | 170 | // First DFU page is untouched |
| 188 | for i in DFU.from + 4096..DFU.to { | 171 | dfu.assert_eq(DFU.from + 4096, &original); |
| 189 | assert_eq!(dfu.mem[i], original[i - DFU.from - 4096], "Index {}", i); | ||
| 190 | } | ||
| 191 | } | 172 | } |
| 192 | 173 | ||
| 193 | #[test] | 174 | #[test] |
| @@ -202,12 +183,10 @@ mod tests { | |||
| 202 | let mut dfu = MemFlash::<16384, 4096, 8>::random(); | 183 | let mut dfu = MemFlash::<16384, 4096, 8>::random(); |
| 203 | let mut state = MemFlash::<4096, 128, 4>::random(); | 184 | let mut state = MemFlash::<4096, 128, 4>::random(); |
| 204 | 185 | ||
| 205 | let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()]; | 186 | let original = [rand::random::<u8>(); ACTIVE.size() as usize]; |
| 206 | let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()]; | 187 | let update = [rand::random::<u8>(); ACTIVE.size() as usize]; |
| 207 | 188 | ||
| 208 | for i in ACTIVE.from..ACTIVE.to { | 189 | active.program(ACTIVE.from, &original).unwrap(); |
| 209 | active.mem[i] = original[i - ACTIVE.from]; | ||
| 210 | } | ||
| 211 | 190 | ||
| 212 | let mut updater = FirmwareUpdater::new(DFU, STATE); | 191 | let mut updater = FirmwareUpdater::new(DFU, STATE); |
| 213 | 192 | ||
| @@ -226,14 +205,9 @@ mod tests { | |||
| 226 | .unwrap() | 205 | .unwrap() |
| 227 | ); | 206 | ); |
| 228 | 207 | ||
| 229 | for i in ACTIVE.from..ACTIVE.to { | 208 | active.assert_eq(ACTIVE.from, &update); |
| 230 | assert_eq!(active.mem[i], update[i - ACTIVE.from], "Index {}", i); | ||
| 231 | } | ||
| 232 | |||
| 233 | // First DFU page is untouched | 209 | // First DFU page is untouched |
| 234 | for i in DFU.from + 4096..DFU.to { | 210 | dfu.assert_eq(DFU.from + 4096, &original); |
| 235 | assert_eq!(dfu.mem[i], original[i - DFU.from - 4096], "Index {}", i); | ||
| 236 | } | ||
| 237 | } | 211 | } |
| 238 | 212 | ||
| 239 | #[test] | 213 | #[test] |
diff --git a/embassy-boot/boot/src/mem_flash.rs b/embassy-boot/boot/src/mem_flash.rs index dd85405c8..c62379b24 100644 --- a/embassy-boot/boot/src/mem_flash.rs +++ b/embassy-boot/boot/src/mem_flash.rs | |||
| @@ -32,6 +32,23 @@ impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> MemFla | |||
| 32 | pending_write_successes: None, | 32 | pending_write_successes: None, |
| 33 | } | 33 | } |
| 34 | } | 34 | } |
| 35 | |||
| 36 | pub fn program(&mut self, offset: u32, bytes: &[u8]) -> Result<(), MemFlashError> { | ||
| 37 | let offset = offset as usize; | ||
| 38 | assert!(bytes.len() % WRITE_SIZE == 0); | ||
| 39 | assert!(offset % WRITE_SIZE == 0); | ||
| 40 | assert!(offset + bytes.len() <= SIZE); | ||
| 41 | |||
| 42 | self.mem[offset..offset + bytes.len()].copy_from_slice(bytes); | ||
| 43 | |||
| 44 | Ok(()) | ||
| 45 | } | ||
| 46 | |||
| 47 | pub fn assert_eq(&self, offset: u32, expectation: &[u8]) { | ||
| 48 | for i in 0..expectation.len() { | ||
| 49 | assert_eq!(self.mem[offset as usize + i], expectation[i], "Index {}", i); | ||
| 50 | } | ||
| 51 | } | ||
| 35 | } | 52 | } |
| 36 | 53 | ||
| 37 | impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> Default | 54 | impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> Default |
diff --git a/embassy-boot/boot/src/partition.rs b/embassy-boot/boot/src/partition.rs index ac6b0ed0f..7529059b6 100644 --- a/embassy-boot/boot/src/partition.rs +++ b/embassy-boot/boot/src/partition.rs | |||
| @@ -6,20 +6,19 @@ use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash | |||
| 6 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 6 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 7 | pub struct Partition { | 7 | pub struct Partition { |
| 8 | /// The offset into the flash where the partition starts. | 8 | /// The offset into the flash where the partition starts. |
| 9 | pub from: usize, | 9 | pub from: u32, |
| 10 | /// The offset into the flash where the partition ends. | 10 | /// The offset into the flash where the partition ends. |
| 11 | pub to: usize, | 11 | pub to: u32, |
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | impl Partition { | 14 | impl Partition { |
| 15 | /// Create a new partition with the provided range | 15 | /// Create a new partition with the provided range |
| 16 | pub const fn new(from: usize, to: usize) -> Self { | 16 | pub const fn new(from: u32, to: u32) -> Self { |
| 17 | Self { from, to } | 17 | Self { from, to } |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | /// Return the size of the partition | 20 | /// Return the size of the partition |
| 21 | #[allow(clippy::len_without_is_empty)] | 21 | pub const fn size(&self) -> u32 { |
| 22 | pub const fn len(&self) -> usize { | ||
| 23 | self.to - self.from | 22 | self.to - self.from |
| 24 | } | 23 | } |
| 25 | 24 | ||
