ESPHome 2026.10.0-dev
Loading...
Searching...
No Matches
ota_backend_esp_idf.h
Go to the documentation of this file.
1#pragma once
2#ifdef USE_ESP32
3#include "ota_backend.h"
4
7
8#include <esp_idf_version.h>
9#include <esp_ota_ops.h>
10
11// esp_ota_resume() (IDF 5.4.2+, backported to 5.3.3) provides a no-erase OTA
12// handle, letting write() block-erase 64 KiB ahead of the write cursor
13// (~4x faster than the per-sector lazy erase of OTA_WITH_SEQUENTIAL_WRITES,
14// used as fallback on older IDF).
15#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2) || \
16 (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 3) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 0))
17#define USE_OTA_BLOCK_ERASE_AHEAD
18#endif
19
20namespace esphome::ota {
21
22#ifdef USE_OTA_PARTITIONS
23// Staging buffer holds the entire partition table for verification before any flash op.
24static constexpr size_t PARTITION_TABLE_BUFFER_SIZE = ESP_PARTITION_TABLE_MAX_LEN; // 0xC00
25
26void get_running_app_position(uint32_t &offset, size_t &size);
27#endif
28
29class IDFOTABackend final {
30 public:
31 OTAResponseTypes begin(size_t image_size, ota::OTAType ota_type = ota::OTA_TYPE_UPDATE_APP);
32 void set_update_md5(const char *md5);
33 OTAResponseTypes write(uint8_t *data, size_t len);
35 void abort();
36 bool supports_compression() { return false; }
37
38 protected:
39#ifdef USE_OTA_PARTITIONS
40 // copy_dest_part non-null means the running app must be copied INTO this slot of the current
41 // table before the new partition table is committed. The destination is in the current table
42 // because that's where esp_partition_copy can write; once the new table replaces it, the same
43 // flash region becomes target_app_index in the new table.
46 const esp_partition_t *copy_dest_part{nullptr};
47 };
48
49 OTAResponseTypes validate_new_partition_table_(uint32_t running_app_offset, size_t running_app_size,
50 PartitionTablePlan &plan);
53 // Defined in ota_bootloader_esp_idf.cpp:
57 OTAResponseTypes finalize_bootloader_update_(esp_err_t ota_end_err);
58
59 // The OTA types that flow through esp_ota_begin/write/end. Partition-table updates take a
60 // separate code path that buffers the table in RAM and never touches the OTA handle.
62 return this->ota_type_ == ota::OTA_TYPE_UPDATE_APP || this->ota_type_ == ota::OTA_TYPE_UPDATE_BOOTLOADER;
63 }
64#endif
65
66 private:
67#ifdef USE_OTA_BLOCK_ERASE_AHEAD
68 OTAResponseTypes erase_ahead_(size_t len);
69#endif
70#ifdef USE_OTA_SIGNED_VERIFICATION_MULTI_KEY
71 // Accept an image signed by any key the running app trusts (up to 3 blocks),
72 // so rotation and backup keys work. Fails closed. Covers app and bootloader.
73 bool verify_signed_image_(const esp_partition_t *incoming);
74#endif
75 // Keep md5_ first since its digest_ is alignas(32) on DMA-SHA variants; md5_set_ stays last so buf_ packs tightly.
76 md5::MD5Digest md5_{};
77 esp_ota_handle_t update_handle_{0};
78 const esp_partition_t *partition_{nullptr};
79 size_t written_{0}; // Bytes handed to esp_ota_write()
80#ifdef USE_OTA_BLOCK_ERASE_AHEAD
81 size_t erased_end_{0}; // Erased up to this partition offset; must stay >= written_
82#endif
83 char expected_bin_md5_[32];
84 bool md5_set_{false};
85#ifdef USE_OTA_PARTITIONS
86 // Buffer first so it packs tightly after the preceding `bool md5_set_` with no alignment
87 // padding. Only resident during an active OTA: the backend is constructed per connection and
88 // destroyed on cleanup_connection_().
89 uint8_t buf_[PARTITION_TABLE_BUFFER_SIZE];
90 size_t buf_written_{0};
91 size_t image_size_{0};
92 const esp_partition_t *partition_table_part_{nullptr};
93 const esp_partition_t *bootloader_part_{nullptr};
95#endif
96};
97
98std::unique_ptr<IDFOTABackend> make_ota_backend();
99
100} // namespace esphome::ota
101#endif // USE_ESP32
void set_update_md5(const char *md5)
OTAResponseTypes finalize_bootloader_update_(esp_err_t ota_end_err)
OTAResponseTypes begin(size_t image_size, ota::OTAType ota_type=ota::OTA_TYPE_UPDATE_APP)
OTAResponseTypes prepare_bootloader_update_(size_t image_size)
OTAResponseTypes register_and_validate_bootloader_part_()
OTAResponseTypes write(uint8_t *data, size_t len)
OTAResponseTypes validate_new_partition_table_(uint32_t running_app_offset, size_t running_app_size, PartitionTablePlan &plan)
OTAResponseTypes register_and_validate_partition_table_part_()
@ OTA_TYPE_UPDATE_BOOTLOADER
Definition ota_backend.h:94
void get_running_app_position(uint32_t &offset, size_t &size)
std::unique_ptr< ArduinoLibreTinyOTABackend > make_ota_backend()
const void size_t len
Definition hal.h:64
uint16_t size
Definition helpers.cpp:25
static void uint32_t