test_switch_ota.c 34 KB

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