eculocate

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 3192605c5915bde52998eec13718926edf033b36
parent 7148c58b3e86d1020bc59a59cf6e9267ea12761e
Author: filipton <filipton12@gmail.com>
Date:   Sun, 12 Jan 2025 15:58:00 +0100

feat: read/write ota image state (rollbacks)

Diffstat:
Msrc/lib.rs | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/structs.rs | 3++-
2 files changed, 78 insertions(+), 5 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs @@ -205,6 +205,24 @@ where } } + pub fn set_ota_state(&mut self, slot: u8, state: OtaImgState) -> Result<()> { + let offset = match slot { + 1 => self.pinfo.otadata_offset, + 2 => self.pinfo.otadata_offset + (self.pinfo.otadata_size >> 1), + _ => { + #[cfg(feature = "log")] + log::error!("Use slot1 or slot2!"); + return Err(OtaError::CannotFindCurrentBootPartition); + } + }; + + _ = self + .flash + .write(offset + 32 - 4 - 4, &(state as u32).to_le_bytes()); + + Ok(()) + } + /// Returns current OTA boot sequences /// /// NOTE: if crc doesn't match, it returns 0 for that seq @@ -234,15 +252,69 @@ where /// BUG: this wont work if user has ota partitions not starting from ota0 /// or if user skips some ota partitions: ota0, ota2, ota3... - /// - /// NOTE: This isn't reading from ota_boot_sequences, maybe in the future - /// it will read from them to eliminate possibility of wrong PADDR result. - /// (ESP-IDF has if's for PADDR-chain so it can fail somehow) pub fn get_next_ota_partition(&self) -> Option<usize> { let curr_part = mmu_hal::esp_get_current_running_partition(self.get_partitions()); curr_part.map(|next_part| (next_part + 1) % self.pinfo.ota_partitions_count) } + fn get_current_slot(&mut self) -> Result<(u8, EspOtaSelectEntry)> { + let (slot1, slot2) = self.get_ota_boot_entries(); + let current_partition = self + .get_currently_booted_partition() + .ok_or_else(|| OtaError::CannotFindCurrentBootPartition)?; + + let slot1_part = helpers::seq_to_part(slot1.seq, self.pinfo.ota_partitions_count); + let slot2_part = helpers::seq_to_part(slot2.seq, self.pinfo.ota_partitions_count); + if current_partition == slot1_part { + return Ok((1, slot1)); + } else if current_partition == slot2_part { + return Ok((2, slot2)); + } + + Err(OtaError::CannotFindCurrentBootPartition) + } + + pub fn get_ota_image_state(&mut self) -> Result<OtaImgState> { + let (slot1, slot2) = self.get_ota_boot_entries(); + let current_partition = self + .get_currently_booted_partition() + .ok_or_else(|| OtaError::CannotFindCurrentBootPartition)?; + + let slot1_part = helpers::seq_to_part(slot1.seq, self.pinfo.ota_partitions_count); + let slot2_part = helpers::seq_to_part(slot2.seq, self.pinfo.ota_partitions_count); + if current_partition == slot1_part { + return Ok(slot1.ota_state); + } else if current_partition == slot2_part { + return Ok(slot2.ota_state); + } + + Err(OtaError::CannotFindCurrentBootPartition) + } + + pub fn ota_mark_app_valid(&mut self) -> Result<()> { + let (current_slot_nmb, current_slot) = self.get_current_slot()?; + if current_slot.ota_state != OtaImgState::EspOtaImgValid { + self.set_ota_state(current_slot_nmb, OtaImgState::EspOtaImgValid)?; + + #[cfg(feature = "log")] + log::info!("Marked current slot as valid!"); + } + + Ok(()) + } + + pub fn ota_mark_app_invalid_rollback(&mut self) -> Result<()> { + let (current_slot_nmb, current_slot) = self.get_current_slot()?; + if current_slot.ota_state != OtaImgState::EspOtaImgValid { + self.set_ota_state(current_slot_nmb, OtaImgState::EspOtaImgInvalid)?; + + #[cfg(feature = "log")] + log::info!("Marked current slot as invalid!"); + } + + Ok(()) + } + fn read_partitions(flash: &mut S) -> Result<PartitionInfo> { let mut tmp_pinfo = PartitionInfo { ota_partitions: [(0, 0); 16], diff --git a/src/structs.rs b/src/structs.rs @@ -9,6 +9,7 @@ pub enum OtaError { WrongOTAPArtitionOrder, OtaVerifyError, NoNextOtaPartition, + CannotFindCurrentBootPartition, } #[derive(Clone)] @@ -32,7 +33,7 @@ pub struct PartitionInfo { } #[repr(u32)] -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum OtaImgState { EspOtaImgNew = 0x0, EspOtaImgPendingVerify = 0x1,