浏览代码

esp_bootloader_format: Adds bootloader description structure to read bootloader version from app

Closes https://github.com/espressif/esp-idf/issues/8800
Closes https://github.com/espressif/esp-idf/issues/9132
KonstantinKondrashov 3 年之前
父节点
当前提交
69838403f9
共有 38 个文件被更改,包括 419 次插入49 次删除
  1. 1 0
      .gitlab/CODEOWNERS
  2. 1 1
      components/app_update/CMakeLists.txt
  3. 28 0
      components/app_update/esp_ota_ops.c
  4. 18 0
      components/app_update/include/esp_ota_ops.h
  5. 2 0
      components/bootloader/Kconfig.projbuild
  6. 6 1
      components/bootloader/subproject/main/ld/esp32/bootloader.ld
  7. 6 1
      components/bootloader/subproject/main/ld/esp32c2/bootloader.ld
  8. 6 1
      components/bootloader/subproject/main/ld/esp32c3/bootloader.ld
  9. 6 1
      components/bootloader/subproject/main/ld/esp32c6/bootloader.ld
  10. 6 0
      components/bootloader/subproject/main/ld/esp32h2/bootloader.ld
  11. 6 1
      components/bootloader/subproject/main/ld/esp32s2/bootloader.ld
  12. 6 1
      components/bootloader/subproject/main/ld/esp32s3/bootloader.ld
  13. 5 2
      components/bootloader_support/CMakeLists.txt
  14. 7 3
      components/bootloader_support/src/bootloader_init.c
  15. 24 19
      components/esp_app_format/CMakeLists.txt
  16. 1 0
      components/esp_app_format/Kconfig.projbuild
  17. 2 2
      components/esp_app_format/esp_app_desc.c
  18. 6 0
      components/esp_bootloader_format/.build-test-rules.yml
  19. 11 0
      components/esp_bootloader_format/CMakeLists.txt
  20. 21 0
      components/esp_bootloader_format/Kconfig.bootloader
  21. 32 0
      components/esp_bootloader_format/esp_bootloader_desc.c
  22. 48 0
      components/esp_bootloader_format/include/esp_bootloader_desc.h
  23. 8 0
      components/esp_bootloader_format/test_apps/CMakeLists.txt
  24. 2 0
      components/esp_bootloader_format/test_apps/README.md
  25. 3 0
      components/esp_bootloader_format/test_apps/main/CMakeLists.txt
  26. 45 0
      components/esp_bootloader_format/test_apps/main/test_bootloader_desc.c
  27. 11 0
      components/esp_bootloader_format/test_apps/pytest_esp_bootloader_format.py
  28. 10 0
      components/esp_bootloader_format/test_apps/sdkconfig.defaults
  29. 1 0
      docs/doxygen/Doxyfile
  30. 1 1
      docs/en/api-guides/reproducible-builds.rst
  31. 6 1
      docs/en/api-reference/system/app_image_format.rst
  32. 76 0
      docs/en/api-reference/system/bootloader_image_format.rst
  33. 1 0
      docs/en/api-reference/system/index.rst
  34. 1 0
      docs/zh_CN/api-reference/system/bootloader_image_format.rst
  35. 1 0
      docs/zh_CN/api-reference/system/index.rst
  36. 0 1
      tools/ci/check_copyright_ignore.txt
  37. 2 13
      tools/test_apps/build_system/ldalign_test/check_alignment.py
  38. 2 0
      tools/test_apps/system/g1_components/CMakeLists.txt

+ 1 - 0
.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

+ 1 - 1
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)

+ 28 - 0
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) {

+ 18 - 0
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.
  *

+ 2 - 0
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

+ 6 - 1
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.*)

+ 6 - 1
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.*)

+ 6 - 1
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.*)

+ 6 - 1
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.*)

+ 6 - 0
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(.);

+ 6 - 1
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.*)

+ 6 - 1
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.*)

+ 5 - 2
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()

+ 7 - 3
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)

+ 24 - 19
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()

+ 1 - 0
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

+ 2 - 2
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

+ 6 - 0
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

+ 11 - 0
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()

+ 21 - 0
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"

+ 32 - 0
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 <assert.h>
+#include <sys/param.h>
+#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;
+}

+ 48 - 0
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 <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#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

+ 8 - 0
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)

+ 2 - 0
components/esp_bootloader_format/test_apps/README.md

@@ -0,0 +1,2 @@
+| Supported Targets | ESP32 |
+| ----------------- | ----- |

+ 3 - 0
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)

+ 45 - 0
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 <stdio.h>
+#include <string.h>
+
+#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);
+}

+ 11 - 0
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()

+ 10 - 0
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

+ 1 - 0
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 \

+ 1 - 1
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<app_image_format_application_description>` if :ref:`CONFIG_APP_REPRODUCIBLE_BUILD` is enabled.
+- Build date and time are not included into the :ref:`application  metadata structure<app-image-format-application-description>` and :ref:`bootloader metadata structure<image-format-bootloader-description>` 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

+ 6 - 1
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
 -----------------------

+ 76 - 0
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 <app-image-structures>`. The only difference is in the :ref:`Bootloader Description <image-format-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

+ 1 - 0
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

+ 1 - 0
docs/zh_CN/api-reference/system/bootloader_image_format.rst

@@ -0,0 +1 @@
+.. include:: ../../../en/api-reference/system/bootloader_image_format.rst

+ 1 - 0
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

+ 0 - 1
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

+ 2 - 13
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

+ 2 - 0
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.