diff --git a/examples/rt685s/bootloader/src/main.rs b/examples/rt685s/bootloader/src/main.rs index e60d4f3..2acf72c 100644 --- a/examples/rt685s/bootloader/src/main.rs +++ b/examples/rt685s/bootloader/src/main.rs @@ -45,6 +45,8 @@ impl ec_slimloader_imxrt::ImxrtConfig for Config { } } +impl ec_slimloader::BootStatePolicy for Config {} + #[embassy_executor::main] async fn main(_spawner: Spawner) -> ! { ec_slimloader::start::, JOURNAL_BUFFER_SIZE>(Config).await diff --git a/libs/ec-slimloader-imxrt/src/lib.rs b/libs/ec-slimloader-imxrt/src/lib.rs index 5e035fe..a264ed2 100644 --- a/libs/ec-slimloader-imxrt/src/lib.rs +++ b/libs/ec-slimloader-imxrt/src/lib.rs @@ -17,7 +17,7 @@ mod mbi; use core::ops::Range; use defmt_or_log::{error, info, panic}; -use ec_slimloader::{Board, BootError}; +use ec_slimloader::{Board, BootError, BootStatePolicy}; use ec_slimloader_state::flash::FlashJournal; use ec_slimloader_state::state::Slot; use embassy_embedded_hal::adapter::BlockingAsync; @@ -77,7 +77,7 @@ impl CheckImage for Imxrt { } } -impl Board for Imxrt { +impl Board for Imxrt { type Config = C; async fn init(config: Self::Config) -> Self { diff --git a/libs/ec-slimloader/src/lib.rs b/libs/ec-slimloader/src/lib.rs index 28b945a..e6b738a 100644 --- a/libs/ec-slimloader/src/lib.rs +++ b/libs/ec-slimloader/src/lib.rs @@ -5,6 +5,19 @@ use ec_slimloader_state::flash::FlashJournal; use ec_slimloader_state::state::{Slot, State, Status}; use embedded_storage_async::nor_flash::NorFlash; +/// A trait for application specific configurations. +pub trait BootStatePolicy { + /// Get the application specific default boot state. + fn default_state() -> State { + State::new(Status::Initial, unwrap!(Slot::try_from(0)), unwrap!(Slot::try_from(0))) + } + + /// Allows application specific validation of the boot state. + fn is_valid_state(_state: &State) -> bool { + true + } +} + /// A board that can boot an application image. /// /// Typically a board needs to support the intrinsics for some microcontroller and @@ -12,7 +25,7 @@ use embedded_storage_async::nor_flash::NorFlash; #[allow(async_fn_in_trait)] pub trait Board { /// Type used to instantiate a [Board] implementation. - type Config; + type Config: BootStatePolicy; /// Initialize the [Board], can only be called once. async fn init(config: Self::Config) -> Self; @@ -82,15 +95,24 @@ pub async fn start(config: B::Config let mut state: State = match state { Some(state) => { info!("Latest state fetched from journal: {:?}", state); - *state + if B::Config::is_valid_state(state) { + *state + } else { + let default_state = B::Config::default_state(); + warn!( + "State {:?} is invalid per application policy, using default state {:?}", + state, default_state + ); + default_state + } } None => { - let slot = unwrap!(Slot::try_from(0)); + let default_state = B::Config::default_state(); warn!( "Initial bootup and no state was loaded into the journal, attempting {:?}", - slot + default_state ); - State::new(Status::Initial, slot, slot) + default_state } };