From 5f80b77b551599473945809a4112abfa83fbff9b Mon Sep 17 00:00:00 2001 From: "nilesh.kale" Date: Tue, 27 Jan 2026 17:36:05 +0530 Subject: [PATCH] fix: Add conflict detection for concurrent OTA operations on same partition This change adds conflict detection to prevent multiple OTA operations from being initiated on the same partition simultaneously. Closes https://github.com/espressif/esp-idf/issues/18127 --- components/app_update/esp_ota_ops.c | 24 +++++++++++++++++++++ components/app_update/include/esp_ota_ops.h | 5 ++++- components/esp_common/src/esp_err_to_name.c | 5 +++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/components/app_update/esp_ota_ops.c b/components/app_update/esp_ota_ops.c index b43194301b4..b9c0e6b864f 100644 --- a/components/app_update/esp_ota_ops.c +++ b/components/app_update/esp_ota_ops.c @@ -61,6 +61,18 @@ const static char *TAG = "esp_ota_ops"; static ota_ops_entry_t *get_ota_ops_entry(esp_ota_handle_t handle); +/* Check if there's already an ongoing OTA operation on the same staging or final partition */ +static bool esp_ota_check_partition_conflict(const esp_partition_t *partition) +{ + ota_ops_entry_t *it; + for (it = LIST_FIRST(&s_ota_ops_entries_head); it != NULL; it = LIST_NEXT(it, entries)) { + if (it->partition.staging == partition || it->partition.final == partition) { + return true; + } + } + return false; +} + /* Return true if this is an OTA app partition */ static bool is_ota_partition(const esp_partition_t *p) { @@ -172,6 +184,12 @@ esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp #endif } + // Check if there's already an ongoing OTA operation on this partition + if (esp_ota_check_partition_conflict(partition)) { + ESP_LOGE(TAG, "OTA operation already in progress on partition %s", partition->label); + return ESP_ERR_OTA_ALREADY_IN_PROGRESS; + } + new_entry = esp_ota_init_entry(partition); if (new_entry == NULL) { return ESP_ERR_NO_MEM; @@ -238,6 +256,12 @@ esp_err_t esp_ota_resume(const esp_partition_t *partition, const size_t erase_si return ESP_ERR_OTA_PARTITION_CONFLICT; } + // Check if there's already an ongoing OTA operation on this partition + if (esp_ota_check_partition_conflict(partition)) { + ESP_LOGE(TAG, "OTA operation already in progress on partition %s", partition->label); + return ESP_ERR_OTA_ALREADY_IN_PROGRESS; + } + new_entry = esp_ota_init_entry(partition); if (new_entry == NULL) { return ESP_ERR_NO_MEM; diff --git a/components/app_update/include/esp_ota_ops.h b/components/app_update/include/esp_ota_ops.h index a04ae9755cc..c08945285ed 100644 --- a/components/app_update/include/esp_ota_ops.h +++ b/components/app_update/include/esp_ota_ops.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,6 +32,7 @@ extern "C" #define ESP_ERR_OTA_SMALL_SEC_VER (ESP_ERR_OTA_BASE + 0x04) /*!< Error if the firmware has a secure version less than the running firmware. */ #define ESP_ERR_OTA_ROLLBACK_FAILED (ESP_ERR_OTA_BASE + 0x05) /*!< Error if flash does not have valid firmware in passive partition and hence rollback is not possible */ #define ESP_ERR_OTA_ROLLBACK_INVALID_STATE (ESP_ERR_OTA_BASE + 0x06) /*!< Error if current active firmware is still marked in pending validation state (ESP_OTA_IMG_PENDING_VERIFY), essentially first boot of firmware image post upgrade and hence firmware upgrade is not possible */ +#define ESP_ERR_OTA_ALREADY_IN_PROGRESS (ESP_ERR_OTA_BASE + 0x07) /*!< Error if another OTA operation is already in progress on the same partition */ /** @@ -72,6 +73,7 @@ typedef uint32_t esp_ota_handle_t; * - ESP_ERR_INVALID_ARG: partition or out_handle arguments were NULL, or partition doesn't point to an OTA app partition. * - ESP_ERR_NO_MEM: Cannot allocate memory for OTA operation. * - ESP_ERR_OTA_PARTITION_CONFLICT: Partition holds the currently running firmware, cannot update in place. + * - ESP_ERR_OTA_ALREADY_IN_PROGRESS: Another OTA operation is already in progress on the same partition. * - ESP_ERR_NOT_FOUND: Partition argument not found in partition table. * - ESP_ERR_OTA_SELECT_INFO_INVALID: The OTA data partition contains invalid data. * - ESP_ERR_INVALID_SIZE: Partition doesn't fit in configured flash size. @@ -99,6 +101,7 @@ esp_err_t esp_ota_begin(const esp_partition_t* partition, size_t image_size, esp * - ESP_ERR_INVALID_ARG: partition, out_handle were NULL or image_offset arguments is negative, or partition doesn't point to an OTA app partition. * - ESP_ERR_NO_MEM: Cannot allocate memory for OTA operation. * - ESP_ERR_OTA_PARTITION_CONFLICT: Partition holds the currently running firmware, cannot update in place. + * - ESP_ERR_OTA_ALREADY_IN_PROGRESS: Another OTA operation is already in progress on the same partition. * - ESP_ERR_NOT_FOUND: Partition argument not found in partition table. * - ESP_ERR_OTA_SELECT_INFO_INVALID: The OTA data partition contains invalid data. * - ESP_ERR_INVALID_SIZE: Partition doesn't fit in configured flash size. diff --git a/components/esp_common/src/esp_err_to_name.c b/components/esp_common/src/esp_err_to_name.c index b85f3a81aa8..8cf292b1afc 100644 --- a/components/esp_common/src/esp_err_to_name.c +++ b/components/esp_common/src/esp_err_to_name.c @@ -289,6 +289,11 @@ static const esp_err_msg_t esp_err_msg_table[] = { essentially first boot of firmware image post upgrade and hence firmware upgrade is not possible */ +# endif +# ifdef ESP_ERR_OTA_ALREADY_IN_PROGRESS + ERR_TBL_IT(ESP_ERR_OTA_ALREADY_IN_PROGRESS), /* 5383 0x1507 Error if another OTA operation is + already in progress on the same + partition */ # endif // components/efuse/include/esp_efuse.h # ifdef ESP_ERR_EFUSE