diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index ef6ebea247..f32511531a 100644 --- a/esphome/components/safe_mode/safe_mode.cpp +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -9,7 +9,7 @@ #include #include -#ifdef USE_OTA_ROLLBACK +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) #include #endif @@ -26,6 +26,17 @@ void SafeModeComponent::dump_config() { this->safe_mode_boot_is_good_after_ / 1000, // because milliseconds this->safe_mode_num_attempts_, this->safe_mode_enable_time_ / 1000); // because milliseconds +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) + const char *state_str; + if (this->ota_state_ == ESP_OTA_IMG_NEW) { + state_str = "not supported"; + } else if (this->ota_state_ == ESP_OTA_IMG_PENDING_VERIFY) { + state_str = "supported"; + } else { + state_str = "support unknown"; + } + ESP_LOGCONFIG(TAG, " Bootloader rollback: %s", state_str); +#endif if (this->safe_mode_rtc_value_ > 1 && this->safe_mode_rtc_value_ != SafeModeComponent::ENTER_SAFE_MODE_MAGIC) { auto remaining_restarts = this->safe_mode_num_attempts_ - this->safe_mode_rtc_value_; @@ -36,7 +47,7 @@ void SafeModeComponent::dump_config() { } } -#ifdef USE_OTA_ROLLBACK +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) const esp_partition_t *last_invalid = esp_ota_get_last_invalid_partition(); if (last_invalid != nullptr) { ESP_LOGW(TAG, @@ -55,7 +66,7 @@ void SafeModeComponent::loop() { ESP_LOGI(TAG, "Boot seems successful; resetting boot loop counter"); this->clean_rtc(); this->boot_successful_ = true; -#ifdef USE_OTA_ROLLBACK +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) // Mark OTA partition as valid to prevent rollback esp_ota_mark_app_valid_cancel_rollback(); #endif @@ -90,6 +101,12 @@ bool SafeModeComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t en this->safe_mode_num_attempts_ = num_attempts; this->rtc_ = global_preferences->make_preference(233825507UL, false); +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) + // Check partition state to detect if bootloader supports rollback + const esp_partition_t *running = esp_ota_get_running_partition(); + esp_ota_get_state_partition(running, &this->ota_state_); +#endif + uint32_t rtc_val = this->read_rtc_(); this->safe_mode_rtc_value_ = rtc_val; diff --git a/esphome/components/safe_mode/safe_mode.h b/esphome/components/safe_mode/safe_mode.h index 4aefd11458..d6f669f39f 100644 --- a/esphome/components/safe_mode/safe_mode.h +++ b/esphome/components/safe_mode/safe_mode.h @@ -5,6 +5,10 @@ #include "esphome/core/helpers.h" #include "esphome/core/preferences.h" +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) +#include +#endif + namespace esphome::safe_mode { /// SafeModeComponent provides a safe way to recover from repeated boot failures @@ -42,6 +46,9 @@ class SafeModeComponent : public Component { // Group 1-byte members together to minimize padding bool boot_successful_{false}; ///< set to true after boot is considered successful uint8_t safe_mode_num_attempts_{0}; +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) + esp_ota_img_states_t ota_state_{ESP_OTA_IMG_UNDEFINED}; +#endif // Larger objects at the end ESPPreferenceObject rtc_; #ifdef USE_SAFE_MODE_CALLBACK