2021-05-09 21:48:25 -04:00
/*
2022-01-24 13:05:40 -05:00
* SPDX - FileCopyrightText : 2021 - 2022 Espressif Systems ( Shanghai ) CO LTD
2021-05-09 21:48:25 -04:00
*
* SPDX - License - Identifier : Apache - 2.0
*/
2018-06-15 07:08:44 -04:00
/*
* Tests for switching between partitions : factory , OTAx , test .
*/
# include <esp_types.h>
# include <stdio.h>
# include "string.h"
2023-02-06 04:07:53 -05:00
# include <inttypes.h>
global: move the soc component out of the common list
This MR removes the common dependency from every IDF components to the SOC component.
Currently, in the ``idf_functions.cmake`` script, we include the header path of SOC component by default for all components.
But for better code organization (or maybe also benifits to the compiling speed), we may remove the dependency to SOC components for most components except the driver and kernel related components.
In CMAKE, we have two kinds of header visibilities (set by include path visibility):
(Assume component A --(depends on)--> B, B is the current component)
1. public (``COMPONENT_ADD_INCLUDEDIRS``): means this path is visible to other depending components (A) (visible to A and B)
2. private (``COMPONENT_PRIV_INCLUDEDIRS``): means this path is only visible to source files inside the component (visible to B only)
and we have two kinds of depending ways:
(Assume component A --(depends on)--> B --(depends on)--> C, B is the current component)
1. public (```COMPONENT_REQUIRES```): means B can access to public include path of C. All other components rely on you (A) will also be available for the public headers. (visible to A, B)
2. private (``COMPONENT_PRIV_REQUIRES``): means B can access to public include path of C, but don't propagate this relation to other components (A). (visible to B)
1. remove the common requirement in ``idf_functions.cmake``, this makes the SOC components invisible to all other components by default.
2. if a component (for example, DRIVER) really needs the dependency to SOC, add a private dependency to SOC for it.
3. some other components that don't really depends on the SOC may still meet some errors saying "can't find header soc/...", this is because it's depended component (DRIVER) incorrectly include the header of SOC in its public headers. Moving all this kind of #include into source files, or private headers
4. Fix the include requirements for some file which miss sufficient #include directives. (Previously they include some headers by the long long long header include link)
This is a breaking change. Previous code may depends on the long include chain.
You may need to include the following headers for some files after this commit:
- soc/soc.h
- soc/soc_memory_layout.h
- driver/gpio.h
- esp_sleep.h
The major broken include chain includes:
1. esp_system.h no longer includes esp_sleep.h. The latter includes driver/gpio.h and driver/touch_pad.h.
2. ets_sys.h no longer includes soc/soc.h
3. freertos/portmacro.h no longer includes soc/soc_memory_layout.h
some peripheral headers no longer includes their hw related headers, e.g. rom/gpio.h no longer includes soc/gpio_pins.h and soc/gpio_reg.h
BREAKING CHANGE
2019-04-03 01:17:38 -04:00
# include "sdkconfig.h"
2018-06-15 07:08:44 -04:00
2021-09-28 02:12:56 -04:00
# include "esp_rom_spiflash.h"
2018-06-15 07:08:44 -04:00
# include "freertos/FreeRTOS.h"
# include "freertos/task.h"
# include "freertos/semphr.h"
# include "freertos/queue.h"
# include "unity.h"
# include "bootloader_common.h"
2021-11-26 03:04:49 -05:00
# include "../bootloader_flash/include/bootloader_flash_priv.h"
2018-06-15 07:08:44 -04:00
2022-10-17 01:10:46 -04:00
# include "esp_err.h"
2018-06-15 07:08:44 -04:00
# include "esp_log.h"
# include "esp_ota_ops.h"
# include "esp_partition.h"
# include "esp_flash_partitions.h"
# include "esp_image_format.h"
# include "nvs_flash.h"
# include "driver/gpio.h"
global: move the soc component out of the common list
This MR removes the common dependency from every IDF components to the SOC component.
Currently, in the ``idf_functions.cmake`` script, we include the header path of SOC component by default for all components.
But for better code organization (or maybe also benifits to the compiling speed), we may remove the dependency to SOC components for most components except the driver and kernel related components.
In CMAKE, we have two kinds of header visibilities (set by include path visibility):
(Assume component A --(depends on)--> B, B is the current component)
1. public (``COMPONENT_ADD_INCLUDEDIRS``): means this path is visible to other depending components (A) (visible to A and B)
2. private (``COMPONENT_PRIV_INCLUDEDIRS``): means this path is only visible to source files inside the component (visible to B only)
and we have two kinds of depending ways:
(Assume component A --(depends on)--> B --(depends on)--> C, B is the current component)
1. public (```COMPONENT_REQUIRES```): means B can access to public include path of C. All other components rely on you (A) will also be available for the public headers. (visible to A, B)
2. private (``COMPONENT_PRIV_REQUIRES``): means B can access to public include path of C, but don't propagate this relation to other components (A). (visible to B)
1. remove the common requirement in ``idf_functions.cmake``, this makes the SOC components invisible to all other components by default.
2. if a component (for example, DRIVER) really needs the dependency to SOC, add a private dependency to SOC for it.
3. some other components that don't really depends on the SOC may still meet some errors saying "can't find header soc/...", this is because it's depended component (DRIVER) incorrectly include the header of SOC in its public headers. Moving all this kind of #include into source files, or private headers
4. Fix the include requirements for some file which miss sufficient #include directives. (Previously they include some headers by the long long long header include link)
This is a breaking change. Previous code may depends on the long include chain.
You may need to include the following headers for some files after this commit:
- soc/soc.h
- soc/soc_memory_layout.h
- driver/gpio.h
- esp_sleep.h
The major broken include chain includes:
1. esp_system.h no longer includes esp_sleep.h. The latter includes driver/gpio.h and driver/touch_pad.h.
2. ets_sys.h no longer includes soc/soc.h
3. freertos/portmacro.h no longer includes soc/soc_memory_layout.h
some peripheral headers no longer includes their hw related headers, e.g. rom/gpio.h no longer includes soc/gpio_pins.h and soc/gpio_reg.h
BREAKING CHANGE
2019-04-03 01:17:38 -04:00
# include "esp_sleep.h"
2022-05-20 06:16:47 -04:00
# include "test_utils.h"
2018-06-15 07:08:44 -04:00
2022-10-17 01:10:46 -04:00
# define BOOT_COUNT_NAMESPACE "boot_count"
2022-05-20 06:16:47 -04:00
2018-06-15 07:08:44 -04:00
static const char * TAG = " ota_test " ;
2022-10-17 01:10:46 -04:00
static void set_boot_count_in_nvs ( uint8_t boot_count )
{
nvs_handle_t boot_count_handle ;
TEST_ESP_OK ( nvs_open ( BOOT_COUNT_NAMESPACE , NVS_READWRITE , & boot_count_handle ) ) ;
TEST_ESP_OK ( nvs_set_u8 ( boot_count_handle , " boot_count " , boot_count ) ) ;
TEST_ESP_OK ( nvs_commit ( boot_count_handle ) ) ;
nvs_close ( boot_count_handle ) ;
}
static uint8_t get_boot_count_from_nvs ( void )
{
nvs_handle_t boot_count_handle ;
esp_err_t err = nvs_open ( BOOT_COUNT_NAMESPACE , NVS_READONLY , & boot_count_handle ) ;
if ( err = = ESP_ERR_NVS_NOT_FOUND ) {
set_boot_count_in_nvs ( 0 ) ;
}
uint8_t boot_count ;
TEST_ESP_OK ( nvs_get_u8 ( boot_count_handle , " boot_count " , & boot_count ) ) ;
nvs_close ( boot_count_handle ) ;
return boot_count ;
}
2018-06-15 07:08:44 -04:00
/* @brief Copies a current app to next partition using handle.
*
* @ param [ in ] update_handle - Handle of API ota .
* @ param [ in ] cur_app - Current app .
*/
static void copy_app_partition ( esp_ota_handle_t update_handle , const esp_partition_t * curr_app )
{
const void * partition_bin = NULL ;
2022-11-07 06:31:29 -05:00
esp_partition_mmap_handle_t data_map ;
2020-01-21 03:55:31 -05:00
ESP_LOGI ( TAG , " start the copy process " ) ;
2022-11-07 06:31:29 -05:00
TEST_ESP_OK ( esp_partition_mmap ( curr_app , 0 , curr_app - > size , ESP_PARTITION_MMAP_DATA , & partition_bin , & data_map ) ) ;
2018-06-15 07:08:44 -04:00
TEST_ESP_OK ( esp_ota_write ( update_handle , ( const void * ) partition_bin , curr_app - > size ) ) ;
2022-11-07 06:31:29 -05:00
esp_partition_munmap ( data_map ) ;
2020-01-21 03:55:31 -05:00
ESP_LOGI ( TAG , " finish the copy process " ) ;
2018-06-15 07:08:44 -04:00
}
2020-04-22 11:26:34 -04:00
/* @brief Copies a current app to next partition using handle.
*
* @ param [ in ] update_handle - Handle of API ota .
* @ param [ in ] cur_app - Current app .
*/
static void copy_app_partition_with_offset ( esp_ota_handle_t update_handle , const esp_partition_t * curr_app )
{
const void * partition_bin = NULL ;
2022-11-07 06:31:29 -05:00
esp_partition_mmap_handle_t data_map ;
2020-04-22 11:26:34 -04:00
ESP_LOGI ( TAG , " start the copy process " ) ;
uint32_t offset = 0 , bytes_to_write = curr_app - > size ;
uint32_t write_bytes ;
while ( bytes_to_write > 0 ) {
write_bytes = ( bytes_to_write > ( 4 * 1024 ) ) ? ( 4 * 1024 ) : bytes_to_write ;
2022-11-07 06:31:29 -05:00
TEST_ESP_OK ( esp_partition_mmap ( curr_app , offset , write_bytes , ESP_PARTITION_MMAP_DATA , & partition_bin , & data_map ) ) ;
2020-04-22 11:26:34 -04:00
TEST_ESP_OK ( esp_ota_write_with_offset ( update_handle , ( const void * ) partition_bin , write_bytes , offset ) ) ;
2022-11-07 06:31:29 -05:00
esp_partition_munmap ( data_map ) ;
2020-04-22 11:26:34 -04:00
bytes_to_write - = write_bytes ;
offset + = write_bytes ;
}
ESP_LOGI ( TAG , " finish the copy process " ) ;
}
2018-08-21 05:55:49 -04:00
# if defined(CONFIG_BOOTLOADER_FACTORY_RESET) || defined(CONFIG_BOOTLOADER_APP_TEST)
2018-06-15 07:08:44 -04:00
/* @brief Copies partition from source partition to destination partition.
*
* Partitions can be of any types and subtypes .
* @ param [ in ] dst_partition - Destination partition
* @ param [ in ] src_partition - Source partition
*/
static void copy_partition ( const esp_partition_t * dst_partition , const esp_partition_t * src_partition )
{
const void * partition_bin = NULL ;
2022-11-07 06:31:29 -05:00
esp_partition_mmap_handle_t data_map ;
TEST_ESP_OK ( esp_partition_mmap ( src_partition , 0 , src_partition - > size , ESP_PARTITION_MMAP_DATA , & partition_bin , & data_map ) ) ;
2018-06-15 07:08:44 -04:00
TEST_ESP_OK ( esp_partition_erase_range ( dst_partition , 0 , dst_partition - > size ) ) ;
TEST_ESP_OK ( esp_partition_write ( dst_partition , 0 , ( const void * ) partition_bin , dst_partition - > size ) ) ;
2022-11-07 06:31:29 -05:00
esp_partition_munmap ( data_map ) ;
2018-06-15 07:08:44 -04:00
}
2018-08-21 05:55:49 -04:00
# endif
2018-06-15 07:08:44 -04:00
/* @brief Get the next partition of OTA for the update.
*
* @ return The next partition of OTA ( OTA0 - 15 ) .
*/
static const esp_partition_t * get_next_update_partition ( void )
{
const esp_partition_t * update_partition = esp_ota_get_next_update_partition ( NULL ) ;
TEST_ASSERT_NOT_EQUAL ( NULL , update_partition ) ;
2023-02-06 04:07:53 -05:00
ESP_LOGI ( TAG , " Writing to partition subtype %d at offset 0x% " PRIx32 , update_partition - > subtype , update_partition - > address ) ;
2018-06-15 07:08:44 -04:00
return update_partition ;
}
/* @brief Copies a current app to next partition (OTA0-15) and then configure OTA data for a new boot partition.
*
* @ param [ in ] cur_app_partition - Current app .
* @ param [ in ] next_app_partition - Next app for boot .
*/
static void copy_current_app_to_next_part ( const esp_partition_t * cur_app_partition , const esp_partition_t * next_app_partition )
{
esp_ota_get_next_update_partition ( NULL ) ;
TEST_ASSERT_NOT_EQUAL ( NULL , next_app_partition ) ;
2023-02-06 04:07:53 -05:00
ESP_LOGI ( TAG , " Writing to partition subtype %d at offset 0x% " PRIx32 , next_app_partition - > subtype , next_app_partition - > address ) ;
2018-06-15 07:08:44 -04:00
esp_ota_handle_t update_handle = 0 ;
TEST_ESP_OK ( esp_ota_begin ( next_app_partition , OTA_SIZE_UNKNOWN , & update_handle ) ) ;
copy_app_partition ( update_handle , cur_app_partition ) ;
TEST_ESP_OK ( esp_ota_end ( update_handle ) ) ;
TEST_ESP_OK ( esp_ota_set_boot_partition ( next_app_partition ) ) ;
}
2020-04-22 11:26:34 -04:00
/* @brief Copies a current app to next partition (OTA0-15) and then configure OTA data for a new boot partition.
*
* @ param [ in ] cur_app_partition - Current app .
* @ param [ in ] next_app_partition - Next app for boot .
*/
static void copy_current_app_to_next_part_with_offset ( const esp_partition_t * cur_app_partition , const esp_partition_t * next_app_partition )
{
esp_ota_get_next_update_partition ( NULL ) ;
TEST_ASSERT_NOT_EQUAL ( NULL , next_app_partition ) ;
2023-02-06 04:07:53 -05:00
ESP_LOGI ( TAG , " Writing to partition subtype %d at offset 0x% " PRIx32 , next_app_partition - > subtype , next_app_partition - > address ) ;
2020-04-22 11:26:34 -04:00
esp_ota_handle_t update_handle = 0 ;
TEST_ESP_OK ( esp_ota_begin ( next_app_partition , OTA_SIZE_UNKNOWN , & update_handle ) ) ;
copy_app_partition_with_offset ( update_handle , cur_app_partition ) ;
TEST_ESP_OK ( esp_ota_end ( update_handle ) ) ;
TEST_ESP_OK ( esp_ota_set_boot_partition ( next_app_partition ) ) ;
}
2018-06-15 07:08:44 -04:00
/* @brief Erase otadata partition
*/
static void erase_ota_data ( void )
{
const esp_partition_t * data_partition = esp_partition_find_first ( ESP_PARTITION_TYPE_DATA , ESP_PARTITION_SUBTYPE_DATA_OTA , NULL ) ;
TEST_ASSERT_NOT_EQUAL ( NULL , data_partition ) ;
TEST_ESP_OK ( esp_partition_erase_range ( data_partition , 0 , 2 * SPI_FLASH_SEC_SIZE ) ) ;
}
/* @brief Reboots ESP using mode deep sleep. This mode guaranty that RTC_DATA_ATTR variables is not reset.
*/
static void reboot_as_deep_sleep ( void )
{
2020-01-21 03:55:31 -05:00
ESP_LOGI ( TAG , " reboot as deep sleep " ) ;
2018-06-15 07:08:44 -04:00
esp_sleep_enable_timer_wakeup ( 2000 ) ;
esp_deep_sleep_start ( ) ;
}
/* @brief Copies a current app to next partition (OTA0-15), after that ESP is rebooting and run this (the next) OTAx.
*/
2019-07-16 05:33:30 -04:00
static void copy_current_app_to_next_part_and_reboot ( void )
2018-06-15 07:08:44 -04:00
{
const esp_partition_t * cur_app = esp_ota_get_running_partition ( ) ;
2020-01-21 03:55:31 -05:00
ESP_LOGI ( TAG , " copy current app to next part " ) ;
2018-06-15 07:08:44 -04:00
copy_current_app_to_next_part ( cur_app , get_next_update_partition ( ) ) ;
reboot_as_deep_sleep ( ) ;
}
2020-04-22 11:26:34 -04:00
/* @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.
*/
static void copy_current_app_to_next_part_with_offset_and_reboot ( void )
{
const esp_partition_t * cur_app = esp_ota_get_running_partition ( ) ;
ESP_LOGI ( TAG , " copy current app to next part " ) ;
copy_current_app_to_next_part_with_offset ( cur_app , get_next_update_partition ( ) ) ;
reboot_as_deep_sleep ( ) ;
}
2018-06-15 07:08:44 -04:00
/* @brief Get running app.
*
* @ return The next partition of OTA ( OTA0 - 15 ) .
*/
static const esp_partition_t * get_running_firmware ( void )
{
const esp_partition_t * configured = esp_ota_get_boot_partition ( ) ;
const esp_partition_t * running = esp_ota_get_running_partition ( ) ;
2023-02-06 04:07:53 -05:00
ESP_LOGI ( TAG , " Running partition type %d subtype %d (offset 0x%08 " PRIx32 " ) " ,
2018-06-15 07:08:44 -04:00
running - > type , running - > subtype , running - > address ) ;
2023-02-06 04:07:53 -05:00
ESP_LOGI ( TAG , " Configured partition type %d subtype %d (offset 0x%08 " PRIx32 " ) " ,
2018-06-15 07:08:44 -04:00
configured - > type , configured - > subtype , configured - > address ) ;
TEST_ASSERT_NOT_EQUAL ( NULL , configured ) ;
TEST_ASSERT_NOT_EQUAL ( NULL , running ) ;
if ( running - > subtype ! = ESP_PARTITION_SUBTYPE_APP_TEST ) {
TEST_ASSERT_EQUAL_PTR ( running , configured ) ;
}
return running ;
}
// type of a corrupt ota_data
typedef enum {
CORR_CRC_1_SECTOR_OTA_DATA = ( 1 < < 0 ) , /*!< Corrupt CRC only 1 sector of ota_data */
CORR_CRC_2_SECTOR_OTA_DATA = ( 1 < < 1 ) , /*!< Corrupt CRC only 2 sector of ota_data */
} corrupt_ota_data_t ;
/* @brief Get two copies ota_data from otadata partition.
*
* @ param [ in ] otadata_partition - otadata partition .
* @ param [ out ] ota_data_0 - First copy from otadata_partition .
* @ param [ out ] ota_data_1 - Second copy from otadata_partition .
*/
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 )
{
uint32_t offset = otadata_partition - > address ;
uint32_t size = otadata_partition - > size ;
if ( offset ! = 0 ) {
const esp_ota_select_entry_t * ota_select_map ;
ota_select_map = bootloader_mmap ( offset , size ) ;
TEST_ASSERT_NOT_EQUAL ( NULL , ota_select_map ) ;
memcpy ( ota_data_0 , ota_select_map , sizeof ( esp_ota_select_entry_t ) ) ;
memcpy ( ota_data_1 , ( uint8_t * ) ota_select_map + SPI_FLASH_SEC_SIZE , sizeof ( esp_ota_select_entry_t ) ) ;
bootloader_munmap ( ota_select_map ) ;
}
}
/* @brief Writes a ota_data into required sector of otadata_partition.
*
* @ param [ in ] otadata_partition - Partition information otadata .
* @ param [ in ] ota_data - otadata structure .
* @ param [ in ] sec_id - Sector number 0 or 1.
*/
static void write_ota_data ( const esp_partition_t * otadata_partition , esp_ota_select_entry_t * ota_data , int sec_id )
{
esp_partition_write ( otadata_partition , SPI_FLASH_SEC_SIZE * sec_id , & ota_data [ sec_id ] , sizeof ( esp_ota_select_entry_t ) ) ;
}
/* @brief Makes a corrupt of ota_data.
* @ param [ in ] err - type error
*/
static void corrupt_ota_data ( corrupt_ota_data_t err )
{
esp_ota_select_entry_t ota_data [ 2 ] ;
const esp_partition_t * otadata_partition = esp_partition_find_first ( ESP_PARTITION_TYPE_DATA , ESP_PARTITION_SUBTYPE_DATA_OTA , NULL ) ;
TEST_ASSERT_NOT_EQUAL ( NULL , otadata_partition ) ;
get_ota_data ( otadata_partition , & ota_data [ 0 ] , & ota_data [ 1 ] ) ;
if ( err & CORR_CRC_1_SECTOR_OTA_DATA ) {
ota_data [ 0 ] . crc = 0 ;
}
if ( err & CORR_CRC_2_SECTOR_OTA_DATA ) {
ota_data [ 1 ] . crc = 0 ;
}
TEST_ESP_OK ( esp_partition_erase_range ( otadata_partition , 0 , otadata_partition - > size ) ) ;
write_ota_data ( otadata_partition , & ota_data [ 0 ] , 0 ) ;
write_ota_data ( otadata_partition , & ota_data [ 1 ] , 1 ) ;
}
2018-08-21 05:55:49 -04:00
# if defined(CONFIG_BOOTLOADER_FACTORY_RESET) || defined(CONFIG_BOOTLOADER_APP_TEST)
2018-06-15 07:08:44 -04:00
/* @brief Sets the pin number to output and sets output level as low. After reboot (deep sleep) this pin keep the same level.
*
* The output level of the pad will be force locked and can not be changed .
* Power down or call gpio_hold_dis will disable this function .
*
* @ param [ in ] num_pin - Pin number
*/
static void set_output_pin ( uint32_t num_pin )
{
TEST_ESP_OK ( gpio_hold_dis ( num_pin ) ) ;
gpio_config_t io_conf ;
2020-06-19 00:00:58 -04:00
io_conf . intr_type = GPIO_INTR_DISABLE ;
2018-06-15 07:08:44 -04:00
io_conf . mode = GPIO_MODE_OUTPUT ;
io_conf . pin_bit_mask = ( 1ULL < < num_pin ) ;
io_conf . pull_down_en = 0 ;
io_conf . pull_up_en = 0 ;
TEST_ESP_OK ( gpio_config ( & io_conf ) ) ;
TEST_ESP_OK ( gpio_set_level ( num_pin , 0 ) ) ;
TEST_ESP_OK ( gpio_hold_en ( num_pin ) ) ;
}
/* @brief Unset the pin number hold function.
*/
static void reset_output_pin ( uint32_t num_pin )
{
TEST_ESP_OK ( gpio_hold_dis ( num_pin ) ) ;
TEST_ESP_OK ( gpio_reset_pin ( num_pin ) ) ;
}
2018-08-21 05:55:49 -04:00
# endif
2018-06-15 07:08:44 -04:00
2019-02-13 04:32:23 -05:00
static void mark_app_valid ( void )
{
2019-05-09 08:10:35 -04:00
# ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
2019-02-13 04:32:23 -05:00
TEST_ESP_OK ( esp_ota_mark_app_valid_cancel_rollback ( ) ) ;
# endif
}
2018-06-15 07:08:44 -04:00
/* @brief Checks and prepares the partition so that the factory app is launched after that.
*/
static void start_test ( void )
{
ESP_LOGI ( TAG , " boot count 1 - reset " ) ;
2022-10-17 01:10:46 -04:00
set_boot_count_in_nvs ( 1 ) ;
2018-06-15 07:08:44 -04:00
erase_ota_data ( ) ;
2020-01-21 03:55:31 -05:00
ESP_LOGI ( TAG , " ota_data erased " ) ;
2018-06-15 07:08:44 -04:00
reboot_as_deep_sleep ( ) ;
}
static void test_flow1 ( void )
{
2022-10-17 01:10:46 -04:00
uint8_t boot_count = get_boot_count_from_nvs ( ) ;
2018-06-15 07:08:44 -04:00
boot_count + + ;
2022-10-17 01:10:46 -04:00
set_boot_count_in_nvs ( boot_count ) ;
2018-06-15 07:08:44 -04:00
ESP_LOGI ( TAG , " boot count %d " , boot_count ) ;
const esp_partition_t * cur_app = get_running_firmware ( ) ;
switch ( boot_count ) {
case 2 :
ESP_LOGI ( TAG , " Factory " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
2019-07-30 00:53:48 -04:00
copy_current_app_to_next_part_and_reboot ( ) ;
2018-06-15 07:08:44 -04:00
break ;
case 3 :
ESP_LOGI ( TAG , " OTA0 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_0 , cur_app - > subtype ) ;
2019-02-13 04:32:23 -05:00
mark_app_valid ( ) ;
2019-07-30 00:53:48 -04:00
copy_current_app_to_next_part_and_reboot ( ) ;
2018-06-15 07:08:44 -04:00
break ;
case 4 :
ESP_LOGI ( TAG , " OTA1 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_1 , cur_app - > subtype ) ;
2019-02-13 04:32:23 -05:00
mark_app_valid ( ) ;
2019-07-30 00:53:48 -04:00
copy_current_app_to_next_part_and_reboot ( ) ;
2018-06-15 07:08:44 -04:00
break ;
case 5 :
ESP_LOGI ( TAG , " OTA0 " ) ;
2019-02-13 04:32:23 -05:00
mark_app_valid ( ) ;
2018-06-15 07:08:44 -04:00
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_0 , cur_app - > subtype ) ;
erase_ota_data ( ) ;
break ;
default :
erase_ota_data ( ) ;
TEST_FAIL_MESSAGE ( " Unexpected stage " ) ;
break ;
}
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
// 4 Stage: run OTA1 -> check it -> copy OTA1 to OTA0 -> reboot --//--
// 5 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
2019-07-16 22:28:50 -04:00
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 ) ;
2018-06-15 07:08:44 -04:00
static void test_flow2 ( void )
{
2022-10-17 01:10:46 -04:00
uint8_t boot_count = get_boot_count_from_nvs ( ) ;
2018-06-15 07:08:44 -04:00
boot_count + + ;
2022-10-17 01:10:46 -04:00
set_boot_count_in_nvs ( boot_count ) ;
2018-06-15 07:08:44 -04:00
ESP_LOGI ( TAG , " boot count %d " , boot_count ) ;
const esp_partition_t * cur_app = get_running_firmware ( ) ;
switch ( boot_count ) {
case 2 :
ESP_LOGI ( TAG , " Factory " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
2019-07-30 00:53:48 -04:00
copy_current_app_to_next_part_and_reboot ( ) ;
2018-06-15 07:08:44 -04:00
break ;
case 3 :
ESP_LOGI ( TAG , " OTA0 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_0 , cur_app - > subtype ) ;
2019-02-13 04:32:23 -05:00
mark_app_valid ( ) ;
2018-06-15 07:08:44 -04:00
copy_current_app_to_next_part ( cur_app , get_next_update_partition ( ) ) ;
corrupt_ota_data ( CORR_CRC_1_SECTOR_OTA_DATA ) ;
reboot_as_deep_sleep ( ) ;
break ;
case 4 :
ESP_LOGI ( TAG , " Factory " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
erase_ota_data ( ) ;
break ;
default :
erase_ota_data ( ) ;
TEST_FAIL_MESSAGE ( " Unexpected stage " ) ;
break ;
}
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> corrupt ota data -> reboot --//--
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
2019-07-16 22:28:50 -04:00
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 ) ;
2018-06-15 07:08:44 -04:00
static void test_flow3 ( void )
{
2022-10-17 01:10:46 -04:00
uint8_t boot_count = get_boot_count_from_nvs ( ) ;
2018-06-15 07:08:44 -04:00
boot_count + + ;
2022-10-17 01:10:46 -04:00
set_boot_count_in_nvs ( boot_count ) ;
2018-06-15 07:08:44 -04:00
ESP_LOGI ( TAG , " boot count %d " , boot_count ) ;
const esp_partition_t * cur_app = get_running_firmware ( ) ;
switch ( boot_count ) {
case 2 :
ESP_LOGI ( TAG , " Factory " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
2019-07-30 00:53:48 -04:00
copy_current_app_to_next_part_and_reboot ( ) ;
2018-06-15 07:08:44 -04:00
break ;
case 3 :
ESP_LOGI ( TAG , " OTA0 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_0 , cur_app - > subtype ) ;
2019-02-13 04:32:23 -05:00
mark_app_valid ( ) ;
2019-07-30 00:53:48 -04:00
copy_current_app_to_next_part_and_reboot ( ) ;
2018-06-15 07:08:44 -04:00
break ;
case 4 :
ESP_LOGI ( TAG , " OTA1 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_1 , cur_app - > subtype ) ;
2019-02-13 04:32:23 -05:00
mark_app_valid ( ) ;
2018-06-15 07:08:44 -04:00
copy_current_app_to_next_part ( cur_app , get_next_update_partition ( ) ) ;
corrupt_ota_data ( CORR_CRC_2_SECTOR_OTA_DATA ) ;
reboot_as_deep_sleep ( ) ;
break ;
case 5 :
ESP_LOGI ( TAG , " OTA0 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_0 , cur_app - > subtype ) ;
erase_ota_data ( ) ;
break ;
default :
erase_ota_data ( ) ;
TEST_FAIL_MESSAGE ( " Unexpected stage " ) ;
break ;
}
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
// 3 Stage: run OTA1 -> check it -> corrupt ota sector2 -> reboot --//--
// 4 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
2022-10-17 01:10:46 -04:00
TEST_CASE_MULTIPLE_STAGES ( " Switching between factory, OTA0, OTA1, corrupt 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 ) ;
2018-06-15 07:08:44 -04:00
2018-08-21 05:55:49 -04:00
# ifdef CONFIG_BOOTLOADER_FACTORY_RESET
2018-06-15 07:08:44 -04:00
static void test_flow4 ( void )
{
2022-10-17 01:10:46 -04:00
uint8_t boot_count = get_boot_count_from_nvs ( ) ;
2018-06-15 07:08:44 -04:00
boot_count + + ;
2022-10-17 01:10:46 -04:00
set_boot_count_in_nvs ( boot_count ) ;
2018-06-15 07:08:44 -04:00
ESP_LOGI ( TAG , " boot count %d " , boot_count ) ;
const esp_partition_t * cur_app = get_running_firmware ( ) ;
switch ( boot_count ) {
case 2 :
ESP_LOGI ( TAG , " Factory " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
2019-07-30 00:53:48 -04:00
copy_current_app_to_next_part_and_reboot ( ) ;
2018-06-15 07:08:44 -04:00
break ;
case 3 :
ESP_LOGI ( TAG , " OTA0 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_0 , cur_app - > subtype ) ;
2019-02-13 04:32:23 -05:00
mark_app_valid ( ) ;
2018-06-15 07:08:44 -04:00
set_output_pin ( CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET ) ;
2022-10-17 01:10:46 -04:00
esp_restart ( ) ;
2018-06-15 07:08:44 -04:00
break ;
case 4 :
reset_output_pin ( CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET ) ;
ESP_LOGI ( TAG , " Factory " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
erase_ota_data ( ) ;
break ;
default :
erase_ota_data ( ) ;
TEST_FAIL_MESSAGE ( " Unexpected stage " ) ;
break ;
}
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
2022-10-17 01:10:46 -04:00
// 3 Stage: run OTA0 -> check it -> set_pin_factory_reset -> reboot
2018-06-15 07:08:44 -04:00
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
2022-10-17 01:10:46 -04:00
TEST_CASE_MULTIPLE_STAGES ( " Switching between factory, OTA0, sets pin_factory_reset, factory " , " [app_update][timeout=90][reset=DEEPSLEEP_RESET, SW_CPU_RESET, DEEPSLEEP_RESET] " , start_test , test_flow4 , test_flow4 , test_flow4 ) ;
2018-08-21 05:55:49 -04:00
# endif
2018-06-15 07:08:44 -04:00
2018-08-21 05:55:49 -04:00
# ifdef CONFIG_BOOTLOADER_APP_TEST
2018-06-15 07:08:44 -04:00
static void test_flow5 ( void )
{
2022-10-17 01:10:46 -04:00
uint8_t boot_count = get_boot_count_from_nvs ( ) ;
2018-06-15 07:08:44 -04:00
boot_count + + ;
2022-10-17 01:10:46 -04:00
set_boot_count_in_nvs ( boot_count ) ;
2018-06-15 07:08:44 -04:00
ESP_LOGI ( TAG , " boot count %d " , boot_count ) ;
const esp_partition_t * cur_app = get_running_firmware ( ) ;
switch ( boot_count ) {
case 2 :
ESP_LOGI ( TAG , " Factory " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
set_output_pin ( CONFIG_BOOTLOADER_NUM_PIN_APP_TEST ) ;
copy_partition ( esp_partition_find_first ( ESP_PARTITION_TYPE_APP , ESP_PARTITION_SUBTYPE_APP_TEST , NULL ) , cur_app ) ;
2022-10-17 01:10:46 -04:00
esp_restart ( ) ;
2018-06-15 07:08:44 -04:00
break ;
case 3 :
reset_output_pin ( CONFIG_BOOTLOADER_NUM_PIN_APP_TEST ) ;
ESP_LOGI ( TAG , " Test " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_TEST , cur_app - > subtype ) ;
2022-10-17 01:10:46 -04:00
esp_restart ( ) ;
2018-06-15 07:08:44 -04:00
break ;
case 4 :
ESP_LOGI ( TAG , " Factory " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
erase_ota_data ( ) ;
break ;
default :
reset_output_pin ( CONFIG_BOOTLOADER_NUM_PIN_APP_TEST ) ;
erase_ota_data ( ) ;
TEST_FAIL_MESSAGE ( " Unexpected stage " ) ;
break ;
}
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
2022-10-17 01:10:46 -04:00
// 2 Stage: run factory -> check it -> copy factory to Test and set pin_test_app -> reboot
// 3 Stage: run test -> check it -> reset pin_test_app -> reboot
2018-06-15 07:08:44 -04:00
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
2022-10-17 01:10:46 -04:00
TEST_CASE_MULTIPLE_STAGES ( " Switching between factory, test, factory " , " [app_update][timeout=90][reset=SW_CPU_RESET, SW_CPU_RESET, DEEPSLEEP_RESET] " , start_test , test_flow5 , test_flow5 , test_flow5 ) ;
2018-08-21 05:55:49 -04:00
# endif
2018-10-23 08:27:32 -04:00
static const esp_partition_t * app_update ( void )
{
const esp_partition_t * cur_app = get_running_firmware ( ) ;
const esp_partition_t * update_partition = esp_ota_get_next_update_partition ( NULL ) ;
TEST_ASSERT_NOT_NULL ( update_partition ) ;
esp_ota_handle_t update_handle = 0 ;
TEST_ESP_OK ( esp_ota_begin ( update_partition , OTA_SIZE_UNKNOWN , & update_handle ) ) ;
copy_app_partition ( update_handle , cur_app ) ;
TEST_ESP_OK ( esp_ota_end ( update_handle ) ) ;
TEST_ESP_OK ( esp_ota_set_boot_partition ( update_partition ) ) ;
return update_partition ;
}
static void test_rollback1 ( void )
{
2022-10-17 01:10:46 -04:00
uint8_t boot_count = get_boot_count_from_nvs ( ) ;
2018-10-23 08:27:32 -04:00
boot_count + + ;
2022-10-17 01:10:46 -04:00
set_boot_count_in_nvs ( boot_count ) ;
2018-10-23 08:27:32 -04:00
ESP_LOGI ( TAG , " boot count %d " , boot_count ) ;
const esp_partition_t * cur_app = get_running_firmware ( ) ;
esp_ota_img_states_t ota_state = 0x5555AAAA ;
const esp_partition_t * update_partition = NULL ;
switch ( boot_count ) {
case 2 :
ESP_LOGI ( TAG , " Factory " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
TEST_ASSERT_NULL ( esp_ota_get_last_invalid_partition ( ) ) ;
TEST_ESP_ERR ( ESP_ERR_NOT_SUPPORTED , esp_ota_get_state_partition ( cur_app , & ota_state ) ) ;
update_partition = app_update ( ) ;
TEST_ESP_OK ( esp_ota_get_state_partition ( update_partition , & ota_state ) ) ;
2019-05-09 08:10:35 -04:00
# ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
2018-10-23 08:27:32 -04:00
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_UNDEFINED , ota_state ) ;
# else
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_NEW , ota_state ) ;
# endif
reboot_as_deep_sleep ( ) ;
break ;
case 3 :
ESP_LOGI ( TAG , " OTA0 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_0 , cur_app - > subtype ) ;
TEST_ASSERT_NULL ( esp_ota_get_last_invalid_partition ( ) ) ;
TEST_ESP_OK ( esp_ota_get_state_partition ( cur_app , & ota_state ) ) ;
2019-05-09 08:10:35 -04:00
# ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
2018-10-23 08:27:32 -04:00
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_UNDEFINED , ota_state ) ;
# else
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_PENDING_VERIFY , ota_state ) ;
# endif
2019-02-13 04:32:23 -05:00
TEST_ESP_OK ( esp_ota_mark_app_valid_cancel_rollback ( ) ) ;
2018-10-23 08:27:32 -04:00
TEST_ESP_OK ( esp_ota_get_state_partition ( cur_app , & ota_state ) ) ;
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_VALID , ota_state ) ;
reboot_as_deep_sleep ( ) ;
break ;
case 4 :
ESP_LOGI ( TAG , " OTA0 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_0 , cur_app - > subtype ) ;
TEST_ESP_OK ( esp_ota_get_state_partition ( cur_app , & ota_state ) ) ;
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_VALID , ota_state ) ;
TEST_ESP_OK ( esp_ota_mark_app_invalid_rollback_and_reboot ( ) ) ;
break ;
default :
erase_ota_data ( ) ;
TEST_FAIL_MESSAGE ( " Unexpected stage " ) ;
break ;
}
}
static void test_rollback1_1 ( void )
{
2022-10-17 01:10:46 -04:00
set_boot_count_in_nvs ( 5 ) ;
2018-10-23 08:27:32 -04:00
esp_ota_img_states_t ota_state = 0x5555AAAA ;
2022-10-17 01:10:46 -04:00
uint8_t boot_count = get_boot_count_from_nvs ( ) ;
2018-10-23 08:27:32 -04:00
ESP_LOGI ( TAG , " boot count %d " , boot_count ) ;
const esp_partition_t * cur_app = get_running_firmware ( ) ;
ESP_LOGI ( TAG , " Factory " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
const esp_partition_t * invalid_partition = esp_ota_get_last_invalid_partition ( ) ;
const esp_partition_t * next_update_partition = esp_ota_get_next_update_partition ( NULL ) ;
TEST_ASSERT_NOT_NULL ( invalid_partition ) ;
TEST_ASSERT_NOT_NULL ( next_update_partition ) ;
TEST_ASSERT_EQUAL_PTR ( invalid_partition , next_update_partition ) ;
TEST_ESP_ERR ( ESP_ERR_NOT_SUPPORTED , esp_ota_get_state_partition ( cur_app , & ota_state ) ) ;
TEST_ESP_OK ( esp_ota_get_state_partition ( invalid_partition , & ota_state ) ) ;
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_INVALID , ota_state ) ;
erase_ota_data ( ) ;
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to next app slot -> reboot --//--
// 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback() -> reboot --//--
// 4 Stage: run OTA0 -> check it -> esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
// 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
2019-07-16 22:28:50 -04:00
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 ) ;
2018-10-23 08:27:32 -04:00
static void test_rollback2 ( void )
{
2022-10-17 01:10:46 -04:00
uint8_t boot_count = get_boot_count_from_nvs ( ) ;
2018-10-23 08:27:32 -04:00
boot_count + + ;
2022-10-17 01:10:46 -04:00
set_boot_count_in_nvs ( boot_count ) ;
2018-10-23 08:27:32 -04:00
ESP_LOGI ( TAG , " boot count %d " , boot_count ) ;
const esp_partition_t * cur_app = get_running_firmware ( ) ;
esp_ota_img_states_t ota_state = 0x5555AAAA ;
const esp_partition_t * update_partition = NULL ;
switch ( boot_count ) {
case 2 :
ESP_LOGI ( TAG , " Factory " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
TEST_ASSERT_NULL ( esp_ota_get_last_invalid_partition ( ) ) ;
TEST_ESP_ERR ( ESP_ERR_NOT_SUPPORTED , esp_ota_get_state_partition ( cur_app , & ota_state ) ) ;
update_partition = app_update ( ) ;
TEST_ESP_OK ( esp_ota_get_state_partition ( update_partition , & ota_state ) ) ;
2019-05-09 08:10:35 -04:00
# ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
2018-10-23 08:27:32 -04:00
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_UNDEFINED , ota_state ) ;
# else
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_NEW , ota_state ) ;
# endif
reboot_as_deep_sleep ( ) ;
break ;
case 3 :
ESP_LOGI ( TAG , " OTA0 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_0 , cur_app - > subtype ) ;
TEST_ASSERT_NULL ( esp_ota_get_last_invalid_partition ( ) ) ;
TEST_ESP_OK ( esp_ota_get_state_partition ( cur_app , & ota_state ) ) ;
2019-05-09 08:10:35 -04:00
# ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
2018-10-23 08:27:32 -04:00
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_UNDEFINED , ota_state ) ;
# else
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_PENDING_VERIFY , ota_state ) ;
# endif
2019-02-13 04:32:23 -05:00
TEST_ESP_OK ( esp_ota_mark_app_valid_cancel_rollback ( ) ) ;
2018-10-23 08:27:32 -04:00
TEST_ASSERT_NULL ( esp_ota_get_last_invalid_partition ( ) ) ;
TEST_ESP_OK ( esp_ota_get_state_partition ( cur_app , & ota_state ) ) ;
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_VALID , ota_state ) ;
update_partition = app_update ( ) ;
TEST_ESP_OK ( esp_ota_get_state_partition ( update_partition , & ota_state ) ) ;
2019-05-09 08:10:35 -04:00
# ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
2018-10-23 08:27:32 -04:00
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_UNDEFINED , ota_state ) ;
# else
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_NEW , ota_state ) ;
# endif
reboot_as_deep_sleep ( ) ;
break ;
case 4 :
ESP_LOGI ( TAG , " OTA1 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_1 , cur_app - > subtype ) ;
TEST_ASSERT_NULL ( esp_ota_get_last_invalid_partition ( ) ) ;
TEST_ESP_OK ( esp_ota_get_state_partition ( cur_app , & ota_state ) ) ;
2019-05-09 08:10:35 -04:00
# ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
2018-10-23 08:27:32 -04:00
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_UNDEFINED , ota_state ) ;
TEST_ESP_OK ( esp_ota_mark_app_invalid_rollback_and_reboot ( ) ) ;
# else
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_PENDING_VERIFY , ota_state ) ;
reboot_as_deep_sleep ( ) ;
# endif
break ;
default :
erase_ota_data ( ) ;
TEST_FAIL_MESSAGE ( " Unexpected stage " ) ;
break ;
}
}
static void test_rollback2_1 ( void )
{
2022-10-17 01:10:46 -04:00
set_boot_count_in_nvs ( 5 ) ;
uint8_t boot_count = get_boot_count_from_nvs ( ) ;
2018-10-23 08:27:32 -04:00
esp_ota_img_states_t ota_state = 0x5555AAAA ;
ESP_LOGI ( TAG , " boot count %d " , boot_count ) ;
const esp_partition_t * cur_app = get_running_firmware ( ) ;
ESP_LOGI ( TAG , " OTA0 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_0 , cur_app - > subtype ) ;
const esp_partition_t * invalid_partition = esp_ota_get_last_invalid_partition ( ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_1 , invalid_partition - > subtype ) ;
const esp_partition_t * next_update_partition = esp_ota_get_next_update_partition ( NULL ) ;
TEST_ASSERT_NOT_NULL ( invalid_partition ) ;
TEST_ASSERT_NOT_NULL ( next_update_partition ) ;
TEST_ASSERT_EQUAL_PTR ( invalid_partition , next_update_partition ) ;
TEST_ESP_OK ( esp_ota_get_state_partition ( cur_app , & ota_state ) ) ;
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_VALID , ota_state ) ;
TEST_ESP_OK ( esp_ota_get_state_partition ( invalid_partition , & ota_state ) ) ;
2019-05-09 08:10:35 -04:00
# ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
2018-10-23 08:27:32 -04:00
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_INVALID , ota_state ) ;
# else
TEST_ASSERT_EQUAL ( ESP_OTA_IMG_ABORTED , ota_state ) ;
# endif
erase_ota_data ( ) ;
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to next app slot -> reboot --//--
// 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback(), copy to next app slot -> reboot --//--
// 4 Stage: run OTA1 -> check it -> PENDING_VERIFY/esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
// 5 Stage: run OTA0(rollback) -> check it -> erase OTA_DATA for next tests -> PASS
2019-07-16 22:28:50 -04:00
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 ) ;
2018-10-23 08:27:32 -04:00
static void test_erase_last_app_flow ( void )
{
2022-10-17 01:10:46 -04:00
uint8_t boot_count = get_boot_count_from_nvs ( ) ;
2018-10-23 08:27:32 -04:00
boot_count + + ;
2022-10-17 01:10:46 -04:00
set_boot_count_in_nvs ( boot_count ) ;
2018-10-23 08:27:32 -04:00
ESP_LOGI ( TAG , " boot count %d " , boot_count ) ;
const esp_partition_t * cur_app = get_running_firmware ( ) ;
switch ( boot_count ) {
case 2 :
ESP_LOGI ( TAG , " Factory " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
app_update ( ) ;
reboot_as_deep_sleep ( ) ;
break ;
case 3 :
ESP_LOGI ( TAG , " OTA0 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_0 , cur_app - > subtype ) ;
2019-02-13 04:32:23 -05:00
mark_app_valid ( ) ;
2018-10-23 08:27:32 -04:00
app_update ( ) ;
reboot_as_deep_sleep ( ) ;
break ;
case 4 :
ESP_LOGI ( TAG , " OTA1 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_1 , cur_app - > subtype ) ;
TEST_ESP_OK ( esp_ota_erase_last_boot_app_partition ( ) ) ;
TEST_ESP_OK ( esp_ota_mark_app_invalid_rollback_and_reboot ( ) ) ;
reboot_as_deep_sleep ( ) ;
break ;
default :
erase_ota_data ( ) ;
TEST_FAIL_MESSAGE ( " Unexpected stage " ) ;
break ;
}
}
static void test_erase_last_app_rollback ( void )
{
2022-10-17 01:10:46 -04:00
set_boot_count_in_nvs ( 5 ) ;
uint8_t boot_count = get_boot_count_from_nvs ( ) ;
2018-10-23 08:27:32 -04:00
ESP_LOGI ( TAG , " boot count %d " , boot_count ) ;
const esp_partition_t * cur_app = get_running_firmware ( ) ;
ESP_LOGI ( TAG , " erase_last_app " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
TEST_ESP_ERR ( ESP_FAIL , esp_ota_erase_last_boot_app_partition ( ) ) ;
erase_ota_data ( ) ;
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> copy factory to OTA1 -> reboot --//--
// 4 Stage: run OTA1 -> check it -> erase OTA0 and rollback -> reboot
// 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
2019-07-16 22:28:50 -04:00
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 ) ;
2020-04-22 11:26:34 -04:00
static void test_flow6 ( void )
{
2022-10-17 01:10:46 -04:00
uint8_t boot_count = get_boot_count_from_nvs ( ) ;
2020-04-22 11:26:34 -04:00
boot_count + + ;
2022-10-17 01:10:46 -04:00
set_boot_count_in_nvs ( boot_count ) ;
2020-04-22 11:26:34 -04:00
ESP_LOGI ( TAG , " boot count %d " , boot_count ) ;
const esp_partition_t * cur_app = get_running_firmware ( ) ;
switch ( boot_count ) {
case 2 :
ESP_LOGI ( TAG , " Factory " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_FACTORY , cur_app - > subtype ) ;
copy_current_app_to_next_part_with_offset_and_reboot ( ) ;
break ;
case 3 :
ESP_LOGI ( TAG , " OTA0 " ) ;
TEST_ASSERT_EQUAL ( ESP_PARTITION_SUBTYPE_APP_OTA_0 , cur_app - > subtype ) ;
mark_app_valid ( ) ;
erase_ota_data ( ) ;
break ;
default :
erase_ota_data ( ) ;
TEST_FAIL_MESSAGE ( " Unexpected stage " ) ;
break ;
}
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
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 ) ;
2022-01-24 13:05:40 -05:00
2022-05-20 06:16:47 -04:00
//IDF-5145
2022-01-24 13:05:40 -05:00
TEST_CASE ( " Test bootloader_common_get_sha256_of_partition returns ESP_ERR_IMAGE_INVALID when image is ivalid " , " [partitions] " )
{
const esp_partition_t * cur_app = esp_ota_get_running_partition ( ) ;
ESP_LOGI ( TAG , " copy current app to next part " ) ;
const esp_partition_t * other_app = get_next_update_partition ( ) ;
copy_current_app_to_next_part ( cur_app , other_app ) ;
erase_ota_data ( ) ;
uint8_t sha_256_cur_app [ 32 ] ;
uint8_t sha_256_other_app [ 32 ] ;
TEST_ESP_OK ( bootloader_common_get_sha256_of_partition ( cur_app - > address , cur_app - > size , cur_app - > type , sha_256_cur_app ) ) ;
TEST_ESP_OK ( bootloader_common_get_sha256_of_partition ( other_app - > address , other_app - > size , other_app - > type , sha_256_other_app ) ) ;
TEST_ASSERT_EQUAL_MEMORY_MESSAGE ( sha_256_cur_app , sha_256_other_app , sizeof ( sha_256_cur_app ) , " must be the same " ) ;
uint32_t data = 0 ;
bootloader_flash_write ( other_app - > address + 0x50 , & data , sizeof ( data ) , false ) ;
TEST_ESP_ERR ( ESP_ERR_IMAGE_INVALID , bootloader_common_get_sha256_of_partition ( other_app - > address , other_app - > size , other_app - > type , sha_256_other_app ) ) ;
TEST_ASSERT_EQUAL_MEMORY_MESSAGE ( sha_256_cur_app , sha_256_other_app , sizeof ( sha_256_cur_app ) , " must be the same " ) ;
}