test_switch_ota.c 30 KB

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