test_switch_ota.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. /*
  2. * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /*
  7. * Tests for switching between partitions: factory, OTAx, test.
  8. */
  9. #include <esp_types.h>
  10. #include <stdio.h>
  11. #include "string.h"
  12. #include "sdkconfig.h"
  13. #if CONFIG_IDF_TARGET_ESP32
  14. #include "esp32/rom/spi_flash.h"
  15. #elif CONFIG_IDF_TARGET_ESP32S2
  16. #include "esp32s2/rom/spi_flash.h"
  17. #endif
  18. #include "freertos/FreeRTOS.h"
  19. #include "freertos/task.h"
  20. #include "freertos/semphr.h"
  21. #include "freertos/queue.h"
  22. #include "unity.h"
  23. #include "bootloader_common.h"
  24. #include "../include_bootloader/bootloader_flash_priv.h"
  25. #include "esp_log.h"
  26. #include "esp_ota_ops.h"
  27. #include "esp_partition.h"
  28. #include "esp_flash_partitions.h"
  29. #include "esp_image_format.h"
  30. #include "nvs_flash.h"
  31. #include "driver/gpio.h"
  32. #include "esp_sleep.h"
  33. RTC_DATA_ATTR static int boot_count = 0;
  34. static const char *TAG = "ota_test";
  35. /* @brief Copies a current app to next partition using handle.
  36. *
  37. * @param[in] update_handle - Handle of API ota.
  38. * @param[in] cur_app - Current app.
  39. */
  40. static void copy_app_partition(esp_ota_handle_t update_handle, const esp_partition_t *curr_app)
  41. {
  42. const void *partition_bin = NULL;
  43. spi_flash_mmap_handle_t data_map;
  44. ESP_LOGI(TAG, "start the copy process");
  45. TEST_ESP_OK(esp_partition_mmap(curr_app, 0, curr_app->size, SPI_FLASH_MMAP_DATA, &partition_bin, &data_map));
  46. TEST_ESP_OK(esp_ota_write(update_handle, (const void *)partition_bin, curr_app->size));
  47. spi_flash_munmap(data_map);
  48. ESP_LOGI(TAG, "finish the copy process");
  49. }
  50. /* @brief Copies a current app to next partition using handle.
  51. *
  52. * @param[in] update_handle - Handle of API ota.
  53. * @param[in] cur_app - Current app.
  54. */
  55. static void copy_app_partition_with_offset(esp_ota_handle_t update_handle, const esp_partition_t *curr_app)
  56. {
  57. const void *partition_bin = NULL;
  58. spi_flash_mmap_handle_t data_map;
  59. ESP_LOGI(TAG, "start the copy process");
  60. uint32_t offset = 0, bytes_to_write = curr_app->size;
  61. uint32_t write_bytes;
  62. while (bytes_to_write > 0) {
  63. write_bytes = (bytes_to_write > (4 * 1024)) ? (4 * 1024) : bytes_to_write;
  64. TEST_ESP_OK(esp_partition_mmap(curr_app, offset, write_bytes, SPI_FLASH_MMAP_DATA, &partition_bin, &data_map));
  65. TEST_ESP_OK(esp_ota_write_with_offset(update_handle, (const void *)partition_bin, write_bytes, offset));
  66. spi_flash_munmap(data_map);
  67. bytes_to_write -= write_bytes;
  68. offset += write_bytes;
  69. }
  70. ESP_LOGI(TAG, "finish the copy process");
  71. }
  72. #if defined(CONFIG_BOOTLOADER_FACTORY_RESET) || defined(CONFIG_BOOTLOADER_APP_TEST)
  73. /* @brief Copies partition from source partition to destination partition.
  74. *
  75. * Partitions can be of any types and subtypes.
  76. * @param[in] dst_partition - Destination partition
  77. * @param[in] src_partition - Source partition
  78. */
  79. static void copy_partition(const esp_partition_t *dst_partition, const esp_partition_t *src_partition)
  80. {
  81. const void *partition_bin = NULL;
  82. spi_flash_mmap_handle_t data_map;
  83. TEST_ESP_OK(esp_partition_mmap(src_partition, 0, src_partition->size, SPI_FLASH_MMAP_DATA, &partition_bin, &data_map));
  84. TEST_ESP_OK(esp_partition_erase_range(dst_partition, 0, dst_partition->size));
  85. TEST_ESP_OK(esp_partition_write(dst_partition, 0, (const void *)partition_bin, dst_partition->size));
  86. spi_flash_munmap(data_map);
  87. }
  88. #endif
  89. /* @brief Get the next partition of OTA for the update.
  90. *
  91. * @return The next partition of OTA(OTA0-15).
  92. */
  93. static const esp_partition_t * get_next_update_partition(void)
  94. {
  95. const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
  96. TEST_ASSERT_NOT_EQUAL(NULL, update_partition);
  97. ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", update_partition->subtype, update_partition->address);
  98. return update_partition;
  99. }
  100. /* @brief Copies a current app to next partition (OTA0-15) and then configure OTA data for a new boot partition.
  101. *
  102. * @param[in] cur_app_partition - Current app.
  103. * @param[in] next_app_partition - Next app for boot.
  104. */
  105. static void copy_current_app_to_next_part(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition)
  106. {
  107. esp_ota_get_next_update_partition(NULL);
  108. TEST_ASSERT_NOT_EQUAL(NULL, next_app_partition);
  109. ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", next_app_partition->subtype, next_app_partition->address);
  110. esp_ota_handle_t update_handle = 0;
  111. TEST_ESP_OK(esp_ota_begin(next_app_partition, OTA_SIZE_UNKNOWN, &update_handle));
  112. copy_app_partition(update_handle, cur_app_partition);
  113. TEST_ESP_OK(esp_ota_end(update_handle));
  114. TEST_ESP_OK(esp_ota_set_boot_partition(next_app_partition));
  115. }
  116. /* @brief Copies a current app to next partition (OTA0-15) and then configure OTA data for a new boot partition.
  117. *
  118. * @param[in] cur_app_partition - Current app.
  119. * @param[in] next_app_partition - Next app for boot.
  120. */
  121. static void copy_current_app_to_next_part_with_offset(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition)
  122. {
  123. esp_ota_get_next_update_partition(NULL);
  124. TEST_ASSERT_NOT_EQUAL(NULL, next_app_partition);
  125. ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", next_app_partition->subtype, next_app_partition->address);
  126. esp_ota_handle_t update_handle = 0;
  127. TEST_ESP_OK(esp_ota_begin(next_app_partition, OTA_SIZE_UNKNOWN, &update_handle));
  128. copy_app_partition_with_offset(update_handle, cur_app_partition);
  129. TEST_ESP_OK(esp_ota_end(update_handle));
  130. TEST_ESP_OK(esp_ota_set_boot_partition(next_app_partition));
  131. }
  132. /* @brief Erase otadata partition
  133. */
  134. static void erase_ota_data(void)
  135. {
  136. const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
  137. TEST_ASSERT_NOT_EQUAL(NULL, data_partition);
  138. TEST_ESP_OK(esp_partition_erase_range(data_partition, 0, 2 * SPI_FLASH_SEC_SIZE));
  139. }
  140. /* @brief Reboots ESP using mode deep sleep. This mode guaranty that RTC_DATA_ATTR variables is not reset.
  141. */
  142. static void reboot_as_deep_sleep(void)
  143. {
  144. ESP_LOGI(TAG, "reboot as deep sleep");
  145. esp_sleep_enable_timer_wakeup(2000);
  146. esp_deep_sleep_start();
  147. }
  148. /* @brief Copies a current app to next partition (OTA0-15), after that ESP is rebooting and run this (the next) OTAx.
  149. */
  150. static void copy_current_app_to_next_part_and_reboot(void)
  151. {
  152. const esp_partition_t *cur_app = esp_ota_get_running_partition();
  153. ESP_LOGI(TAG, "copy current app to next part");
  154. copy_current_app_to_next_part(cur_app, get_next_update_partition());
  155. reboot_as_deep_sleep();
  156. }
  157. /* @brief Copies a current app to next partition (OTA0-15) using esp_ota_write_with_offest(), after that ESP is rebooting and run this (the next) OTAx.
  158. */
  159. static void copy_current_app_to_next_part_with_offset_and_reboot(void)
  160. {
  161. const esp_partition_t *cur_app = esp_ota_get_running_partition();
  162. ESP_LOGI(TAG, "copy current app to next part");
  163. copy_current_app_to_next_part_with_offset(cur_app, get_next_update_partition());
  164. reboot_as_deep_sleep();
  165. }
  166. /* @brief Get running app.
  167. *
  168. * @return The next partition of OTA(OTA0-15).
  169. */
  170. static const esp_partition_t* get_running_firmware(void)
  171. {
  172. const esp_partition_t *configured = esp_ota_get_boot_partition();
  173. const esp_partition_t *running = esp_ota_get_running_partition();
  174. ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)",
  175. running->type, running->subtype, running->address);
  176. ESP_LOGI(TAG, "Configured partition type %d subtype %d (offset 0x%08x)",
  177. configured->type, configured->subtype, configured->address);
  178. TEST_ASSERT_NOT_EQUAL(NULL, configured);
  179. TEST_ASSERT_NOT_EQUAL(NULL, running);
  180. if (running->subtype != ESP_PARTITION_SUBTYPE_APP_TEST) {
  181. TEST_ASSERT_EQUAL_PTR(running, configured);
  182. }
  183. return running;
  184. }
  185. // type of a corrupt ota_data
  186. typedef enum {
  187. CORR_CRC_1_SECTOR_OTA_DATA = (1 << 0), /*!< Corrupt CRC only 1 sector of ota_data */
  188. CORR_CRC_2_SECTOR_OTA_DATA = (1 << 1), /*!< Corrupt CRC only 2 sector of ota_data */
  189. } corrupt_ota_data_t;
  190. /* @brief Get two copies ota_data from otadata partition.
  191. *
  192. * @param[in] otadata_partition - otadata partition.
  193. * @param[out] ota_data_0 - First copy from otadata_partition.
  194. * @param[out] ota_data_1 - Second copy from otadata_partition.
  195. */
  196. static void get_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data_0, esp_ota_select_entry_t *ota_data_1)
  197. {
  198. uint32_t offset = otadata_partition->address;
  199. uint32_t size = otadata_partition->size;
  200. if (offset != 0) {
  201. const esp_ota_select_entry_t *ota_select_map;
  202. ota_select_map = bootloader_mmap(offset, size);
  203. TEST_ASSERT_NOT_EQUAL(NULL, ota_select_map);
  204. memcpy(ota_data_0, ota_select_map, sizeof(esp_ota_select_entry_t));
  205. memcpy(ota_data_1, (uint8_t *)ota_select_map + SPI_FLASH_SEC_SIZE, sizeof(esp_ota_select_entry_t));
  206. bootloader_munmap(ota_select_map);
  207. }
  208. }
  209. /* @brief Writes a ota_data into required sector of otadata_partition.
  210. *
  211. * @param[in] otadata_partition - Partition information otadata.
  212. * @param[in] ota_data - otadata structure.
  213. * @param[in] sec_id - Sector number 0 or 1.
  214. */
  215. static void write_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data, int sec_id)
  216. {
  217. esp_partition_write(otadata_partition, SPI_FLASH_SEC_SIZE * sec_id, &ota_data[sec_id], sizeof(esp_ota_select_entry_t));
  218. }
  219. /* @brief Makes a corrupt of ota_data.
  220. * @param[in] err - type error
  221. */
  222. static void corrupt_ota_data(corrupt_ota_data_t err)
  223. {
  224. esp_ota_select_entry_t ota_data[2];
  225. const esp_partition_t *otadata_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
  226. TEST_ASSERT_NOT_EQUAL(NULL, otadata_partition);
  227. get_ota_data(otadata_partition, &ota_data[0], &ota_data[1]);
  228. if (err & CORR_CRC_1_SECTOR_OTA_DATA) {
  229. ota_data[0].crc = 0;
  230. }
  231. if (err & CORR_CRC_2_SECTOR_OTA_DATA) {
  232. ota_data[1].crc = 0;
  233. }
  234. TEST_ESP_OK(esp_partition_erase_range(otadata_partition, 0, otadata_partition->size));
  235. write_ota_data(otadata_partition, &ota_data[0], 0);
  236. write_ota_data(otadata_partition, &ota_data[1], 1);
  237. }
  238. #if defined(CONFIG_BOOTLOADER_FACTORY_RESET) || defined(CONFIG_BOOTLOADER_APP_TEST)
  239. /* @brief Sets the pin number to output and sets output level as low. After reboot (deep sleep) this pin keep the same level.
  240. *
  241. * The output level of the pad will be force locked and can not be changed.
  242. * Power down or call gpio_hold_dis will disable this function.
  243. *
  244. * @param[in] num_pin - Pin number
  245. */
  246. static void set_output_pin(uint32_t num_pin)
  247. {
  248. TEST_ESP_OK(gpio_hold_dis(num_pin));
  249. gpio_config_t io_conf;
  250. io_conf.intr_type = GPIO_INTR_DISABLE;
  251. io_conf.mode = GPIO_MODE_OUTPUT;
  252. io_conf.pin_bit_mask = (1ULL << num_pin);
  253. io_conf.pull_down_en = 0;
  254. io_conf.pull_up_en = 0;
  255. TEST_ESP_OK(gpio_config(&io_conf));
  256. TEST_ESP_OK(gpio_set_level(num_pin, 0));
  257. TEST_ESP_OK(gpio_hold_en(num_pin));
  258. }
  259. /* @brief Unset the pin number hold function.
  260. */
  261. static void reset_output_pin(uint32_t num_pin)
  262. {
  263. TEST_ESP_OK(gpio_hold_dis(num_pin));
  264. TEST_ESP_OK(gpio_reset_pin(num_pin));
  265. }
  266. #endif
  267. static void mark_app_valid(void)
  268. {
  269. #ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
  270. TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
  271. #endif
  272. }
  273. /* @brief Checks and prepares the partition so that the factory app is launched after that.
  274. */
  275. static void start_test(void)
  276. {
  277. ESP_LOGI(TAG, "boot count 1 - reset");
  278. boot_count = 1;
  279. erase_ota_data();
  280. ESP_LOGI(TAG, "ota_data erased");
  281. reboot_as_deep_sleep();
  282. }
  283. static void test_flow1(void)
  284. {
  285. boot_count++;
  286. ESP_LOGI(TAG, "boot count %d", boot_count);
  287. const esp_partition_t *cur_app = get_running_firmware();
  288. switch (boot_count) {
  289. case 2:
  290. ESP_LOGI(TAG, "Factory");
  291. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  292. copy_current_app_to_next_part_and_reboot();
  293. break;
  294. case 3:
  295. ESP_LOGI(TAG, "OTA0");
  296. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
  297. mark_app_valid();
  298. copy_current_app_to_next_part_and_reboot();
  299. break;
  300. case 4:
  301. ESP_LOGI(TAG, "OTA1");
  302. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
  303. mark_app_valid();
  304. copy_current_app_to_next_part_and_reboot();
  305. break;
  306. case 5:
  307. ESP_LOGI(TAG, "OTA0");
  308. mark_app_valid();
  309. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
  310. erase_ota_data();
  311. break;
  312. default:
  313. erase_ota_data();
  314. TEST_FAIL_MESSAGE("Unexpected stage");
  315. break;
  316. }
  317. }
  318. // 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
  319. // 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
  320. // 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
  321. // 4 Stage: run OTA1 -> check it -> copy OTA1 to OTA0 -> reboot --//--
  322. // 5 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
  323. TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow1, test_flow1, test_flow1, test_flow1);
  324. static void test_flow2(void)
  325. {
  326. boot_count++;
  327. ESP_LOGI(TAG, "boot count %d", boot_count);
  328. const esp_partition_t *cur_app = get_running_firmware();
  329. switch (boot_count) {
  330. case 2:
  331. ESP_LOGI(TAG, "Factory");
  332. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  333. copy_current_app_to_next_part_and_reboot();
  334. break;
  335. case 3:
  336. ESP_LOGI(TAG, "OTA0");
  337. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
  338. mark_app_valid();
  339. copy_current_app_to_next_part(cur_app, get_next_update_partition());
  340. corrupt_ota_data(CORR_CRC_1_SECTOR_OTA_DATA);
  341. reboot_as_deep_sleep();
  342. break;
  343. case 4:
  344. ESP_LOGI(TAG, "Factory");
  345. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  346. erase_ota_data();
  347. break;
  348. default:
  349. erase_ota_data();
  350. TEST_FAIL_MESSAGE("Unexpected stage");
  351. break;
  352. }
  353. }
  354. // 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
  355. // 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
  356. // 3 Stage: run OTA0 -> check it -> corrupt ota data -> reboot --//--
  357. // 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
  358. TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, corrupt ota_sec1, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow2, test_flow2, test_flow2);
  359. static void test_flow3(void)
  360. {
  361. boot_count++;
  362. ESP_LOGI(TAG, "boot count %d", boot_count);
  363. const esp_partition_t *cur_app = get_running_firmware();
  364. switch (boot_count) {
  365. case 2:
  366. ESP_LOGI(TAG, "Factory");
  367. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  368. copy_current_app_to_next_part_and_reboot();
  369. break;
  370. case 3:
  371. ESP_LOGI(TAG, "OTA0");
  372. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
  373. mark_app_valid();
  374. copy_current_app_to_next_part_and_reboot();
  375. break;
  376. case 4:
  377. ESP_LOGI(TAG, "OTA1");
  378. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
  379. mark_app_valid();
  380. copy_current_app_to_next_part(cur_app, get_next_update_partition());
  381. corrupt_ota_data(CORR_CRC_2_SECTOR_OTA_DATA);
  382. reboot_as_deep_sleep();
  383. break;
  384. case 5:
  385. ESP_LOGI(TAG, "OTA0");
  386. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
  387. erase_ota_data();
  388. break;
  389. default:
  390. erase_ota_data();
  391. TEST_FAIL_MESSAGE("Unexpected stage");
  392. break;
  393. }
  394. }
  395. // 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
  396. // 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
  397. // 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
  398. // 3 Stage: run OTA1 -> check it -> corrupt ota sector2 -> reboot --//--
  399. // 4 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
  400. TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, currupt ota_sec2, OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow3, test_flow3, test_flow3, test_flow3);
  401. #ifdef CONFIG_BOOTLOADER_FACTORY_RESET
  402. #define STORAGE_NAMESPACE "update_ota"
  403. static void test_flow4(void)
  404. {
  405. boot_count++;
  406. ESP_LOGI(TAG, "boot count %d", boot_count);
  407. const esp_partition_t *cur_app = get_running_firmware();
  408. nvs_handle_t handle = 0;
  409. int32_t boot_count_nvs = 0;
  410. switch (boot_count) {
  411. case 2:
  412. ESP_LOGI(TAG, "Factory");
  413. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  414. TEST_ESP_OK(nvs_flash_erase());
  415. TEST_ESP_OK(nvs_flash_init());
  416. TEST_ESP_OK(nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &handle));
  417. TEST_ESP_OK(nvs_set_i32(handle, "boot_count", boot_count));
  418. TEST_ESP_OK(nvs_commit(handle));
  419. nvs_close(handle);
  420. nvs_flash_deinit();
  421. copy_current_app_to_next_part_and_reboot();
  422. break;
  423. case 3:
  424. ESP_LOGI(TAG, "OTA0");
  425. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
  426. mark_app_valid();
  427. TEST_ESP_OK(nvs_flash_init());
  428. TEST_ESP_OK(nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &handle));
  429. TEST_ESP_OK(nvs_get_i32(handle, "boot_count", &boot_count_nvs));
  430. TEST_ASSERT_EQUAL(boot_count_nvs + 1, boot_count);
  431. nvs_close(handle);
  432. nvs_flash_deinit();
  433. set_output_pin(CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET);
  434. reboot_as_deep_sleep();
  435. break;
  436. case 4:
  437. reset_output_pin(CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET);
  438. ESP_LOGI(TAG, "Factory");
  439. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  440. int32_t boot_count_nvs;
  441. TEST_ESP_OK(nvs_flash_init());
  442. TEST_ESP_OK(nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &handle));
  443. TEST_ESP_ERR(ESP_ERR_NVS_NOT_FOUND, nvs_get_i32(handle, "boot_count", &boot_count_nvs));
  444. nvs_close(handle);
  445. nvs_flash_deinit();
  446. erase_ota_data();
  447. break;
  448. default:
  449. reset_output_pin(CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET);
  450. erase_ota_data();
  451. TEST_FAIL_MESSAGE("Unexpected stage");
  452. break;
  453. }
  454. }
  455. // 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
  456. // 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
  457. // 3 Stage: run OTA0 -> check it -> set_pin_factory_reset -> reboot --//--
  458. // 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
  459. TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, sets pin_factory_reset, factory", "[app_update][timeout=90][ignore][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow4, test_flow4, test_flow4);
  460. #endif
  461. #ifdef CONFIG_BOOTLOADER_APP_TEST
  462. static void test_flow5(void)
  463. {
  464. boot_count++;
  465. ESP_LOGI(TAG, "boot count %d", boot_count);
  466. const esp_partition_t *cur_app = get_running_firmware();
  467. switch (boot_count) {
  468. case 2:
  469. ESP_LOGI(TAG, "Factory");
  470. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  471. set_output_pin(CONFIG_BOOTLOADER_NUM_PIN_APP_TEST);
  472. copy_partition(esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEST, NULL), cur_app);
  473. esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
  474. reboot_as_deep_sleep();
  475. break;
  476. case 3:
  477. reset_output_pin(CONFIG_BOOTLOADER_NUM_PIN_APP_TEST);
  478. ESP_LOGI(TAG, "Test");
  479. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_TEST, cur_app->subtype);
  480. reboot_as_deep_sleep();
  481. break;
  482. case 4:
  483. ESP_LOGI(TAG, "Factory");
  484. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  485. erase_ota_data();
  486. break;
  487. default:
  488. reset_output_pin(CONFIG_BOOTLOADER_NUM_PIN_APP_TEST);
  489. erase_ota_data();
  490. TEST_FAIL_MESSAGE("Unexpected stage");
  491. break;
  492. }
  493. }
  494. // 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
  495. // 2 Stage: run factory -> check it -> copy factory to Test and set pin_test_app -> reboot --//--
  496. // 3 Stage: run test -> check it -> reset pin_test_app -> reboot --//--
  497. // 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
  498. TEST_CASE_MULTIPLE_STAGES("Switching between factory, test, factory", "[app_update][timeout=90][ignore][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow5, test_flow5, test_flow5);
  499. #endif
  500. static const esp_partition_t* app_update(void)
  501. {
  502. const esp_partition_t *cur_app = get_running_firmware();
  503. const esp_partition_t* update_partition = esp_ota_get_next_update_partition(NULL);
  504. TEST_ASSERT_NOT_NULL(update_partition);
  505. esp_ota_handle_t update_handle = 0;
  506. TEST_ESP_OK(esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle));
  507. copy_app_partition(update_handle, cur_app);
  508. TEST_ESP_OK(esp_ota_end(update_handle));
  509. TEST_ESP_OK(esp_ota_set_boot_partition(update_partition));
  510. return update_partition;
  511. }
  512. static void test_rollback1(void)
  513. {
  514. boot_count++;
  515. ESP_LOGI(TAG, "boot count %d", boot_count);
  516. const esp_partition_t *cur_app = get_running_firmware();
  517. esp_ota_img_states_t ota_state = 0x5555AAAA;
  518. const esp_partition_t* update_partition = NULL;
  519. switch (boot_count) {
  520. case 2:
  521. ESP_LOGI(TAG, "Factory");
  522. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  523. TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
  524. TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_ota_get_state_partition(cur_app, &ota_state));
  525. update_partition = app_update();
  526. TEST_ESP_OK(esp_ota_get_state_partition(update_partition, &ota_state));
  527. #ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
  528. TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
  529. #else
  530. TEST_ASSERT_EQUAL(ESP_OTA_IMG_NEW, ota_state);
  531. #endif
  532. reboot_as_deep_sleep();
  533. break;
  534. case 3:
  535. ESP_LOGI(TAG, "OTA0");
  536. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
  537. TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
  538. TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
  539. #ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
  540. TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
  541. #else
  542. TEST_ASSERT_EQUAL(ESP_OTA_IMG_PENDING_VERIFY, ota_state);
  543. #endif
  544. TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
  545. TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
  546. TEST_ASSERT_EQUAL(ESP_OTA_IMG_VALID, ota_state);
  547. reboot_as_deep_sleep();
  548. break;
  549. case 4:
  550. ESP_LOGI(TAG, "OTA0");
  551. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
  552. TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
  553. TEST_ASSERT_EQUAL(ESP_OTA_IMG_VALID, ota_state);
  554. TEST_ESP_OK(esp_ota_mark_app_invalid_rollback_and_reboot());
  555. break;
  556. default:
  557. erase_ota_data();
  558. TEST_FAIL_MESSAGE("Unexpected stage");
  559. break;
  560. }
  561. }
  562. static void test_rollback1_1(void)
  563. {
  564. boot_count = 5;
  565. esp_ota_img_states_t ota_state = 0x5555AAAA;
  566. ESP_LOGI(TAG, "boot count %d", boot_count);
  567. const esp_partition_t *cur_app = get_running_firmware();
  568. ESP_LOGI(TAG, "Factory");
  569. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  570. const esp_partition_t *invalid_partition = esp_ota_get_last_invalid_partition();
  571. const esp_partition_t* next_update_partition = esp_ota_get_next_update_partition(NULL);
  572. TEST_ASSERT_NOT_NULL(invalid_partition);
  573. TEST_ASSERT_NOT_NULL(next_update_partition);
  574. TEST_ASSERT_EQUAL_PTR(invalid_partition, next_update_partition);
  575. TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_ota_get_state_partition(cur_app, &ota_state));
  576. TEST_ESP_OK(esp_ota_get_state_partition(invalid_partition, &ota_state));
  577. TEST_ASSERT_EQUAL(ESP_OTA_IMG_INVALID, ota_state);
  578. erase_ota_data();
  579. }
  580. // 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
  581. // 2 Stage: run factory -> check it -> copy factory to next app slot -> reboot --//--
  582. // 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback() -> reboot --//--
  583. // 4 Stage: run OTA0 -> check it -> esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
  584. // 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
  585. TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA0, rollback -> factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback1, test_rollback1, test_rollback1, test_rollback1_1);
  586. static void test_rollback2(void)
  587. {
  588. boot_count++;
  589. ESP_LOGI(TAG, "boot count %d", boot_count);
  590. const esp_partition_t *cur_app = get_running_firmware();
  591. esp_ota_img_states_t ota_state = 0x5555AAAA;
  592. const esp_partition_t* update_partition = NULL;
  593. switch (boot_count) {
  594. case 2:
  595. ESP_LOGI(TAG, "Factory");
  596. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  597. TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
  598. TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_ota_get_state_partition(cur_app, &ota_state));
  599. update_partition = app_update();
  600. TEST_ESP_OK(esp_ota_get_state_partition(update_partition, &ota_state));
  601. #ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
  602. TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
  603. #else
  604. TEST_ASSERT_EQUAL(ESP_OTA_IMG_NEW, ota_state);
  605. #endif
  606. reboot_as_deep_sleep();
  607. break;
  608. case 3:
  609. ESP_LOGI(TAG, "OTA0");
  610. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
  611. TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
  612. TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
  613. #ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
  614. TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
  615. #else
  616. TEST_ASSERT_EQUAL(ESP_OTA_IMG_PENDING_VERIFY, ota_state);
  617. #endif
  618. TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
  619. TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
  620. TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
  621. TEST_ASSERT_EQUAL(ESP_OTA_IMG_VALID, ota_state);
  622. update_partition = app_update();
  623. TEST_ESP_OK(esp_ota_get_state_partition(update_partition, &ota_state));
  624. #ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
  625. TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
  626. #else
  627. TEST_ASSERT_EQUAL(ESP_OTA_IMG_NEW, ota_state);
  628. #endif
  629. reboot_as_deep_sleep();
  630. break;
  631. case 4:
  632. ESP_LOGI(TAG, "OTA1");
  633. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
  634. TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
  635. TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
  636. #ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
  637. TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
  638. TEST_ESP_OK(esp_ota_mark_app_invalid_rollback_and_reboot());
  639. #else
  640. TEST_ASSERT_EQUAL(ESP_OTA_IMG_PENDING_VERIFY, ota_state);
  641. reboot_as_deep_sleep();
  642. #endif
  643. break;
  644. default:
  645. erase_ota_data();
  646. TEST_FAIL_MESSAGE("Unexpected stage");
  647. break;
  648. }
  649. }
  650. static void test_rollback2_1(void)
  651. {
  652. boot_count = 5;
  653. esp_ota_img_states_t ota_state = 0x5555AAAA;
  654. ESP_LOGI(TAG, "boot count %d", boot_count);
  655. const esp_partition_t *cur_app = get_running_firmware();
  656. ESP_LOGI(TAG, "OTA0");
  657. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
  658. const esp_partition_t *invalid_partition = esp_ota_get_last_invalid_partition();
  659. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, invalid_partition->subtype);
  660. const esp_partition_t* next_update_partition = esp_ota_get_next_update_partition(NULL);
  661. TEST_ASSERT_NOT_NULL(invalid_partition);
  662. TEST_ASSERT_NOT_NULL(next_update_partition);
  663. TEST_ASSERT_EQUAL_PTR(invalid_partition, next_update_partition);
  664. TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
  665. TEST_ASSERT_EQUAL(ESP_OTA_IMG_VALID, ota_state);
  666. TEST_ESP_OK(esp_ota_get_state_partition(invalid_partition, &ota_state));
  667. #ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
  668. TEST_ASSERT_EQUAL(ESP_OTA_IMG_INVALID, ota_state);
  669. #else
  670. TEST_ASSERT_EQUAL(ESP_OTA_IMG_ABORTED, ota_state);
  671. #endif
  672. erase_ota_data();
  673. }
  674. // 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
  675. // 2 Stage: run factory -> check it -> copy factory to next app slot -> reboot --//--
  676. // 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback(), copy to next app slot -> reboot --//--
  677. // 4 Stage: run OTA1 -> check it -> PENDING_VERIFY/esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
  678. // 5 Stage: run OTA0(rollback) -> check it -> erase OTA_DATA for next tests -> PASS
  679. TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA1, rollback -> OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback2, test_rollback2, test_rollback2, test_rollback2_1);
  680. static void test_erase_last_app_flow(void)
  681. {
  682. boot_count++;
  683. ESP_LOGI(TAG, "boot count %d", boot_count);
  684. const esp_partition_t *cur_app = get_running_firmware();
  685. switch (boot_count) {
  686. case 2:
  687. ESP_LOGI(TAG, "Factory");
  688. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  689. app_update();
  690. reboot_as_deep_sleep();
  691. break;
  692. case 3:
  693. ESP_LOGI(TAG, "OTA0");
  694. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
  695. mark_app_valid();
  696. app_update();
  697. reboot_as_deep_sleep();
  698. break;
  699. case 4:
  700. ESP_LOGI(TAG, "OTA1");
  701. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
  702. TEST_ESP_OK(esp_ota_erase_last_boot_app_partition());
  703. TEST_ESP_OK(esp_ota_mark_app_invalid_rollback_and_reboot());
  704. reboot_as_deep_sleep();
  705. break;
  706. default:
  707. erase_ota_data();
  708. TEST_FAIL_MESSAGE("Unexpected stage");
  709. break;
  710. }
  711. }
  712. static void test_erase_last_app_rollback(void)
  713. {
  714. boot_count = 5;
  715. ESP_LOGI(TAG, "boot count %d", boot_count);
  716. const esp_partition_t *cur_app = get_running_firmware();
  717. ESP_LOGI(TAG, "erase_last_app");
  718. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  719. TEST_ESP_ERR(ESP_FAIL, esp_ota_erase_last_boot_app_partition());
  720. erase_ota_data();
  721. }
  722. // 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
  723. // 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
  724. // 3 Stage: run OTA0 -> check it -> copy factory to OTA1 -> reboot --//--
  725. // 4 Stage: run OTA1 -> check it -> erase OTA0 and rollback -> reboot
  726. // 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
  727. TEST_CASE_MULTIPLE_STAGES("Test erase_last_boot_app_partition. factory, OTA1, OTA0, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_rollback);
  728. static void test_flow6(void)
  729. {
  730. boot_count++;
  731. ESP_LOGI(TAG, "boot count %d", boot_count);
  732. const esp_partition_t *cur_app = get_running_firmware();
  733. switch (boot_count) {
  734. case 2:
  735. ESP_LOGI(TAG, "Factory");
  736. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
  737. copy_current_app_to_next_part_with_offset_and_reboot();
  738. break;
  739. case 3:
  740. ESP_LOGI(TAG, "OTA0");
  741. TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
  742. mark_app_valid();
  743. erase_ota_data();
  744. break;
  745. default:
  746. erase_ota_data();
  747. TEST_FAIL_MESSAGE("Unexpected stage");
  748. break;
  749. }
  750. }
  751. // 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
  752. // 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
  753. // 3 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
  754. TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0 using esp_ota_write_with_offset", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow6, test_flow6);