From fd902a646ac2b0cfa5650edc1b2d16740135f009 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Oct 2026 01:09:13 -1000 Subject: [PATCH] [ota] Accept an unknown image size in the RP2040 backend so web_server OTA works (#21178) --- esphome/components/ota/ota_backend.h | 5 +++-- .../components/ota/ota_backend_arduino_rp2.cpp | 15 ++++++++++++--- tests/components/web_server/test.rp2040-ard.yaml | 3 +++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/esphome/components/ota/ota_backend.h b/esphome/components/ota/ota_backend.h index 840d1ac11c7..3e8b5954906 100644 --- a/esphome/components/ota/ota_backend.h +++ b/esphome/components/ota/ota_backend.h @@ -122,8 +122,9 @@ class UpdateLock { // The OTA backend method surface. Exactly one backend exists per build, // selected in ota_backend_factory.h where this concept is asserted on // make_ota_backend()'s return type. Semantics beyond the signatures: -// - begin: prepare for an image of the given size; ota_type defaults to an -// app update, so both call forms must be accepted. +// - begin: prepare for an image of the given size; 0 means the size is unknown +// (web_server upload) and the backend allows the largest image it can take. +// ota_type defaults to an app update, so both call forms must be accepted. // - set_update_md5: expected digest of the incoming image, hex string. // - write: consume the next chunk; end: finalize and mark bootable. // - abort: safe to call in any state, including after end(). diff --git a/esphome/components/ota/ota_backend_arduino_rp2.cpp b/esphome/components/ota/ota_backend_arduino_rp2.cpp index d4d94be2363..6c56819c281 100644 --- a/esphome/components/ota/ota_backend_arduino_rp2.cpp +++ b/esphome/components/ota/ota_backend_arduino_rp2.cpp @@ -9,6 +9,12 @@ #include +// LittleFS region bounds, provided by the arduino-pico linker script. +// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) +extern "C" uint8_t _FS_start; +// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) +extern "C" uint8_t _FS_end; + namespace esphome::ota { ESPHOME_LOG_TAG(TAG, "ota"); @@ -21,8 +27,11 @@ OTAResponseTypes ArduinoRP2OTABackend::begin(size_t image_size, OTAType ota_type if (ota_type != OTA_TYPE_UPDATE_APP) { return OTA_RESPONSE_ERROR_UNSUPPORTED_OTA_TYPE; } - // OTA size of 0 is not currently handled, but - // web_server is not supported for RP2040, so this is not an issue. + // 0 means the size is unknown (web_server upload). The updater only checks the size + // against the LittleFS region it stages the image in, so ask for all of it. + if (image_size == 0) { + image_size = reinterpret_cast(&_FS_end) - reinterpret_cast(&_FS_start); + } bool ret = Update.begin(image_size, U_FLASH); if (ret) { rp2::preferences_prevent_write(true); @@ -36,7 +45,7 @@ OTAResponseTypes ArduinoRP2OTABackend::begin(size_t image_size, OTAType ota_type return OTA_RESPONSE_ERROR_WRONG_NEW_FLASH_CONFIG; if (error == UPDATE_ERROR_FLASH_CONFIG) return OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG; - if (error == UPDATE_ERROR_SPACE) + if (error == UPDATE_ERROR_SPACE || error == UPDATE_ERROR_SIZE) return OTA_RESPONSE_ERROR_RP2040_NOT_ENOUGH_SPACE; ESP_LOGE(TAG, "Begin error: %d", error); diff --git a/tests/components/web_server/test.rp2040-ard.yaml b/tests/components/web_server/test.rp2040-ard.yaml index 6a01180892a..56bd155717f 100644 --- a/tests/components/web_server/test.rp2040-ard.yaml +++ b/tests/components/web_server/test.rp2040-ard.yaml @@ -6,3 +6,6 @@ web_server: username: admin password: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA type: basic + +ota: + - platform: web_server