esp_https_ota.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. /*
  2. * SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <esp_https_ota.h>
  10. #include <esp_log.h>
  11. #include <esp_ota_ops.h>
  12. #include <errno.h>
  13. #include <sys/param.h>
  14. #include <inttypes.h>
  15. ESP_EVENT_DEFINE_BASE(ESP_HTTPS_OTA_EVENT);
  16. #define IMAGE_HEADER_SIZE (1024)
  17. /* This is kept sufficiently large enough to cover image format headers
  18. * and also this defines default minimum OTA buffer chunk size */
  19. #define DEFAULT_OTA_BUF_SIZE (IMAGE_HEADER_SIZE)
  20. _Static_assert(DEFAULT_OTA_BUF_SIZE > (sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t) + 1), "OTA data buffer too small");
  21. #define DEFAULT_REQUEST_SIZE (64 * 1024)
  22. static const int DEFAULT_MAX_AUTH_RETRIES = 10;
  23. static const char *TAG = "esp_https_ota";
  24. typedef enum {
  25. ESP_HTTPS_OTA_INIT,
  26. ESP_HTTPS_OTA_BEGIN,
  27. ESP_HTTPS_OTA_IN_PROGRESS,
  28. ESP_HTTPS_OTA_SUCCESS,
  29. } esp_https_ota_state;
  30. struct esp_https_ota_handle {
  31. esp_ota_handle_t update_handle;
  32. const esp_partition_t *update_partition;
  33. esp_http_client_handle_t http_client;
  34. char *ota_upgrade_buf;
  35. size_t ota_upgrade_buf_size;
  36. int binary_file_len;
  37. int image_length;
  38. int max_http_request_size;
  39. esp_https_ota_state state;
  40. bool bulk_flash_erase;
  41. bool partial_http_download;
  42. int max_authorization_retries;
  43. #if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB
  44. decrypt_cb_t decrypt_cb;
  45. void *decrypt_user_ctx;
  46. uint16_t enc_img_header_size;
  47. #endif
  48. };
  49. typedef struct esp_https_ota_handle esp_https_ota_t;
  50. static bool redirection_required(int status_code)
  51. {
  52. switch (status_code) {
  53. case HttpStatus_MovedPermanently:
  54. case HttpStatus_Found:
  55. case HttpStatus_SeeOther:
  56. case HttpStatus_TemporaryRedirect:
  57. case HttpStatus_PermanentRedirect:
  58. return true;
  59. default:
  60. return false;
  61. }
  62. return false;
  63. }
  64. static bool process_again(int status_code)
  65. {
  66. switch (status_code) {
  67. case HttpStatus_MovedPermanently:
  68. case HttpStatus_Found:
  69. case HttpStatus_SeeOther:
  70. case HttpStatus_TemporaryRedirect:
  71. case HttpStatus_PermanentRedirect:
  72. case HttpStatus_Unauthorized:
  73. return true;
  74. default:
  75. return false;
  76. }
  77. return false;
  78. }
  79. static esp_err_t _http_handle_response_code(esp_https_ota_t *https_ota_handle, int status_code)
  80. {
  81. esp_err_t err;
  82. if (redirection_required(status_code)) {
  83. err = esp_http_client_set_redirection(https_ota_handle->http_client);
  84. if (err != ESP_OK) {
  85. ESP_LOGE(TAG, "URL redirection Failed");
  86. return err;
  87. }
  88. } else if (status_code == HttpStatus_Unauthorized) {
  89. if (https_ota_handle->max_authorization_retries == 0) {
  90. ESP_LOGE(TAG, "Reached max_authorization_retries (%d)", status_code);
  91. return ESP_FAIL;
  92. }
  93. https_ota_handle->max_authorization_retries--;
  94. esp_http_client_add_auth(https_ota_handle->http_client);
  95. } else if(status_code == HttpStatus_NotFound || status_code == HttpStatus_Forbidden) {
  96. ESP_LOGE(TAG, "File not found(%d)", status_code);
  97. return ESP_FAIL;
  98. } else if (status_code >= HttpStatus_BadRequest && status_code < HttpStatus_InternalError) {
  99. ESP_LOGE(TAG, "Client error (%d)", status_code);
  100. return ESP_FAIL;
  101. } else if (status_code >= HttpStatus_InternalError) {
  102. ESP_LOGE(TAG, "Server error (%d)", status_code);
  103. return ESP_FAIL;
  104. }
  105. char upgrade_data_buf[256];
  106. // process_again() returns true only in case of redirection.
  107. if (process_again(status_code)) {
  108. while (1) {
  109. /*
  110. * In case of redirection, esp_http_client_read() is called
  111. * to clear the response buffer of http_client.
  112. */
  113. int data_read = esp_http_client_read(https_ota_handle->http_client, upgrade_data_buf, sizeof(upgrade_data_buf));
  114. if (data_read <= 0) {
  115. return ESP_OK;
  116. }
  117. }
  118. }
  119. return ESP_OK;
  120. }
  121. static esp_err_t _http_connect(esp_https_ota_t *https_ota_handle)
  122. {
  123. esp_err_t err = ESP_FAIL;
  124. int status_code, header_ret;
  125. do {
  126. char *post_data = NULL;
  127. /* Send POST request if body is set.
  128. * Note: Sending POST request is not supported if partial_http_download
  129. * is enabled
  130. */
  131. int post_len = esp_http_client_get_post_field(https_ota_handle->http_client, &post_data);
  132. err = esp_http_client_open(https_ota_handle->http_client, post_len);
  133. if (err != ESP_OK) {
  134. ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
  135. return err;
  136. }
  137. if (post_len) {
  138. int write_len = 0;
  139. while (post_len > 0) {
  140. write_len = esp_http_client_write(https_ota_handle->http_client, post_data, post_len);
  141. if (write_len < 0) {
  142. ESP_LOGE(TAG, "Write failed");
  143. return ESP_FAIL;
  144. }
  145. post_len -= write_len;
  146. post_data += write_len;
  147. }
  148. }
  149. header_ret = esp_http_client_fetch_headers(https_ota_handle->http_client);
  150. if (header_ret < 0) {
  151. return header_ret;
  152. }
  153. status_code = esp_http_client_get_status_code(https_ota_handle->http_client);
  154. err = _http_handle_response_code(https_ota_handle, status_code);
  155. if (err != ESP_OK) {
  156. return err;
  157. }
  158. } while (process_again(status_code));
  159. return err;
  160. }
  161. static void _http_cleanup(esp_http_client_handle_t client)
  162. {
  163. esp_http_client_close(client);
  164. esp_http_client_cleanup(client);
  165. }
  166. // Table to lookup ota event name
  167. static const char* ota_event_name_table[] = {
  168. "ESP_HTTPS_OTA_START",
  169. "ESP_HTTPS_OTA_CONNECTED",
  170. "ESP_HTTPS_OTA_GET_IMG_DESC",
  171. "ESP_HTTPS_OTA_VERIFY_CHIP_ID",
  172. "ESP_HTTPS_OTA_DECRYPT_CB",
  173. "ESP_HTTPS_OTA_WRITE_FLASH",
  174. "ESP_HTTPS_OTA_UPDATE_BOOT_PARTITION",
  175. "ESP_HTTPS_OTA_FINISH",
  176. "ESP_HTTPS_OTA_ABORT",
  177. };
  178. static void esp_https_ota_dispatch_event(int32_t event_id, const void* event_data, size_t event_data_size)
  179. {
  180. if (esp_event_post(ESP_HTTPS_OTA_EVENT, event_id, event_data, event_data_size, portMAX_DELAY) != ESP_OK) {
  181. ESP_LOGE(TAG, "Failed to post https_ota event: %s", ota_event_name_table[event_id]);
  182. }
  183. }
  184. #if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB
  185. static esp_err_t esp_https_ota_decrypt_cb(esp_https_ota_t *handle, decrypt_cb_arg_t *args)
  186. {
  187. esp_https_ota_dispatch_event(ESP_HTTPS_OTA_DECRYPT_CB, NULL, 0);
  188. esp_err_t ret = handle->decrypt_cb(args, handle->decrypt_user_ctx);
  189. if (ret != ESP_OK) {
  190. ESP_LOGE(TAG, "Decrypt callback failed %d", ret);
  191. return ret;
  192. }
  193. if (args->data_out_len > 0) {
  194. return ESP_OK;
  195. } else {
  196. return ESP_HTTPS_OTA_IN_PROGRESS;
  197. }
  198. }
  199. static void esp_https_ota_decrypt_cb_free_buf(void *buffer)
  200. {
  201. free(buffer);
  202. }
  203. #endif // CONFIG_ESP_HTTPS_OTA_DECRYPT_CB
  204. static esp_err_t _ota_write(esp_https_ota_t *https_ota_handle, const void *buffer, size_t buf_len)
  205. {
  206. if (buffer == NULL || https_ota_handle == NULL) {
  207. return ESP_FAIL;
  208. }
  209. esp_err_t err = esp_ota_write(https_ota_handle->update_handle, buffer, buf_len);
  210. if (err != ESP_OK) {
  211. ESP_LOGE(TAG, "Error: esp_ota_write failed! err=0x%x", err);
  212. } else {
  213. https_ota_handle->binary_file_len += buf_len;
  214. ESP_LOGD(TAG, "Written image length %d", https_ota_handle->binary_file_len);
  215. err = ESP_ERR_HTTPS_OTA_IN_PROGRESS;
  216. }
  217. esp_https_ota_dispatch_event(ESP_HTTPS_OTA_WRITE_FLASH, (void *)(&https_ota_handle->binary_file_len), sizeof(int));
  218. #if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB
  219. esp_https_ota_decrypt_cb_free_buf((void *) buffer);
  220. #endif
  221. return err;
  222. }
  223. static bool is_server_verification_enabled(const esp_https_ota_config_t *ota_config) {
  224. return (ota_config->http_config->cert_pem
  225. || ota_config->http_config->use_global_ca_store
  226. || ota_config->http_config->crt_bundle_attach != NULL);
  227. }
  228. esp_err_t esp_https_ota_begin(const esp_https_ota_config_t *ota_config, esp_https_ota_handle_t *handle)
  229. {
  230. esp_https_ota_dispatch_event(ESP_HTTPS_OTA_START, NULL, 0);
  231. esp_err_t err;
  232. if (handle == NULL || ota_config == NULL || ota_config->http_config == NULL) {
  233. ESP_LOGE(TAG, "esp_https_ota_begin: Invalid argument");
  234. if (handle) {
  235. *handle = NULL;
  236. }
  237. return ESP_ERR_INVALID_ARG;
  238. }
  239. if (!is_server_verification_enabled(ota_config)) {
  240. #if CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP
  241. ESP_LOGW(TAG, "Continuing with insecure option because CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP is set.");
  242. #else
  243. ESP_LOGE(TAG, "No option for server verification is enabled in esp_http_client config.");
  244. *handle = NULL;
  245. return ESP_ERR_INVALID_ARG;
  246. #endif
  247. }
  248. esp_https_ota_t *https_ota_handle = calloc(1, sizeof(esp_https_ota_t));
  249. if (!https_ota_handle) {
  250. ESP_LOGE(TAG, "Couldn't allocate memory to upgrade data buffer");
  251. *handle = NULL;
  252. return ESP_ERR_NO_MEM;
  253. }
  254. https_ota_handle->partial_http_download = ota_config->partial_http_download;
  255. https_ota_handle->max_http_request_size = (ota_config->max_http_request_size == 0) ? DEFAULT_REQUEST_SIZE : ota_config->max_http_request_size;
  256. https_ota_handle->max_authorization_retries = ota_config->http_config->max_authorization_retries;
  257. if (https_ota_handle->max_authorization_retries == 0) {
  258. https_ota_handle->max_authorization_retries = DEFAULT_MAX_AUTH_RETRIES;
  259. } else if (https_ota_handle->max_authorization_retries == -1) {
  260. https_ota_handle->max_authorization_retries = 0;
  261. }
  262. /* Initiate HTTP Connection */
  263. https_ota_handle->http_client = esp_http_client_init(ota_config->http_config);
  264. if (https_ota_handle->http_client == NULL) {
  265. ESP_LOGE(TAG, "Failed to initialise HTTP connection");
  266. err = ESP_FAIL;
  267. goto failure;
  268. }
  269. if (ota_config->http_client_init_cb) {
  270. err = ota_config->http_client_init_cb(https_ota_handle->http_client);
  271. if (err != ESP_OK) {
  272. ESP_LOGE(TAG, "http_client_init_cb returned 0x%x", err);
  273. goto http_cleanup;
  274. }
  275. }
  276. if (https_ota_handle->partial_http_download) {
  277. esp_http_client_set_method(https_ota_handle->http_client, HTTP_METHOD_HEAD);
  278. err = esp_http_client_perform(https_ota_handle->http_client);
  279. if (err == ESP_OK) {
  280. int status = esp_http_client_get_status_code(https_ota_handle->http_client);
  281. if (status != HttpStatus_Ok) {
  282. ESP_LOGE(TAG, "Received incorrect http status %d", status);
  283. err = ESP_FAIL;
  284. goto http_cleanup;
  285. }
  286. } else {
  287. ESP_LOGE(TAG, "ESP HTTP client perform failed: %d", err);
  288. goto http_cleanup;
  289. }
  290. https_ota_handle->image_length = esp_http_client_get_content_length(https_ota_handle->http_client);
  291. #if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB
  292. /* In case of pre ecnrypted OTA, actual image size of OTA binary includes header size
  293. which stored in variable enc_img_header_size*/
  294. https_ota_handle->image_length -= ota_config->enc_img_header_size;
  295. #endif
  296. esp_http_client_close(https_ota_handle->http_client);
  297. if (https_ota_handle->image_length > https_ota_handle->max_http_request_size) {
  298. char *header_val = NULL;
  299. asprintf(&header_val, "bytes=0-%d", https_ota_handle->max_http_request_size - 1);
  300. if (header_val == NULL) {
  301. ESP_LOGE(TAG, "Failed to allocate memory for HTTP header");
  302. err = ESP_ERR_NO_MEM;
  303. goto http_cleanup;
  304. }
  305. esp_http_client_set_header(https_ota_handle->http_client, "Range", header_val);
  306. free(header_val);
  307. }
  308. esp_http_client_set_method(https_ota_handle->http_client, HTTP_METHOD_GET);
  309. }
  310. err = _http_connect(https_ota_handle);
  311. if (err != ESP_OK) {
  312. ESP_LOGE(TAG, "Failed to establish HTTP connection");
  313. goto http_cleanup;
  314. } else {
  315. esp_https_ota_dispatch_event(ESP_HTTPS_OTA_CONNECTED, NULL, 0);
  316. }
  317. if (!https_ota_handle->partial_http_download) {
  318. https_ota_handle->image_length = esp_http_client_get_content_length(https_ota_handle->http_client);
  319. #if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB
  320. /* In case of pre ecnrypted OTA, actual image size of OTA binary includes header size
  321. which stored in variable enc_img_header_size*/
  322. https_ota_handle->image_length -= ota_config->enc_img_header_size;
  323. #endif
  324. }
  325. https_ota_handle->update_partition = NULL;
  326. ESP_LOGI(TAG, "Starting OTA...");
  327. https_ota_handle->update_partition = esp_ota_get_next_update_partition(NULL);
  328. if (https_ota_handle->update_partition == NULL) {
  329. ESP_LOGE(TAG, "Passive OTA partition not found");
  330. err = ESP_FAIL;
  331. goto http_cleanup;
  332. }
  333. ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%" PRIx32,
  334. https_ota_handle->update_partition->subtype, https_ota_handle->update_partition->address);
  335. const int alloc_size = MAX(ota_config->http_config->buffer_size, DEFAULT_OTA_BUF_SIZE);
  336. https_ota_handle->ota_upgrade_buf = (char *)malloc(alloc_size);
  337. if (!https_ota_handle->ota_upgrade_buf) {
  338. ESP_LOGE(TAG, "Couldn't allocate memory to upgrade data buffer");
  339. err = ESP_ERR_NO_MEM;
  340. goto http_cleanup;
  341. }
  342. #if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB
  343. if (ota_config->decrypt_cb == NULL) {
  344. err = ESP_ERR_INVALID_ARG;
  345. goto http_cleanup;
  346. }
  347. https_ota_handle->decrypt_cb = ota_config->decrypt_cb;
  348. https_ota_handle->decrypt_user_ctx = ota_config->decrypt_user_ctx;
  349. https_ota_handle->enc_img_header_size = ota_config->enc_img_header_size;
  350. #endif
  351. https_ota_handle->ota_upgrade_buf_size = alloc_size;
  352. https_ota_handle->bulk_flash_erase = ota_config->bulk_flash_erase;
  353. https_ota_handle->binary_file_len = 0;
  354. *handle = (esp_https_ota_handle_t)https_ota_handle;
  355. https_ota_handle->state = ESP_HTTPS_OTA_BEGIN;
  356. return ESP_OK;
  357. http_cleanup:
  358. _http_cleanup(https_ota_handle->http_client);
  359. failure:
  360. free(https_ota_handle);
  361. *handle = NULL;
  362. return err;
  363. }
  364. static esp_err_t read_header(esp_https_ota_t *handle)
  365. {
  366. /*
  367. * `data_read_size` holds number of bytes needed to read complete header.
  368. * `bytes_read` holds number of bytes read.
  369. */
  370. int data_read_size = IMAGE_HEADER_SIZE;
  371. int data_read = 0, bytes_read = 0;
  372. /*
  373. * while loop is added to download complete image headers, even if the headers
  374. * are not sent in a single packet.
  375. */
  376. while (data_read_size > 0 && !esp_http_client_is_complete_data_received(handle->http_client)) {
  377. data_read = esp_http_client_read(handle->http_client,
  378. (handle->ota_upgrade_buf + bytes_read),
  379. data_read_size);
  380. if (data_read < 0) {
  381. if (data_read == -ESP_ERR_HTTP_EAGAIN) {
  382. ESP_LOGD(TAG, "ESP_ERR_HTTP_EAGAIN invoked: Call timed out before data was ready");
  383. continue;
  384. }
  385. ESP_LOGE(TAG, "Connection closed, errno = %d", errno);
  386. break;
  387. }
  388. data_read_size -= data_read;
  389. bytes_read += data_read;
  390. }
  391. if (data_read_size > 0) {
  392. ESP_LOGE(TAG, "Complete headers were not received");
  393. return ESP_FAIL;
  394. }
  395. handle->binary_file_len = bytes_read;
  396. return ESP_OK;
  397. }
  398. esp_err_t esp_https_ota_get_img_desc(esp_https_ota_handle_t https_ota_handle, esp_app_desc_t *new_app_info)
  399. {
  400. esp_https_ota_dispatch_event(ESP_HTTPS_OTA_GET_IMG_DESC, NULL, 0);
  401. #if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB
  402. // This API is not supported in case firmware image is encrypted in nature.
  403. // It is recommended to retrieve image description through decryption callback in application layer.
  404. return ESP_ERR_NOT_SUPPORTED;
  405. #endif
  406. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  407. if (handle == NULL || new_app_info == NULL) {
  408. ESP_LOGE(TAG, "esp_https_ota_read_img_desc: Invalid argument");
  409. return ESP_ERR_INVALID_ARG;
  410. }
  411. if (handle->state < ESP_HTTPS_OTA_BEGIN) {
  412. ESP_LOGE(TAG, "esp_https_ota_read_img_desc: Invalid state");
  413. return ESP_ERR_INVALID_STATE;
  414. }
  415. if (read_header(handle) != ESP_OK) {
  416. return ESP_FAIL;
  417. }
  418. const int app_desc_offset = sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t);
  419. esp_app_desc_t *app_info = (esp_app_desc_t *) &handle->ota_upgrade_buf[app_desc_offset];
  420. if (app_info->magic_word != ESP_APP_DESC_MAGIC_WORD) {
  421. ESP_LOGE(TAG, "Incorrect app descriptor magic");
  422. return ESP_FAIL;
  423. }
  424. memcpy(new_app_info, app_info, sizeof(esp_app_desc_t));
  425. return ESP_OK;
  426. }
  427. static esp_err_t esp_ota_verify_chip_id(const void *arg)
  428. {
  429. esp_image_header_t *data = (esp_image_header_t *)(arg);
  430. esp_https_ota_dispatch_event(ESP_HTTPS_OTA_VERIFY_CHIP_ID, (void *)(&data->chip_id), sizeof(esp_chip_id_t));
  431. if (data->chip_id != CONFIG_IDF_FIRMWARE_CHIP_ID) {
  432. ESP_LOGE(TAG, "Mismatch chip id, expected %d, found %d", CONFIG_IDF_FIRMWARE_CHIP_ID, data->chip_id);
  433. return ESP_ERR_INVALID_VERSION;
  434. }
  435. return ESP_OK;
  436. }
  437. esp_err_t esp_https_ota_perform(esp_https_ota_handle_t https_ota_handle)
  438. {
  439. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  440. if (handle == NULL) {
  441. ESP_LOGE(TAG, "esp_https_ota_perform: Invalid argument");
  442. return ESP_ERR_INVALID_ARG;
  443. }
  444. if (handle->state < ESP_HTTPS_OTA_BEGIN) {
  445. ESP_LOGE(TAG, "esp_https_ota_perform: Invalid state");
  446. return ESP_FAIL;
  447. }
  448. esp_err_t err;
  449. int data_read;
  450. const int erase_size = handle->bulk_flash_erase ? OTA_SIZE_UNKNOWN : OTA_WITH_SEQUENTIAL_WRITES;
  451. switch (handle->state) {
  452. case ESP_HTTPS_OTA_BEGIN:
  453. err = esp_ota_begin(handle->update_partition, erase_size, &handle->update_handle);
  454. if (err != ESP_OK) {
  455. ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err));
  456. return err;
  457. }
  458. handle->state = ESP_HTTPS_OTA_IN_PROGRESS;
  459. /* In case `esp_https_ota_read_img_desc` was invoked first,
  460. then the image data read there should be written to OTA partition
  461. */
  462. int binary_file_len = 0;
  463. if (handle->binary_file_len) {
  464. binary_file_len = handle->binary_file_len;
  465. } else {
  466. if (read_header(handle) != ESP_OK) {
  467. return ESP_FAIL;
  468. }
  469. binary_file_len = IMAGE_HEADER_SIZE;
  470. }
  471. /*
  472. * Header length gets added to handle->binary_file_len in _ota_write
  473. * Clear handle->binary_file_len to avoid additional bytes in upgrade image size calculation
  474. */
  475. handle->binary_file_len = 0;
  476. const void *data_buf = (const void *) handle->ota_upgrade_buf;
  477. #if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB
  478. decrypt_cb_arg_t args = {};
  479. args.data_in = handle->ota_upgrade_buf;
  480. args.data_in_len = binary_file_len;
  481. err = esp_https_ota_decrypt_cb(handle, &args);
  482. if (err == ESP_OK) {
  483. data_buf = args.data_out;
  484. binary_file_len = args.data_out_len;
  485. } else {
  486. ESP_LOGE(TAG, "Decryption of image header failed");
  487. return ESP_FAIL;
  488. }
  489. #endif // CONFIG_ESP_HTTPS_OTA_DECRYPT_CB
  490. err = esp_ota_verify_chip_id(data_buf);
  491. if (err != ESP_OK) {
  492. return err;
  493. }
  494. return _ota_write(handle, data_buf, binary_file_len);
  495. case ESP_HTTPS_OTA_IN_PROGRESS:
  496. data_read = esp_http_client_read(handle->http_client,
  497. handle->ota_upgrade_buf,
  498. handle->ota_upgrade_buf_size);
  499. if (data_read == 0) {
  500. /*
  501. * esp_http_client_is_complete_data_received is added to check whether
  502. * complete image is received.
  503. */
  504. if (!esp_http_client_is_complete_data_received(handle->http_client)) {
  505. ESP_LOGE(TAG, "Connection closed before complete data was received!");
  506. return ESP_FAIL;
  507. }
  508. ESP_LOGD(TAG, "Connection closed");
  509. } else if (data_read > 0) {
  510. const void *data_buf = (const void *) handle->ota_upgrade_buf;
  511. int data_len = data_read;
  512. #if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB
  513. decrypt_cb_arg_t args = {};
  514. args.data_in = handle->ota_upgrade_buf;
  515. args.data_in_len = data_read;
  516. err = esp_https_ota_decrypt_cb(handle, &args);
  517. if (err == ESP_OK) {
  518. data_buf = args.data_out;
  519. data_len = args.data_out_len;
  520. } else {
  521. return err;
  522. }
  523. #endif // CONFIG_ESP_HTTPS_OTA_DECRYPT_CB
  524. return _ota_write(handle, data_buf, data_len);
  525. } else {
  526. if (data_read == -ESP_ERR_HTTP_EAGAIN) {
  527. ESP_LOGD(TAG, "ESP_ERR_HTTP_EAGAIN invoked: Call timed out before data was ready");
  528. return ESP_ERR_HTTPS_OTA_IN_PROGRESS;
  529. }
  530. ESP_LOGE(TAG, "data read %d, errno %d", data_read, errno);
  531. return ESP_FAIL;
  532. }
  533. if (!handle->partial_http_download || (handle->partial_http_download && handle->image_length == handle->binary_file_len)) {
  534. handle->state = ESP_HTTPS_OTA_SUCCESS;
  535. }
  536. break;
  537. default:
  538. ESP_LOGE(TAG, "Invalid ESP HTTPS OTA State");
  539. return ESP_FAIL;
  540. break;
  541. }
  542. if (handle->partial_http_download) {
  543. if (handle->state == ESP_HTTPS_OTA_IN_PROGRESS && handle->image_length > handle->binary_file_len) {
  544. esp_http_client_close(handle->http_client);
  545. char *header_val = NULL;
  546. int header_size = 0;
  547. #if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB
  548. header_size = handle->enc_img_header_size;
  549. #endif
  550. if ((handle->image_length - handle->binary_file_len) > handle->max_http_request_size) {
  551. asprintf(&header_val, "bytes=%d-%d", handle->binary_file_len + header_size, (handle->binary_file_len + header_size + handle->max_http_request_size - 1));
  552. } else {
  553. asprintf(&header_val, "bytes=%d-", handle->binary_file_len + header_size);
  554. }
  555. if (header_val == NULL) {
  556. ESP_LOGE(TAG, "Failed to allocate memory for HTTP header");
  557. return ESP_ERR_NO_MEM;
  558. }
  559. esp_http_client_set_header(handle->http_client, "Range", header_val);
  560. free(header_val);
  561. err = _http_connect(handle);
  562. if (err != ESP_OK) {
  563. ESP_LOGE(TAG, "Failed to establish HTTP connection");
  564. return ESP_FAIL;
  565. }
  566. ESP_LOGD(TAG, "Connection start");
  567. return ESP_ERR_HTTPS_OTA_IN_PROGRESS;
  568. }
  569. }
  570. return ESP_OK;
  571. }
  572. bool esp_https_ota_is_complete_data_received(esp_https_ota_handle_t https_ota_handle)
  573. {
  574. bool ret = false;
  575. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  576. if (handle->partial_http_download) {
  577. ret = (handle->image_length == handle->binary_file_len);
  578. } else {
  579. ret = esp_http_client_is_complete_data_received(handle->http_client);
  580. }
  581. return ret;
  582. }
  583. esp_err_t esp_https_ota_finish(esp_https_ota_handle_t https_ota_handle)
  584. {
  585. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  586. if (handle == NULL) {
  587. return ESP_ERR_INVALID_ARG;
  588. }
  589. if (handle->state < ESP_HTTPS_OTA_BEGIN) {
  590. return ESP_FAIL;
  591. }
  592. esp_err_t err = ESP_OK;
  593. switch (handle->state) {
  594. case ESP_HTTPS_OTA_SUCCESS:
  595. case ESP_HTTPS_OTA_IN_PROGRESS:
  596. err = esp_ota_end(handle->update_handle);
  597. /* falls through */
  598. case ESP_HTTPS_OTA_BEGIN:
  599. if (handle->ota_upgrade_buf) {
  600. free(handle->ota_upgrade_buf);
  601. }
  602. if (handle->http_client) {
  603. _http_cleanup(handle->http_client);
  604. }
  605. break;
  606. default:
  607. ESP_LOGE(TAG, "Invalid ESP HTTPS OTA State");
  608. break;
  609. }
  610. if ((err == ESP_OK) && (handle->state == ESP_HTTPS_OTA_SUCCESS)) {
  611. esp_err_t err = esp_ota_set_boot_partition(handle->update_partition);
  612. if (err != ESP_OK) {
  613. ESP_LOGE(TAG, "esp_ota_set_boot_partition failed! err=0x%x", err);
  614. } else {
  615. esp_https_ota_dispatch_event(ESP_HTTPS_OTA_UPDATE_BOOT_PARTITION, (void *)(&handle->update_partition->subtype), sizeof(esp_partition_subtype_t));
  616. }
  617. }
  618. free(handle);
  619. esp_https_ota_dispatch_event(ESP_HTTPS_OTA_FINISH, NULL, 0);
  620. return err;
  621. }
  622. esp_err_t esp_https_ota_abort(esp_https_ota_handle_t https_ota_handle)
  623. {
  624. esp_https_ota_dispatch_event(ESP_HTTPS_OTA_ABORT, NULL, 0);
  625. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  626. if (handle == NULL) {
  627. return ESP_ERR_INVALID_ARG;
  628. }
  629. if (handle->state < ESP_HTTPS_OTA_BEGIN) {
  630. return ESP_FAIL;
  631. }
  632. esp_err_t err = ESP_OK;
  633. switch (handle->state) {
  634. case ESP_HTTPS_OTA_SUCCESS:
  635. case ESP_HTTPS_OTA_IN_PROGRESS:
  636. err = esp_ota_abort(handle->update_handle);
  637. /* falls through */
  638. case ESP_HTTPS_OTA_BEGIN:
  639. if (handle->ota_upgrade_buf) {
  640. free(handle->ota_upgrade_buf);
  641. }
  642. if (handle->http_client) {
  643. _http_cleanup(handle->http_client);
  644. }
  645. break;
  646. default:
  647. err = ESP_ERR_INVALID_STATE;
  648. ESP_LOGE(TAG, "Invalid ESP HTTPS OTA State");
  649. break;
  650. }
  651. free(handle);
  652. return err;
  653. }
  654. int esp_https_ota_get_image_len_read(esp_https_ota_handle_t https_ota_handle)
  655. {
  656. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  657. if (handle == NULL) {
  658. return -1;
  659. }
  660. if (handle->state < ESP_HTTPS_OTA_IN_PROGRESS) {
  661. return -1;
  662. }
  663. return handle->binary_file_len;
  664. }
  665. int esp_https_ota_get_image_size(esp_https_ota_handle_t https_ota_handle)
  666. {
  667. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  668. if (handle == NULL) {
  669. return -1;
  670. }
  671. if (handle->state < ESP_HTTPS_OTA_BEGIN) {
  672. return -1;
  673. }
  674. return handle->image_length;
  675. }
  676. esp_err_t esp_https_ota(const esp_https_ota_config_t *ota_config)
  677. {
  678. if (ota_config == NULL || ota_config->http_config == NULL) {
  679. ESP_LOGE(TAG, "esp_https_ota: Invalid argument");
  680. return ESP_ERR_INVALID_ARG;
  681. }
  682. esp_https_ota_handle_t https_ota_handle = NULL;
  683. esp_err_t err = esp_https_ota_begin(ota_config, &https_ota_handle);
  684. if (https_ota_handle == NULL) {
  685. return ESP_FAIL;
  686. }
  687. while (1) {
  688. err = esp_https_ota_perform(https_ota_handle);
  689. if (err != ESP_ERR_HTTPS_OTA_IN_PROGRESS) {
  690. break;
  691. }
  692. }
  693. if (err != ESP_OK) {
  694. esp_https_ota_abort(https_ota_handle);
  695. return err;
  696. }
  697. esp_err_t ota_finish_err = esp_https_ota_finish(https_ota_handle);
  698. if (ota_finish_err != ESP_OK) {
  699. return ota_finish_err;
  700. }
  701. return ESP_OK;
  702. }