mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/add_doc_about_app_desc_t' into 'master'
docs: Add description about the app image Closes IDF-597 See merge request idf/esp-idf!4912
This commit is contained in:
commit
5cb71b5213
109
components/bootloader_support/include/esp_app_format.h
Normal file
109
components/bootloader_support/include/esp_app_format.h
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright 2015-2019 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.
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief SPI flash mode, used in esp_image_header_t
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_IMAGE_SPI_MODE_QIO, /*!< SPI mode QIO */
|
||||
ESP_IMAGE_SPI_MODE_QOUT, /*!< SPI mode QOUT */
|
||||
ESP_IMAGE_SPI_MODE_DIO, /*!< SPI mode DIO */
|
||||
ESP_IMAGE_SPI_MODE_DOUT, /*!< SPI mode DOUT */
|
||||
ESP_IMAGE_SPI_MODE_FAST_READ, /*!< SPI mode FAST_READ */
|
||||
ESP_IMAGE_SPI_MODE_SLOW_READ /*!< SPI mode SLOW_READ */
|
||||
} esp_image_spi_mode_t;
|
||||
|
||||
/**
|
||||
* @brief SPI flash clock frequency
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_IMAGE_SPI_SPEED_40M, /*!< SPI clock frequency 40 MHz */
|
||||
ESP_IMAGE_SPI_SPEED_26M, /*!< SPI clock frequency 26 MHz */
|
||||
ESP_IMAGE_SPI_SPEED_20M, /*!< SPI clock frequency 20 MHz */
|
||||
ESP_IMAGE_SPI_SPEED_80M = 0xF /*!< SPI clock frequency 80 MHz */
|
||||
} esp_image_spi_freq_t;
|
||||
|
||||
/**
|
||||
* @brief Supported SPI flash sizes
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_IMAGE_FLASH_SIZE_1MB = 0, /*!< SPI flash size 1 MB */
|
||||
ESP_IMAGE_FLASH_SIZE_2MB, /*!< SPI flash size 2 MB */
|
||||
ESP_IMAGE_FLASH_SIZE_4MB, /*!< SPI flash size 4 MB */
|
||||
ESP_IMAGE_FLASH_SIZE_8MB, /*!< SPI flash size 8 MB */
|
||||
ESP_IMAGE_FLASH_SIZE_16MB, /*!< SPI flash size 16 MB */
|
||||
ESP_IMAGE_FLASH_SIZE_MAX /*!< SPI flash size MAX */
|
||||
} esp_image_flash_size_t;
|
||||
|
||||
#define ESP_IMAGE_HEADER_MAGIC 0xE9 /*!< The magic word for the esp_image_header_t structure. */
|
||||
|
||||
/**
|
||||
* @brief Main header of binary image
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t magic; /*!< Magic word ESP_IMAGE_HEADER_MAGIC */
|
||||
uint8_t segment_count; /*!< Count of memory segments */
|
||||
uint8_t spi_mode; /*!< flash read mode (esp_image_spi_mode_t as uint8_t) */
|
||||
uint8_t spi_speed: 4; /*!< flash frequency (esp_image_spi_freq_t as uint8_t) */
|
||||
uint8_t spi_size: 4; /*!< flash chip size (esp_image_flash_size_t as uint8_t) */
|
||||
uint32_t entry_addr; /*!< Entry address */
|
||||
uint8_t wp_pin; /*!< WP pin when SPI pins set via efuse (read by ROM bootloader,
|
||||
* the IDF bootloader uses software to configure the WP
|
||||
* pin and sets this field to 0xEE=disabled) */
|
||||
uint8_t spi_pin_drv[3]; /*!< Drive settings for the SPI flash pins (read by ROM bootloader) */
|
||||
uint8_t reserved[11]; /*!< Reserved bytes in ESP32 additional header space, currently unused */
|
||||
uint8_t hash_appended; /*!< If 1, a SHA256 digest "simple hash" (of the entire image) is appended after the checksum.
|
||||
* Included in image length. This digest
|
||||
* is separate to secure boot and only used for detecting corruption.
|
||||
* For secure boot signed images, the signature
|
||||
* is appended after this (and the simple hash is included in the signed data). */
|
||||
} __attribute__((packed)) esp_image_header_t;
|
||||
|
||||
/** @cond */
|
||||
_Static_assert(sizeof(esp_image_header_t) == 24, "binary image header should be 24 bytes");
|
||||
/** @endcond */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Header of binary image segment
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t load_addr; /*!< Address of segment */
|
||||
uint32_t data_len; /*!< Length of data */
|
||||
} 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 */
|
@ -16,6 +16,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <esp_err.h>
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_app_format.h"
|
||||
|
||||
#define ESP_ERR_IMAGE_BASE 0x2000
|
||||
#define ESP_ERR_IMAGE_FLASH_FAIL (ESP_ERR_IMAGE_BASE + 1)
|
||||
@ -25,91 +26,8 @@
|
||||
Can be compiled as part of app or bootloader code.
|
||||
*/
|
||||
|
||||
/* SPI flash mode, used in esp_image_header_t */
|
||||
typedef enum {
|
||||
ESP_IMAGE_SPI_MODE_QIO,
|
||||
ESP_IMAGE_SPI_MODE_QOUT,
|
||||
ESP_IMAGE_SPI_MODE_DIO,
|
||||
ESP_IMAGE_SPI_MODE_DOUT,
|
||||
ESP_IMAGE_SPI_MODE_FAST_READ,
|
||||
ESP_IMAGE_SPI_MODE_SLOW_READ
|
||||
} esp_image_spi_mode_t;
|
||||
|
||||
/* SPI flash clock frequency */
|
||||
typedef enum {
|
||||
ESP_IMAGE_SPI_SPEED_40M,
|
||||
ESP_IMAGE_SPI_SPEED_26M,
|
||||
ESP_IMAGE_SPI_SPEED_20M,
|
||||
ESP_IMAGE_SPI_SPEED_80M = 0xF
|
||||
} esp_image_spi_freq_t;
|
||||
|
||||
/* Supported SPI flash sizes */
|
||||
typedef enum {
|
||||
ESP_IMAGE_FLASH_SIZE_1MB = 0,
|
||||
ESP_IMAGE_FLASH_SIZE_2MB,
|
||||
ESP_IMAGE_FLASH_SIZE_4MB,
|
||||
ESP_IMAGE_FLASH_SIZE_8MB,
|
||||
ESP_IMAGE_FLASH_SIZE_16MB,
|
||||
ESP_IMAGE_FLASH_SIZE_MAX
|
||||
} esp_image_flash_size_t;
|
||||
|
||||
#define ESP_IMAGE_HEADER_MAGIC 0xE9
|
||||
|
||||
/* Main header of binary image */
|
||||
typedef struct {
|
||||
uint8_t magic;
|
||||
uint8_t segment_count;
|
||||
/* flash read mode (esp_image_spi_mode_t as uint8_t) */
|
||||
uint8_t spi_mode;
|
||||
/* flash frequency (esp_image_spi_freq_t as uint8_t) */
|
||||
uint8_t spi_speed: 4;
|
||||
/* flash chip size (esp_image_flash_size_t as uint8_t) */
|
||||
uint8_t spi_size: 4;
|
||||
uint32_t entry_addr;
|
||||
/* WP pin when SPI pins set via efuse (read by ROM bootloader, the IDF bootloader uses software to configure the WP
|
||||
* pin and sets this field to 0xEE=disabled) */
|
||||
uint8_t wp_pin;
|
||||
/* Drive settings for the SPI flash pins (read by ROM bootloader) */
|
||||
uint8_t spi_pin_drv[3];
|
||||
/* Reserved bytes in ESP32 additional header space, currently unused */
|
||||
uint8_t reserved[11];
|
||||
/* If 1, a SHA256 digest "simple hash" (of the entire image) is appended after the checksum. Included in image length. This digest
|
||||
* is separate to secure boot and only used for detecting corruption. For secure boot signed images, the signature
|
||||
* is appended after this (and the simple hash is included in the signed data). */
|
||||
uint8_t hash_appended;
|
||||
} __attribute__((packed)) esp_image_header_t;
|
||||
|
||||
_Static_assert(sizeof(esp_image_header_t) == 24, "binary image header should be 24 bytes");
|
||||
|
||||
#define ESP_IMAGE_HASH_LEN 32 /* Length of the appended SHA-256 digest */
|
||||
|
||||
/* Header of binary image segment */
|
||||
typedef struct {
|
||||
uint32_t load_addr;
|
||||
uint32_t data_len;
|
||||
} esp_image_segment_header_t;
|
||||
|
||||
#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]; /*!< --- */
|
||||
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]; /*!< --- */
|
||||
} esp_app_desc_t;
|
||||
_Static_assert(sizeof(esp_app_desc_t) == 256, "esp_app_desc_t should be 256 bytes");
|
||||
|
||||
#define ESP_IMAGE_MAX_SEGMENTS 16
|
||||
|
||||
/* Structure to hold on-flash image metadata */
|
||||
typedef struct {
|
||||
uint32_t start_addr; /* Start address of image */
|
||||
|
@ -208,6 +208,8 @@ INPUT = \
|
||||
../../components/esp_event/include/esp_event_base.h \
|
||||
### eFuse Manager
|
||||
../../components/efuse/include/esp_efuse.h \
|
||||
### App Image Format
|
||||
../../components/bootloader_support/include/esp_app_format.h \
|
||||
### ESP Pthread parameters
|
||||
../../components/pthread/include/esp_pthread.h \
|
||||
###
|
||||
|
108
docs/en/api-reference/system/app_image_format.rst
Normal file
108
docs/en/api-reference/system/app_image_format.rst
Normal file
@ -0,0 +1,108 @@
|
||||
App Image Format
|
||||
================
|
||||
|
||||
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.
|
||||
2. The :cpp:type:`esp_image_segment_header_t` structure describes each segment, its length, and its location in ESP32's memory, followed by the data with a length of ``data_len``. The data offset for each segment in the image is calculated in the following way:
|
||||
|
||||
* offset for 0 Segment = sizeof(:cpp:type:`esp_image_header_t`) + sizeof(:cpp:type:`esp_image_segment_header_t`).
|
||||
* offset for 1 Segment = offset for 0 Segment + length of 0 Segment + sizeof(:cpp:type:`esp_image_segment_header_t`).
|
||||
* offset for 2 Segment = offset for 1 Segment + length of 1 Segment + sizeof(:cpp:type:`esp_image_segment_header_t`).
|
||||
* ...
|
||||
|
||||
The count of each segment is defined in the ``segment_count`` field that is stored in :cpp:type:`esp_image_header_t`. The count cannot be more than :cpp:type:`ESP_IMAGE_MAX_SEGMENTS`.
|
||||
|
||||
To get the list of your image segments, please run the following command:
|
||||
|
||||
::
|
||||
|
||||
esptool.py --chip esp32 image_info build/app.bin
|
||||
|
||||
::
|
||||
|
||||
esptool.py v2.3.1
|
||||
Image version: 1
|
||||
Entry point: 40080ea4
|
||||
13 segments
|
||||
Segment 1: len 0x13ce0 load 0x3f400020 file_offs 0x00000018 SOC_DROM
|
||||
Segment 2: len 0x00000 load 0x3ff80000 file_offs 0x00013d00 SOC_RTC_DRAM
|
||||
Segment 3: len 0x00000 load 0x3ff80000 file_offs 0x00013d08 SOC_RTC_DRAM
|
||||
Segment 4: len 0x028e0 load 0x3ffb0000 file_offs 0x00013d10 DRAM
|
||||
Segment 5: len 0x00000 load 0x3ffb28e0 file_offs 0x000165f8 DRAM
|
||||
Segment 6: len 0x00400 load 0x40080000 file_offs 0x00016600 SOC_IRAM
|
||||
Segment 7: len 0x09600 load 0x40080400 file_offs 0x00016a08 SOC_IRAM
|
||||
Segment 8: len 0x62e4c load 0x400d0018 file_offs 0x00020010 SOC_IROM
|
||||
Segment 9: len 0x06cec load 0x40089a00 file_offs 0x00082e64 SOC_IROM
|
||||
Segment 10: len 0x00000 load 0x400c0000 file_offs 0x00089b58 SOC_RTC_IRAM
|
||||
Segment 11: len 0x00004 load 0x50000000 file_offs 0x00089b60 SOC_RTC_DATA
|
||||
Segment 12: len 0x00000 load 0x50000004 file_offs 0x00089b6c SOC_RTC_DATA
|
||||
Segment 13: len 0x00000 load 0x50000004 file_offs 0x00089b74 SOC_RTC_DATA
|
||||
Checksum: e8 (valid)Validation Hash: 407089ca0eae2bbf83b4120979d3354b1c938a49cb7a0c997f240474ef2ec76b (valid)
|
||||
|
||||
You can also see the information on segments in the IDF logs while your application is booting:
|
||||
|
||||
::
|
||||
|
||||
I (443) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x13ce0 ( 81120) map
|
||||
I (489) esp_image: segment 1: paddr=0x00033d08 vaddr=0x3ff80000 size=0x00000 ( 0) load
|
||||
I (530) esp_image: segment 2: paddr=0x00033d10 vaddr=0x3ff80000 size=0x00000 ( 0) load
|
||||
I (571) esp_image: segment 3: paddr=0x00033d18 vaddr=0x3ffb0000 size=0x028e0 ( 10464) load
|
||||
I (612) esp_image: segment 4: paddr=0x00036600 vaddr=0x3ffb28e0 size=0x00000 ( 0) load
|
||||
I (654) esp_image: segment 5: paddr=0x00036608 vaddr=0x40080000 size=0x00400 ( 1024) load
|
||||
I (695) esp_image: segment 6: paddr=0x00036a10 vaddr=0x40080400 size=0x09600 ( 38400) load
|
||||
I (737) esp_image: segment 7: paddr=0x00040018 vaddr=0x400d0018 size=0x62e4c (405068) map
|
||||
I (847) esp_image: segment 8: paddr=0x000a2e6c vaddr=0x40089a00 size=0x06cec ( 27884) load
|
||||
I (888) esp_image: segment 9: paddr=0x000a9b60 vaddr=0x400c0000 size=0x00000 ( 0) load
|
||||
I (929) esp_image: segment 10: paddr=0x000a9b68 vaddr=0x50000000 size=0x00004 ( 4) load
|
||||
I (971) esp_image: segment 11: paddr=0x000a9b74 vaddr=0x50000004 size=0x00000 ( 0) load
|
||||
I (1012) esp_image: segment 12: paddr=0x000a9b7c vaddr=0x50000004 size=0x00000 ( 0) load
|
||||
|
||||
For more details on the type of memory segments and their address ranges, see the ESP32 Technical Reference Manual, Section 1.3.2 *Embedded Memory*.
|
||||
|
||||
3. The image has a single checksum byte after the last segment. This byte is written on a sixteen byte padded boundary, so the application image might need padding.
|
||||
4. If the ``hash_appended`` field from :cpp:type:`esp_image_header_t` is set then a SHA256 checksum will be appended. The value of SHA256 is calculated on the range from first byte and up to this field. The length of this field is 32 bytes.
|
||||
5. If the options :ref:`CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT` or :ref:`CONFIG_SECURE_BOOT_ENABLED` are enabled then the application image will have additional 68 bytes for an ECDSA signature, which includes:
|
||||
|
||||
* version word (4 bytes),
|
||||
* signature data (64 bytes).
|
||||
|
||||
Application Description
|
||||
-----------------------
|
||||
|
||||
The ``DROM`` segment starts with the :cpp:type:`esp_app_desc_t` structure which carries specific fields describing the application:
|
||||
|
||||
* ``secure_version`` - see :doc:`Anti-rollback</api-reference/system/ota>`.
|
||||
* ``version`` - see :doc:`App version</api-reference/system/system>`. ``*``
|
||||
* ``project_name`` is filled from ``PROJECT_NAME``. ``*``
|
||||
* ``time`` and ``date`` - compile time and date.
|
||||
* ``idf_ver`` - version of ESP-IDF. ``*``
|
||||
* ``app_elf_sha256`` - contains sha256 for the elf application file.
|
||||
|
||||
``*`` - The maximum length is 32 characters, including null-termination character. For example, if the length of ``PROJECT_NAME`` exceeds 32 characters, the excess characters will be disregarded.
|
||||
|
||||
This structure is useful for identification of images uploaded OTA because it has a fixed offset = sizeof(:cpp:type:`esp_image_header_t`) + sizeof(:cpp:type:`esp_image_segment_header_t`). As soon as a device receives the first fragment containing this structure, it has all the information to determine whether the update should be continued or not.
|
||||
|
||||
Adding a Custom Structure to an Application
|
||||
-------------------------------------------
|
||||
|
||||
Customer also has the opportunity to have similar structure with a fixed offset relative to the beginning of the image.
|
||||
The following pattern can be used to add a custom structure to your image:
|
||||
|
||||
::
|
||||
|
||||
const __attribute__((section(".rodata_custom_desc"))) esp_custom_app_desc_t custom_app_desc = { ... }
|
||||
|
||||
Offset for custom structure is sizeof(:cpp:type:`esp_image_header_t`) + sizeof(:cpp:type:`esp_image_segment_header_t`) + sizeof(:cpp:type:`esp_app_desc_t`).
|
||||
|
||||
To guarantee that the custom structure is located in the image even if it is not used, you need to add:
|
||||
|
||||
* For Make: add ``COMPONENT_ADD_LDFLAGS += -u custom_app_desc`` into ``component.mk``
|
||||
* For Cmake: add ``target_link_libraries(${COMPONENT_TARGET} "-u custom_app_desc")`` into ``CMakeLists.txt``
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. include:: /_build/inc/esp_app_format.inc
|
||||
|
||||
|
@ -23,6 +23,7 @@ System API
|
||||
ESP HTTPS OTA <esp_https_ota>
|
||||
ESP pthread <esp_pthread>
|
||||
Error Codes and Helper Functions <esp_err>
|
||||
App image format <app_image_format>
|
||||
Miscellaneous System APIs <system>
|
||||
|
||||
|
||||
|
@ -188,8 +188,7 @@ Restrictions:
|
||||
|
||||
``security_version``:
|
||||
|
||||
- In application image it is stored in ``esp_app_desc`` structure. The number is set
|
||||
:ref:`CONFIG_BOOTLOADER_APP_SECURE_VERSION`.
|
||||
- In application image it is stored in ``esp_app_desc`` structure. The number is set :ref:`CONFIG_BOOTLOADER_APP_SECURE_VERSION`.
|
||||
- In ESP32 it is stored in efuse ``EFUSE_BLK3_RDATA4_REG``. (when a eFuse bit is programmed to 1, it can never be reverted to 0). The number of bits set in this register is the ``security_version`` from app.
|
||||
|
||||
.. _secure-ota-updates:
|
||||
|
1
docs/zh_CN/api-reference/system/app_image_format.rst
Normal file
1
docs/zh_CN/api-reference/system/app_image_format.rst
Normal file
@ -0,0 +1 @@
|
||||
.. include:: ../../../en/api-reference/system/app_image_format.rst
|
Loading…
Reference in New Issue
Block a user