diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index 3ce3f2302db..5d3deca4896 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -117,8 +117,8 @@ void ESPHomeOTAComponent::dump_config() { " Partition table:\n" " %-12s %-4s %-8s %-10s %-10s", "Name", "Type", "Subtype", "Address", "Size"); - esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL); - while (it != NULL) { + esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, nullptr); + while (it != nullptr) { const esp_partition_t *partition = esp_partition_get(it); ESP_LOGCONFIG(TAG, " %-12s 0x%-2X 0x%-6X 0x%-8" PRIX32 " 0x%-8" PRIX32, partition->label, partition->type, partition->subtype, partition->address, partition->size); diff --git a/esphome/components/ota/ota_backend_esp_idf.cpp b/esphome/components/ota/ota_backend_esp_idf.cpp index 42d106bf1fb..50a0988ba21 100644 --- a/esphome/components/ota/ota_backend_esp_idf.cpp +++ b/esphome/components/ota/ota_backend_esp_idf.cpp @@ -20,8 +20,7 @@ OTAResponseTypes IDFOTABackend::begin(size_t image_size, ota::OTAType ota_type) #ifdef USE_OTA_PARTITIONS this->ota_type_ = ota_type; if (this->ota_type_ == ota::OTA_TYPE_UPDATE_PARTITION_TABLE) { - // Reject any size other than ESP_PARTITION_TABLE_MAX_LEN: under- leaves stale bytes from the - // previous table; over- can't fit the reserved region. + // Reject any size other than ESP_PARTITION_TABLE_MAX_LEN if (image_size != ESP_PARTITION_TABLE_MAX_LEN) { ESP_LOGE(TAG, "Wrong partition table size: expected %u bytes, got %zu", ESP_PARTITION_TABLE_MAX_LEN, image_size); return OTA_RESPONSE_ERROR_PARTITION_TABLE_VERIFY; diff --git a/esphome/components/ota/ota_partitions_esp_idf.cpp b/esphome/components/ota/ota_partitions_esp_idf.cpp index 2a2ed577f1e..f7fd529986d 100644 --- a/esphome/components/ota/ota_partitions_esp_idf.cpp +++ b/esphome/components/ota/ota_partitions_esp_idf.cpp @@ -11,6 +11,7 @@ #include #include +#include #include namespace esphome::ota { @@ -135,10 +136,20 @@ OTAResponseTypes IDFOTABackend::validate_new_partition_table_(uint32_t running_a // Rejecting here is non-destructive (no flash op has run yet); the user can safely retry with // a different .bin. Log enough info that they can pick the right method without guessing. ESP_LOGE(TAG, - "Running app at 0x%X (%u bytes used) does not fit any compatible slot in the new " - "partition table. Pick a migration method whose size limit is at least %u bytes and " - "retry; no flash content was modified.", - running_app_offset, running_app_size, running_app_size); + "The new partition table must contain a compatible app partition with:\n" + " size: at least %" PRIu32 " bytes (0x%" PRIX32 ")\n" + " address: one of", + (uint32_t) running_app_size, (uint32_t) running_app_size); + esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, nullptr); + while (it != nullptr) { + const esp_partition_t *partition = esp_partition_get(it); + if (partition->size >= running_app_size) { + ESP_LOGE(TAG, " 0x%" PRIX32, partition->address); + } + it = esp_partition_next(it); + } + esp_partition_iterator_release(it); + ESP_LOGE(TAG, "Upload a different partition table. No flash content was modified."); return OTA_RESPONSE_ERROR_PARTITION_TABLE_VERIFY; } if (app_partitions_found < 2) { @@ -154,11 +165,11 @@ OTAResponseTypes IDFOTABackend::validate_new_partition_table_(uint32_t running_a return OTA_RESPONSE_ERROR_PARTITION_TABLE_VERIFY; } if (otadata_overlap) { + // Unlikely, the otadata partition is before the start of the first app partition in most cases ESP_LOGE(TAG, - "New otadata partition overlaps with the running app at 0x%X (size %u). The chosen " - "partition table is not compatible with this device's current flash layout; pick a " - "different migration method.", - running_app_offset, running_app_size); + "New otadata partition overlaps with the running app at address: 0x%" PRIX32 ", running app size: %" PRIu32 + " bytes", + running_app_offset, (uint32_t) running_app_size); return OTA_RESPONSE_ERROR_PARTITION_TABLE_VERIFY; } @@ -198,8 +209,8 @@ OTAResponseTypes IDFOTABackend::update_partition_table() { // 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 render the device unable to boot until\n" - " it is recovered via a serial flash."); + " Loss of power during this operation may render the device\n" + " unable to boot until 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. @@ -214,7 +225,7 @@ OTAResponseTypes IDFOTABackend::update_partition_table() { // which leaves esp_ota_get_running_partition() returning nullptr. const esp_partition_t *running_app_part = find_app_partition_at(running_app_offset, running_app_size); if (running_app_part == nullptr) { - ESP_LOGE(TAG, "Cannot resolve running app partition at offset 0x%X", running_app_offset); + ESP_LOGE(TAG, "Cannot resolve running app partition at address 0x%" PRIX32, running_app_offset); return OTA_RESPONSE_ERROR_PARTITION_TABLE_UPDATE; } ESP_LOGD(TAG, "Copying running app from 0x%X to 0x%X (size: 0x%X)", running_app_part->address, diff --git a/esphome/espota2.py b/esphome/espota2.py index a45a6ef2343..b2a1fd2a40a 100644 --- a/esphome/espota2.py +++ b/esphome/espota2.py @@ -139,9 +139,9 @@ _ERROR_MESSAGES: dict[int, str] = { ), RESPONSE_ERROR_PARTITION_TABLE_UPDATE: ( "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." + "in a degraded state and may not be able to boot. Open the logs and retry " + "the partition table update without rebooting the device. If the device " + "fails to boot, recover it via a serial flash." ), RESPONSE_ERROR_UNKNOWN: "Unknown error from ESP", }