mirror of
https://github.com/esphome/esphome.git
synced 2026-09-14 16:48:40 +00:00
[ota] Drop ineffective NvsReinitGuard; soften brick wording
Mat931 verified empirically that ``nvs_flash_init()`` after ``nvs_flash_deinit()`` does not revive NVS handles already held by other components: writes still fail with ESP_ERR_NVS_INVALID_HANDLE. The guard therefore only created the appearance of a recovery path. Remove it and document the actual contract: from nvs_flash_deinit() onward, components that hold open NVS handles will fail until the device is rebooted. The success path reboots immediately, so it is unaffected; the failure path now tells the user clearly to reboot and retry, rather than implying retry-without-reboot will work. Also soften the "permanently brick" wording in the pre-write log warning -- a bad partition-table OTA leaves a device that needs a serial flash to recover, not a permanently-dead one.
This commit is contained in:
@@ -38,19 +38,6 @@ static const esp_partition_t *find_app_partition_at(uint32_t address, size_t min
|
||||
return found;
|
||||
}
|
||||
|
||||
// Re-inits NVS unless disarmed. Used so failure paths past nvs_flash_deinit() leave NVS usable
|
||||
// for any component still running after a failed OTA.
|
||||
namespace {
|
||||
struct NvsReinitGuard {
|
||||
bool armed{true};
|
||||
~NvsReinitGuard() {
|
||||
if (armed) {
|
||||
nvs_flash_init();
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// Validates the staged partition table and picks the post-update boot slot. All non-destructive
|
||||
// checks live here; the destructive write is in update_partition_table().
|
||||
// Side effect: registers the live partition-table region as partition_table_part_ so the caller
|
||||
@@ -197,10 +184,11 @@ OTAResponseTypes IDFOTABackend::update_partition_table() {
|
||||
}
|
||||
|
||||
// ERROR severity so the warning shows up in default log filters; any failure past this point
|
||||
// can leave the device unable to boot.
|
||||
// can leave the device unbootable until it is recovered with a serial flash.
|
||||
ESP_LOGE(TAG, "Starting partition table update.\n"
|
||||
" DO NOT REMOVE POWER until the device reboots successfully.\n"
|
||||
" Loss of power during this operation may permanently brick the device.");
|
||||
" Loss of power during this operation may render the device unable to boot until\n"
|
||||
" it is recovered via a serial flash.");
|
||||
|
||||
// One guard over the whole critical section in case an IDF call takes longer than expected on
|
||||
// some chip variant.
|
||||
@@ -228,9 +216,12 @@ OTAResponseTypes IDFOTABackend::update_partition_table() {
|
||||
}
|
||||
|
||||
// Deinit NVS only just before the first destructive write so verify/copy failure paths return
|
||||
// with NVS still functional. The guard re-inits on early returns; success disarms it.
|
||||
// with NVS still functional. From this point on, components that hold open NVS handles
|
||||
// (e.g. preferences) will fail with ESP_ERR_NVS_INVALID_HANDLE on success or failure;
|
||||
// nvs_flash_init() can re-init the subsystem but cannot revive existing handles. On the
|
||||
// success path the device reboots immediately afterwards so this doesn't matter; on the
|
||||
// failure path the user must reboot the device before retrying.
|
||||
nvs_flash_deinit();
|
||||
NvsReinitGuard nvs_guard;
|
||||
|
||||
// Update the partition table
|
||||
err = esp_ota_begin(this->partition_table_part_, ESP_PARTITION_TABLE_MAX_LEN, &this->update_handle_);
|
||||
@@ -272,7 +263,6 @@ OTAResponseTypes IDFOTABackend::update_partition_table() {
|
||||
ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (err=0x%X)", err);
|
||||
return OTA_RESPONSE_ERROR_PARTITION_TABLE_UPDATE;
|
||||
}
|
||||
nvs_guard.armed = false;
|
||||
return OTA_RESPONSE_OK;
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -138,9 +138,10 @@ _ERROR_MESSAGES: dict[int, str] = {
|
||||
"made to the flash content. Check the logs for more information and retry."
|
||||
),
|
||||
RESPONSE_ERROR_PARTITION_TABLE_UPDATE: (
|
||||
"An error occurred while updating the partition table. The device may "
|
||||
"not be able to reboot to a working application. Check the logs and retry "
|
||||
"the update without rebooting the device."
|
||||
"An error occurred while updating the partition table. The device is now "
|
||||
"in a degraded state (NVS handles are invalid; many components will fail) "
|
||||
"and may not be able to boot. Check the logs, reboot the device, and "
|
||||
"retry the update. If the device fails to boot, recover it via a serial flash."
|
||||
),
|
||||
RESPONSE_ERROR_UNKNOWN: "Unknown error from ESP",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user