test_switch_ota.c 34 KB

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