#define MODULE "ota" #define DEBUG 1 #include "common.h" #include "fw.h" #include #define BUFFER_SIZE 4096 static int esp_err_to_fwupdate(int err) { switch (err) { case ESP_OK: return Z_OK; case ESP_ERR_NO_MEM: return Z_MEM_ERROR; case ESP_ERR_NOT_FOUND: return FWUPDATE_ERR_ESP_NO_PARTITION; case ESP_ERR_INVALID_ARG: case ESP_ERR_OTA_PARTITION_CONFLICT: case ESP_ERR_OTA_SELECT_INFO_INVALID: case ESP_ERR_OTA_ROLLBACK_INVALID_STATE: return FWUPDATE_ERR_ESP_BAD_OTA; case ESP_ERR_FLASH_OP_TIMEOUT: case ESP_ERR_FLASH_OP_FAIL: return FWUPDATE_ERR_ESP_FLASH_FAILED; case ESP_ERR_OTA_VALIDATE_FAILED: return FWUPDATE_ERR_ESP_BAD_DATA; default: return FWUPDATE_ERR_UNKNOWN; } } int esp_update(read_func_t read_func, token_t token, size_t size) { const esp_partition_t *partition; int err = ESP_FAIL; esp_ota_handle_t handle; bool ota_started = false; int len; char *buf = xmalloc_dma(BUFFER_SIZE); partition = esp_ota_get_next_update_partition(NULL); if (!partition) { err = ESP_ERR_NOT_FOUND; goto fail; } MSG("starting ESP OTA update, total %zu bytes\n", size); err = esp_ota_begin(partition, size, &handle); if (err) goto fail; ota_started = true; size_t left = size; while (left) { size_t chunk = left; if (chunk > BUFFER_SIZE) chunk = BUFFER_SIZE; len = read_func(token, buf, chunk); if (len <= 0) break; left -= len; MSG("writing %d bytes, %zu left\r", len, left); err = esp_ota_write(handle, buf, len); CMSG("\n"); if (err) goto fail; } if (left) { MSG("short input data, aborting update\n"); err = ESP_ERR_OTA_VALIDATE_FAILED; goto fail; } MSG("finalizing flash update\n"); err = esp_ota_end(handle); if (err) goto fail; free(buf); buf = NULL; MSG("setting boot partition\n"); err = esp_ota_set_boot_partition(partition); fail: err = esp_err_to_fwupdate(err); if (err) { MSG("failure: error %d\n", err); if (ota_started) esp_ota_abort(handle); } if (buf) free(buf); return err; }