diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index 14f32db48a2..0cbcd47e909 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -80,6 +80,7 @@ /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_bootloader_format/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities /components/esp_coex/ @esp-idf-codeowners/wifi @esp-idf-codeowners/bluetooth @esp-idf-codeowners/ieee802154 /components/esp_common/ @esp-idf-codeowners/system /components/esp_eth/ @esp-idf-codeowners/network diff --git a/components/app_update/CMakeLists.txt b/components/app_update/CMakeLists.txt index 5d9692a73de..3653938e807 100644 --- a/components/app_update/CMakeLists.txt +++ b/components/app_update/CMakeLists.txt @@ -1,6 +1,6 @@ idf_component_register(SRCS "esp_ota_ops.c" "esp_ota_app_desc.c" INCLUDE_DIRS "include" - REQUIRES partition_table bootloader_support esp_app_format esp_partition + REQUIRES partition_table bootloader_support esp_app_format esp_bootloader_format esp_partition PRIV_REQUIRES esptool_py efuse spi_flash) if(NOT BOOTLOADER_BUILD) diff --git a/components/app_update/esp_ota_ops.c b/components/app_update/esp_ota_ops.c index 6b80abab30d..94bcc430fe8 100644 --- a/components/app_update/esp_ota_ops.c +++ b/components/app_update/esp_ota_ops.c @@ -28,6 +28,8 @@ #include "esp_system.h" #include "esp_efuse.h" #include "esp_attr.h" +#include "esp_bootloader_desc.h" +#include "esp_flash.h" #if CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/secure_boot.h" @@ -628,6 +630,32 @@ const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t * } +esp_err_t esp_ota_get_bootloader_description(const esp_partition_t *bootloader_partition, esp_bootloader_desc_t *desc) +{ + if (desc == NULL) { + return ESP_ERR_INVALID_ARG; + } + esp_partition_t partition = { 0 }; + if (bootloader_partition == NULL) { + partition.flash_chip = esp_flash_default_chip; + partition.encrypted = esp_flash_encryption_enabled(); + partition.address = CONFIG_BOOTLOADER_OFFSET_IN_FLASH; + partition.size = CONFIG_PARTITION_TABLE_OFFSET - CONFIG_BOOTLOADER_OFFSET_IN_FLASH; + } else { + memcpy(&partition, bootloader_partition, sizeof(partition)); + } + esp_err_t err = esp_partition_read(&partition, sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t), desc, sizeof(esp_bootloader_desc_t)); + if (err != ESP_OK) { + return err; + } + + if (desc->magic_byte != ESP_BOOTLOADER_DESC_MAGIC_BYTE) { + return ESP_ERR_NOT_FOUND; + } + + return ESP_OK; +} + esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc) { if (partition == NULL || app_desc == NULL) { diff --git a/components/app_update/include/esp_ota_ops.h b/components/app_update/include/esp_ota_ops.h index 1364b543a8b..362fa1d22b4 100644 --- a/components/app_update/include/esp_ota_ops.h +++ b/components/app_update/include/esp_ota_ops.h @@ -13,6 +13,7 @@ #include "esp_err.h" #include "esp_partition.h" #include "esp_app_desc.h" +#include "esp_bootloader_desc.h" #include "esp_flash_partitions.h" #include "soc/soc_caps.h" @@ -251,6 +252,23 @@ const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t * */ esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc); +/** + * @brief Returns the description structure of the bootloader. + * + * @param[in] bootloader_partition Pointer to bootloader partition. + * If NULL, then the current bootloader is used (the default location). + * offset = CONFIG_BOOTLOADER_OFFSET_IN_FLASH, + * size = CONFIG_PARTITION_TABLE_OFFSET - CONFIG_BOOTLOADER_OFFSET_IN_FLASH, + * @param[out] desc Structure of info about bootloader. + * @return + * - ESP_OK Successful. + * - ESP_ERR_NOT_FOUND Description structure is not found in the bootloader image. Magic byte is incorrect. + * - ESP_ERR_INVALID_ARG Arguments is NULL. + * - ESP_ERR_INVALID_SIZE Read would go out of bounds of the partition. + * - or one of error codes from lower-level flash driver. + */ +esp_err_t esp_ota_get_bootloader_description(const esp_partition_t *bootloader_partition, esp_bootloader_desc_t *desc); + /** * @brief Returns number of ota partitions provided in partition table. * diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index 8049f3477b5..8967a137996 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -1,5 +1,7 @@ menu "Bootloader config" + orsource "../esp_bootloader_format/Kconfig.bootloader" + config BOOTLOADER_OFFSET_IN_FLASH hex default 0x1000 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 diff --git a/components/bootloader/subproject/main/ld/esp32/bootloader.ld b/components/bootloader/subproject/main/ld/esp32/bootloader.ld index 6516fc3c278..380ecc11638 100644 --- a/components/bootloader/subproject/main/ld/esp32/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32/bootloader.ld @@ -109,9 +109,14 @@ SECTIONS _bss_end = ABSOLUTE(.); } >dram_seg - .dram0.data : + .dram0.bootdesc : ALIGN(0x10) { _data_start = ABSOLUTE(.); + *(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */ + } > dram_seg + + .dram0.data : ALIGN(0x10) + { *(.data) *(.data.*) *(.gnu.linkonce.d.*) diff --git a/components/bootloader/subproject/main/ld/esp32c2/bootloader.ld b/components/bootloader/subproject/main/ld/esp32c2/bootloader.ld index e2502dee522..bf503cadada 100644 --- a/components/bootloader/subproject/main/ld/esp32c2/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32c2/bootloader.ld @@ -131,9 +131,14 @@ SECTIONS _bss_end = ABSOLUTE(.); } > dram_seg - .dram0.data : + .dram0.bootdesc : ALIGN(0x10) { _data_start = ABSOLUTE(.); + *(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */ + } > dram_seg + + .dram0.data : + { *(.data) *(.data.*) *(.gnu.linkonce.d.*) diff --git a/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld b/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld index 68e3a1c38f0..1be543618bc 100644 --- a/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld @@ -131,9 +131,14 @@ SECTIONS _bss_end = ABSOLUTE(.); } > dram_seg - .dram0.data : + .dram0.bootdesc : ALIGN(0x10) { _data_start = ABSOLUTE(.); + *(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */ + } > dram_seg + + .dram0.data : + { *(.data) *(.data.*) *(.gnu.linkonce.d.*) diff --git a/components/bootloader/subproject/main/ld/esp32c6/bootloader.ld b/components/bootloader/subproject/main/ld/esp32c6/bootloader.ld index 412214031f4..d15b5f4803e 100644 --- a/components/bootloader/subproject/main/ld/esp32c6/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32c6/bootloader.ld @@ -128,9 +128,14 @@ SECTIONS _bss_end = ABSOLUTE(.); } > dram_seg - .dram0.data : + .dram0.bootdesc : ALIGN(0x10) { _data_start = ABSOLUTE(.); + *(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */ + } > dram_seg + + .dram0.data : + { *(.data) *(.data.*) *(.gnu.linkonce.d.*) diff --git a/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld b/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld index b40c4ed46ab..e36c24c237d 100644 --- a/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld @@ -129,6 +129,12 @@ SECTIONS _bss_end = ABSOLUTE(.); } > dram_seg + .dram0.bootdesc : ALIGN(0x10) + { + _data_start = ABSOLUTE(.); + *(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */ + } > dram_seg + .dram0.data : { _data_start = ABSOLUTE(.); diff --git a/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld b/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld index e3e8edab165..5f0c65b3a6b 100644 --- a/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld @@ -98,9 +98,14 @@ SECTIONS _bss_end = ABSOLUTE(.); } >dram_seg - .dram0.data : + .dram0.bootdesc : ALIGN(0x10) { _data_start = ABSOLUTE(.); + *(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */ + } > dram_seg + + .dram0.data : + { *(.data) *(.data.*) *(.gnu.linkonce.d.*) diff --git a/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld b/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld index 9f6e17b2b9d..ecca26afc70 100644 --- a/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld @@ -132,9 +132,14 @@ SECTIONS _bss_end = ABSOLUTE(.); } > dram_seg - .dram0.data : + .dram0.bootdesc : ALIGN(0x10) { _data_start = ABSOLUTE(.); + *(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */ + } > dram_seg + + .dram0.data : + { *(.data) *(.data.*) *(.gnu.linkonce.d.*) diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt index 197e46b0528..24ced5ff444 100644 --- a/components/bootloader_support/CMakeLists.txt +++ b/components/bootloader_support/CMakeLists.txt @@ -29,7 +29,7 @@ endif() if(BOOTLOADER_BUILD OR CONFIG_APP_BUILD_TYPE_RAM) set(include_dirs "include" "bootloader_flash/include" "private_include") - set(priv_requires micro-ecc spi_flash efuse esp_app_format) + set(priv_requires micro-ecc spi_flash efuse esp_bootloader_format esp_app_format) list(APPEND srcs "src/bootloader_init.c" "src/bootloader_clock_loader.c" @@ -50,7 +50,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 heap esp_app_format) + set(priv_requires spi_flash mbedtls efuse heap esp_bootloader_format esp_app_format) endif() if(BOOTLOADER_BUILD) @@ -170,4 +170,7 @@ endif() if(BOOTLOADER_BUILD) target_link_libraries(${COMPONENT_LIB} INTERFACE "-u abort") + # esp_bootloader_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_bootloader_desc") endif() diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index 44d2d90e693..1dd9b3958de 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -19,6 +19,7 @@ #include "soc/rtc.h" #include "hal/wdt_hal.h" #include "hal/efuse_hal.h" +#include "esp_bootloader_desc.h" static const char *TAG = "boot"; @@ -92,10 +93,13 @@ void bootloader_enable_random(void) void bootloader_print_banner(void) { - ESP_EARLY_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER); -#ifndef CONFIG_APP_REPRODUCIBLE_BUILD - ESP_EARLY_LOGI(TAG, "compile time " __DATE__ " " __TIME__); + if (CONFIG_BOOTLOADER_LOG_LEVEL >= ESP_LOG_INFO) { + const esp_bootloader_desc_t *desc = esp_bootloader_get_description(); + ESP_EARLY_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", desc->idf_ver); +#ifdef CONFIG_BOOTLOADER_COMPILE_TIME_DATE + ESP_EARLY_LOGI(TAG, "compile time %s", desc->date_time); #endif + } #if CONFIG_FREERTOS_UNICORE #if (SOC_CPU_CORES_NUM > 1) diff --git a/components/esp_app_format/CMakeLists.txt b/components/esp_app_format/CMakeLists.txt index 5a0d7460bb6..9e93c2aa498 100644 --- a/components/esp_app_format/CMakeLists.txt +++ b/components/esp_app_format/CMakeLists.txt @@ -1,26 +1,31 @@ -idf_component_register(SRCS "esp_app_desc.c" +if(NOT BOOTLOADER_BUILD) + set(src "esp_app_desc.c") +else() + set(src "") +endif() +idf_component_register(SRCS ${src} 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) + # 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") -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() + 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}") + # 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}\"") + set_source_files_properties( + SOURCE "esp_app_desc.c" + PROPERTIES COMPILE_DEFINITIONS + "PROJECT_VER=\"${PROJECT_VER_CUT}\"; PROJECT_NAME=\"${PROJECT_NAME_CUT}\"") +endif() diff --git a/components/esp_app_format/Kconfig.projbuild b/components/esp_app_format/Kconfig.projbuild index 6121f635097..8471162c6dc 100644 --- a/components/esp_app_format/Kconfig.projbuild +++ b/components/esp_app_format/Kconfig.projbuild @@ -3,6 +3,7 @@ menu "Application manager" config APP_COMPILE_TIME_DATE bool "Use time/date stamp for app" default y + depends on !APP_REPRODUCIBLE_BUILD help If set, then the app will be built with the current time/date stamp. It is stored in the app description structure. If not set, time/date stamp will be excluded from app image. This can be useful for getting the diff --git a/components/esp_app_format/esp_app_desc.c b/components/esp_app_format/esp_app_desc.c index edb22d08936..4ce5726448b 100644 --- a/components/esp_app_format/esp_app_desc.c +++ b/components/esp_app_format/esp_app_desc.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,7 +33,7 @@ const __attribute__((weak)) __attribute__((section(".rodata_desc"))) esp_app_de .secure_version = 0, #endif -#if defined(CONFIG_APP_COMPILE_TIME_DATE) && !defined(CONFIG_APP_REPRODUCIBLE_BUILD) +#ifdef CONFIG_APP_COMPILE_TIME_DATE .time = __TIME__, .date = __DATE__, #else diff --git a/components/esp_bootloader_format/.build-test-rules.yml b/components/esp_bootloader_format/.build-test-rules.yml new file mode 100644 index 00000000000..58ae08698aa --- /dev/null +++ b/components/esp_bootloader_format/.build-test-rules.yml @@ -0,0 +1,6 @@ +# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps + +components/esp_bootloader_format/test_apps: + disable: + - if: IDF_TARGET != "esp32" + reason: It is enough to test it only for one target diff --git a/components/esp_bootloader_format/CMakeLists.txt b/components/esp_bootloader_format/CMakeLists.txt new file mode 100644 index 00000000000..e0b8873cdbd --- /dev/null +++ b/components/esp_bootloader_format/CMakeLists.txt @@ -0,0 +1,11 @@ +idf_component_register(SRCS "esp_bootloader_desc.c" + INCLUDE_DIRS "include") + +if(BOOTLOADER_BUILD) + # esp_bootloader_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_bootloader_desc") + + idf_build_get_property(project_name PROJECT_NAME) + message(STATUS "Bootloader project name: \"${project_name}\" version: ${CONFIG_BOOTLOADER_PROJECT_VER}") +endif() diff --git a/components/esp_bootloader_format/Kconfig.bootloader b/components/esp_bootloader_format/Kconfig.bootloader new file mode 100644 index 00000000000..f4e2d6971db --- /dev/null +++ b/components/esp_bootloader_format/Kconfig.bootloader @@ -0,0 +1,21 @@ +menu "Bootloader manager" + + config BOOTLOADER_COMPILE_TIME_DATE + bool "Use time/date stamp for bootloader" + default y + depends on !APP_REPRODUCIBLE_BUILD + help + If set, then the bootloader will be built with the current time/date stamp. + It is stored in the bootloader description + structure. If not set, time/date stamp will be excluded from bootloader image. + This can be useful for getting the + same binary image files made from the same source, but at different times. + + config BOOTLOADER_PROJECT_VER + int "Project version" + default 1 + range 0 4294967295 + help + Project version. It is placed in "version" field of the esp_bootloader_desc structure. + The type of this field is "uint32_t". +endmenu # "Bootloader manager" diff --git a/components/esp_bootloader_format/esp_bootloader_desc.c b/components/esp_bootloader_format/esp_bootloader_desc.c new file mode 100644 index 00000000000..d25d984c386 --- /dev/null +++ b/components/esp_bootloader_format/esp_bootloader_desc.c @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "esp_bootloader_desc.h" +#include "sdkconfig.h" + + +// Bootloader version info +const __attribute__((weak)) __attribute__((section(".data_bootloader_desc"))) esp_bootloader_desc_t esp_bootloader_desc = { + .magic_byte = ESP_BOOTLOADER_DESC_MAGIC_BYTE, + .reserved = { 0 }, + .version = CONFIG_BOOTLOADER_PROJECT_VER, + .idf_ver = IDF_VER, +#ifdef CONFIG_BOOTLOADER_COMPILE_TIME_DATE + .date_time = __DATE__ " " __TIME__, +#else + .date_time = "", +#endif + .reserved2 = { 0 }, +}; + +_Static_assert(sizeof(IDF_VER) <= sizeof(esp_bootloader_desc.idf_ver), "IDF_VER is longer than idf_ver field in structure"); + +const esp_bootloader_desc_t *esp_bootloader_get_description(void) +{ + return &esp_bootloader_desc; +} diff --git a/components/esp_bootloader_format/include/esp_bootloader_desc.h b/components/esp_bootloader_format/include/esp_bootloader_desc.h new file mode 100644 index 00000000000..868fb9c7354 --- /dev/null +++ b/components/esp_bootloader_format/include/esp_bootloader_desc.h @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include "esp_err.h" +#include "esp_assert.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define ESP_BOOTLOADER_DESC_MAGIC_BYTE (80) /*!< The magic byte for the esp_bootloader_desc structure that is in DRAM. */ + +/** + * @brief Bootloader description structure + */ +typedef struct { + uint8_t magic_byte; /*!< Magic byte ESP_BOOTLOADER_DESC_MAGIC_BYTE */ + uint8_t reserved[3]; /*!< reserved for IDF */ + uint32_t version; /*!< Bootloader version */ + char idf_ver[32]; /*!< Version IDF */ + char date_time[24]; /*!< Compile date and time*/ + uint8_t reserved2[16]; /*!< reserved for IDF */ +} esp_bootloader_desc_t; + +/** @cond */ +ESP_STATIC_ASSERT(sizeof(esp_bootloader_desc_t) == 80, "esp_bootloader_desc_t should be 80 bytes"); +/** @endcond */ + +/** + * @brief Return esp_bootloader_desc structure. + * + * Intended for use by the bootloader. + * @return Pointer to esp_bootloader_desc structure. + */ +const esp_bootloader_desc_t *esp_bootloader_get_description(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_bootloader_format/test_apps/CMakeLists.txt b/components/esp_bootloader_format/test_apps/CMakeLists.txt new file mode 100644 index 00000000000..72305349c8c --- /dev/null +++ b/components/esp_bootloader_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_bootloader_format_test) diff --git a/components/esp_bootloader_format/test_apps/README.md b/components/esp_bootloader_format/test_apps/README.md new file mode 100644 index 00000000000..f708a1985a3 --- /dev/null +++ b/components/esp_bootloader_format/test_apps/README.md @@ -0,0 +1,2 @@ +| Supported Targets | ESP32 | +| ----------------- | ----- | diff --git a/components/esp_bootloader_format/test_apps/main/CMakeLists.txt b/components/esp_bootloader_format/test_apps/main/CMakeLists.txt new file mode 100644 index 00000000000..f7e62586b60 --- /dev/null +++ b/components/esp_bootloader_format/test_apps/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "test_bootloader_desc.c" + PRIV_INCLUDE_DIRS . + PRIV_REQUIRES esp_bootloader_format app_update unity) diff --git a/components/esp_bootloader_format/test_apps/main/test_bootloader_desc.c b/components/esp_bootloader_format/test_apps/main/test_bootloader_desc.c new file mode 100644 index 00000000000..80ea3348932 --- /dev/null +++ b/components/esp_bootloader_format/test_apps/main/test_bootloader_desc.c @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#include "esp_ota_ops.h" +#include "esp_bootloader_desc.h" +#include "unity.h" +#include "unity_fixture.h" +#include "unity_internals.h" + +TEST_GROUP(esp_bootloader_format); + +TEST_SETUP(esp_bootloader_format) +{ +} + +TEST_TEAR_DOWN(esp_bootloader_format) +{ +} + +TEST(esp_bootloader_format, esp_ota_get_bootloader_description) +{ + esp_bootloader_desc_t desc; + printf("\n"); + TEST_ESP_OK(esp_ota_get_bootloader_description(NULL, &desc)); + TEST_ASSERT_EQUAL(desc.magic_byte, ESP_BOOTLOADER_DESC_MAGIC_BYTE); + TEST_ASSERT_EQUAL(desc.version, CONFIG_BOOTLOADER_PROJECT_VER); + printf("\tESP-IDF version from 2nd stage bootloader: %s\n", desc.idf_ver); + printf("\tESP-IDF version from app: %s\n", IDF_VER); + TEST_ASSERT_EQUAL(0, memcmp(desc.idf_ver, IDF_VER, sizeof(IDF_VER))); +} + +TEST_GROUP_RUNNER(esp_bootloader_format) +{ + RUN_TEST_CASE(esp_bootloader_format, esp_ota_get_bootloader_description) +} + +void app_main(void) +{ + UNITY_MAIN(esp_bootloader_format); +} diff --git a/components/esp_bootloader_format/test_apps/pytest_esp_bootloader_format.py b/components/esp_bootloader_format/test_apps/pytest_esp_bootloader_format.py new file mode 100644 index 00000000000..76879159c73 --- /dev/null +++ b/components/esp_bootloader_format/test_apps/pytest_esp_bootloader_format.py @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32 +@pytest.mark.generic +def test_esp_bootloader_format(dut: Dut) -> None: + dut.expect_unity_test_output() diff --git a/components/esp_bootloader_format/test_apps/sdkconfig.defaults b/components/esp_bootloader_format/test_apps/sdkconfig.defaults new file mode 100644 index 00000000000..3f6029c64e7 --- /dev/null +++ b/components/esp_bootloader_format/test_apps/sdkconfig.defaults @@ -0,0 +1,10 @@ +# General options for additional checks +CONFIG_HEAP_POISONING_COMPREHENSIVE=y +CONFIG_COMPILER_WARN_WRITE_STRINGS=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/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index f7a3d0c5f64..33d0171c91f 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -121,6 +121,7 @@ INPUT = \ $(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_bootloader_format/include/esp_bootloader_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-guides/reproducible-builds.rst b/docs/en/api-guides/reproducible-builds.rst index e1744e96efa..4c2a192c4ff 100644 --- a/docs/en/api-guides/reproducible-builds.rst +++ b/docs/en/api-guides/reproducible-builds.rst @@ -45,7 +45,7 @@ ESP-IDF achieves reproducible builds using the following measures: - Path to the build directory is replaced with ``/IDF_BUILD`` - Paths to components are replaced with ``/COMPONENT_NAME_DIR`` (where ``NAME`` is the name of the component) -- Build date and time are not included into the :ref:`application metadata structure` if :ref:`CONFIG_APP_REPRODUCIBLE_BUILD` is enabled. +- Build date and time are not included into the :ref:`application metadata structure` and :ref:`bootloader metadata structure` if :ref:`CONFIG_APP_REPRODUCIBLE_BUILD` is enabled. - ESP-IDF build system ensures that source file lists, component lists and other sequences are sorted before passing them to CMake. Various other parts of the build system, such as the linker script generator also perform sorting to ensure that same output is produced regardless of the environment. Reproducible builds and debugging diff --git a/docs/en/api-reference/system/app_image_format.rst b/docs/en/api-reference/system/app_image_format.rst index e2c72515bff..1616410ddf3 100644 --- a/docs/en/api-reference/system/app_image_format.rst +++ b/docs/en/api-reference/system/app_image_format.rst @@ -1,6 +1,11 @@ App Image Format ================ +.. _app-image-structures: + +Application Image Structures +---------------------------- + An application image consists of the following structures: 1. The :cpp:type:`esp_image_header_t` structure describes the mode of SPI flash and the count of memory segments. @@ -77,7 +82,7 @@ You can also see the information on segments in the ESP-IDF logs while your appl 6. If the option :ref:`CONFIG_SECURE_SIGNED_APPS_SCHEME` is set to RSA or ECDSA (V2) then the application image will have an additional signature sector of 4K size. For more details on the format of this signature sector, please refer to :ref:`signature-block-format`. -.. _app_image_format_application_description: +.. _app-image-format-application-description: Application Description ----------------------- diff --git a/docs/en/api-reference/system/bootloader_image_format.rst b/docs/en/api-reference/system/bootloader_image_format.rst new file mode 100644 index 00000000000..3bbd6836de3 --- /dev/null +++ b/docs/en/api-reference/system/bootloader_image_format.rst @@ -0,0 +1,76 @@ +Bootloader Image Format +======================= + +The bootloader image consists of the same structures as the application image, see :ref:`Application Image Structures `. The only difference is in the :ref:`Bootloader Description ` structure. + +To get information about the bootloader image, please run the following command: + +.. code-block:: + + esptool.py --chip {IDF_TARGET_PATH_NAME} image_info build/bootloader/bootloader.bin --version 2 + +.. code-block:: + + File size: 26576 (bytes) + + ESP32 image header + ================== + Image version: 1 + Entry point: 0x40080658 + Segments: 4 + Flash size: 2MB + Flash freq: 40m + Flash mode: DIO + + ESP32 extended image header + =========================== + WP pin: 0xee + Flash pins drive settings: clk_drv: 0x0, q_drv: 0x0, d_drv: 0x0, cs0_drv: 0x0, hd_drv: 0x0, wp_drv: 0x0 + Chip ID: 0 + Minimal chip revision: v0.0, (legacy min_rev = 0) + Maximal chip revision: v3.99 + + Segments information + ==================== + Segment Length Load addr File offs Memory types + ------- ------- ---------- ---------- ------------ + 1 0x01bb0 0x3fff0030 0x00000018 BYTE_ACCESSIBLE, DRAM, DIRAM_DRAM + 2 0x03c90 0x40078000 0x00001bd0 CACHE_APP + 3 0x00004 0x40080400 0x00005868 IRAM + 4 0x00f2c 0x40080404 0x00005874 IRAM + + ESP32 image footer + ================== + Checksum: 0x65 (valid) + Validation hash: 6f31a7f8512f26f6bce7c3b270f93bf6cf1ee4602c322998ca8ce27433527e92 (valid) + + Bootloader information + ====================== + Bootloader version: 1 + ESP-IDF: v5.1-dev-4304-gcb51a3b-dirty + Compile time: Mar 30 2023 19:14:17 + +.. _image-format-bootloader-description: + +Bootloader Description +---------------------- + +The ``DRAM0`` segment of the bootloader binary starts with the :cpp:type:`esp_bootloader_desc_t` structure which carries specific fields describing the bootloader. This structure is located at a fixed offset = sizeof(:cpp:type:`esp_image_header_t`) + sizeof(:cpp:type:`esp_image_segment_header_t`). + + * ``magic_byte`` - the magic byte for the esp_bootloader_desc structure. + * ``reserved`` - reserved for the future IDF use. + * ``version`` - bootloader version, see :ref:`CONFIG_BOOTLOADER_PROJECT_VER` + * ``idf_ver`` - ESP-IDF version. ``*`` + * ``date`` and ``time`` - compile date and time. + * ``reserved2`` - reserved for the future IDF use. + +``*`` - The maximum length is 32 characters, including null-termination character. + +To get the :cpp:type:`esp_bootloader_desc_t` structure from the running bootloader, use :cpp:func:`esp_bootloader_get_description`. + +To get the :cpp:type:`esp_bootloader_desc_t` structure from a running application, use :cpp:func:`esp_ota_get_bootloader_description`. + +API Reference +------------- + +.. include-build-file:: inc/esp_bootloader_desc.inc diff --git a/docs/en/api-reference/system/index.rst b/docs/en/api-reference/system/index.rst index 9fadf2b1a70..1c4f936b366 100644 --- a/docs/en/api-reference/system/index.rst +++ b/docs/en/api-reference/system/index.rst @@ -7,6 +7,7 @@ System API :maxdepth: 1 app_image_format + bootloader_image_format app_trace esp_function_with_shared_stack chip_revision diff --git a/docs/zh_CN/api-reference/system/bootloader_image_format.rst b/docs/zh_CN/api-reference/system/bootloader_image_format.rst new file mode 100644 index 00000000000..3a87e9b16ba --- /dev/null +++ b/docs/zh_CN/api-reference/system/bootloader_image_format.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/system/bootloader_image_format.rst \ No newline at end of file diff --git a/docs/zh_CN/api-reference/system/index.rst b/docs/zh_CN/api-reference/system/index.rst index 2ab39f8a310..75953dc505e 100644 --- a/docs/zh_CN/api-reference/system/index.rst +++ b/docs/zh_CN/api-reference/system/index.rst @@ -7,6 +7,7 @@ System API :maxdepth: 1 app_image_format + bootloader_image_format app_trace esp_function_with_shared_stack chip_revision diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 9d838d8aaee..4492198e3f6 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -1623,7 +1623,6 @@ tools/ldgen/test/data/linker_script.ld tools/templates/sample_component/include/main.h tools/templates/sample_component/main.c tools/test_apps/build_system/embed_test/main/test_main.c -tools/test_apps/build_system/ldalign_test/check_alignment.py tools/test_apps/build_system/ldalign_test/main/test_main.c tools/test_apps/build_system/ldgen_test/check_placements.py tools/test_apps/build_system/ldgen_test/main/src1.c diff --git a/tools/test_apps/build_system/ldalign_test/check_alignment.py b/tools/test_apps/build_system/ldalign_test/check_alignment.py index 1f988fd9c77..a5cc4c60d0f 100644 --- a/tools/test_apps/build_system/ldalign_test/check_alignment.py +++ b/tools/test_apps/build_system/ldalign_test/check_alignment.py @@ -1,18 +1,7 @@ #!/usr/bin/env python # -# Copyright 2020 Espressif Systems (Shanghai) PTE LTD -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 # import argparse diff --git a/tools/test_apps/system/g1_components/CMakeLists.txt b/tools/test_apps/system/g1_components/CMakeLists.txt index 31c6c2fdc5e..2c1925c027d 100644 --- a/tools/test_apps/system/g1_components/CMakeLists.txt +++ b/tools/test_apps/system/g1_components/CMakeLists.txt @@ -38,6 +38,8 @@ set(extra_components_which_shouldnt_be_included driver # esp_app_format is dependency of bootloader_support, app_update esp_app_format + # esp_bootloader_format is dependency of bootloader_support, app_update + esp_bootloader_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.