diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index a55dbf8495..21af3d87db 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -78,6 +78,7 @@ /components/driver/ @esp-idf-codeowners/peripherals /components/efuse/ @esp-idf-codeowners/system /components/esp_adc/ @esp-idf-codeowners/peripherals +/components/esp_app_format/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities /components/esp_common/ @esp-idf-codeowners/system /components/esp_eth/ @esp-idf-codeowners/network /components/esp_event/ @esp-idf-codeowners/system diff --git a/components/app_update/CMakeLists.txt b/components/app_update/CMakeLists.txt index 789799ed7c..2fb1be8cdb 100644 --- a/components/app_update/CMakeLists.txt +++ b/components/app_update/CMakeLists.txt @@ -1,31 +1,8 @@ -idf_component_register(SRCS "esp_ota_ops.c" - "esp_app_desc.c" +idf_component_register(SRCS "esp_ota_ops.c" "esp_ota_app_desc.c" INCLUDE_DIRS "include" - REQUIRES spi_flash partition_table bootloader_support + REQUIRES spi_flash partition_table bootloader_support esp_app_format PRIV_REQUIRES esptool_py efuse) -# esp_app_desc structure is added as an undefined symbol because otherwise the -# linker will ignore this structure as it has no other files depending on it. -target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_app_desc") - -if(CONFIG_APP_PROJECT_VER_FROM_CONFIG) - # Ignore current PROJECT_VER (which was set in __project_get_revision()). - # Gets the version from the CONFIG_APP_PROJECT_VER. - idf_build_set_property(PROJECT_VER "${CONFIG_APP_PROJECT_VER}") -endif() - -# cut PROJECT_VER and PROJECT_NAME to required 32 characters. -idf_build_get_property(project_ver PROJECT_VER) -idf_build_get_property(project_name PROJECT_NAME) -string(SUBSTRING "${project_ver}" 0 31 PROJECT_VER_CUT) -string(SUBSTRING "${project_name}" 0 31 PROJECT_NAME_CUT) -message(STATUS "App \"${PROJECT_NAME_CUT}\" version: ${PROJECT_VER_CUT}") - -set_source_files_properties( - SOURCE "esp_app_desc.c" - PROPERTIES COMPILE_DEFINITIONS - "PROJECT_VER=\"${PROJECT_VER_CUT}\"; PROJECT_NAME=\"${PROJECT_NAME_CUT}\"") - if(NOT BOOTLOADER_BUILD) partition_table_get_partition_info(otadata_offset "--partition-type data --partition-subtype ota" "offset") partition_table_get_partition_info(otadata_size "--partition-type data --partition-subtype ota" "size") diff --git a/components/app_update/esp_ota_app_desc.c b/components/app_update/esp_ota_app_desc.c new file mode 100644 index 0000000000..70774d50e0 --- /dev/null +++ b/components/app_update/esp_ota_app_desc.c @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "esp_ota_ops.h" +#include "esp_attr.h" +#include "sdkconfig.h" + +const esp_app_desc_t *esp_ota_get_app_description(void) +{ + return esp_app_get_description(); +} + +int IRAM_ATTR esp_ota_get_app_elf_sha256(char* dst, size_t size) +{ + return esp_app_get_elf_sha256(dst, size); +} diff --git a/components/app_update/esp_ota_ops.c b/components/app_update/esp_ota_ops.c index a1bfe77cc8..eda7f97260 100644 --- a/components/app_update/esp_ota_ops.c +++ b/components/app_update/esp_ota_ops.c @@ -651,8 +651,14 @@ esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, es #ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK static esp_err_t esp_ota_set_anti_rollback(void) { - const esp_app_desc_t *app_desc = esp_ota_get_app_description(); - return esp_efuse_update_secure_version(app_desc->secure_version); + const esp_partition_t* partition = esp_ota_get_running_partition(); + esp_app_desc_t app_desc = {0}; + + esp_err_t err = esp_ota_get_partition_description(partition, &app_desc); + if (err == ESP_OK) { + return esp_efuse_update_secure_version(app_desc.secure_version); + } + return err; } #endif diff --git a/components/app_update/include/esp_ota_ops.h b/components/app_update/include/esp_ota_ops.h index 355c61f2f5..1058c728ae 100644 --- a/components/app_update/include/esp_ota_ops.h +++ b/components/app_update/include/esp_ota_ops.h @@ -12,7 +12,7 @@ #include #include "esp_err.h" #include "esp_partition.h" -#include "esp_image_format.h" +#include "esp_app_desc.h" #include "esp_flash_partitions.h" #include "soc/soc_caps.h" @@ -44,20 +44,27 @@ typedef uint32_t esp_ota_handle_t; /** * @brief Return esp_app_desc structure. This structure includes app version. * + * @note This API is present for backward compatibility reasons. Alternative function + * with the same functionality is `esp_app_get_description` + * * Return description for running app. * @return Pointer to esp_app_desc structure. */ -const esp_app_desc_t *esp_ota_get_app_description(void); +const esp_app_desc_t *esp_ota_get_app_description(void) __attribute__((deprecated("Please use esp_app_get_description instead"))); /** * @brief Fill the provided buffer with SHA256 of the ELF file, formatted as hexadecimal, null-terminated. * If the buffer size is not sufficient to fit the entire SHA256 in hex plus a null terminator, * the largest possible number of bytes will be written followed by a null. + * +* @note This API is present for backward compatibility reasons. Alternative function + * with the same functionality is `esp_app_get_elf_sha256` + * * @param dst Destination buffer * @param size Size of the buffer * @return Number of bytes written to dst (including null terminator) */ -int esp_ota_get_app_elf_sha256(char* dst, size_t size); +int esp_ota_get_app_elf_sha256(char* dst, size_t size) __attribute__((deprecated("Please use esp_app_get_elf_sha256 instead"))); /** * @brief Commence an OTA update writing to the specified partition. diff --git a/components/app_update/test/test_ota_ops.c b/components/app_update/test/test_ota_ops.c index 9b283b64ed..b72142d6e1 100644 --- a/components/app_update/test/test_ota_ops.c +++ b/components/app_update/test/test_ota_ops.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,7 +13,6 @@ #include #include #include -#include "bootloader_common.h" /* These OTA tests currently don't assume an OTA partition exists on the device, so they're a bit limited @@ -91,6 +90,8 @@ TEST_CASE("esp_ota_get_next_update_partition logic", "[ota]") TEST_CASE("esp_ota_get_partition_description", "[ota]") { + extern esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc); + const esp_partition_t *running = esp_ota_get_running_partition(); TEST_ASSERT_NOT_NULL(running); esp_app_desc_t app_desc1, app_desc2; diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt index 42b8f85f49..cd2e1eac74 100644 --- a/components/bootloader_support/CMakeLists.txt +++ b/components/bootloader_support/CMakeLists.txt @@ -19,7 +19,7 @@ set(srcs if(BOOTLOADER_BUILD) set(include_dirs "include" "bootloader_flash/include" "private_include") - set(priv_requires micro-ecc spi_flash efuse) + set(priv_requires micro-ecc spi_flash efuse esp_app_format) list(APPEND srcs "src/bootloader_init.c" "src/bootloader_clock_loader.c" @@ -37,7 +37,7 @@ else() set(include_dirs "include" "bootloader_flash/include") set(priv_include_dirs "private_include") # heap is required for `heap_memory_layout.h` header - set(priv_requires spi_flash mbedtls efuse app_update heap) + set(priv_requires spi_flash mbedtls efuse heap esp_app_format) endif() if(BOOTLOADER_BUILD) @@ -86,6 +86,15 @@ idf_component_register(SRCS "${srcs}" REQUIRES "${requires}" PRIV_REQUIRES "${priv_requires}") +if(NOT BOOTLOADER_BUILD) + if(CONFIG_SECURE_SIGNED_ON_UPDATE) + if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR + CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME) + target_link_libraries(${COMPONENT_LIB} PRIVATE idf::app_update) + endif() + endif() +endif() + if(CONFIG_SECURE_SIGNED_APPS AND (CONFIG_SECURE_BOOT_V1_ENABLED OR CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)) if(BOOTLOADER_BUILD) # Whether CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES or not, we need verification key to embed diff --git a/components/bootloader_support/include/bootloader_common.h b/components/bootloader_support/include/bootloader_common.h index 3237de61c0..6145a72ef8 100644 --- a/components/bootloader_support/include/bootloader_common.h +++ b/components/bootloader_support/include/bootloader_common.h @@ -7,7 +7,6 @@ #pragma once #include "esp_flash_partitions.h" #include "esp_image_format.h" -#include "esp_app_format.h" #ifdef __cplusplus extern "C" { @@ -151,20 +150,6 @@ int bootloader_common_get_active_otadata(esp_ota_select_entry_t *two_otadata); */ int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata, bool *valid_two_otadata, bool max); -/** - * @brief Returns esp_app_desc structure for app partition. This structure includes app version. - * - * Returns a description for the requested app partition. - * @param[in] partition App partition description. - * @param[out] app_desc Structure of info about app. - * @return - * - ESP_OK: Successful. - * - ESP_ERR_INVALID_ARG: The arguments passed are not valid. - * - ESP_ERR_NOT_FOUND: app_desc structure is not found. Magic word is incorrect. - * - ESP_FAIL: mapping is fail. - */ -esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc); - /** * @brief Get chip package * diff --git a/components/bootloader_support/include/esp_app_format.h b/components/bootloader_support/include/esp_app_format.h index a6c4d9b283..5fa0975ee1 100644 --- a/components/bootloader_support/include/esp_app_format.h +++ b/components/bootloader_support/include/esp_app_format.h @@ -106,25 +106,3 @@ typedef struct { } esp_image_segment_header_t; #define ESP_IMAGE_MAX_SEGMENTS 16 /*!< Max count of segments in the image. */ - -#define ESP_APP_DESC_MAGIC_WORD 0xABCD5432 /*!< The magic word for the esp_app_desc structure that is in DROM. */ - -/** - * @brief Description about application. - */ -typedef struct { - uint32_t magic_word; /*!< Magic word ESP_APP_DESC_MAGIC_WORD */ - uint32_t secure_version; /*!< Secure version */ - uint32_t reserv1[2]; /*!< reserv1 */ - char version[32]; /*!< Application version */ - char project_name[32]; /*!< Project name */ - char time[16]; /*!< Compile time */ - char date[16]; /*!< Compile date*/ - char idf_ver[32]; /*!< Version IDF */ - uint8_t app_elf_sha256[32]; /*!< sha256 of elf file */ - uint32_t reserv2[20]; /*!< reserv2 */ -} esp_app_desc_t; - -/** @cond */ -_Static_assert(sizeof(esp_app_desc_t) == 256, "esp_app_desc_t should be 256 bytes"); -/** @endcond */ diff --git a/components/bootloader_support/src/bootloader_common_loader.c b/components/bootloader_support/src/bootloader_common_loader.c index 3d9f5c857d..7bc3571127 100644 --- a/components/bootloader_support/src/bootloader_common_loader.c +++ b/components/bootloader_support/src/bootloader_common_loader.c @@ -112,30 +112,6 @@ int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata, return active_otadata; } -esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc) -{ - if (partition == NULL || app_desc == NULL || partition->offset == 0) { - return ESP_ERR_INVALID_ARG; - } - - const uint32_t app_desc_offset = sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t); - const uint32_t mmap_size = app_desc_offset + sizeof(esp_app_desc_t); - const uint8_t *image = bootloader_mmap(partition->offset, mmap_size); - if (image == NULL) { - ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", partition->offset, mmap_size); - return ESP_FAIL; - } - - memcpy(app_desc, image + app_desc_offset, sizeof(esp_app_desc_t)); - bootloader_munmap(image); - - if (app_desc->magic_word != ESP_APP_DESC_MAGIC_WORD) { - return ESP_ERR_NOT_FOUND; - } - - return ESP_OK; -} - #if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC ) #define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t)) diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index 5ef053ce87..b3c4ed1bf0 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -60,6 +60,7 @@ #include "esp_cpu.h" #include "esp_image_format.h" +#include "esp_app_desc.h" #include "esp_secure_boot.h" #include "esp_flash_encrypt.h" #include "esp_flash_partitions.h" @@ -119,6 +120,31 @@ static esp_err_t read_otadata(const esp_partition_pos_t *ota_info, esp_ota_selec return ESP_OK; } +esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc) +{ + if (partition == NULL || app_desc == NULL || partition->offset == 0) { + return ESP_ERR_INVALID_ARG; + } + + const uint32_t app_desc_offset = sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t); + const uint32_t mmap_size = app_desc_offset + sizeof(esp_app_desc_t); + const uint8_t *image = bootloader_mmap(partition->offset, mmap_size); + if (image == NULL) { + ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", partition->offset, mmap_size); + return ESP_FAIL; + } + + memcpy(app_desc, image + app_desc_offset, sizeof(esp_app_desc_t)); + bootloader_munmap(image); + + if (app_desc->magic_word != ESP_APP_DESC_MAGIC_WORD) { + return ESP_ERR_NOT_FOUND; + } + + return ESP_OK; +} + + bool bootloader_utility_load_partition_table(bootloader_state_t *bs) { const esp_partition_info_t *partitions; diff --git a/components/esp_app_format/CMakeLists.txt b/components/esp_app_format/CMakeLists.txt new file mode 100644 index 0000000000..5a0d7460bb --- /dev/null +++ b/components/esp_app_format/CMakeLists.txt @@ -0,0 +1,26 @@ +idf_component_register(SRCS "esp_app_desc.c" + INCLUDE_DIRS "include") + +# esp_app_desc structure is added as an undefined symbol because otherwise the +# linker will ignore this structure as it has no other files depending on it. +if(NOT BOOTLOADER_BUILD) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_app_desc") +endif() + +if(CONFIG_APP_PROJECT_VER_FROM_CONFIG) + # Ignore current PROJECT_VER (which was set in __project_get_revision()). + # Gets the version from the CONFIG_APP_PROJECT_VER. + idf_build_set_property(PROJECT_VER "${CONFIG_APP_PROJECT_VER}") +endif() + +# cut PROJECT_VER and PROJECT_NAME to required 32 characters. +idf_build_get_property(project_ver PROJECT_VER) +idf_build_get_property(project_name PROJECT_NAME) +string(SUBSTRING "${project_ver}" 0 31 PROJECT_VER_CUT) +string(SUBSTRING "${project_name}" 0 31 PROJECT_NAME_CUT) +message(STATUS "App \"${PROJECT_NAME_CUT}\" version: ${PROJECT_VER_CUT}") + +set_source_files_properties( + SOURCE "esp_app_desc.c" + PROPERTIES COMPILE_DEFINITIONS + "PROJECT_VER=\"${PROJECT_VER_CUT}\"; PROJECT_NAME=\"${PROJECT_NAME_CUT}\"") diff --git a/components/app_update/Kconfig.projbuild b/components/esp_app_format/Kconfig.projbuild similarity index 100% rename from components/app_update/Kconfig.projbuild rename to components/esp_app_format/Kconfig.projbuild diff --git a/components/app_update/esp_app_desc.c b/components/esp_app_format/esp_app_desc.c similarity index 88% rename from components/app_update/esp_app_desc.c rename to components/esp_app_format/esp_app_desc.c index ae3325b1c3..909bb94a4c 100644 --- a/components/app_update/esp_app_desc.c +++ b/components/esp_app_format/esp_app_desc.c @@ -1,15 +1,16 @@ /* - * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include #include -#include "esp_ota_ops.h" +#include "esp_app_desc.h" #include "esp_attr.h" #include "sdkconfig.h" + // Application version info const __attribute__((section(".rodata_desc"))) esp_app_desc_t esp_app_desc = { .magic_word = ESP_APP_DESC_MAGIC_WORD, @@ -50,7 +51,7 @@ _Static_assert(sizeof(IDF_VER) <= sizeof(esp_app_desc.idf_ver), "IDF_VER is long _Static_assert(sizeof(PROJECT_NAME) <= sizeof(esp_app_desc.project_name), "PROJECT_NAME is longer than project_name field in structure"); #endif -const esp_app_desc_t *esp_ota_get_app_description(void) +const esp_app_desc_t *esp_app_get_description(void) { return &esp_app_desc; } @@ -64,18 +65,18 @@ static inline char IRAM_ATTR to_hex_digit(unsigned val) return (val < 10) ? ('0' + val) : ('a' + val - 10); } -__attribute__((constructor)) void esp_ota_init_app_elf_sha256(void) +__attribute__((constructor)) void esp_init_app_elf_sha256(void) { - esp_ota_get_app_elf_sha256(NULL, 0); + esp_app_get_elf_sha256(NULL, 0); } /* The esp_app_desc.app_elf_sha256 should be possible to print in panic handler during cache is disabled. * But because the cache is disabled the reading esp_app_desc.app_elf_sha256 is not right and * can lead to a complete lock-up of the CPU. - * For this reason we do a reading of esp_app_desc.app_elf_sha256 while start up in esp_ota_init_app_elf_sha256() + * For this reason we do a reading of esp_app_desc.app_elf_sha256 while start up in esp_init_app_elf_sha256() * and keep it in the static s_app_elf_sha256 value. */ -int IRAM_ATTR esp_ota_get_app_elf_sha256(char* dst, size_t size) +int IRAM_ATTR esp_app_get_elf_sha256(char* dst, size_t size) { static char s_app_elf_sha256[CONFIG_APP_RETRIEVE_LEN_ELF_SHA / 2]; static bool first_call = true; diff --git a/components/esp_app_format/include/esp_app_desc.h b/components/esp_app_format/include/esp_app_desc.h new file mode 100644 index 0000000000..8f8241ba42 --- /dev/null +++ b/components/esp_app_format/include/esp_app_desc.h @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define ESP_APP_DESC_MAGIC_WORD (0xABCD5432) /*!< The magic word for the esp_app_desc structure that is in DROM. */ + +/** + * @brief Description about application. + */ +typedef struct { + uint32_t magic_word; /*!< Magic word ESP_APP_DESC_MAGIC_WORD */ + uint32_t secure_version; /*!< Secure version */ + uint32_t reserv1[2]; /*!< reserv1 */ + char version[32]; /*!< Application version */ + char project_name[32]; /*!< Project name */ + char time[16]; /*!< Compile time */ + char date[16]; /*!< Compile date*/ + char idf_ver[32]; /*!< Version IDF */ + uint8_t app_elf_sha256[32]; /*!< sha256 of elf file */ + uint32_t reserv2[20]; /*!< reserv2 */ +} esp_app_desc_t; + +/** @cond */ +_Static_assert(sizeof(esp_app_desc_t) == 256, "esp_app_desc_t should be 256 bytes"); +/** @endcond */ + +/** + * @brief Return esp_app_desc structure. This structure includes app version. + * + * Return description for running app. + * @return Pointer to esp_app_desc structure. + */ +const esp_app_desc_t *esp_app_get_description(void); + +/** + * @brief Fill the provided buffer with SHA256 of the ELF file, formatted as hexadecimal, null-terminated. + * If the buffer size is not sufficient to fit the entire SHA256 in hex plus a null terminator, + * the largest possible number of bytes will be written followed by a null. + * @param dst Destination buffer + * @param size Size of the buffer + * @return Number of bytes written to dst (including null terminator) + */ +int esp_app_get_elf_sha256(char* dst, size_t size); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_app_format/test_apps/CMakeLists.txt b/components/esp_app_format/test_apps/CMakeLists.txt new file mode 100644 index 0000000000..3ec91ae10d --- /dev/null +++ b/components/esp_app_format/test_apps/CMakeLists.txt @@ -0,0 +1,8 @@ +# This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.16) + +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +set(COMPONENTS main) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(esp_app_format_test) diff --git a/components/esp_app_format/test_apps/README.md b/components/esp_app_format/test_apps/README.md new file mode 100644 index 0000000000..b5be4985c5 --- /dev/null +++ b/components/esp_app_format/test_apps/README.md @@ -0,0 +1,2 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | diff --git a/components/esp_app_format/test_apps/main/CMakeLists.txt b/components/esp_app_format/test_apps/main/CMakeLists.txt new file mode 100644 index 0000000000..9c31d04cdf --- /dev/null +++ b/components/esp_app_format/test_apps/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "test_app_desc.c" + PRIV_INCLUDE_DIRS . + PRIV_REQUIRES esp_app_format unity) diff --git a/components/app_update/test/test_app_desc.c b/components/esp_app_format/test_apps/main/test_app_desc.c similarity index 67% rename from components/app_update/test/test_app_desc.c rename to components/esp_app_format/test_apps/main/test_app_desc.c index c37fbe614b..99992702f0 100644 --- a/components/app_update/test/test_app_desc.c +++ b/components/esp_app_format/test_apps/main/test_app_desc.c @@ -1,13 +1,26 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include #include -#include "esp_ota_ops.h" -#include "unity.h" -TEST_CASE("esp_ota_get_app_elf_sha256 test", "[esp_app_desc]") +#include "esp_app_desc.h" +#include "unity.h" +#include "unity_fixture.h" + +TEST_GROUP(esp_app_format); + +TEST_SETUP(esp_app_format) +{ +} + +TEST_TEAR_DOWN(esp_app_format) +{ +} + +TEST(esp_app_format, esp_app_get_elf_sha256_test) { const int sha256_hex_len = CONFIG_APP_RETRIEVE_LEN_ELF_SHA; char dst[sha256_hex_len + 2]; @@ -16,17 +29,17 @@ TEST_CASE("esp_ota_get_app_elf_sha256 test", "[esp_app_desc]") size_t len; char ref_sha256[sha256_hex_len + 1]; - const esp_app_desc_t* desc = esp_ota_get_app_description(); + const esp_app_desc_t* desc = esp_app_get_description(); for (int i = 0; i < sizeof(ref_sha256) / 2; ++i) { snprintf(ref_sha256 + 2*i, 3, "%02x", desc->app_elf_sha256[i]); } ref_sha256[sha256_hex_len] = 0; - printf("Ref: %s\n", ref_sha256); + printf("\nRef: %s\n", ref_sha256); memset(dst, fill, sizeof(dst)); len = sizeof(dst); - res = esp_ota_get_app_elf_sha256(dst, len); + res = esp_app_get_elf_sha256(dst, len); printf("%d: %s (%d)\n", len, dst, res); TEST_ASSERT_EQUAL(sha256_hex_len + 1, res); TEST_ASSERT_EQUAL(0, memcmp(dst, ref_sha256, res - 1)); @@ -35,7 +48,7 @@ TEST_CASE("esp_ota_get_app_elf_sha256 test", "[esp_app_desc]") memset(dst, fill, sizeof(dst)); len = 9; - res = esp_ota_get_app_elf_sha256(dst, len); + res = esp_app_get_elf_sha256(dst, len); printf("%d: %s (%d)\n", len, dst, res); TEST_ASSERT_EQUAL(9, res); TEST_ASSERT_EQUAL(0, memcmp(dst, ref_sha256, res - 1)); @@ -44,7 +57,7 @@ TEST_CASE("esp_ota_get_app_elf_sha256 test", "[esp_app_desc]") memset(dst, fill, sizeof(dst)); len = 8; - res = esp_ota_get_app_elf_sha256(dst, len); + res = esp_app_get_elf_sha256(dst, len); printf("%d: %s (%d)\n", len, dst, res); // should output even number of characters plus '\0' TEST_ASSERT_EQUAL(7, res); @@ -53,3 +66,13 @@ TEST_CASE("esp_ota_get_app_elf_sha256 test", "[esp_app_desc]") TEST_ASSERT_EQUAL_HEX(fill, dst[7]); TEST_ASSERT_EQUAL_HEX(fill, dst[8]); } + +TEST_GROUP_RUNNER(esp_app_format) +{ + RUN_TEST_CASE(esp_app_format, esp_app_get_elf_sha256_test) +} + +void app_main(void) +{ + UNITY_MAIN(esp_app_format); +} diff --git a/components/esp_app_format/test_apps/pytest_esp_app_format.py b/components/esp_app_format/test_apps/pytest_esp_app_format.py new file mode 100644 index 0000000000..6c10ccd929 --- /dev/null +++ b/components/esp_app_format/test_apps/pytest_esp_app_format.py @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import pytest +from pytest_embedded import Dut + + +@pytest.mark.supported_targets +@pytest.mark.generic +def test_esp_app_format(dut: Dut) -> None: + dut.expect_unity_test_output() diff --git a/components/esp_app_format/test_apps/sdkconfig.defaults b/components/esp_app_format/test_apps/sdkconfig.defaults new file mode 100644 index 0000000000..a3253f171f --- /dev/null +++ b/components/esp_app_format/test_apps/sdkconfig.defaults @@ -0,0 +1,11 @@ +# General options for additional checks +CONFIG_HEAP_POISONING_COMPREHENSIVE=y +CONFIG_COMPILER_WARN_WRITE_STRINGS=y +CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y +CONFIG_COMPILER_STACK_CHECK_MODE_STRONG=y +CONFIG_COMPILER_STACK_CHECK=y + +# Enable Unity fixture support +CONFIG_UNITY_ENABLE_FIXTURE=y +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n diff --git a/components/esp_https_ota/CMakeLists.txt b/components/esp_https_ota/CMakeLists.txt index cee9eb7620..ef037f8b0f 100644 --- a/components/esp_https_ota/CMakeLists.txt +++ b/components/esp_https_ota/CMakeLists.txt @@ -1,6 +1,6 @@ idf_component_register(SRCS "src/esp_https_ota.c" INCLUDE_DIRS "include" - REQUIRES esp_http_client bootloader_support + REQUIRES esp_http_client bootloader_support esp_app_format PRIV_REQUIRES log app_update) target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") diff --git a/components/esp_https_ota/include/esp_https_ota.h b/components/esp_https_ota/include/esp_https_ota.h index 9dee205c5b..ba13ad619e 100644 --- a/components/esp_https_ota/include/esp_https_ota.h +++ b/components/esp_https_ota/include/esp_https_ota.h @@ -8,6 +8,7 @@ #include #include +#include "esp_app_desc.h" #include #ifdef __cplusplus diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index 620396fcfd..5e7e8e3c2f 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -85,7 +85,7 @@ endif() # need to introduce panic "event" concept to remove this dependency (IDF-2194) idf_component_optional_requires(PRIVATE esp_gdbstub) -idf_component_optional_requires(PRIVATE app_update) +idf_component_optional_requires(PRIVATE esp_app_format) if(CONFIG_PM_ENABLE) idf_component_optional_requires(PRIVATE pm) diff --git a/components/esp_system/panic.c b/components/esp_system/panic.c index 3903796a79..d060f48bfb 100644 --- a/components/esp_system/panic.c +++ b/components/esp_system/panic.c @@ -24,9 +24,9 @@ #include "sdkconfig.h" -#if __has_include("esp_ota_ops.h") -#include "esp_ota_ops.h" -#define HAS_ESP_OTA 1 +#if __has_include("esp_app_desc.h") +#define WITH_ELF_SHA256 +#include "esp_app_desc.h" #endif #if CONFIG_ESP_COREDUMP_ENABLE @@ -312,13 +312,13 @@ void esp_panic_handler(panic_info_t *info) PANIC_INFO_DUMP(info, state); panic_print_str("\r\n"); -#if HAS_ESP_OTA +#ifdef WITH_ELF_SHA256 panic_print_str("\r\nELF file SHA256: "); char sha256_buf[65]; - esp_ota_get_app_elf_sha256(sha256_buf, sizeof(sha256_buf)); + esp_app_get_elf_sha256(sha256_buf, sizeof(sha256_buf)); panic_print_str(sha256_buf); panic_print_str("\r\n"); -#endif //HAS_ESP_OTA +#endif panic_print_str("\r\n"); diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index 6adda6dbd3..bf2254d7fc 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -20,8 +20,6 @@ #include "hal/uart_types.h" #include "hal/uart_ll.h" -#include "esp_system.h" -#include "esp_log.h" #include "esp_heap_caps_init.h" #include "spi_flash_mmap.h" #include "esp_flash_internal.h" @@ -33,10 +31,7 @@ #include "esp_xt_wdt.h" #include "esp_cpu.h" -#if __has_include("esp_ota_ops.h") -#include "esp_ota_ops.h" -#define HAS_ESP_OTA 1 -#endif +#include "esp_partition.h" /***********************************************/ // Headers for other components init functions @@ -44,6 +39,11 @@ #include "esp_coexist_internal.h" #endif +#if __has_include("esp_app_desc.h") +#define WITH_APP_IMAGE_INFO +#include "esp_app_desc.h" +#endif + #if CONFIG_ESP_COREDUMP_ENABLE #include "esp_core_dump.h" #endif @@ -408,10 +408,10 @@ static void start_cpu0_default(void) int cpu_freq = esp_clk_cpu_freq(); ESP_EARLY_LOGI(TAG, "cpu freq: %d Hz", cpu_freq); -#if HAS_ESP_OTA // [refactor-todo] find a better way to handle this. +#ifdef WITH_APP_IMAGE_INFO // Display information about the current running image. if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) { - const esp_app_desc_t *app_desc = esp_ota_get_app_description(); + const esp_app_desc_t *app_desc = esp_app_get_description(); ESP_EARLY_LOGI(TAG, "Application information:"); #ifndef CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR ESP_EARLY_LOGI(TAG, "Project name: %s", app_desc->project_name); @@ -426,11 +426,11 @@ static void start_cpu0_default(void) ESP_EARLY_LOGI(TAG, "Compile time: %s %s", app_desc->date, app_desc->time); #endif char buf[17]; - esp_ota_get_app_elf_sha256(buf, sizeof(buf)); + esp_app_get_elf_sha256(buf, sizeof(buf)); ESP_EARLY_LOGI(TAG, "ELF file SHA256: %s...", buf); ESP_EARLY_LOGI(TAG, "ESP-IDF: %s", app_desc->idf_ver); } -#endif //HAS_ESP_OTA +#endif // Initialize core components and services. do_core_init(); diff --git a/components/espcoredump/CMakeLists.txt b/components/espcoredump/CMakeLists.txt index 7f936a1cb4..6be5b6a29a 100644 --- a/components/espcoredump/CMakeLists.txt +++ b/components/espcoredump/CMakeLists.txt @@ -24,4 +24,8 @@ idf_component_register(SRCS ${srcs} INCLUDE_DIRS ${includes} PRIV_INCLUDE_DIRS ${priv_includes} LDFRAGMENTS linker.lf - PRIV_REQUIRES spi_flash app_update mbedtls esp_rom soc driver) + PRIV_REQUIRES spi_flash bootloader_support mbedtls esp_rom soc esp_system driver) + +if(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF) + target_link_libraries(${COMPONENT_LIB} PRIVATE idf::esp_app_format) +endif() diff --git a/components/espcoredump/src/core_dump_elf.c b/components/espcoredump/src/core_dump_elf.c index 2cd0b53f30..11bde327c7 100644 --- a/components/espcoredump/src/core_dump_elf.c +++ b/components/espcoredump/src/core_dump_elf.c @@ -6,7 +6,6 @@ #include #include "esp_attr.h" #include "esp_partition.h" -#include "esp_ota_ops.h" #include "spi_flash_mmap.h" #include "esp_flash_encrypt.h" #include "sdkconfig.h" @@ -16,6 +15,10 @@ #include "esp_core_dump_port_impl.h" #include "esp_core_dump_common.h" +#ifdef CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF +#include "esp_app_desc.h" +#endif + #define ELF_CLASS ELFCLASS32 #include "elf.h" // for ELF file types @@ -496,7 +499,7 @@ static int elf_write_core_dump_info(core_dump_elf_t *self) ESP_COREDUMP_LOG_PROCESS("================ Processing coredump info ================"); int data_len = (int)sizeof(self->elf_version_info.app_elf_sha256); - data_len = esp_ota_get_app_elf_sha256((char*)self->elf_version_info.app_elf_sha256, (size_t)data_len); + data_len = esp_app_get_elf_sha256((char*)self->elf_version_info.app_elf_sha256, (size_t)data_len); ESP_COREDUMP_LOG_PROCESS("Application SHA256='%s', length=%d.", self->elf_version_info.app_elf_sha256, data_len); self->elf_version_info.version = esp_core_dump_elf_version(); diff --git a/components/spi_flash/sim/Makefile.files b/components/spi_flash/sim/Makefile.files index 8f360aed14..186fce56d3 100644 --- a/components/spi_flash/sim/Makefile.files +++ b/components/spi_flash/sim/Makefile.files @@ -18,6 +18,7 @@ INCLUDE_DIRS := \ app_update/include \ bsd/include \ driver/include \ + esp_app_format/include \ esp_timer/include \ freertos/include \ log/include \ @@ -34,7 +35,7 @@ INCLUDE_DIRS := \ xtensa/include \ xtensa/esp32/include \ soc/esp32/include \ - heap/include \ + heap/include \ soc/include \ esp32/include \ esp_timer/include \ diff --git a/components/spi_flash/sim/stubs/Makefile.files b/components/spi_flash/sim/stubs/Makefile.files index dd6591666d..b2f789c39b 100644 --- a/components/spi_flash/sim/stubs/Makefile.files +++ b/components/spi_flash/sim/stubs/Makefile.files @@ -14,6 +14,7 @@ INCLUDE_DIRS := \ app_update/include \ bsd/include \ driver/include \ + esp_app_format/include \ esp_timer/include \ freertos/include \ log/include \ @@ -26,7 +27,7 @@ INCLUDE_DIRS := \ esp_hw_support/include/soc \ esp_system/include \ soc/esp32/include \ - heap/include \ + heap/include \ soc/include \ xtensa/include \ xtensa/esp32/include \ diff --git a/components/spi_flash/sim/stubs/esp_app_format/include/esp_app_desc.h b/components/spi_flash/sim/stubs/esp_app_format/include/esp_app_desc.h new file mode 100644 index 0000000000..70c698c185 --- /dev/null +++ b/components/spi_flash/sim/stubs/esp_app_format/include/esp_app_desc.h @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + * + * This is a STUB FILE used when compiling ESP-IDF to run tests on the host system. + * The source file used normally for ESP-IDF has the same name but is located elsewhere. + */ + +#pragma once + +#include +#include +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define ESP_APP_DESC_MAGIC_WORD (0xABCD5432) /*!< The magic word for the esp_app_desc structure that is in DROM. */ + +/** + * @brief Description about application. + */ +typedef struct { + uint32_t magic_word; /*!< Magic word ESP_APP_DESC_MAGIC_WORD */ + uint32_t secure_version; /*!< Secure version */ + uint32_t reserv1[2]; /*!< reserv1 */ + char version[32]; /*!< Application version */ + char project_name[32]; /*!< Project name */ + char time[16]; /*!< Compile time */ + char date[16]; /*!< Compile date*/ + char idf_ver[32]; /*!< Version IDF */ + uint8_t app_elf_sha256[32]; /*!< sha256 of elf file */ + uint32_t reserv2[20]; /*!< reserv2 */ +} esp_app_desc_t; + +/** @cond */ +_Static_assert(sizeof(esp_app_desc_t) == 256, "esp_app_desc_t should be 256 bytes"); +/** @endcond */ + +#ifdef __cplusplus +} +#endif diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 56d0cb7f7e..6ef69491fc 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -86,6 +86,7 @@ INPUT = \ $(PROJECT_PATH)/components/esp_adc/include/esp_adc/adc_cali.h \ $(PROJECT_PATH)/components/esp_adc/include/esp_adc/adc_continuous.h \ $(PROJECT_PATH)/components/esp_adc/include/esp_adc/adc_oneshot.h \ + $(PROJECT_PATH)/components/esp_app_format/include/esp_app_desc.h \ $(PROJECT_PATH)/components/esp_common/include/esp_check.h \ $(PROJECT_PATH)/components/esp_common/include/esp_err.h \ $(PROJECT_PATH)/components/esp_common/include/esp_idf_version.h \ diff --git a/docs/en/api-reference/system/misc_system_api.rst b/docs/en/api-reference/system/misc_system_api.rst index 25c5cd78c4..9a53942c0e 100644 --- a/docs/en/api-reference/system/misc_system_api.rst +++ b/docs/en/api-reference/system/misc_system_api.rst @@ -211,7 +211,7 @@ The application version is stored in :cpp:class:`esp_app_desc_t` structure. It i To set the version in your project manually, you need to set the ``PROJECT_VER`` variable in the ``CMakeLists.txt`` of your project. In application ``CMakeLists.txt``, put ``set(PROJECT_VER "0.1.0.1")`` before including ``project.cmake``. -If the :ref:`CONFIG_APP_PROJECT_VER_FROM_CONFIG` option is set, the value of :ref:`CONFIG_APP_PROJECT_VER` will be used. Otherwise, if the ``PROJECT_VER`` variable is not set in the project, it will be retrieved either from the ``$(PROJECT_PATH)/version.txt`` file (if present) or using git command ``git describe``. If neither is available, ``PROJECT_VER`` will be set to "1". Application can make use of this by calling :cpp:func:`esp_ota_get_app_description` or :cpp:func:`esp_ota_get_partition_description` functions. +If the :ref:`CONFIG_APP_PROJECT_VER_FROM_CONFIG` option is set, the value of :ref:`CONFIG_APP_PROJECT_VER` will be used. Otherwise, if the ``PROJECT_VER`` variable is not set in the project, it will be retrieved either from the ``$(PROJECT_PATH)/version.txt`` file (if present) or using git command ``git describe``. If neither is available, ``PROJECT_VER`` will be set to "1". Application can make use of this by calling :cpp:func:`esp_app_get_description` or :cpp:func:`esp_ota_get_partition_description` functions. API Reference ------------- @@ -221,3 +221,4 @@ API Reference .. include-build-file:: inc/esp_mac.inc .. include-build-file:: inc/esp_chip_info.inc .. include-build-file:: inc/esp_cpu.inc +.. include-build-file:: inc/esp_app_desc.inc diff --git a/docs/en/migration-guides/release-5.x/system.rst b/docs/en/migration-guides/release-5.x/system.rst index 00d39e5662..81534abbc8 100644 --- a/docs/en/migration-guides/release-5.x/system.rst +++ b/docs/en/migration-guides/release-5.x/system.rst @@ -149,3 +149,15 @@ The file ``portmacro_deprecated.h`` which was added to maintain backward compati - ``vPortCPUAcquireMutex()`` is removed. Users should use the ``spinlock_acquire()`` function instead. - ``vPortCPUAcquireMutexTimeout()`` is removed. Users should use the ``spinlock_acquire()`` function instead. - ``vPortCPUReleaseMutex()`` is removed. Users should use the ``spinlock_release()`` function instead. + +App Update +---------- + +- The functions :cpp:func:`esp_ota_get_app_description` and :cpp:func:`esp_ota_get_app_elf_sha256` have been termed as deprecated. Please use the alternative functions :cpp:func:`esp_app_get_description` and :cpp:func:`esp_app_get_elf_sha256` respectively. These functions have now been moved to a new component :component:`esp_app_format`. (Refer header file :component_file:`esp_app_desc.h `) + +Bootloader Support +------------------ + +- The :cpp:type:`esp_app_desc_t` structure, which used to be declared in :component_file:`esp_app_format.h `, is now declared in :component_file:`esp_app_desc.h `. + +- The function :cpp:func:`bootloader_common_get_partition_description` has now been made private. Please use the alternative function :cpp:func:`esp_ota_get_partition_description`. Note that this function takes :cpp:type:`esp_partition_t` as its first argument instead of :cpp:type:`esp_partition_pos_t`. diff --git a/docs/zh_CN/api-reference/system/misc_system_api.rst b/docs/zh_CN/api-reference/system/misc_system_api.rst index 736025bab3..223f29e32b 100644 --- a/docs/zh_CN/api-reference/system/misc_system_api.rst +++ b/docs/zh_CN/api-reference/system/misc_system_api.rst @@ -211,7 +211,7 @@ SDK 版本 若需手动设置版本,需要在项目的 ``CMakeLists.txt`` 文件中设置 ``PROJECT_VER`` 变量,即在 ``CMakeLists.txt`` 文件中,在包含 ``project.cmake`` 之前添加 ``set(PROJECT_VER "0.1.0.1")``。 -如果设置了 :ref:`CONFIG_APP_PROJECT_VER_FROM_CONFIG` 选项,则将使用 :ref:`CONFIG_APP_PROJECT_VER` 的值。否则,如果在项目中未设置 ``PROJECT_VER`` 变量,则该变量将从 ``$(PROJECT_PATH)/version.txt`` 文件(若有)中检索,或使用 git 命令 ``git describe`` 检索。如果两者都不可用,则 ``PROJECT_VER`` 将被设置为 “1”。应用程序可通过调用 :cpp:func:`esp_ota_get_app_description` 或 :cpp:func:`esp_ota_get_partition_description` 函数来获取应用程序的版本信息。 +如果设置了 :ref:`CONFIG_APP_PROJECT_VER_FROM_CONFIG` 选项,则将使用 :ref:`CONFIG_APP_PROJECT_VER` 的值。否则,如果在项目中未设置 ``PROJECT_VER`` 变量,则该变量将从 ``$(PROJECT_PATH)/version.txt`` 文件(若有)中检索,或使用 git 命令 ``git describe`` 检索。如果两者都不可用,则 ``PROJECT_VER`` 将被设置为 “1”。应用程序可通过调用 :cpp:func:`esp_app_get_description` 或 :cpp:func:`esp_ota_get_partition_description` 函数来获取应用程序的版本信息。 API 参考 ------------- @@ -221,3 +221,4 @@ API 参考 .. include-build-file:: inc/esp_mac.inc .. include-build-file:: inc/esp_chip_info.inc .. include-build-file:: inc/esp_cpu.inc +.. include-build-file:: inc/esp_app_desc.inc diff --git a/examples/system/ota/native_ota_example/main/native_ota_example.c b/examples/system/ota/native_ota_example/main/native_ota_example.c index ebebbabd99..287405436f 100644 --- a/examples/system/ota/native_ota_example/main/native_ota_example.c +++ b/examples/system/ota/native_ota_example/main/native_ota_example.c @@ -13,6 +13,7 @@ #include "esp_event.h" #include "esp_log.h" #include "esp_ota_ops.h" +#include "esp_app_format.h" #include "esp_http_client.h" #include "esp_flash_partitions.h" #include "esp_partition.h" diff --git a/tools/test_apps/system/g1_components/CMakeLists.txt b/tools/test_apps/system/g1_components/CMakeLists.txt index 7c69876019..0380cdd395 100644 --- a/tools/test_apps/system/g1_components/CMakeLists.txt +++ b/tools/test_apps/system/g1_components/CMakeLists.txt @@ -21,8 +21,8 @@ set(extra_allowed_components # These components are currently included into "G1" build, but shouldn't. # After removing the extra dependencies, remove the components from this list as well. set(extra_components_which_shouldnt_be_included - # app_update gets added because of bootloader_support, spi_flash, espcoredump. - # bootloader_support, spi_flash, espcoredump should be removed from dependencies; + # app_update gets added because of spi_flash. + # spi_flash should be removed from dependencies; app_update # of G1 components, bootloader is only included from spi_flash # [refactor-todo]: see if this dependency from spi_flash can be made weak @@ -36,6 +36,8 @@ set(extra_components_which_shouldnt_be_included # [refactor-todo]: driver is a dependency of esp_pm, esp_timer, spi_flash, vfs, esp_wifi, ${IDF_TARGET} # all of these should be removed from G1 except for spi_flash. driver + # esp_app_format is dependency of bootloader_support, app_update + esp_app_format # [refactor-todo]: efuse is a dependency of esp_hw_support, esp_system. # Figure out if these components can exist without a dependency on efuse. # If not, see if esp_hw_support can provide minimal efuse component replacement in G1 build.