diff options
Diffstat (limited to 'embassy-boot/boot/src/boot_loader.rs')
| -rw-r--r-- | embassy-boot/boot/src/boot_loader.rs | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/embassy-boot/boot/src/boot_loader.rs b/embassy-boot/boot/src/boot_loader.rs index e2e361e3c..9d047f778 100644 --- a/embassy-boot/boot/src/boot_loader.rs +++ b/embassy-boot/boot/src/boot_loader.rs | |||
| @@ -31,7 +31,7 @@ where | |||
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | /// Extension of the embedded-storage flash type information with block size and erase value. | 33 | /// Extension of the embedded-storage flash type information with block size and erase value. |
| 34 | pub trait Flash: NorFlash + ReadNorFlash { | 34 | pub trait Flash: NorFlash { |
| 35 | /// The block size that should be used when writing to flash. For most builtin flashes, this is the same as the erase | 35 | /// The block size that should be used when writing to flash. For most builtin flashes, this is the same as the erase |
| 36 | /// size of the flash, but for external QSPI flash modules, this can be lower. | 36 | /// size of the flash, but for external QSPI flash modules, this can be lower. |
| 37 | const BLOCK_SIZE: usize; | 37 | const BLOCK_SIZE: usize; |
| @@ -60,9 +60,11 @@ pub trait FlashConfig { | |||
| 60 | /// different page sizes and flash write sizes. | 60 | /// different page sizes and flash write sizes. |
| 61 | pub struct BootLoader { | 61 | pub struct BootLoader { |
| 62 | // Page with current state of bootloader. The state partition has the following format: | 62 | // Page with current state of bootloader. The state partition has the following format: |
| 63 | // | Range | Description | | 63 | // All ranges are in multiples of WRITE_SIZE bytes. |
| 64 | // | 0 - WRITE_SIZE | Magic indicating bootloader state. BOOT_MAGIC means boot, SWAP_MAGIC means swap. | | 64 | // | Range | Description | |
| 65 | // | WRITE_SIZE - N | Progress index used while swapping or reverting | | 65 | // | 0..1 | Magic indicating bootloader state. BOOT_MAGIC means boot, SWAP_MAGIC means swap. | |
| 66 | // | 1..2 | Progress validity. ERASE_VALUE means valid, !ERASE_VALUE means invalid. | | ||
| 67 | // | 2..2 + N | Progress index used while swapping or reverting | | ||
| 66 | state: Partition, | 68 | state: Partition, |
| 67 | // Location of the partition which will be booted from | 69 | // Location of the partition which will be booted from |
| 68 | active: Partition, | 70 | active: Partition, |
| @@ -192,12 +194,17 @@ impl BootLoader { | |||
| 192 | trace!("Reverting"); | 194 | trace!("Reverting"); |
| 193 | self.revert(p, magic, page)?; | 195 | self.revert(p, magic, page)?; |
| 194 | 196 | ||
| 195 | // Overwrite magic and reset progress | ||
| 196 | let state_flash = p.state(); | 197 | let state_flash = p.state(); |
| 198 | |||
| 199 | // Invalidate progress | ||
| 197 | magic.fill(!P::STATE::ERASE_VALUE); | 200 | magic.fill(!P::STATE::ERASE_VALUE); |
| 198 | self.state.write_blocking(state_flash, 0, magic)?; | 201 | self.state |
| 202 | .write_blocking(state_flash, P::STATE::WRITE_SIZE as u32, magic)?; | ||
| 203 | |||
| 204 | // Clear magic and progress | ||
| 199 | self.state.wipe_blocking(state_flash)?; | 205 | self.state.wipe_blocking(state_flash)?; |
| 200 | 206 | ||
| 207 | // Set magic | ||
| 201 | magic.fill(BOOT_MAGIC); | 208 | magic.fill(BOOT_MAGIC); |
| 202 | self.state.write_blocking(state_flash, 0, magic)?; | 209 | self.state.write_blocking(state_flash, 0, magic)?; |
| 203 | } | 210 | } |
| @@ -215,28 +222,34 @@ impl BootLoader { | |||
| 215 | 222 | ||
| 216 | fn current_progress<P: FlashConfig>(&mut self, config: &mut P, aligned: &mut [u8]) -> Result<usize, BootError> { | 223 | fn current_progress<P: FlashConfig>(&mut self, config: &mut P, aligned: &mut [u8]) -> Result<usize, BootError> { |
| 217 | let write_size = aligned.len(); | 224 | let write_size = aligned.len(); |
| 218 | let max_index = ((self.state.len() - write_size) / write_size) - 1; | 225 | let max_index = ((self.state.len() - write_size) / write_size) - 2; |
| 219 | aligned.fill(!P::STATE::ERASE_VALUE); | 226 | aligned.fill(!P::STATE::ERASE_VALUE); |
| 220 | 227 | ||
| 221 | let state_flash = config.state(); | 228 | let state_flash = config.state(); |
| 222 | for i in 0..max_index { | 229 | |
| 230 | self.state | ||
| 231 | .read_blocking(state_flash, P::STATE::WRITE_SIZE as u32, aligned)?; | ||
| 232 | if aligned.iter().any(|&b| b != P::STATE::ERASE_VALUE) { | ||
| 233 | // Progress is invalid | ||
| 234 | return Ok(max_index); | ||
| 235 | } | ||
| 236 | |||
| 237 | for index in 0..max_index { | ||
| 223 | self.state | 238 | self.state |
| 224 | .read_blocking(state_flash, (write_size + i * write_size) as u32, aligned)?; | 239 | .read_blocking(state_flash, (2 + index) as u32 * P::STATE::WRITE_SIZE as u32, aligned)?; |
| 225 | 240 | ||
| 226 | if aligned.iter().any(|&b| b == P::STATE::ERASE_VALUE) { | 241 | if aligned.iter().any(|&b| b == P::STATE::ERASE_VALUE) { |
| 227 | return Ok(i); | 242 | return Ok(index); |
| 228 | } | 243 | } |
| 229 | } | 244 | } |
| 230 | Ok(max_index) | 245 | Ok(max_index) |
| 231 | } | 246 | } |
| 232 | 247 | ||
| 233 | fn update_progress<P: FlashConfig>(&mut self, idx: usize, p: &mut P, magic: &mut [u8]) -> Result<(), BootError> { | 248 | fn update_progress<P: FlashConfig>(&mut self, index: usize, p: &mut P, magic: &mut [u8]) -> Result<(), BootError> { |
| 234 | let write_size = magic.len(); | ||
| 235 | |||
| 236 | let aligned = magic; | 249 | let aligned = magic; |
| 237 | aligned.fill(!P::STATE::ERASE_VALUE); | 250 | aligned.fill(!P::STATE::ERASE_VALUE); |
| 238 | self.state | 251 | self.state |
| 239 | .write_blocking(p.state(), (write_size + idx * write_size) as u32, aligned)?; | 252 | .write_blocking(p.state(), (2 + index) as u32 * P::STATE::WRITE_SIZE as u32, aligned)?; |
| 240 | Ok(()) | 253 | Ok(()) |
| 241 | } | 254 | } |
| 242 | 255 | ||
| @@ -360,7 +373,7 @@ fn assert_partitions(active: Partition, dfu: Partition, state: Partition, page_s | |||
| 360 | assert_eq!(active.len() % page_size, 0); | 373 | assert_eq!(active.len() % page_size, 0); |
| 361 | assert_eq!(dfu.len() % page_size, 0); | 374 | assert_eq!(dfu.len() % page_size, 0); |
| 362 | assert!(dfu.len() - active.len() >= page_size); | 375 | assert!(dfu.len() - active.len() >= page_size); |
| 363 | assert!(2 * (active.len() / page_size) <= (state.len() - write_size) / write_size); | 376 | assert!(2 + 2 * (active.len() / page_size) <= state.len() / write_size); |
| 364 | } | 377 | } |
| 365 | 378 | ||
| 366 | /// A flash wrapper implementing the Flash and embedded_storage traits. | 379 | /// A flash wrapper implementing the Flash and embedded_storage traits. |
