diff options
Diffstat (limited to 'embassy-boot/boot/src/boot_loader.rs')
| -rw-r--r-- | embassy-boot/boot/src/boot_loader.rs | 102 |
1 files changed, 50 insertions, 52 deletions
diff --git a/embassy-boot/boot/src/boot_loader.rs b/embassy-boot/boot/src/boot_loader.rs index ad6735112..e2e361e3c 100644 --- a/embassy-boot/boot/src/boot_loader.rs +++ b/embassy-boot/boot/src/boot_loader.rs | |||
| @@ -79,7 +79,7 @@ impl BootLoader { | |||
| 79 | Self { active, dfu, state } | 79 | Self { active, dfu, state } |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | /// Return the boot address for the active partition. | 82 | /// Return the offset of the active partition into the active flash. |
| 83 | pub fn boot_address(&self) -> usize { | 83 | pub fn boot_address(&self) -> usize { |
| 84 | self.active.from | 84 | self.active.from |
| 85 | } | 85 | } |
| @@ -193,13 +193,13 @@ impl BootLoader { | |||
| 193 | self.revert(p, magic, page)?; | 193 | self.revert(p, magic, page)?; |
| 194 | 194 | ||
| 195 | // Overwrite magic and reset progress | 195 | // Overwrite magic and reset progress |
| 196 | let fstate = p.state(); | 196 | let state_flash = p.state(); |
| 197 | magic.fill(!P::STATE::ERASE_VALUE); | 197 | magic.fill(!P::STATE::ERASE_VALUE); |
| 198 | fstate.write(self.state.from as u32, magic)?; | 198 | self.state.write_blocking(state_flash, 0, magic)?; |
| 199 | fstate.erase(self.state.from as u32, self.state.to as u32)?; | 199 | self.state.wipe_blocking(state_flash)?; |
| 200 | 200 | ||
| 201 | magic.fill(BOOT_MAGIC); | 201 | magic.fill(BOOT_MAGIC); |
| 202 | fstate.write(self.state.from as u32, magic)?; | 202 | self.state.write_blocking(state_flash, 0, magic)?; |
| 203 | } | 203 | } |
| 204 | } | 204 | } |
| 205 | Ok(state) | 205 | Ok(state) |
| @@ -218,9 +218,10 @@ impl BootLoader { | |||
| 218 | let max_index = ((self.state.len() - write_size) / write_size) - 1; | 218 | let max_index = ((self.state.len() - write_size) / write_size) - 1; |
| 219 | aligned.fill(!P::STATE::ERASE_VALUE); | 219 | aligned.fill(!P::STATE::ERASE_VALUE); |
| 220 | 220 | ||
| 221 | let flash = config.state(); | 221 | let state_flash = config.state(); |
| 222 | for i in 0..max_index { | 222 | for i in 0..max_index { |
| 223 | flash.read((self.state.from + write_size + i * write_size) as u32, aligned)?; | 223 | self.state |
| 224 | .read_blocking(state_flash, (write_size + i * write_size) as u32, aligned)?; | ||
| 224 | 225 | ||
| 225 | if aligned.iter().any(|&b| b == P::STATE::ERASE_VALUE) { | 226 | if aligned.iter().any(|&b| b == P::STATE::ERASE_VALUE) { |
| 226 | return Ok(i); | 227 | return Ok(i); |
| @@ -230,47 +231,39 @@ impl BootLoader { | |||
| 230 | } | 231 | } |
| 231 | 232 | ||
| 232 | fn update_progress<P: FlashConfig>(&mut self, idx: usize, p: &mut P, magic: &mut [u8]) -> Result<(), BootError> { | 233 | fn update_progress<P: FlashConfig>(&mut self, idx: usize, p: &mut P, magic: &mut [u8]) -> Result<(), BootError> { |
| 233 | let flash = p.state(); | ||
| 234 | let write_size = magic.len(); | 234 | let write_size = magic.len(); |
| 235 | let w = self.state.from + write_size + idx * write_size; | ||
| 236 | 235 | ||
| 237 | let aligned = magic; | 236 | let aligned = magic; |
| 238 | aligned.fill(!P::STATE::ERASE_VALUE); | 237 | aligned.fill(!P::STATE::ERASE_VALUE); |
| 239 | flash.write(w as u32, aligned)?; | 238 | self.state |
| 239 | .write_blocking(p.state(), (write_size + idx * write_size) as u32, aligned)?; | ||
| 240 | Ok(()) | 240 | Ok(()) |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | fn active_addr(&self, n: usize, page_size: usize) -> usize { | ||
| 244 | self.active.from + n * page_size | ||
| 245 | } | ||
| 246 | |||
| 247 | fn dfu_addr(&self, n: usize, page_size: usize) -> usize { | ||
| 248 | self.dfu.from + n * page_size | ||
| 249 | } | ||
| 250 | |||
| 251 | fn copy_page_once_to_active<P: FlashConfig>( | 243 | fn copy_page_once_to_active<P: FlashConfig>( |
| 252 | &mut self, | 244 | &mut self, |
| 253 | idx: usize, | 245 | idx: usize, |
| 254 | from_page: usize, | 246 | from_offset: u32, |
| 255 | to_page: usize, | 247 | to_offset: u32, |
| 256 | p: &mut P, | 248 | p: &mut P, |
| 257 | magic: &mut [u8], | 249 | magic: &mut [u8], |
| 258 | page: &mut [u8], | 250 | page: &mut [u8], |
| 259 | ) -> Result<(), BootError> { | 251 | ) -> Result<(), BootError> { |
| 260 | let buf = page; | 252 | let buf = page; |
| 261 | if self.current_progress(p, magic)? <= idx { | 253 | if self.current_progress(p, magic)? <= idx { |
| 262 | let mut offset = from_page; | 254 | let mut offset = from_offset; |
| 263 | for chunk in buf.chunks_mut(P::DFU::BLOCK_SIZE) { | 255 | for chunk in buf.chunks_mut(P::DFU::BLOCK_SIZE) { |
| 264 | p.dfu().read(offset as u32, chunk)?; | 256 | self.dfu.read_blocking(p.dfu(), offset, chunk)?; |
| 265 | offset += chunk.len(); | 257 | offset += chunk.len() as u32; |
| 266 | } | 258 | } |
| 267 | 259 | ||
| 268 | p.active().erase(to_page as u32, (to_page + buf.len()) as u32)?; | 260 | self.active |
| 261 | .erase_blocking(p.active(), to_offset, to_offset + buf.len() as u32)?; | ||
| 269 | 262 | ||
| 270 | let mut offset = to_page; | 263 | let mut offset = to_offset; |
| 271 | for chunk in buf.chunks(P::ACTIVE::BLOCK_SIZE) { | 264 | for chunk in buf.chunks(P::ACTIVE::BLOCK_SIZE) { |
| 272 | p.active().write(offset as u32, chunk)?; | 265 | self.active.write_blocking(p.active(), offset, chunk)?; |
| 273 | offset += chunk.len(); | 266 | offset += chunk.len() as u32; |
| 274 | } | 267 | } |
| 275 | self.update_progress(idx, p, magic)?; | 268 | self.update_progress(idx, p, magic)?; |
| 276 | } | 269 | } |
| @@ -280,26 +273,27 @@ impl BootLoader { | |||
| 280 | fn copy_page_once_to_dfu<P: FlashConfig>( | 273 | fn copy_page_once_to_dfu<P: FlashConfig>( |
| 281 | &mut self, | 274 | &mut self, |
| 282 | idx: usize, | 275 | idx: usize, |
| 283 | from_page: usize, | 276 | from_offset: u32, |
| 284 | to_page: usize, | 277 | to_offset: u32, |
| 285 | p: &mut P, | 278 | p: &mut P, |
| 286 | magic: &mut [u8], | 279 | magic: &mut [u8], |
| 287 | page: &mut [u8], | 280 | page: &mut [u8], |
| 288 | ) -> Result<(), BootError> { | 281 | ) -> Result<(), BootError> { |
| 289 | let buf = page; | 282 | let buf = page; |
| 290 | if self.current_progress(p, magic)? <= idx { | 283 | if self.current_progress(p, magic)? <= idx { |
| 291 | let mut offset = from_page; | 284 | let mut offset = from_offset; |
| 292 | for chunk in buf.chunks_mut(P::ACTIVE::BLOCK_SIZE) { | 285 | for chunk in buf.chunks_mut(P::ACTIVE::BLOCK_SIZE) { |
| 293 | p.active().read(offset as u32, chunk)?; | 286 | self.active.read_blocking(p.active(), offset, chunk)?; |
| 294 | offset += chunk.len(); | 287 | offset += chunk.len() as u32; |
| 295 | } | 288 | } |
| 296 | 289 | ||
| 297 | p.dfu().erase(to_page as u32, (to_page + buf.len()) as u32)?; | 290 | self.dfu |
| 291 | .erase_blocking(p.dfu(), to_offset as u32, to_offset + buf.len() as u32)?; | ||
| 298 | 292 | ||
| 299 | let mut offset = to_page; | 293 | let mut offset = to_offset; |
| 300 | for chunk in buf.chunks(P::DFU::BLOCK_SIZE) { | 294 | for chunk in buf.chunks(P::DFU::BLOCK_SIZE) { |
| 301 | p.dfu().write(offset as u32, chunk)?; | 295 | self.dfu.write_blocking(p.dfu(), offset, chunk)?; |
| 302 | offset += chunk.len(); | 296 | offset += chunk.len() as u32; |
| 303 | } | 297 | } |
| 304 | self.update_progress(idx, p, magic)?; | 298 | self.update_progress(idx, p, magic)?; |
| 305 | } | 299 | } |
| @@ -312,17 +306,20 @@ impl BootLoader { | |||
| 312 | trace!("Page count: {}", page_count); | 306 | trace!("Page count: {}", page_count); |
| 313 | for page_num in 0..page_count { | 307 | for page_num in 0..page_count { |
| 314 | trace!("COPY PAGE {}", page_num); | 308 | trace!("COPY PAGE {}", page_num); |
| 309 | |||
| 310 | let idx = page_num * 2; | ||
| 311 | |||
| 315 | // Copy active page to the 'next' DFU page. | 312 | // Copy active page to the 'next' DFU page. |
| 316 | let active_page = self.active_addr(page_count - 1 - page_num, page_size); | 313 | let active_from_offset = ((page_count - 1 - page_num) * page_size) as u32; |
| 317 | let dfu_page = self.dfu_addr(page_count - page_num, page_size); | 314 | let dfu_to_offset = ((page_count - page_num) * page_size) as u32; |
| 318 | //trace!("Copy active {} to dfu {}", active_page, dfu_page); | 315 | //trace!("Copy active {} to dfu {}", active_from_offset, dfu_to_offset); |
| 319 | self.copy_page_once_to_dfu(page_num * 2, active_page, dfu_page, p, magic, page)?; | 316 | self.copy_page_once_to_dfu(idx, active_from_offset, dfu_to_offset, p, magic, page)?; |
| 320 | 317 | ||
| 321 | // Copy DFU page to the active page | 318 | // Copy DFU page to the active page |
| 322 | let active_page = self.active_addr(page_count - 1 - page_num, page_size); | 319 | let active_to_offset = ((page_count - 1 - page_num) * page_size) as u32; |
| 323 | let dfu_page = self.dfu_addr(page_count - 1 - page_num, page_size); | 320 | let dfu_from_offset = ((page_count - 1 - page_num) * page_size) as u32; |
| 324 | //trace!("Copy dfy {} to active {}", dfu_page, active_page); | 321 | //trace!("Copy dfy {} to active {}", dfu_from_offset, active_to_offset); |
| 325 | self.copy_page_once_to_active(page_num * 2 + 1, dfu_page, active_page, p, magic, page)?; | 322 | self.copy_page_once_to_active(idx + 1, dfu_from_offset, active_to_offset, p, magic, page)?; |
| 326 | } | 323 | } |
| 327 | 324 | ||
| 328 | Ok(()) | 325 | Ok(()) |
| @@ -332,23 +329,24 @@ impl BootLoader { | |||
| 332 | let page_size = page.len(); | 329 | let page_size = page.len(); |
| 333 | let page_count = self.active.len() / page_size; | 330 | let page_count = self.active.len() / page_size; |
| 334 | for page_num in 0..page_count { | 331 | for page_num in 0..page_count { |
| 332 | let idx = page_count * 2 + page_num * 2; | ||
| 333 | |||
| 335 | // Copy the bad active page to the DFU page | 334 | // Copy the bad active page to the DFU page |
| 336 | let active_page = self.active_addr(page_num, page_size); | 335 | let active_from_offset = (page_num * page_size) as u32; |
| 337 | let dfu_page = self.dfu_addr(page_num, page_size); | 336 | let dfu_to_offset = (page_num * page_size) as u32; |
| 338 | self.copy_page_once_to_dfu(page_count * 2 + page_num * 2, active_page, dfu_page, p, magic, page)?; | 337 | self.copy_page_once_to_dfu(idx, active_from_offset, dfu_to_offset, p, magic, page)?; |
| 339 | 338 | ||
| 340 | // Copy the DFU page back to the active page | 339 | // Copy the DFU page back to the active page |
| 341 | let active_page = self.active_addr(page_num, page_size); | 340 | let active_to_offset = (page_num * page_size) as u32; |
| 342 | let dfu_page = self.dfu_addr(page_num + 1, page_size); | 341 | let dfu_from_offset = ((page_num + 1) * page_size) as u32; |
| 343 | self.copy_page_once_to_active(page_count * 2 + page_num * 2 + 1, dfu_page, active_page, p, magic, page)?; | 342 | self.copy_page_once_to_active(idx + 1, dfu_from_offset, active_to_offset, p, magic, page)?; |
| 344 | } | 343 | } |
| 345 | 344 | ||
| 346 | Ok(()) | 345 | Ok(()) |
| 347 | } | 346 | } |
| 348 | 347 | ||
| 349 | fn read_state<P: FlashConfig>(&mut self, config: &mut P, magic: &mut [u8]) -> Result<State, BootError> { | 348 | fn read_state<P: FlashConfig>(&mut self, config: &mut P, magic: &mut [u8]) -> Result<State, BootError> { |
| 350 | let flash = config.state(); | 349 | self.state.read_blocking(config.state(), 0, magic)?; |
| 351 | flash.read(self.state.from as u32, magic)?; | ||
| 352 | 350 | ||
| 353 | if !magic.iter().any(|&b| b != SWAP_MAGIC) { | 351 | if !magic.iter().any(|&b| b != SWAP_MAGIC) { |
| 354 | Ok(State::Swap) | 352 | Ok(State::Swap) |
