diff --git a/esphome/components/qr_code/qr_code.cpp b/esphome/components/qr_code/qr_code.cpp index c2db741e173..0322c8a1412 100644 --- a/esphome/components/qr_code/qr_code.cpp +++ b/esphome/components/qr_code/qr_code.cpp @@ -27,7 +27,16 @@ void QrCode::set_ecc(qrcodegen_Ecc ecc) { void QrCode::generate_qr_code() { ESP_LOGV(TAG, "Generating QR code"); + +#ifdef USE_ESP32 + // ESP32 has 8KB stack, safe to allocate ~4KB buffer on stack uint8_t tempbuffer[qrcodegen_BUFFER_LEN_MAX]; +#else + // Other platforms (ESP8266: 4KB, RP2040: 2KB, LibreTiny: ~4KB) have smaller stacks + // Allocate buffer on heap to avoid stack overflow + auto tempbuffer_owner = std::make_unique(qrcodegen_BUFFER_LEN_MAX); + uint8_t *tempbuffer = tempbuffer_owner.get(); +#endif if (!qrcodegen_encodeText(this->value_.c_str(), tempbuffer, this->qr_, this->ecc_, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true)) { diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index ef6ebea2477..f32511531a0 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 4aefd114580..d6f669f39ff 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