9#include <esp_ota_ops.h>
10#include <esp_task_wdt.h>
11#include <spi_flash_mmap.h>
15static const char *
const TAG =
"ota.idf";
17std::unique_ptr<IDFOTABackend>
make_ota_backend() {
return make_unique<IDFOTABackend>(); }
20#ifdef USE_OTA_PARTITIONS
21 this->ota_type_ = ota_type;
24 if (image_size != ESP_PARTITION_TABLE_MAX_LEN) {
25 ESP_LOGE(TAG,
"Wrong partition table size: expected %u bytes, got %zu", ESP_PARTITION_TABLE_MAX_LEN, image_size);
28 memset(this->buf_, 0xFF,
sizeof this->buf_);
29 this->buf_written_ = 0;
30 this->image_size_ = image_size;
48#ifdef USE_OTA_ROLLBACK
52 esp_ota_mark_app_valid_cancel_rollback();
55 this->partition_ = esp_ota_get_next_update_partition(
nullptr);
56 if (this->partition_ ==
nullptr) {
61 esp_err_t err = esp_ota_begin(this->partition_, image_size, &this->update_handle_);
64 ESP_LOGE(TAG,
"esp_ota_begin failed (err=0x%X)", err);
65 esp_ota_abort(this->update_handle_);
66 this->update_handle_ = 0;
67 if (err == ESP_ERR_INVALID_SIZE) {
69 }
else if (err == ESP_ERR_FLASH_OP_TIMEOUT || err == ESP_ERR_FLASH_OP_FAIL) {
71 }
else if (err == ESP_ERR_OTA_PARTITION_CONFLICT) {
77#ifdef USE_OTA_PARTITIONS
90 memcpy(this->expected_bin_md5_, expected_md5, 32);
91 this->md5_set_ =
true;
95#ifdef USE_OTA_PARTITIONS
97 if (
len > PARTITION_TABLE_BUFFER_SIZE - this->buf_written_) {
98 ESP_LOGE(TAG,
"Wrong partition table size");
101 memcpy(this->buf_ + this->buf_written_, data,
len);
102 this->buf_written_ +=
len;
103 this->md5_.
add(data,
len);
110 esp_err_t err = esp_ota_write(this->update_handle_, data,
len);
111 this->md5_.
add(data,
len);
113 ESP_LOGE(TAG,
"esp_ota_write failed (err=0x%X)", err);
114 if (err == ESP_ERR_OTA_VALIDATE_FAILED) {
116 }
else if (err == ESP_ERR_FLASH_OP_TIMEOUT || err == ESP_ERR_FLASH_OP_FAIL) {
125 if (this->md5_set_) {
127 if (!this->md5_.
equals_hex(this->expected_bin_md5_)) {
132#ifdef USE_OTA_PARTITIONS
140 esp_err_t err = esp_ota_end(this->update_handle_);
141 this->update_handle_ = 0;
143 ESP_LOGE(TAG,
"esp_ota_end failed (err=0x%X)", err);
145#ifdef USE_OTA_PARTITIONS
151 err = esp_ota_set_boot_partition(this->partition_);
156 if (err == ESP_ERR_OTA_VALIDATE_FAILED) {
157#ifdef USE_OTA_SIGNED_VERIFICATION
158 ESP_LOGE(TAG,
"OTA validation failed (err=0x%X) - possible signature verification failure", err);
164 if (err == ESP_ERR_FLASH_OP_TIMEOUT || err == ESP_ERR_FLASH_OP_FAIL) {
171#ifdef USE_OTA_PARTITIONS
172 if (this->partition_table_part_ !=
nullptr) {
173 esp_partition_deregister_external(this->partition_table_part_);
174 this->partition_table_part_ =
nullptr;
176 if (this->bootloader_part_ !=
nullptr) {
177 esp_partition_deregister_external(this->bootloader_part_);
178 this->bootloader_part_ =
nullptr;
183 esp_ota_abort(this->update_handle_);
184 this->update_handle_ = 0;
bool equals_hex(const char *expected)
Compare the hash against a provided hex-encoded hash.
void calculate() override
Compute the digest, based on the provided data.
void add(const uint8_t *data, size_t len) override
Add bytes of data for the digest.
void init() override
Initialize a new MD5 digest computation.
OTAResponseTypes setup_bootloader_staging_()
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 write(uint8_t *data, size_t len)
OTAResponseTypes update_partition_table()
bool is_app_or_bootloader_update_() const
@ OTA_TYPE_UPDATE_BOOTLOADER
@ OTA_TYPE_UPDATE_PARTITION_TABLE
@ OTA_RESPONSE_ERROR_MD5_MISMATCH
@ OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE
@ OTA_RESPONSE_ERROR_WRITING_FLASH
@ OTA_RESPONSE_ERROR_UNSUPPORTED_OTA_TYPE
@ OTA_RESPONSE_ERROR_UPDATE_END
@ OTA_RESPONSE_ERROR_SIGNATURE_INVALID
@ OTA_RESPONSE_ERROR_UNKNOWN
@ OTA_RESPONSE_ERROR_NO_UPDATE_PARTITION
@ OTA_RESPONSE_ERROR_MAGIC
@ OTA_RESPONSE_ERROR_PARTITION_TABLE_VERIFY
std::unique_ptr< ArduinoLibreTinyOTABackend > make_ota_backend()