aboutsummaryrefslogtreecommitdiff
path: root/embassy-boot/boot/src/boot_loader.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-boot/boot/src/boot_loader.rs')
-rw-r--r--embassy-boot/boot/src/boot_loader.rs102
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)