test_switch_ota.c 34 KB

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