diff --git a/README.md b/README.md index 78ac862..8ba154a 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ The `ec-slimloader` crate will handle for you: * it will read from the state journal what image slot will be booted. * on subsequent reboots, it will fall back to your defined backup slot if you do not mark your current application image as `confirmed`. +If that backup fails validation and differs from the target, the loader also tries the target before giving up. It records `Attempting` before this reverse fallback, so the application identifies the correct running slot and inactive update slot. Each distinct candidate is checked at most once per boot. + However, some aspects are handled by the platform support crate (and can differ from project-to-project): * how application images are loaded. For `ec-slimloader-imxrt` images are copied to RAM in a quite chip-specific way. Typically for other platforms you might want to swap images between on-chip NOR flash and external NOR flash. The latter method is not implemented in this repository (yet). * how application images are verified. By default the images themselves are not checked at all. `ec-slimloader-imxrt` leverages the native NXP authentication routines to check image integrity. diff --git a/libs/ec-slimloader/src/lib.rs b/libs/ec-slimloader/src/lib.rs index 14cac4c..32de9c9 100644 --- a/libs/ec-slimloader/src/lib.rs +++ b/libs/ec-slimloader/src/lib.rs @@ -164,6 +164,16 @@ pub async fn start(config: B::Config info!("Attempting to boot backup in {:?}", slot); let error = board.check_and_boot(&state.backup()).await; // If this function returns, it implies that the boot has failed. warn!("Failed to boot backup in {:?} because {:?}", slot, error); + } else if slot != state.target() { + // We started in [Attempting] or [Failed], so the backup was tried first and could not boot. + // The target has not been tried this boot; an interrupted earlier attempt may have left it usable. + // Try the target as a last resort, recording [Attempting] in the journal so the app + // identifies the target as running and writes future updates to the backup. + + set_status::<_, JOURNAL_BUFFER_SIZE>(&mut board, &mut state, Status::Attempting).await; + info!("Backup unusable, retrying target {:?}", state.target()); + let error = board.check_and_boot(&state.target()).await; + warn!("Failed to boot target {:?} because {:?}", state.target(), error); } error!("No candidates booted successfully, giving up...");