esp_https_ota.c 27 KB

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