mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 17:19:09 -04:00
docs: standardize the names of bootloaders in esp-idf
This commit is contained in:
parent
64ccb22025
commit
46770a50a6
@ -3,16 +3,16 @@ Bootloader
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
The ESP-IDF Software Bootloader performs the following functions:
|
||||
The ESP-IDF second stage bootloader performs the following functions:
|
||||
|
||||
1. Minimal initial configuration of internal modules;
|
||||
2. Initialize :doc:`/security/flash-encryption` and/or :doc:`Secure Boot </security/secure-boot-v2>` features, if configured;
|
||||
3. Select the application partition to boot, based on the partition table and ota_data (if any);
|
||||
4. Load this image to RAM (IRAM & DRAM) and transfer management to the image that was just loaded.
|
||||
|
||||
Bootloader is located at the address {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} in the flash.
|
||||
ESP-IDF second stage bootloader is located at the address {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} in the flash.
|
||||
|
||||
For a full description of the startup process including the ESP-IDF bootloader, see :doc:`startup`.
|
||||
For a full description of the startup process including the ESP-IDF second stage bootloader, see :doc:`startup`.
|
||||
|
||||
.. _bootloader-compatibility:
|
||||
|
||||
@ -50,7 +50,7 @@ SPI Flash Configuration
|
||||
|
||||
Each ESP-IDF application or bootloader .bin file contains a header with :ref:`CONFIG_ESPTOOLPY_FLASHMODE`, :ref:`CONFIG_ESPTOOLPY_FLASHFREQ`, :ref:`CONFIG_ESPTOOLPY_FLASHSIZE` embedded in it. These are used to configure the SPI flash during boot.
|
||||
|
||||
The :ref:`first-stage-bootloader` in ROM reads the :ref:`second-stage-bootloader` header information from flash and uses this information to load the rest of the :ref:`second-stage-bootloader` from flash. However, at this time the system clock speed is lower than configured and not all flash modes are supported. When the :ref:`second-stage-bootloader` then runs, it will reconfigure the flash using values read from the currently selected app binary's header (and NOT from the :ref:`second-stage-bootloader` header). This allows an OTA update to change the SPI flash settings in use.
|
||||
The :ref:`first-stage-bootloader` reads the :ref:`second-stage-bootloader` header information from flash and uses this information to load the rest of the :ref:`second-stage-bootloader` from flash. However, at this time the system clock speed is lower than configured and not all flash modes are supported. When the :ref:`second-stage-bootloader` then runs, it will reconfigure the flash using values read from the currently selected app binary's header (and NOT from the :ref:`second-stage-bootloader` header). This allows an OTA update to change the SPI flash settings in use.
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
|
@ -1670,7 +1670,7 @@ Application Examples
|
||||
|
||||
- :example:`build_system/wrappers` demonstrates how to use a linker feature to redefine or override any public function in both ESP-IDF and the bootloader, allowing modification or extension of a function's default behavior.
|
||||
|
||||
- :example:`custom_bootloader/bootloader_override` demonstrates how to override the second-stage bootloader from a regular project, providing a custom bootloader that prints an extra message on startup, with the ability to conditionally override the bootloader based on certain conditions like target-dependency or KConfig options.
|
||||
- :example:`custom_bootloader/bootloader_override` demonstrates how to override the second stage bootloader from a regular project, providing a custom bootloader that prints an extra message on startup, with the ability to conditionally override the bootloader based on certain conditions like target-dependency or KConfig options.
|
||||
|
||||
- :example:`build_system/cmake/import_lib` demonstrates how to import and use third-party libraries using ExternalProject CMake module.
|
||||
|
||||
|
@ -288,14 +288,14 @@ RTC Watchdog Timeout
|
||||
--------------------
|
||||
{IDF_TARGET_RTCWDT_RTC_RESET:default="Not updated", esp32="RTCWDT_RTC_RESET", esp32s2="RTCWDT_RTC_RST", esp32s3="RTCWDT_RTC_RST", esp32c3="RTCWDT_RTC_RST", esp32c2="RTCWDT_RTC_RST", esp32c6="LP_WDT_SYS", esp32h2="LP_WDT_SYS", esp32p4="LP_WDT_SYS"}
|
||||
|
||||
The RTC watchdog is used in the startup code to keep track of execution time and it also helps to prevent a lock-up caused by an unstable power source. It is enabled by default (see :ref:`CONFIG_BOOTLOADER_WDT_ENABLE`). If the execution time is exceeded, the RTC watchdog will restart the system. In this case, the ROM bootloader will print a message with the ``RTC Watchdog Timeout`` reason for the reboot.
|
||||
The RTC watchdog is used in the startup code to keep track of execution time and it also helps to prevent a lock-up caused by an unstable power source. It is enabled by default (see :ref:`CONFIG_BOOTLOADER_WDT_ENABLE`). If the execution time is exceeded, the RTC watchdog will restart the system. In this case, the first stage (ROM) bootloader will print a message with the ``RTC Watchdog Timeout`` reason for the reboot.
|
||||
|
||||
::
|
||||
|
||||
rst:0x10 ({IDF_TARGET_RTCWDT_RTC_RESET})
|
||||
|
||||
|
||||
The RTC watchdog covers the execution time from the first stage bootloader (ROM bootloader) to application startup. It is initially set in the ROM bootloader, then configured in the bootloader with the :ref:`CONFIG_BOOTLOADER_WDT_TIME_MS` option (9000 ms by default). During the application initialization stage, it is reconfigured because the source of the slow clock may have changed, and finally disabled right before the ``app_main()`` call. There is an option :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` which prevents the RTC watchdog from being disabled before ``app_main``. Instead, the RTC watchdog remains active and must be fed periodically in your application's code.
|
||||
The RTC watchdog covers the execution time from the first stage (ROM) bootloader to application startup. It is initially set in the first stage (ROM) bootloader, then configured in the bootloader with the :ref:`CONFIG_BOOTLOADER_WDT_TIME_MS` option (9000 ms by default). During the application initialization stage, it is reconfigured because the source of the slow clock may have changed, and finally disabled right before the ``app_main()`` call. There is an option :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` which prevents the RTC watchdog from being disabled before ``app_main``. Instead, the RTC watchdog remains active and must be fed periodically in your application's code.
|
||||
|
||||
.. _Guru-Meditation-Errors:
|
||||
|
||||
|
@ -73,7 +73,7 @@ To enable PSRAM, please enable the :ref:`CONFIG_SPIRAM` under ``Component config
|
||||
|
||||
.. note::
|
||||
|
||||
If a board with Octal flash resets before the second-stage bootloader, please refer to :ref:`Error Handling Chapter <flash-psram-error>`.
|
||||
If a board with Octal flash resets before the second stage bootloader, please refer to :ref:`Error Handling Chapter <flash-psram-error>`.
|
||||
|
||||
|
||||
.. _flash-psram-combination:
|
||||
@ -228,7 +228,7 @@ F4R4 Hardware
|
||||
Error Handling
|
||||
--------------
|
||||
|
||||
1. If a board with Octal flash resets before the second-stage bootloader:
|
||||
1. If a board with Octal flash resets before the second stage bootloader:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
@ -243,7 +243,7 @@ Error Handling
|
||||
|
||||
this may mean that the necessary eFuses are not correctly burnt. Please check the eFuse bits of the chip using ``idf.py efuse-summary``.
|
||||
|
||||
The ROM bootloader relies on an eFuse bit ``FLASH_TYPE`` to reset the flash into the default mode (SPI mode). If this bit is not burnt and the flash is working in OPI mode, ROM bootloader may not be able to read from the flash and load the following images.
|
||||
The first stage (ROM) bootloader relies on an eFuse bit ``FLASH_TYPE`` to reset the flash into the default mode (SPI mode). If this bit is not burnt and the flash is working in OPI mode, the first stage (ROM) bootloader may not be able to read from the flash and load the following images.
|
||||
|
||||
2. If you enabled :ref:`CONFIG_ESPTOOLPY_OCT_FLASH`, and there's an error log saying:
|
||||
|
||||
|
@ -30,7 +30,7 @@ Here is the summary printed for the "Single factory app, no OTA" configuration::
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
factory, app, factory, 0x10000, 1M,
|
||||
|
||||
* At a 0x10000 (64 KB) offset in the flash is the app labelled "factory". The bootloader will run this app by default.
|
||||
* At a 0x10000 (64 KB) offset in the flash is the app labelled "factory". The bootloader runs this app by default.
|
||||
* There are also two data regions defined in the partition table for storing NVS library partition and PHY init data.
|
||||
|
||||
Here is the summary printed for the "Factory app, two OTA definitions" configuration::
|
||||
@ -89,7 +89,7 @@ If writing in C++ then specifying a application-defined partition type requires
|
||||
|
||||
static const esp_partition_type_t APP_PARTITION_TYPE_A = (esp_partition_type_t)0x40;
|
||||
|
||||
The ESP-IDF bootloader ignores any partition types other than ``app`` (0x00) and ``data`` (0x01).
|
||||
The bootloader ignores any partition types other than ``app`` (0x00) and ``data`` (0x01).
|
||||
|
||||
SubType
|
||||
~~~~~~~
|
||||
|
@ -199,9 +199,9 @@ The following options will reduce IRAM usage of some ESP-IDF features:
|
||||
Using SRAM1 for IRAM
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The SRAM1 memory area is normally used for DRAM, but it is possible to use parts of it for IRAM with :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM`. This memory would previously be reserved for DRAM data usage (e.g., ``.bss``) by the software bootloader and later added to the heap. After this option was introduced, the bootloader DRAM size was reduced to a value closer to what it normally actually needs.
|
||||
The SRAM1 memory area is normally used for DRAM, but it is possible to use parts of it for IRAM with :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM`. This memory would previously be reserved for DRAM data usage (e.g., ``.bss``) by the ESP-IDF second stage bootloader and later added to the heap. After this option was introduced, the bootloader DRAM size was reduced to a value closer to what it normally actually needs.
|
||||
|
||||
To use this option, ESP-IDF should be able to recognize that the new SRAM1 area is also a valid load address for an image segment. If the software bootloader was compiled before this option existed, then the bootloader will not be able to load the app that has code placed in this new extended IRAM area. This would typically happen if you are doing an OTA update, where only the app would be updated.
|
||||
To use this option, ESP-IDF should be able to recognize that the new SRAM1 area is also a valid load address for an image segment. If the second stage bootloader was compiled before this option existed, then the bootloader will not be able to load the app that has code placed in this new extended IRAM area. This would typically happen if you are doing an OTA update, where only the app would be updated.
|
||||
|
||||
If the IRAM section were to be placed in an invalid area, then this would be detected during the boot up process, and result in a failed boot:
|
||||
|
||||
@ -211,7 +211,7 @@ The following options will reduce IRAM usage of some ESP-IDF features:
|
||||
|
||||
.. warning::
|
||||
|
||||
Apps compiled with :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM` may fail to boot, if used together with a software bootloader that was compiled before this config option was introduced. If you are using an older bootloader and updating over OTA, please test carefully before pushing any updates.
|
||||
Apps compiled with :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM` may fail to boot, if used together with a second stage bootloader that was compiled before this config option was introduced. If you are using an older bootloader and updating over OTA, please test carefully before pushing any updates.
|
||||
|
||||
Any memory that ends up unused for static IRAM will be added to the heap.
|
||||
|
||||
|
@ -9,7 +9,7 @@ The high level view of startup process is as follows:
|
||||
|
||||
.. list::
|
||||
|
||||
1. :ref:`first-stage-bootloader` in ROM loads second-stage bootloader image to RAM (IRAM & DRAM) from flash offset {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH}.
|
||||
1. :ref:`first-stage-bootloader` loads the second stage bootloader image to RAM (IRAM & DRAM) from flash offset {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH}.
|
||||
|
||||
2. :ref:`second-stage-bootloader` loads partition table and main app image from flash. Main app incorporates both RAM segments and read-only segments mapped via flash cache.
|
||||
|
||||
@ -21,8 +21,8 @@ This process is explained in detail in the following sections.
|
||||
|
||||
.. _first-stage-bootloader:
|
||||
|
||||
First Stage Bootloader
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
First stage (ROM) bootloader
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES
|
||||
|
||||
@ -71,7 +71,7 @@ Second Stage Bootloader
|
||||
|
||||
In ESP-IDF, the binary image which resides at offset {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} in flash is the second stage bootloader. Second stage bootloader source code is available in :idf:`components/bootloader` directory of ESP-IDF. Second stage bootloader is used in ESP-IDF to add flexibility to flash layout (using partition tables), and allow for various flows associated with flash encryption, secure boot, and over-the-air updates (OTA) to take place.
|
||||
|
||||
When the first stage bootloader is finished checking and loading the second stage bootloader, it jumps to the second stage bootloader entry point found in the binary image header.
|
||||
When the first stage (ROM) bootloader is finished checking and loading the second stage bootloader, it jumps to the second stage bootloader entry point found in the binary image header.
|
||||
|
||||
Second stage bootloader reads the partition table found by default at offset {IDF_TARGET_CONFIG_PARTITION_TABLE_OFFSET} (:ref:`configurable value <CONFIG_PARTITION_TABLE_OFFSET>`). See :doc:`partition tables <partition-tables>` documentation for more information. The bootloader finds factory and OTA app partitions. If OTA app partitions are found in the partition table, the bootloader consults the ``otadata`` partition to determine which one should be booted. See :doc:`/api-reference/system/ota` for more information.
|
||||
|
||||
|
@ -116,7 +116,7 @@ Generally, try to avoid using the raw SPI flash functions to the "main" SPI flas
|
||||
SPI Flash Size
|
||||
--------------
|
||||
|
||||
The SPI flash size is configured by writing a field in the software bootloader image header, flashed at offset 0x1000.
|
||||
The SPI flash size is configured by writing a field in the ESP-IDF second stage bootloader image header, flashed at offset 0x1000.
|
||||
|
||||
By default, the SPI flash size is detected by ``esptool.py`` when this bootloader is written to flash, and the header is updated with the correct size. Alternatively, it is possible to generate a fixed flash size by setting :ref:`CONFIG_ESPTOOLPY_FLASHSIZE` in the project configuration.
|
||||
|
||||
|
@ -110,7 +110,7 @@ Below is the information about troubleshooting when the chip revision fails the
|
||||
Troubleshooting
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
1. If the 2nd stage bootloader is run on a chip revision smaller than minimum revision specified in the image (i.e., the application), a reboot occurs. The following message will be printed:
|
||||
1. If the second stage bootloader is run on a chip revision smaller than minimum revision specified in the image (i.e., the application), a reboot occurs. The following message will be printed:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
@ -132,7 +132,7 @@ To resolve this issue, update ESP-IDF to a newer version that supports the chip'
|
||||
Representing Revision Requirements of a Binary Image
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For the chip revision, the 2nd stage bootloader and the application binary images contain the :cpp:type:`esp_image_header_t` header, which stores information specifying the chip revisions that the image is permitted to run on. This header has 3 fields related to the chip revisions:
|
||||
For the chip revision, the second stage bootloader and the application binary images contain the :cpp:type:`esp_image_header_t` header, which stores information specifying the chip revisions that the image is permitted to run on. This header has 3 fields related to the chip revisions:
|
||||
|
||||
- ``min_chip_rev`` - Minimum chip MAJOR revision required by image (but for ESP32-C3 it is MINOR revision). Its value is determined by :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN`.
|
||||
- ``min_chip_rev_full`` - Minimum chip MINOR revision required by image in format: ``major * 100 + minor``. Its value is determined by :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN`.
|
||||
@ -148,11 +148,11 @@ Maximum And Minimum Revision Restrictions
|
||||
|
||||
The order for checking the minimum and maximum revisions during application boot up is as follows:
|
||||
|
||||
1. The 1st stage bootloader (ROM bootloader) does not check minimum and maximum revision fields from :cpp:type:`esp_image_header_t` before running the 2nd stage bootloader.
|
||||
1. The first stage (ROM) bootloader does not check minimum and maximum revision fields from :cpp:type:`esp_image_header_t` before running the 2nd stage bootloader.
|
||||
|
||||
2. The initialization phase of the 2nd stage bootloader checks that the 2nd stage bootloader itself can be launched on the chip of this revision. It extracts the minimum revision from the header of the bootloader image and checks against the chip revision from eFuses. If the chip revision is less than the minimum revision, the bootloader refuses to boot up and aborts. The maximum revision is not checked at this phase.
|
||||
2. The initialization phase of the second stage bootloader checks that the second stage bootloader itself can be launched on the chip of this revision. It extracts the minimum revision from the header of the bootloader image and checks against the chip revision from eFuses. If the chip revision is less than the minimum revision, the bootloader refuses to boot up and aborts. The maximum revision is not checked at this phase.
|
||||
|
||||
3. Then the 2nd stage bootloader checks the revision requirements of the application. It extracts the minimum and maximum revisions of the chip from the application image header, and the eFuse block from the segment header. Then the bootloader checks these versions against the chip and eFuse block revision from eFuses. If the these revisions are less than their minimum revision or higher than the maximum revision, the bootloader refuses to boot up and aborts. However, if the ignore maximum revision bit is set, the maximum revision constraint can be ignored. The ignore bits are set by the customer themselves when there is confirmation that the software is able to work with this chip revision or eFuse block revision.
|
||||
3. Then the second stage bootloader checks the revision requirements of the application. It extracts the minimum and maximum revisions of the chip from the application image header, and the eFuse block from the segment header. Then the bootloader checks these versions against the chip and eFuse block revision from eFuses. If the these revisions are less than their minimum revision or higher than the maximum revision, the bootloader refuses to boot up and aborts. However, if the ignore maximum revision bit is set, the maximum revision constraint can be ignored. The ignore bits are set by the customer themselves when there is confirmation that the software is able to work with this chip revision or eFuse block revision.
|
||||
|
||||
4. Furthermore, at the OTA update stage, the running application checks if the new software matches the chip revision and eFuse block revision. It extracts the minimum and maximum chip revisions from the header of the new application image and the eFuse block constraints from the application description to check against the these revisions from eFuses. It checks for revisions matching in the same way that the bootloader does, so that the chip and eFuse block revisions are between their min and max revisions (logic of ignoring max revision also applies).
|
||||
|
||||
|
@ -19,7 +19,7 @@ OTA Data Partition
|
||||
|
||||
An OTA data partition (type ``data``, subtype ``ota``) must be included in the :doc:`../../api-guides/partition-tables` of any project which uses the OTA functions.
|
||||
|
||||
For factory boot settings, the OTA data partition should contain no data (all bytes erased to 0xFF). In this case, the ESP-IDF software bootloader will boot the factory app if it is present in the partition table. If no factory app is included in the partition table, the first available OTA slot (usually ``ota_0``) is booted.
|
||||
For factory boot settings, the OTA data partition should contain no data (all bytes erased to 0xFF). In this case, the ESP-IDF second stage bootloader boots the factory app if it is present in the partition table. If no factory app is included in the partition table, the first available OTA slot (usually ``ota_0``) is booted.
|
||||
|
||||
After the first OTA update, the OTA data partition is updated to specify which OTA app slot partition should be booted next.
|
||||
|
||||
|
@ -8,7 +8,7 @@ Failed to Connect
|
||||
|
||||
{IDF_TARGET_STRAP_GPIO:default="[NEEDS TO BE UPDATED]", esp32="GPIO0", esp32s2="GPIO0", esp32s3="GPIO0", esp32c2="GPIO9", esp32c3="GPIO9", esp32c6="GPIO9", esp32h2="GPIO9", esp32p4="GPIO35"}
|
||||
|
||||
If you run the given command and see errors such as "Failed to connect", there might be several reasons for this. One of the reasons might be issues encountered by ``esptool.py``, the utility that is called by the build system to reset the chip, interact with the ROM bootloader, and flash firmware. One simple solution to try is to manually reset as described below. If it does not help, you can find more details about possible issues in the `esptool troubleshooting <https://docs.espressif.com/projects/esptool/en/latest/esp32/troubleshooting.html>`_ page.
|
||||
If you run the given command and see errors such as "Failed to connect", there might be several reasons for this. One of the reasons might be issues encountered by ``esptool.py``, the utility that is called by the build system to reset the chip, interact with the first stage (ROM) bootloader, and flash firmware. One simple solution to try is to manually reset as described below. If it does not help, you can find more details about possible issues in the `esptool troubleshooting <https://docs.espressif.com/projects/esptool/en/latest/esp32/troubleshooting.html>`_ page.
|
||||
|
||||
``esptool.py`` resets {IDF_TARGET_NAME} automatically by asserting DTR and RTS control lines of the USB-to-UART bridge, i.e., FTDI or CP210x (for more information, see :doc:`establish-serial-connection`). The DTR and RTS control lines are in turn connected to ``{IDF_TARGET_STRAP_GPIO}`` and ``CHIP_PU`` (EN) pins of {IDF_TARGET_NAME}, thus changes in the voltage levels of DTR and RTS will boot {IDF_TARGET_NAME} into Firmware Download mode. As an example, check the `schematic <https://dl.espressif.com/dl/schematics/esp32_devkitc_v4-sch-20180607a.pdf>`_ for the ESP32 DevKitC development board.
|
||||
|
||||
|
@ -39,7 +39,7 @@ Encrypted Partitions
|
||||
|
||||
With flash encryption enabled, the following types of data are encrypted by default:
|
||||
|
||||
- :ref:`second-stage-bootloader` (Firmware Bootloader)
|
||||
- :ref:`second-stage-bootloader`
|
||||
- Partition Table
|
||||
- :ref:`nvs_encr_key_partition`
|
||||
- Otadata
|
||||
@ -175,39 +175,39 @@ Read and write access to eFuse bits is controlled by appropriate fields in the r
|
||||
Flash Encryption Process
|
||||
------------------------
|
||||
|
||||
Assuming that the eFuse values are in their default states and the firmware bootloader is compiled to support flash encryption, the flash encryption process executes as shown below:
|
||||
Assuming that the eFuse values are in their default states and the second stage bootloader is compiled to support flash encryption, the flash encryption process executes as shown below:
|
||||
|
||||
.. only:: not SOC_FLASH_ENCRYPTION_XTS_AES
|
||||
|
||||
1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader.
|
||||
1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The first stage (ROM) bootloader loads the second stage bootloader.
|
||||
|
||||
2. Firmware bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b0000000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. It also sets the ``FLASH_CRYPT_CONFIG`` eFuse to 0xF. For more information on the flash encryption block, see *{IDF_TARGET_NAME} Technical Reference Manual* > *eFuse Controller (eFuse)* > *Flash Encryption Block* [`PDF <{IDF_TARGET_TRM_EN_URL}#efuse>`__].
|
||||
2. Second stage bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b0000000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. It also sets the ``FLASH_CRYPT_CONFIG`` eFuse to 0xF. For more information on the flash encryption block, see *{IDF_TARGET_NAME} Technical Reference Manual* > *eFuse Controller (eFuse)* > *Flash Encryption Block* [`PDF <{IDF_TARGET_TRM_EN_URL}#efuse>`__].
|
||||
|
||||
3. Firmware bootloader first checks if a valid key is already present in the eFuse (e.g., burned using espefuse tool), then the process of key generation is skipped and the same key is used for flash encryption process. Otherwise, Firmware bootloader uses RNG (random) module to generate an AES-256 bit key and then writes it into the ``flash_encryption`` eFuse. The key cannot be accessed via software as the write and read protection bits for the ``flash_encryption`` eFuse are set. The flash encryption operations happen entirely by hardware, and the key cannot be accessed via software.
|
||||
3. Second stage bootloader first checks if a valid key is already present in the eFuse (e.g., burned using espefuse tool), then the process of key generation is skipped and the same key is used for flash encryption process. Otherwise, Second stage bootloader uses RNG (random) module to generate an AES-256 bit key and then writes it into the ``flash_encryption`` eFuse. The key cannot be accessed via software as the write and read protection bits for the ``flash_encryption`` eFuse are set. The flash encryption operations happen entirely by hardware, and the key cannot be accessed via software.
|
||||
|
||||
4. Flash encryption block encrypts the flash contents - the firmware bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions.
|
||||
4. Flash encryption block encrypts the flash contents - the second stage bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions.
|
||||
|
||||
5. Firmware bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b0000001) to mark the flash contents as encrypted. Odd number of bits is set.
|
||||
5. Second stage bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b0000001) to mark the flash contents as encrypted. Odd number of bits is set.
|
||||
|
||||
6. For :ref:`flash-enc-development-mode`, the firmware bootloader sets only the eFuse bits ``DISABLE_DL_DECRYPT`` and ``DISABLE_DL_CACHE`` to allow the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected.
|
||||
6. For :ref:`flash-enc-development-mode`, the second stage bootloader sets only the eFuse bits ``DISABLE_DL_DECRYPT`` and ``DISABLE_DL_CACHE`` to allow the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected.
|
||||
|
||||
7. For :ref:`flash-enc-release-mode`, the firmware bootloader sets the eFuse bits ``DISABLE_DL_ENCRYPT``, ``DISABLE_DL_DECRYPT``, and ``DISABLE_DL_CACHE`` to 1 to prevent the UART bootloader from decrypting the flash contents. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`.
|
||||
7. For :ref:`flash-enc-release-mode`, the second stage bootloader sets the eFuse bits ``DISABLE_DL_ENCRYPT``, ``DISABLE_DL_DECRYPT``, and ``DISABLE_DL_CACHE`` to 1 to prevent the UART bootloader from decrypting the flash contents. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`.
|
||||
|
||||
8. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM.
|
||||
8. The device is then rebooted to start executing the encrypted image. The second stage bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM.
|
||||
|
||||
.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_256
|
||||
|
||||
1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader.
|
||||
1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The first stage (ROM) bootloader loads the second stage bootloader.
|
||||
|
||||
2. Firmware bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. For more information on the flash encryption block, see *{IDF_TARGET_NAME} Technical Reference Manual* > *eFuse Controller (eFuse)* > *Auto Encryption Block* [`PDF <{IDF_TARGET_TRM_EN_URL}#efuse>`__].
|
||||
2. Second stage bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. For more information on the flash encryption block, see *{IDF_TARGET_NAME} Technical Reference Manual* > *eFuse Controller (eFuse)* > *Auto Encryption Block* [`PDF <{IDF_TARGET_TRM_EN_URL}#efuse>`__].
|
||||
|
||||
3. Firmware bootloader first checks if a valid key is already present in the eFuse (e.g., burned using espefuse tool) then the process of key generation is skipped and the same key is used for flash encryption process. Otherwise, Firmware bootloader uses RNG (random) module to generate an 256 bit or 512 bit key, depending on the value of :ref:`Size of generated XTS-AES key <CONFIG_SECURE_FLASH_ENCRYPTION_KEYSIZE>`, and then writes it into respectively one or two `BLOCK_KEYN` eFuses. The software also updates the ``KEY_PURPOSE_N`` for the blocks where the keys were stored. The key cannot be accessed via software as the write and read protection bits for one or two `BLOCK_KEYN` eFuses are set. ``KEY_PURPOSE_N`` field is write-protected as well. The flash encryption operations happen entirely by hardware, and the key cannot be accessed via software.
|
||||
3. Second stage bootloader first checks if a valid key is already present in the eFuse (e.g., burned using espefuse tool) then the process of key generation is skipped and the same key is used for flash encryption process. Otherwise, second stage bootloader uses RNG (random) module to generate an 256 bit or 512 bit key, depending on the value of :ref:`Size of generated XTS-AES key <CONFIG_SECURE_FLASH_ENCRYPTION_KEYSIZE>`, and then writes it into respectively one or two `BLOCK_KEYN` eFuses. The software also updates the ``KEY_PURPOSE_N`` for the blocks where the keys were stored. The key cannot be accessed via software as the write and read protection bits for one or two `BLOCK_KEYN` eFuses are set. ``KEY_PURPOSE_N`` field is write-protected as well. The flash encryption operations happen entirely by hardware, and the key cannot be accessed via software.
|
||||
|
||||
4. Flash encryption block encrypts the flash contents - the firmware bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions.
|
||||
4. Flash encryption block encrypts the flash contents - the second stage bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions.
|
||||
|
||||
5. Firmware bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b001) to mark the flash contents as encrypted. Odd number of bits is set.
|
||||
5. Second stage bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b001) to mark the flash contents as encrypted. Odd number of bits is set.
|
||||
|
||||
6. For :ref:`flash-enc-development-mode`, the firmware bootloader allows the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. In addition, the firmware bootloader by default sets the following eFuse bits:
|
||||
6. For :ref:`flash-enc-development-mode`, the second stage bootloader allows the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. In addition, the second stage bootloader by default sets the following eFuse bits:
|
||||
|
||||
.. list::
|
||||
|
||||
@ -217,45 +217,45 @@ Assuming that the eFuse values are in their default states and the firmware boot
|
||||
- ``HARD_DIS_JTAG``
|
||||
- ``DIS_LEGACY_SPI_BOOT``
|
||||
|
||||
7. For :ref:`flash-enc-release-mode`, the firmware bootloader sets all the eFuse bits set under development mode as well as ``DIS_DOWNLOAD_MANUAL_ENCRYPT``. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`.
|
||||
7. For :ref:`flash-enc-release-mode`, the second stage bootloader sets all the eFuse bits set under development mode as well as ``DIS_DOWNLOAD_MANUAL_ENCRYPT``. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`.
|
||||
|
||||
8. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM.
|
||||
8. The device is then rebooted to start executing the encrypted image. The second stage bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM.
|
||||
|
||||
.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_128 and not SOC_FLASH_ENCRYPTION_XTS_AES_256 and not SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK
|
||||
|
||||
1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader.
|
||||
1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The first stage (ROM) bootloader loads the second stage bootloader.
|
||||
|
||||
2. Firmware bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_.
|
||||
2. Second stage bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_.
|
||||
|
||||
3. Firmware bootloader uses RNG (random) module to generate an 256 bit key and then writes it into `BLOCK_KEYN` eFuse. The software also updates the ``KEY_PURPOSE_N`` for the block where the key is stored. The key cannot be accessed via software as the write and read protection bits for `BLOCK_KEYN` eFuse are set. ``KEY_PURPOSE_N`` field is write-protected as well. The flash encryption is completely conducted by hardware, and the key cannot be accessed via software. If a valid key is already present in the eFuse (e.g., burned using espefuse tool) then the process of key generation is skipped and the same key is used for flash encryption process.
|
||||
3. Second stage bootloader uses RNG (random) module to generate an 256 bit key and then writes it into `BLOCK_KEYN` eFuse. The software also updates the ``KEY_PURPOSE_N`` for the block where the key is stored. The key cannot be accessed via software as the write and read protection bits for `BLOCK_KEYN` eFuse are set. ``KEY_PURPOSE_N`` field is write-protected as well. The flash encryption is completely conducted by hardware, and the key cannot be accessed via software. If a valid key is already present in the eFuse (e.g., burned using espefuse tool) then the process of key generation is skipped and the same key is used for flash encryption process.
|
||||
|
||||
4. Flash encryption block encrypts the flash contents - the firmware bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions.
|
||||
4. Flash encryption block encrypts the flash contents - the second stage bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions.
|
||||
|
||||
5. Firmware bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b001) to mark the flash contents as encrypted. Odd number of bits is set.
|
||||
5. Second stage bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b001) to mark the flash contents as encrypted. Odd number of bits is set.
|
||||
|
||||
6. For :ref:`flash-enc-development-mode`, the firmware bootloader allows the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. In addition, the firmware bootloader by default sets the eFuse bits ``DIS_DOWNLOAD_ICACHE``, ``DIS_PAD_JTAG``, ``DIS_USB_JTAG`` and ``DIS_LEGACY_SPI_BOOT``.
|
||||
6. For :ref:`flash-enc-development-mode`, the second stage bootloader allows the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. In addition, the second stage bootloader by default sets the eFuse bits ``DIS_DOWNLOAD_ICACHE``, ``DIS_PAD_JTAG``, ``DIS_USB_JTAG`` and ``DIS_LEGACY_SPI_BOOT``.
|
||||
|
||||
7. For :ref:`flash-enc-release-mode`, the firmware bootloader sets all the eFuse bits set under development mode as well as ``DIS_DOWNLOAD_MANUAL_ENCRYPT``. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`.
|
||||
7. For :ref:`flash-enc-release-mode`, the second stage bootloader sets all the eFuse bits set under development mode as well as ``DIS_DOWNLOAD_MANUAL_ENCRYPT``. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`.
|
||||
|
||||
8. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM.
|
||||
8. The device is then rebooted to start executing the encrypted image. The second stage bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM.
|
||||
|
||||
.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_128 and SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK
|
||||
|
||||
1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The ROM bootloader loads the firmware bootloader.
|
||||
1. On the first power-on reset, all data in flash is un-encrypted (plaintext). The first stage (ROM) bootloaders loads the second stage bootloader.
|
||||
|
||||
2. Firmware bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_.
|
||||
2. The second stage bootloader reads the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value (``0b000``). Since the value is ``0`` (even number of bits set), it configures and enables the flash encryption block. For more information on the flash encryption block, see `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_.
|
||||
|
||||
3. Firmware bootloader uses RNG (random) module to generate an 256 or 128 bit key (depends on :ref:`Size of generated XTS-AES key <CONFIG_SECURE_FLASH_ENCRYPTION_KEYSIZE>`) and then writes it into `BLOCK_KEY0` eFuse. The software also updates the ``XTS_KEY_LENGTH_256`` according to the chosen option. The key cannot be accessed via software as the write and read protection bits for ``BLOCK_KEY0`` eFuse are set. The flash encryption operations happen entirely by hardware, and the key cannot be accessed via software. If 128-bit flash encryption key is used, then only the lower 128 bits of the eFuse key block are read-protected, the remaining 128 bits are readable, which is required for secure boot. The entire eFuse block is write-protected. If the FE key is 256 bits long, then ``XTS_KEY_LENGTH_256`` is 1, otherwise it is 0. To prevent this eFuse from being accidentally changed in the future (from 0 to 1), we set a write-protect bit for the RELEASE mode. If a valid key is already present in the eFuse (e.g., burned using espefuse tool) then the process of key generation is skipped and the same key is used for flash encryption process.
|
||||
3. The second stage bootloader uses RNG (random) module to generate an 256 or 128 bit key (depends on :ref:`Size of generated XTS-AES key <CONFIG_SECURE_FLASH_ENCRYPTION_KEYSIZE>`) and then writes it into `BLOCK_KEY0` eFuse. The software also updates the ``XTS_KEY_LENGTH_256`` according to the chosen option. The key cannot be accessed via software as the write and read protection bits for ``BLOCK_KEY0`` eFuse are set. The flash encryption operations happen entirely by hardware, and the key cannot be accessed via software. If 128-bit flash encryption key is used, then only the lower 128 bits of the eFuse key block are read-protected, the remaining 128 bits are readable, which is required for secure boot. The entire eFuse block is write-protected. If the FE key is 256 bits long, then ``XTS_KEY_LENGTH_256`` is 1, otherwise it is 0. To prevent this eFuse from being accidentally changed in the future (from 0 to 1), we set a write-protect bit for the RELEASE mode. If a valid key is already present in the eFuse (e.g., burned using espefuse tool) then the process of key generation is skipped and the same key is used for flash encryption process.
|
||||
|
||||
4. Flash encryption block encrypts the flash contents - the firmware bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions.
|
||||
4. Flash encryption block encrypts the flash contents - the second stage bootloader, applications and partitions marked as ``encrypted``. Encrypting in-place can take time, up to a minute for large partitions.
|
||||
|
||||
5. Firmware bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b001) to mark the flash contents as encrypted. Odd number of bits is set.
|
||||
5. The second stage bootloader sets the first available bit in ``{IDF_TARGET_CRYPT_CNT}`` (0b001) to mark the flash contents as encrypted. Odd number of bits is set.
|
||||
|
||||
6. For :ref:`flash-enc-development-mode`, the firmware bootloader allows the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. In addition, the firmware bootloader by default sets the eFuse bits ``DIS_DOWNLOAD_ICACHE``, ``DIS_PAD_JTAG``, and ``DIS_DIRECT_BOOT``.
|
||||
6. For :ref:`flash-enc-development-mode`, the second stage bootloader allows the UART bootloader to re-flash encrypted binaries. Also, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits are NOT write-protected. In addition, the second stage bootloader by default sets the eFuse bits ``DIS_DOWNLOAD_ICACHE``, ``DIS_PAD_JTAG``, and ``DIS_DIRECT_BOOT``.
|
||||
|
||||
7. For :ref:`flash-enc-release-mode`, the firmware bootloader sets all the eFuse bits set under development mode as well as ``DIS_DOWNLOAD_MANUAL_ENCRYPT``. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`.
|
||||
7. For :ref:`flash-enc-release-mode`, the second stage bootloader sets all the eFuse bits set under development mode as well as ``DIS_DOWNLOAD_MANUAL_ENCRYPT``. It also write-protects the ``{IDF_TARGET_CRYPT_CNT}`` eFuse bits. To modify this behavior, see :ref:`uart-bootloader-encryption`.
|
||||
|
||||
8. The device is then rebooted to start executing the encrypted image. The firmware bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM.
|
||||
8. The device is then rebooted to start executing the encrypted image. The second stage bootloader calls the flash decryption block to decrypt the flash contents and then loads the decrypted contents into IRAM.
|
||||
|
||||
During the development stage, there is a frequent need to program different plaintext flash images and test the flash encryption process. This requires that Firmware Download mode is able to load new plaintext images as many times as it might be needed. However, during manufacturing or production stages, Firmware Download mode should not be allowed to access flash contents for security reasons.
|
||||
|
||||
@ -316,7 +316,7 @@ Enabling flash encryption will increase the size of bootloader, which might requ
|
||||
|
||||
This command does not include any user files which should be written to the partitions on the flash memory. Please write them manually before running this command otherwise the files should be encrypted separately before writing.
|
||||
|
||||
This command will write to flash memory unencrypted images: the firmware bootloader, the partition table and applications. Once the flashing is complete, {IDF_TARGET_NAME} will reset. On the next boot, the firmware bootloader encrypts: the firmware bootloader, application partitions and partitions marked as ``encrypted`` then resets. Encrypting in-place can take time, up to a minute for large partitions. After that, the application is decrypted at runtime and executed.
|
||||
This command will write to flash memory unencrypted images: the second stage bootloader, the partition table and applications. Once the flashing is complete, {IDF_TARGET_NAME} will reset. On the next boot, the second stage bootloader encrypts: the second stage bootloader, application partitions and partitions marked as ``encrypted`` then resets. Encrypting in-place can take time, up to a minute for large partitions. After that, the application is decrypted at runtime and executed.
|
||||
|
||||
A sample output of the first {IDF_TARGET_NAME} boot after enabling flash encryption is given below:
|
||||
|
||||
@ -486,7 +486,7 @@ Enabling flash encryption will increase the size of bootloader, which might requ
|
||||
|
||||
This command does not include any user files which should be written to the partitions on the flash memory. Please write them manually before running this command otherwise the files should be encrypted separately before writing.
|
||||
|
||||
This command will write to flash memory unencrypted images: the firmware bootloader, the partition table and applications. Once the flashing is complete, {IDF_TARGET_NAME} will reset. On the next boot, the firmware bootloader encrypts: the firmware bootloader, application partitions and partitions marked as ``encrypted`` then resets. Encrypting in-place can take time, up to a minute for large partitions. After that, the application is decrypted at runtime and executed.
|
||||
This command will write to flash memory unencrypted images: the second stage bootloader, the partition table and applications. Once the flashing is complete, {IDF_TARGET_NAME} will reset. On the next boot, the second stage bootloader encrypts: the second stage bootloader, application partitions and partitions marked as ``encrypted`` then resets. Encrypting in-place can take time, up to a minute for large partitions. After that, the application is decrypted at runtime and executed.
|
||||
|
||||
If using Development Mode, then the easiest way to update and re-flash binaries is :ref:`encrypt-partitions`.
|
||||
|
||||
@ -549,7 +549,7 @@ Enabling flash encryption will increase the size of bootloader, which might requ
|
||||
|
||||
This command does not include any user files which should be written to the partitions on the flash memory. Please write them manually before running this command otherwise the files should be encrypted separately before writing.
|
||||
|
||||
This command will write to flash memory unencrypted images: the firmware bootloader, the partition table and applications. Once the flashing is complete, {IDF_TARGET_NAME} will reset. On the next boot, the firmware bootloader encrypts: the firmware bootloader, application partitions and partitions marked as ``encrypted`` then resets. Encrypting in-place can take time, up to a minute for large partitions. After that, the application is decrypted at runtime and executed.
|
||||
This command will write to flash memory unencrypted images: the second stage bootloader, the partition table and applications. Once the flashing is complete, {IDF_TARGET_NAME} will reset. On the next boot, the second stage bootloader encrypts: the second stage bootloader, application partitions and partitions marked as ``encrypted`` then resets. Encrypting in-place can take time, up to a minute for large partitions. After that, the application is decrypted at runtime and executed.
|
||||
|
||||
Once the flash encryption is enabled in Release mode, the bootloader will write-protect the ``{IDF_TARGET_CRYPT_CNT}`` eFuse.
|
||||
|
||||
@ -576,14 +576,14 @@ When using Flash Encryption in production:
|
||||
Enable Flash Encryption Externally
|
||||
----------------------------------
|
||||
|
||||
In the process mentioned above, flash encryption related eFuses which ultimately enable flash encryption are programmed through the firmware bootloader. Alternatively, all the eFuses can be programmed with the help of ``espefuse`` tool. Please refer :ref:`enable-flash-encryption-externally` for more details.
|
||||
In the process mentioned above, flash encryption related eFuses which ultimately enable flash encryption are programmed through the second stage bootloader. Alternatively, all the eFuses can be programmed with the help of ``espefuse`` tool. Please refer :ref:`enable-flash-encryption-externally` for more details.
|
||||
|
||||
Possible Failures
|
||||
-----------------
|
||||
|
||||
Once flash encryption is enabled, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value will have an odd number of bits set. It means that all the partitions marked with the encryption flag are expected to contain encrypted ciphertext. Below are the three typical failure cases if the {IDF_TARGET_NAME} is erroneously loaded with plaintext data:
|
||||
|
||||
1. If the bootloader partition is re-flashed with a **plaintext firmware bootloader image**, the ROM bootloader will fail to load the firmware bootloader resulting in the following failure:
|
||||
1. If the bootloader partition is re-flashed with a **plaintext second stage bootloader image**, the first stage (ROM) bootloader will fail to load the second stage bootloader resulting in the following failure:
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
@ -635,7 +635,7 @@ Once flash encryption is enabled, the ``{IDF_TARGET_CRYPT_CNT}`` eFuse value wil
|
||||
|
||||
This error also appears if the flash contents are erased or corrupted.
|
||||
|
||||
2. If the firmware bootloader is encrypted, but the partition table is re-flashed with a **plaintext partition table image**, the bootloader will fail to read the partition table resulting in the following failure:
|
||||
2. If the second stage bootloader is encrypted, but the partition table is re-flashed with a **plaintext partition table image**, the bootloader will fail to read the partition table resulting in the following failure:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@ -727,7 +727,7 @@ Whenever the ``{IDF_TARGET_CRYPT_CNT}`` eFuse is set to a value with an odd numb
|
||||
- Executable application code in flash (IROM).
|
||||
- All read-only data stored in flash (DROM).
|
||||
- Any data accessed via :cpp:func:`spi_flash_mmap`.
|
||||
- The firmware bootloader image when it is read by the ROM bootloader.
|
||||
- The second stage bootloader image when it is read by the first stage (ROM) bootloader.
|
||||
|
||||
.. important::
|
||||
|
||||
@ -776,7 +776,7 @@ OTA updates to encrypted partitions will automatically write encrypted data if t
|
||||
|
||||
Before building the application image for OTA updating of an already encrypted device, enable the option :ref:`Enable flash encryption on boot <CONFIG_SECURE_FLASH_ENC_ENABLED>` in project configuration menu.
|
||||
|
||||
For general information about ESP-IDF OTA updates, please refer to :doc:`OTA <../api-reference/system/ota>`
|
||||
For general information about ESP-IDF OTA updates, please refer to :doc:`OTA <../api-reference/system/ota>`.
|
||||
|
||||
|
||||
.. _updating-encrypted-flash-serial:
|
||||
@ -976,7 +976,7 @@ However, before the first boot you can choose to keep any of these features enab
|
||||
|
||||
The eFuse ``FLASH_CRYPT_CONFIG`` determines the number of bits in the flash encryption key which are "tweaked" with the block offset. For details, see :ref:`flash-encryption-algorithm`.
|
||||
|
||||
On the first boot of the firmware bootloader, this value is set to the maximum ``0xF``.
|
||||
On the first boot of the second stage bootloader, this value is set to the maximum ``0xF``.
|
||||
|
||||
It is possible to burn this eFuse manually and write protect it before the first boot in order to select different tweak values. However, this is not recommended.
|
||||
|
||||
|
@ -30,7 +30,7 @@ Background
|
||||
|
||||
- To understand the secure boot process, please familiarize yourself with the standard :doc:`../api-guides/startup`.
|
||||
|
||||
- Both stages of the boot process, including initial software bootloader load and subsequent partition & app loading, are verified by the secure boot process, in a chain of trust relationship.
|
||||
- Both stages of the boot process, including initial second stage bootloader load and subsequent partition & app loading, are verified by the secure boot process, in a chain of trust relationship.
|
||||
|
||||
|
||||
Secure Boot Process Overview
|
||||
@ -42,18 +42,18 @@ This is a high-level overview of the secure boot process. Step-by-step instructi
|
||||
|
||||
2. Secure boot defaults to signing images and partition table data during the build process. The ``Secure boot private signing key`` config item is a file path to an ECDSA public/private key pair in a PEM format file.
|
||||
|
||||
3. The software bootloader image is built by ESP-IDF with secure boot support enabled, and the public key for signature verification is integrated into the bootloader image. This software bootloader image is flashed at offset 0x1000.
|
||||
3. The second stage bootloader image is built by ESP-IDF with secure boot support enabled, and the public key for signature verification is integrated into the bootloader image. This second stage bootloader image is flashed at offset 0x1000.
|
||||
|
||||
4. On the first boot, the software bootloader follows the following process to enable a secure boot:
|
||||
4. On the first boot, the second stage bootloader follows the following process to enable a secure boot:
|
||||
|
||||
- Hardware secure boot support generates a device-secure bootloader key and a secure digest. The secure bootloader key is generated with the help of the hardware RNG, and then stored in eFuse with read and write protection enabled. The digest is derived from the key, an initialization vector (IV), and the bootloader image contents.
|
||||
- The secure digest is flashed at offset 0x0 in the flash.
|
||||
- Depending on Secure Boot Configuration, eFuses are burned to disable JTAG and the ROM BASIC interpreter. It is **strongly recommended** that these options are turned on.
|
||||
- Bootloader permanently enables secure boot by burning the ABS_DONE_0 eFuse. The software bootloader then becomes protected. After this point, the chip will only boot a bootloader image if the digest matches.
|
||||
- Bootloader permanently enables secure boot by burning the ABS_DONE_0 eFuse. The second stage bootloader then becomes protected. After this point, the chip will only boot a bootloader image if the digest matches.
|
||||
|
||||
5. On subsequent boots, the ROM bootloader sees that the secure boot eFuse is burned, reads the saved digest at 0x0, and uses hardware secure boot support to compare it with a newly calculated digest. If the digest does not match then booting will not continue. The digest and comparison are performed entirely by hardware, and the calculated digest is not readable by software. For technical details see :ref:`secure-boot-hardware-support`.
|
||||
5. On subsequent boots, the first stage (ROM) bootloader sees that the secure boot eFuse is burned, reads the saved digest at 0x0, and uses hardware secure boot support to compare it with a newly calculated digest. If the digest does not match then booting will not continue. The digest and comparison are performed entirely by hardware, and the calculated digest is not readable by software. For technical details see :ref:`secure-boot-hardware-support`.
|
||||
|
||||
6. When running in secure boot mode, the software bootloader uses the secure boot signing key, the public key of which is embedded in the bootloader itself and therefore validated as part of the bootloader, to verify the signature appended to all subsequent partition tables and app images before they are booted.
|
||||
6. When running in secure boot mode, the second stage bootloader uses the secure boot signing key, the public key of which is embedded in the bootloader itself and therefore validated as part of the bootloader, to verify the signature appended to all subsequent partition tables and app images before they are booted.
|
||||
|
||||
|
||||
Keys
|
||||
@ -73,7 +73,7 @@ The following keys are used by the secure boot process:
|
||||
|
||||
- ``secure boot signing key`` is a standard ECDSA public/private key pair in PEM format, see :ref:`secure-boot-image-signing-algorithm`.
|
||||
|
||||
- The public key from this key pair is compiled into the software bootloader. It is only used for signature verification purposes and not signature creation. This public key is used to verify the second stage of booting, including the partition table and app image, before booting continues. The public key can be freely distributed; it does not need to be kept secret.
|
||||
- The public key from this key pair is compiled into the second stage bootloader. It is only used for signature verification purposes and not signature creation. This public key is used to verify the second stage of booting, including the partition table and app image, before booting continues. The public key can be freely distributed; it does not need to be kept secret.
|
||||
|
||||
- The private key from this key pair **must be securely kept private**, as anyone who has this key can authenticate to any bootloader that is configured with a secure boot and the matching public key.
|
||||
|
||||
@ -117,7 +117,7 @@ How to Enable Secure Boot
|
||||
|
||||
``idf.py flash`` does not flash the bootloader if secure boot is enabled.
|
||||
|
||||
8. Reset the {IDF_TARGET_NAME} and it will boot the software bootloader you flashed. The software bootloader will enable secure boot on the chip, and then it verifies the app image signature and boots the app. You should watch the serial console output from the {IDF_TARGET_NAME} to verify that secure boot is enabled and no errors have occurred due to the build configuration.
|
||||
8. Reset the {IDF_TARGET_NAME} and it will boot the second stage bootloader you flashed. The second stage bootloader will enable secure boot on the chip, and then it verifies the app image signature and boots the app. You should watch the serial console output from the {IDF_TARGET_NAME} to verify that secure boot is enabled and no errors have occurred due to the build configuration.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -127,13 +127,13 @@ How to Enable Secure Boot
|
||||
|
||||
If {IDF_TARGET_NAME} is reset or powered down during the first boot, it will start the process again on the next boot.
|
||||
|
||||
9. On subsequent boots, the secure boot hardware will verify the software bootloader has not changed using the secure bootloader key, and then the software bootloader will verify the signed partition table and app image using the public key portion of the secure boot signing key.
|
||||
9. On subsequent boots, the secure boot hardware will verify the second stage bootloader has not changed using the secure bootloader key, and then the second stage bootloader will verify the signed partition table and app image using the public key portion of the secure boot signing key.
|
||||
|
||||
|
||||
.. _secure-boot-reflashable:
|
||||
|
||||
Reflashable Software Bootloader
|
||||
-------------------------------
|
||||
Reflashable Second Stage Bootloader
|
||||
-----------------------------------
|
||||
|
||||
Configuration ``Secure Boot: One-Time Flash`` is the recommended configuration for production devices. In this mode, each device gets a unique key that is never stored outside the device.
|
||||
|
||||
@ -229,7 +229,7 @@ The following sections contain low-level reference descriptions of various secur
|
||||
Secure Boot Hardware Support
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The first stage of secure boot verification, i.e., checking the software bootloader, is done via hardware. The {IDF_TARGET_NAME}'s secure boot support hardware can perform three basic operations:
|
||||
The first stage of secure boot verification, i.e., checking the second stage bootloader, is done via hardware. The {IDF_TARGET_NAME}'s secure boot support hardware can perform three basic operations:
|
||||
|
||||
1. Generate a random sequence of bytes from a hardware random number generator.
|
||||
|
||||
|
@ -31,7 +31,7 @@ Secure Boot v2
|
||||
|
||||
For ESP32 before chip revision v3.0, refer to :doc:`secure-boot-v1`. It is recommended to use Secure Boot v2 if you have a chip revision that supports it. Secure Boot v2 is safer and more flexible than Secure Boot V1.
|
||||
|
||||
Secure Boot v2 uses {IDF_TARGET_SBV2_SCHEME} based app and bootloader :ref:`second-stage-bootloader` verification. This document can also be used as a reference for signing apps using the {IDF_TARGET_SBV2_SCHEME} scheme without signing the bootloader.
|
||||
Secure Boot v2 uses {IDF_TARGET_SBV2_SCHEME} based app and :ref:`second-stage-bootloader` verification. This document can also be used as a reference for signing apps using the {IDF_TARGET_SBV2_SCHEME} scheme without signing the bootloader.
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
@ -49,7 +49,7 @@ Secure Boot v2
|
||||
Background
|
||||
----------
|
||||
|
||||
Secure Boot protects a device from running any unauthorized (i.e., unsigned) code by checking that each piece of software that is being booted is signed. On an {IDF_TARGET_NAME}, these pieces of software include the second stage bootloader and each application binary. Note that the first stage bootloader does not require signing as it is ROM code and thus cannot be changed.
|
||||
Secure Boot protects a device from running any unauthorized (i.e., unsigned) code by checking that each piece of software that is being booted is signed. On an {IDF_TARGET_NAME}, these pieces of software include the second stage bootloader and each application binary. Note that the first stage (ROM) bootloader does not require signing as it is ROM code and thus cannot be changed.
|
||||
|
||||
.. only:: esp32 or (SOC_SECURE_BOOT_V2_RSA and not SOC_SECURE_BOOT_V2_ECC)
|
||||
|
||||
@ -65,7 +65,7 @@ Secure Boot protects a device from running any unauthorized (i.e., unsigned) cod
|
||||
|
||||
The Secure Boot process on {IDF_TARGET_NAME} involves the following steps:
|
||||
|
||||
1. The first stage bootloader (i.e. ROM boot), which is residing in ROM, loads the second stage bootloader, and the second stage bootloader's {IDF_TARGET_SBV2_SCHEME} signature is verified. Only if the verification is successful, the second stage bootloader is executed.
|
||||
1. The first stage (ROM) bootloader loads the second stage bootloader, and the second stage bootloader's {IDF_TARGET_SBV2_SCHEME} signature is verified. Only if the verification is successful, the second stage bootloader is executed.
|
||||
|
||||
2. When the second stage bootloader loads a particular application image, the application's {IDF_TARGET_SBV2_SCHEME} signature is verified. If the verification is successful, the application image is executed.
|
||||
|
||||
@ -88,7 +88,7 @@ Advantages
|
||||
- Conservatively: The old key is revoked after the bootloader and application have successfully migrated to a new key.
|
||||
- Aggressively: The key is revoked as soon as verification with this key fails.
|
||||
|
||||
- The same image format and signature verification method is applied for applications and the software bootloader.
|
||||
- The same image format and signature verification method is applied for applications and the second stage bootloader.
|
||||
|
||||
- No secrets are stored on the device. Therefore, it is immune to passive side-channel attacks, e.g., timing or power analysis.
|
||||
|
||||
@ -415,7 +415,7 @@ How To Enable Secure Boot v2
|
||||
|
||||
``idf.py flash`` does not flash the bootloader if Secure Boot is enabled.
|
||||
|
||||
10. Reset the {IDF_TARGET_NAME} and it will boot the software bootloader you flashed. The software bootloader will enable Secure Boot on the chip, and then it verifies the app image signature and boots the app. You should watch the serial console output from the {IDF_TARGET_NAME} to verify that Secure Boot is enabled and no errors have occurred due to the build configuration.
|
||||
10. Reset the {IDF_TARGET_NAME} and it will boot the second stage bootloader you flashed. The second stage bootloader will enable Secure Boot on the chip, and then it verifies the app image signature and boots the app. You should watch the serial console output from the {IDF_TARGET_NAME} to verify that Secure Boot is enabled and no errors have occurred due to the build configuration.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -425,7 +425,7 @@ How To Enable Secure Boot v2
|
||||
|
||||
If the {IDF_TARGET_NAME} is reset or powered down during the first boot, it will start the process again on the next boot.
|
||||
|
||||
11. On subsequent boots, the Secure Boot hardware will verify the software bootloader has not changed and the software bootloader will verify the signed app image using the validated public key portion of its appended signature block.
|
||||
11. On subsequent boots, the Secure Boot hardware will verify that the second stage bootloader has not changed, and the second stage bootloader will verify the signed app image using the validated public key portion of its appended signature block.
|
||||
|
||||
|
||||
Restrictions After Secure Boot Is Enabled
|
||||
@ -589,9 +589,9 @@ Secure Boot Best Practices
|
||||
* Between 1 and 3 {IDF_TARGET_SBV2_KEY} public key pairs (Keys #0, #1, #2) should be computed independently and stored separately.
|
||||
* The KEY_DIGEST eFuses should be write-protected after being programmed.
|
||||
* The unused KEY_DIGEST slots must have their corresponding KEY_REVOKE eFuse burned to permanently disable them. This must happen before the device leaves the factory.
|
||||
* The eFuses can either be written by the software bootloader during first boot after enabling ``Secure Boot v2`` from menuconfig or can be done using ``espefuse.py`` which communicates with the serial bootloader program in ROM.
|
||||
* The eFuses can either be written by the second stage bootloader during first boot after enabling ``Secure Boot v2`` from menuconfig or can be done using ``espefuse.py`` which communicates with the serial bootloader program in ROM.
|
||||
* The KEY_DIGESTs should be numbered sequentially beginning at key digest #0. If key digest #1 is used, key digest #0 should be used. If key digest #2 is used, key digest #0 & #1 must be used.
|
||||
* The software bootloader is non-OTA upgradeable, and is signed using at least one, possibly all three, private keys and flashed in the factory.
|
||||
* The second stage bootloader is non-OTA upgradeable, and is signed using at least one, possibly all three, private keys and flashed in the factory.
|
||||
* Apps should only be signed with a single private key, with the others being stored securely elsewhere. However, they may be signed with multiple private keys if some are being revoked, see :ref:`secure-boot-v2-key-revocation` below.
|
||||
|
||||
|
||||
@ -672,8 +672,7 @@ The following sections contain low-level reference descriptions of various Secur
|
||||
|
||||
Secure Boot is integrated into the ESP-IDF build system, so ``idf.py build`` will sign an app image, and ``idf.py bootloader`` will produce a signed bootloader if :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` is enabled.
|
||||
|
||||
However, it is possible to use the ``idf.py`` or the ``openssl`` tool to generate standalone signatures and verify them. Using ``idf.py`` is recommended, but in case you need to generate or verify signatures in non-ESP-IDF environments,
|
||||
you could also use the ``openssl`` commands as the Secure Boot V2 signature generation is compliant with the standard signing algorithms.
|
||||
However, it is possible to use the ``idf.py`` or the ``openssl`` tool to generate standalone signatures and verify them. Using ``idf.py`` is recommended, but in case you need to generate or verify signatures in non-ESP-IDF environments, you could also use the ``openssl`` commands as the Secure Boot v2 signature generation is compliant with the standard signing algorithms.
|
||||
|
||||
Generating and Verifying signatures using ``idf.py``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -30,7 +30,7 @@ Goals
|
||||
#. Simplify the traditional workflow for enabling security features with stepwise instructions.
|
||||
#. Design a more flexible workflow when compared to the traditional firmware-based workflow.
|
||||
#. Improve reliability by dividing the workflow into small operations.
|
||||
#. Eliminate dependency on :ref:`second-stage-bootloader` (firmware bootloader).
|
||||
#. Eliminate dependency on :ref:`second-stage-bootloader`.
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
@ -329,7 +329,7 @@ In this case all the eFuses related to Flash Encryption are written with help of
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
If your ESP32 uses non-default :ref:`FLASH_CRYPT_CONFIG value in eFuse <setting-flash-crypt-config>` then you will need to pass the ``--flash_crypt_conf`` argument to ``espsecure.py`` to set the matching value. This will not happen when the Flash Encryption is enabled by the firmware bootloader but may happen when burning eFuses manually to enable Flash Encryption.
|
||||
If your ESP32 uses non-default :ref:`FLASH_CRYPT_CONFIG value in eFuse <setting-flash-crypt-config>` then you will need to pass the ``--flash_crypt_conf`` argument to ``espsecure.py`` to set the matching value. This will not happen when the Flash Encryption is enabled by the second stage bootloader but may happen when burning eFuses manually to enable Flash Encryption.
|
||||
|
||||
The command ``espsecure.py decrypt_flash_data`` can be used with the same options (and different input or output files), to decrypt ciphertext flash contents or a previously encrypted file.
|
||||
|
||||
@ -523,7 +523,7 @@ In this workflow we shall use ``espsecure`` tool to generate signing keys and us
|
||||
|
||||
6. Configure the project
|
||||
|
||||
By default, the ROM bootloader would only verify the :ref:`second-stage-bootloader` (firmware bootloader). The firmware bootloader would verify the app partition only when the :ref:`CONFIG_SECURE_BOOT` option is enabled (and :ref:`CONFIG_SECURE_BOOT_VERSION` is set to ``SECURE_BOOT_V2_ENABLED``) while building the bootloader.
|
||||
By default, the first stage (ROM) bootloader would only verify the :ref:`second-stage-bootloader`. The second stage bootloader would verify the app partition only when the :ref:`CONFIG_SECURE_BOOT` option is enabled (and :ref:`CONFIG_SECURE_BOOT_VERSION` is set to ``SECURE_BOOT_V2_ENABLED``) while building the bootloader.
|
||||
|
||||
A) Open the :ref:`project-configuration-menu`, in ``Security features`` set ``Enable hardware Secure Boot in bootloader`` to enable Secure Boot.
|
||||
|
||||
|
@ -125,7 +125,7 @@ The local ESP-IDF version can be checked by using idf.py::
|
||||
|
||||
idf.py --version
|
||||
|
||||
The ESP-IDF version is also compiled into the firmware and can be accessed (as a string) via the macro ``IDF_VER``. The default ESP-IDF bootloader will print the version on boot (the version information is not always updated if the code in the GitHub repo is updated, it only changes if there is a clean build or if that particular source file is recompiled).
|
||||
The ESP-IDF version is also compiled into the firmware and can be accessed (as a string) via the macro ``IDF_VER``. The default ESP-IDF bootloader prints the version on boot (The version information is not always updated if the code in the GitHub repo is updated, it only changes if there is a clean build or if that particular source file is recompiled).
|
||||
|
||||
If writing code that needs to support multiple ESP-IDF versions, the version can be checked at compile time using :ref:`compile-time macros <idf-version-h>`.
|
||||
|
||||
|
@ -3,16 +3,16 @@
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
ESP-IDF 软件引导加载程序 (Bootloader) 主要执行以下任务:
|
||||
ESP-IDF 二级引导加载程序 (second stage bootloader) 主要执行以下任务:
|
||||
|
||||
1. 内部模块的最小化初始配置;
|
||||
2. 如果配置了 :doc:`/security/flash-encryption` 和/或 :doc:`Secure Boot </security/secure-boot-v2>`,则对其进行初始化。
|
||||
3. 根据分区表和 ota_data(如果存在)选择需要引导的应用程序 (app) 分区;
|
||||
4. 将此应用程序镜像加载到 RAM(IRAM 和 DRAM)中,最后把控制权转交给此应用程序。
|
||||
|
||||
引导加载程序位于 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处。
|
||||
ESP-IDF 二级引导加载程序位于 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处。
|
||||
|
||||
关于启动过程以及 ESP-IDF 引导加载程序的更多信息,请参考 :doc:`startup`。
|
||||
如需了解包括 ESP-IDF 二级引导加载程序在内的完整启动过程,请参考 :doc:`startup`。
|
||||
|
||||
.. _bootloader-compatibility:
|
||||
|
||||
@ -21,11 +21,11 @@ ESP-IDF 软件引导加载程序 (Bootloader) 主要执行以下任务:
|
||||
|
||||
建议使用最新发布的 :doc:`ESP-IDF 版本 </versions>`。OTA(空中升级)更新可以在现场烧录新的应用程序,但不能烧录一个新的引导加载程序。因此,引导加载程序支持引导从 ESP-IDF 新版本中构建的应用程序。
|
||||
|
||||
但不支持引导从 ESP-IDF 旧版本中构建的程序。如果现有产品可能需要将应用程序降级到旧版本,那么在手动更新 ESP-IDF 时,请继续使用旧版本 ESP-IDF 引导加载程序的二进制文件。
|
||||
但不支持引导从 ESP-IDF 旧版本中构建的程序。如果现有产品可能需要将应用程序降级到旧版本,那么在手动更新 ESP-IDF 时,请继续使用旧版本引导加载程序的二进制文件。
|
||||
|
||||
.. note::
|
||||
|
||||
如果在生产中测试现有产品的 OTA 更新,请确保测试中使用的 ESP-IDF 引导加载程序二进制文件与生产中部署的相同。
|
||||
如果在生产中测试现有产品的 OTA 更新,请确保测试中使用的引导加载程序二进制文件与生产中部署的相同。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
@ -50,11 +50,11 @@ ESP-IDF 软件引导加载程序 (Bootloader) 主要执行以下任务:
|
||||
|
||||
每个 ESP-IDF 应用程序或引导加载程序的二进制文件中都包含一个文件头,其中内置了 :ref:`CONFIG_ESPTOOLPY_FLASHMODE`、:ref:`CONFIG_ESPTOOLPY_FLASHFREQ`、和 :ref:`CONFIG_ESPTOOLPY_FLASHSIZE`。这些是用于在启动时配置 SPI flash。
|
||||
|
||||
ROM 中的 :ref:`first-stage-bootloader` 从 flash 中读取 :ref:`second-stage-bootloader` 文件头中的配置信息,并使用这些信息来加载剩余的 :ref:`second-stage-bootloader`。然而,此时系统的时钟速度低于其被配置的速度,并且在这个阶段,只支持部分 flash 模式。因此,当 :ref:`second-stage-bootloader` 运行时,它会从当前应用程序的二进制文件头中读取数据(而不是从引导加载程序的文件头中读取数据),并使用这些数据重新配置 flash。这样的配置流程可让 OTA 更新去更改当前使用的 SPI flash 的配置。
|
||||
:ref:`first-stage-bootloader` 从 flash 中读取 :ref:`second-stage-bootloader` 文件头中的配置信息,并使用这些信息来加载剩余的 :ref:`second-stage-bootloader`。然而,此时系统的时钟速度低于其被配置的速度,并且在这个阶段,只支持部分 flash 模式。因此,当 :ref:`second-stage-bootloader` 运行时,它会从当前应用程序的二进制文件头中读取数据(而不是从 :ref:`second-stage-bootloader` 的文件头中读取数据),并使用这些数据重新配置 flash。这样的配置流程可让 OTA 更新去更改当前使用的 SPI flash 的配置。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
ESP-IDF V4.0 版本之前的引导加载程序使用其自身的文件头来配置 SPI flash,这意味着无法在 OTA 更新时更改 SPI flash 配置。为了与旧引导加载程序兼容,应用程序在其启动期间使用应用程序文件头中的配置信息重新初始化 flash 配置。
|
||||
ESP-IDF V4.0 版本之前的引导加载程序使用其自身的文件头来配置 SPI flash,这意味着无法在 OTA 更新时更改 SPI flash 配置。为了与旧版本的引导加载程序兼容,应用程序在其启动期间使用应用程序文件头中的配置信息重新初始化 flash 配置。
|
||||
|
||||
日志级别
|
||||
---------
|
||||
@ -125,7 +125,7 @@ ROM 中的 :ref:`first-stage-bootloader` 从 flash 中读取 :ref:`second-stage-
|
||||
回滚
|
||||
--------
|
||||
|
||||
回滚和反回滚功能也必须在引导程序中配置。
|
||||
回滚和反回滚功能也必须在引导加载程序中配置。
|
||||
|
||||
请参考 :doc:`OTA API 参考文档 </api-reference/system/ota>` 中的 :ref:`app_rollback` 和 :ref:`anti-rollback` 章节。
|
||||
|
||||
@ -157,7 +157,7 @@ ROM 中的 :ref:`first-stage-bootloader` 从 flash 中读取 :ref:`second-stage-
|
||||
|
||||
可以使用如下方法解决此问题:
|
||||
|
||||
- 将 :ref:`bootloader 编译器优化 <CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION>` 重新设置回默认值“Size”。
|
||||
- 将 :ref:`引导加载程序编译器优化 <CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION>` 重新设置回默认值“Size”。
|
||||
- 降低 :ref:`引导加载程序日志级别 <CONFIG_BOOTLOADER_LOG_LEVEL>`。将日志级别设置为 Warning, Error 或 None 都会显著减少最终二进制文件的大小(但也可能会让调试变得更加困难)。
|
||||
- 将 :ref:`CONFIG_PARTITION_TABLE_OFFSET` 设置为高于 0x8000 的值,以便稍后将分区表放置在 flash 中,这样可以增加引导加载程序的可用空间。如果 :doc:`分区表 </api-guides/partition-tables>` 的 CSV 文件包含明确的分区偏移量,则需要修改这些偏移量,从而保证没有分区的偏移量低于 ``CONFIG_PARTITION_TABLE_OFFSET + 0x1000``。(这包括随 ESP-IDF 提供的默认分区 CSV 文件)
|
||||
|
||||
@ -186,4 +186,4 @@ ROM 中的 :ref:`first-stage-bootloader` 从 flash 中读取 :ref:`second-stage-
|
||||
|
||||
在引导加载程序的代码中,用户不能使用其他组件提供的驱动和函数,如果确实需要,请将该功能的实现部分放在项目的 `bootloader_components` 目录中(注意,这会增加引导加载程序的大小)。
|
||||
|
||||
如果引导加载程序过大,则可能与内存中的分区表重叠,分区表默认烧录在偏移量 0x8000 处。增加 :ref:`分区表偏移量 <CONFIG_PARTITION_TABLE_OFFSET>` ,将分区表放在 flash 中靠后的区域,这样可以增加引导程序的可用空间。
|
||||
如果引导加载程序过大,则可能与内存中的分区表重叠,分区表默认烧录在偏移量 0x8000 处。增加 :ref:`分区表偏移量 <CONFIG_PARTITION_TABLE_OFFSET>` ,将分区表放在 flash 中靠后的区域,这样可以增加引导加载程序的可用空间。
|
||||
|
@ -25,11 +25,11 @@ ESP-IDF 可以显式地指定和配置每个组件。在构建项目的时候,
|
||||
概念
|
||||
----
|
||||
|
||||
- ``项目`` 特指一个目录,其中包含了构建可执行应用程序所需的全部文件和配置,以及其他支持型文件,例如分区表、数据/文件系统分区和引导程序。
|
||||
- ``项目`` 特指一个目录,其中包含了构建可执行应用程序所需的全部文件和配置,以及其他支持型文件,例如分区表、数据/文件系统分区和引导加载程序。
|
||||
|
||||
- ``项目配置`` 保存在项目根目录下名为 ``sdkconfig`` 的文件中,可以通过 ``idf.py menuconfig`` 进行修改,且一个项目只能包含一个项目配置。
|
||||
|
||||
- ``应用程序`` 是由 ESP-IDF 构建得到的可执行文件。一个项目通常会构建两个应用程序:项目应用程序(可执行的主文件,即用户自定义的固件)和引导程序(启动并初始化项目应用程序)。
|
||||
- ``应用程序`` 是由 ESP-IDF 构建得到的可执行文件。一个项目通常会构建两个应用程序:项目应用程序(可执行的主文件,即用户自定义的固件)和引导加载程序(启动并初始化项目应用程序)。
|
||||
|
||||
- ``组件`` 是模块化且独立的代码,会被编译成静态库(.a 文件)并链接到应用程序。部分组件由 ESP-IDF 官方提供,其他组件则来源于其它开源项目。
|
||||
|
||||
@ -97,7 +97,7 @@ idf.py
|
||||
|
||||
make app-flash
|
||||
|
||||
可用的目标还包括:``flash``、``app-flash`` (仅用于 app)、``bootloader-flash`` (仅用于 bootloader)。
|
||||
可用的目标还包括:``flash``、``app-flash`` (仅用于 app)、``bootloader-flash`` (仅用于引导加载程序)。
|
||||
|
||||
以这种方式烧录时,可以通过设置 ``ESPPORT`` 和 ``ESPBAUD`` 环境变量来指定串口设备和波特率。可以在操作系统或 IDE 项目中设置该环境变量,或者直接在命令行中进行设置::
|
||||
|
||||
@ -1093,9 +1093,9 @@ flash 参数
|
||||
|
||||
运行项目构建之后,构建目录将包含项目二进制输出文件(``.bin`` 文件),同时也包含以下烧录数据文件:
|
||||
|
||||
- ``flash_project_args`` 包含烧录整个项目的参数,包括应用程序 (app)、引导程序 (bootloader)、分区表,如果设置了 PHY 数据,也会包含此数据。
|
||||
- ``flash_project_args`` 包含烧录整个项目的参数,包括应用程序 (app)、引导加载程序 (bootloader)、分区表,如果设置了 PHY 数据,也会包含此数据。
|
||||
- ``flash_app_args`` 只包含烧录应用程序的参数。
|
||||
- ``flash_bootloader_args`` 只包含烧录引导程序的参数。
|
||||
- ``flash_bootloader_args`` 只包含烧录引导加载程序的参数。
|
||||
|
||||
.. highlight:: bash
|
||||
|
||||
@ -1108,12 +1108,12 @@ flash 参数
|
||||
构建目录中还包含生成的 ``flasher_args.json`` 文件,此文件包含 JSON 格式的项目烧录信息,可用于 ``idf.py`` 和其它需要项目构建信息的工具。
|
||||
|
||||
|
||||
构建 Bootloader
|
||||
===============
|
||||
构建引导加载程序
|
||||
================
|
||||
|
||||
引导程序是 :idf:`/components/bootloader/subproject` 内部独特的“子项目”,它有自己的项目 CMakeLists.txt 文件,能够构建独立于主项目的 ``.ELF`` 和 ``.BIN`` 文件,同时它又与主项目共享配置和构建目录。
|
||||
引导加载程序是 :idf:`/components/bootloader/subproject` 内部独特的“子项目”,它有自己的项目 CMakeLists.txt 文件,能够构建独立于主项目的 ``.ELF`` 和 ``.BIN`` 文件,同时它又与主项目共享配置和构建目录。
|
||||
|
||||
子项目通过 :idf_file:`/components/bootloader/project_include.cmake` 文件作为外部项目插入到项目的顶层,主构建进程会运行子项目的 CMake,包括查找组件(主项目使用的组件的子集),生成引导程序专用的配置文件(从主 ``sdkconfig`` 文件中派生)。
|
||||
子项目通过 :idf_file:`/components/bootloader/project_include.cmake` 文件作为外部项目插入到项目的顶层,主构建进程会运行子项目的 CMake,包括查找组件(主项目使用的组件的子集),生成引导加载程序专用的配置文件(从主 ``sdkconfig`` 文件中派生)。
|
||||
|
||||
|
||||
.. _write-pure-component:
|
||||
@ -1668,9 +1668,9 @@ CMake 中不可用的功能
|
||||
应用示例
|
||||
--------------------
|
||||
|
||||
- :example:`build_system/wrappers` 演示了如何使用链接器功能在 ESP-IDF 和引导程序中重新定义或覆盖任何公共函数,以修改或扩展函数的默认行为。
|
||||
- :example:`build_system/wrappers` 演示了如何使用链接器功能在 ESP-IDF 和引导加载程序中重新定义或覆盖任何公共函数,以修改或扩展函数的默认行为。
|
||||
|
||||
- :example:`custom_bootloader/bootloader_override` 演示了如何从常规项目中覆盖二级引导程序,提供一个自定义引导程序,在启动时打印额外的消息,并能够基于某些条件(如目标依赖性或 KConfig 选项)有条件地覆盖引导程序。
|
||||
- :example:`custom_bootloader/bootloader_override` 演示了如何从常规项目中覆盖二级引导加载程序,提供一个自定义引导加载程序,在启动时打印额外的消息,并能够基于某些条件(如目标依赖性或 KConfig 选项)有条件地覆盖引导加载程序。
|
||||
|
||||
- :example:`build_system/cmake/import_lib` 演示了如何使用 ExternalProject CMake 模块导入和使用第三方库。
|
||||
|
||||
|
@ -288,14 +288,14 @@ RTC 看门狗超时
|
||||
----------------
|
||||
{IDF_TARGET_RTCWDT_RTC_RESET:default="Not updated", esp32="RTCWDT_RTC_RESET", esp32s2="RTCWDT_RTC_RST", esp32s3="RTCWDT_RTC_RST", esp32c3="RTCWDT_RTC_RST", esp32c2="RTCWDT_RTC_RST", esp32c6="LP_WDT_SYS", esp32h2="LP_WDT_SYS", esp32p4="LP_WDT_SYS"}
|
||||
|
||||
RTC 看门狗在启动代码中用于跟踪执行时间,也有助于防止由于电源不稳定引起的锁定。RTC 看门狗默认启用,参见 :ref:`CONFIG_BOOTLOADER_WDT_ENABLE`。如果执行时间超时,RTC 看门狗将自动重启系统。此时,ROM 引导加载程序将打印消息 ``RTC Watchdog Timeout`` 说明重启原因。
|
||||
RTC 看门狗在启动代码中用于跟踪执行时间,也有助于防止由于电源不稳定引起的锁定。RTC 看门狗默认启用,参见 :ref:`CONFIG_BOOTLOADER_WDT_ENABLE`。如果执行时间超时,RTC 看门狗将自动重启系统。此时,一级 (ROM) 引导加载程序将打印消息 ``RTC Watchdog Timeout`` 说明重启原因。
|
||||
|
||||
::
|
||||
|
||||
rst:0x10 ({IDF_TARGET_RTCWDT_RTC_RESET})
|
||||
|
||||
|
||||
RTC 看门狗涵盖了从一级引导程序(ROM 引导程序)到应用程序启动的执行时间,最初在 ROM 引导程序中设置,而后在引导程序中使用 :ref:`CONFIG_BOOTLOADER_WDT_TIME_MS` 选项进行配置(默认 9000 ms)。在应用初始化阶段,由于慢速时钟源可能已更改,RTC 看门狗将被重新配置,最后在调用 ``app_main()`` 之前被禁用。可以使用选项 :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` 以保证 RTC 看门狗在调用 ``app_main`` 之前不被禁用,而是保持运行状态,用户需要在应用代码中定期“喂狗”。
|
||||
RTC 看门狗涵盖了从一级 (ROM) 引导加载程序到应用程序启动的执行时间,最初在一级 (ROM) 引导加载程序中设置,而后在引导加载程序中使用 :ref:`CONFIG_BOOTLOADER_WDT_TIME_MS` 选项进行配置(默认 9000 ms)。在应用初始化阶段,由于慢速时钟源可能已更改,RTC 看门狗将被重新配置,最后在调用 ``app_main()`` 之前被禁用。可以使用选项 :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` 以保证 RTC 看门狗在调用 ``app_main`` 之前不被禁用,而是保持运行状态,用户需要在应用代码中定期“喂狗”。
|
||||
|
||||
.. _Guru-Meditation-Errors:
|
||||
|
||||
|
@ -73,7 +73,7 @@ SPI Flash 和片外 SPI RAM 配置
|
||||
|
||||
.. note::
|
||||
|
||||
如果配有八线 flash 的开发板在第二阶段引导加载程序之前复位,请参考 :ref:`错误处理章节 <flash-psram-error>`。
|
||||
如果配有八线 flash 的开发板在二级引导加载程序之前复位,请参考 :ref:`错误处理章节 <flash-psram-error>`。
|
||||
|
||||
|
||||
.. _flash-psram-combination:
|
||||
@ -228,7 +228,7 @@ F4R4 硬件
|
||||
错误处理
|
||||
--------
|
||||
|
||||
1. 如果配有八线 flash 的开发板在第二阶段引导加载程序之前复位:
|
||||
1. 如果配有八线 flash 的开发板在二级引导加载程序之前复位:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
@ -243,7 +243,7 @@ F4R4 硬件
|
||||
|
||||
这可能意味着必要的 efuse 未得到正确烧录。请使用命令 ``espefuse.py summary``,检查芯片的 eFuse 位。
|
||||
|
||||
ROM 引导加载程序可通过 eFuse 位 ``FLASH_TYPE`` 将 flash 复位为默认模式(SPI 模式)。如果未烧录此位,且 flash 处于 OPI 模式,则 ROM 引导加载程序可能无法从 flash 中读取并加载以下图像。
|
||||
一级 (ROM) 引导加载程序可通过 eFuse 位 ``FLASH_TYPE`` 将 flash 复位为默认模式(SPI 模式)。如果未烧录此位,且 flash 处于 OPI 模式,则一级 (ROM) 引导加载程序可能无法从 flash 中读取并加载以下图像。
|
||||
|
||||
2. 如果启用 :ref:`CONFIG_ESPTOOLPY_OCT_FLASH` 后出现如下错误日志:
|
||||
|
||||
|
@ -232,7 +232,7 @@ JTAG 管脚是否能用于其他功能
|
||||
JTAG 与 flash 加密和安全引导
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
默认情况下,开启了 flash 加密和(或者)安全引导后,系统在首次启动时,引导程序会烧写 eFuse 的某个比特,从而将 JTAG 永久关闭。
|
||||
默认情况下,开启了 flash 加密和(或者)安全引导后,系统在首次启动时,引导加载程序会烧写 eFuse 的某个比特,从而将 JTAG 永久关闭。
|
||||
|
||||
.. only:: SOC_HMAC_SUPPORTED
|
||||
|
||||
@ -249,7 +249,7 @@ Kconfig 配置项 :ref:`CONFIG_SECURE_BOOT_ALLOW_JTAG` 可以改变这个默认
|
||||
|
||||
.. note::
|
||||
|
||||
同样地,当启用该选项,并且在调试过程中设置了软件断点,引导程序将无法校验通过应用程序的签名。
|
||||
同样地,当启用该选项,并且在调试过程中设置了软件断点,引导加载程序将无法校验通过应用程序的签名。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
factory, app, factory, 0x10000, 1M,
|
||||
|
||||
- flash 的 0x10000 (64 KB) 偏移地址处存放一个标记为 "factory" 的二进制应用程序,且启动加载器将默认加载这个应用程序。
|
||||
- flash 的 0x10000 (64 KB) 偏移地址处存放一个标记为 "factory" 的二进制应用程序。引导加载程序默认加载这个应用程序。
|
||||
- 分区表中还定义了两个数据区域,分别用于存储 NVS 库专用分区和 PHY 初始化数据。
|
||||
|
||||
以下是 "Factory app, two OTA definitions" 选项的分区表信息摘要::
|
||||
@ -45,7 +45,7 @@
|
||||
ota_1, app, ota_1, 0x210000, 1M,
|
||||
|
||||
- 分区表中定义了三个应用程序分区,这三个分区的类型都被设置为 “app”,但具体 app 类型不同。其中,位于 0x10000 偏移地址处的为出厂应用程序 (factory),其余两个为 OTA 应用程序(ota_0,ota_1)。
|
||||
- 新增了一个名为 “otadata” 的数据分区,用于保存 OTA 升级时需要的数据。启动加载器会查询该分区的数据,以判断该从哪个 OTA 应用程序分区加载程序。如果 “otadata” 分区为空,则会执行出厂程序。
|
||||
- 新增了一个名为 “otadata” 的数据分区,用于保存 OTA 升级时需要的数据。引导加载程序会查询该分区的数据,以判断该从哪个 OTA 应用程序分区加载程序。如果 “otadata” 分区为空,则会执行出厂程序。
|
||||
|
||||
创建自定义分区表
|
||||
----------------
|
||||
@ -85,7 +85,7 @@ Type 字段可以指定为 app (0x00) 或者 data (0x01),也可以直接使用
|
||||
|
||||
static const esp_partition_type_t APP_PARTITION_TYPE_A = (esp_partition_type_t)0x40;
|
||||
|
||||
注意,启动加载器将忽略 ``app`` (0x00) 和 ``data`` (0x01) 以外的其他分区类型。
|
||||
注意,引导加载程序会忽略 ``app`` (0x00) 和 ``data`` (0x01) 以外的其他分区类型。
|
||||
|
||||
SubType 字段
|
||||
~~~~~~~~~~~~
|
||||
@ -97,13 +97,13 @@ SubType 字段长度为 8 bit,内容与具体分区 Type 有关。目前,esp
|
||||
|
||||
* 当 Type 定义为 ``app`` 时,SubType 字段可以指定为 ``factory`` (0x00)、 ``ota_0`` (0x10) … ``ota_15`` (0x1F) 或者 ``test`` (0x20)。
|
||||
|
||||
- ``factory`` (0x00) 是默认的 app 分区。启动加载器将默认加载该应用程序。但如果存在类型为 data/ota 分区,则启动加载器将加载 data/ota 分区中的数据,进而判断启动哪个 OTA 镜像文件。
|
||||
- ``factory`` (0x00) 是默认的 app 分区。引导加载程序默认加载该应用程序。但如果存在类型为 data/ota 的分区,则引导加载程序将加载 data/ota 分区中的数据,进而判断启动哪个 OTA 镜像文件。
|
||||
|
||||
- OTA 升级永远都不会更新 factory 分区中的内容。
|
||||
- 如果你希望在 OTA 项目中预留更多 flash,可以删除 factory 分区,转而使用 ota_0 分区。
|
||||
|
||||
- ota_0 (0x10) … ota_15 (0x1F) 为 OTA 应用程序分区,启动加载器将根据 OTA 数据分区中的数据来决定加载哪个 OTA 应用程序分区中的程序。在使用 OTA 功能时,应用程序应至少拥有 2 个 OTA 应用程序分区(``ota_0`` 和 ``ota_1``)。更多详细信息,请参考 :doc:`OTA 文档 </api-reference/system/ota>` 。
|
||||
- ``test`` (0x20) 为预留的子类型,用于工厂测试流程。如果没有其他有效 app 分区,test 将作为备选启动分区使用。也可以配置启动加载器在每次启动时读取 GPIO,如果 GPIO 被拉低则启动该分区。详细信息请查阅 :ref:`bootloader_boot_from_test_firmware`。
|
||||
- ota_0 (0x10) … ota_15 (0x1F) 为 OTA 应用程序分区,引导加载程序将根据 OTA 数据分区中的数据来决定加载哪个 OTA 应用程序分区中的程序。在使用 OTA 功能时,应用程序应至少拥有 2 个 OTA 应用程序分区(``ota_0`` 和 ``ota_1``)。更多详细信息,请参考 :doc:`OTA 文档 </api-reference/system/ota>` 。
|
||||
- ``test`` (0x20) 为预留的子类型,用于工厂测试流程。如果没有其他有效 app 分区,test 将作为备选启动分区使用。也可以配置引导加载程序在每次启动时读取 GPIO,如果 GPIO 被拉低则启动该分区。详细信息请查阅 :ref:`bootloader_boot_from_test_firmware`。
|
||||
|
||||
* 当 Type 定义为 ``data`` 时,SubType 字段可以指定为 ``ota`` (0x00)、``phy`` (0x01)、``nvs`` (0x02)、``nvs_keys`` (0x04) 或者其他组件特定的子类型(请参考 :cpp:type:`子类型枚举 <esp_partition_subtype_t>`).
|
||||
|
||||
|
@ -199,9 +199,9 @@ IRAM 优化
|
||||
将 SRAM1 用于 IRAM
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
SRAM1 内存区域通常用于 DRAM 存储,但可以设置 :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM` 选项,将其中一部分用作 IRAM 存储。引入该选项前,这个内存区域通常预留给 DRAM 数据使用(如 ``.bss`` ),随后由软件引导加载程序加入到堆中。引入该选项后,引导加载程序的 DRAM 大小会减少到更接近实际需要的值。
|
||||
SRAM1 内存区域通常用于 DRAM 存储,但可以设置 :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM` 选项,将其中一部分用作 IRAM 存储。引入该选项前,这个内存区域通常预留给 DRAM 数据使用(如 ``.bss``),随后由二级引导加载程序加入到堆中。引入该选项后,二级引导加载程序的 DRAM 大小会减少到更接近实际需要的值。
|
||||
|
||||
要使用以上选项,ESP-IDF 应能够将新的 SRAM1 区域识别为有效镜像段的加载地址。部分应用程序的代码置于新扩展的 IRAM 区域,如果软件引导加载程序在引入该选项前编译,将无法加载这类应用程序。这类情况通常在进行 OTA 更新时发生,此时仅会更新应用程序。
|
||||
要使用以上选项,ESP-IDF 应能够将新的 SRAM1 区域识别为有效镜像段的加载地址。部分应用程序的代码置于新扩展的 IRAM 区域,如果二级引导加载程序在引入该选项前编译,将无法加载这类应用程序。这类情况通常在进行 OTA 更新时发生,此时仅会更新应用程序。
|
||||
|
||||
如果 IRAM 段放置在无效区域,在启动过程中将检测到以下问题,并导致启动失败:
|
||||
|
||||
@ -211,7 +211,7 @@ IRAM 优化
|
||||
|
||||
.. warning::
|
||||
|
||||
若与在引入以上配置选项前编译的软件引导加载程序一同使用,使用 :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM` 选项编译的应用程序很可能无法启动。若使用旧版本的引导加载程序,并进行 OTA 更新,请在提交任何更新前仔细测试。
|
||||
若与在引入以上配置选项前编译的二级引导加载程序一同使用,使用 :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM` 选项编译的应用程序很可能无法启动。若使用旧版本的引导加载程序,并进行 OTA 更新,请在提交任何更新前仔细测试。
|
||||
|
||||
任何最终未用于静态 IRAM 的内存都将添加到堆内存中。
|
||||
|
||||
|
@ -260,7 +260,7 @@ MbedTLS 功能
|
||||
|
||||
本文档仅涉及 ESP-IDF 应用程序的二进制文件大小,而不涉及 ESP-IDF :ref:`second-stage-bootloader`。
|
||||
|
||||
关于 ESP-IDF 引导加载程序二进制文件大小的讨论,参阅 :ref:`bootloader-size`。
|
||||
关于 ESP-IDF 引导加载程序二进制文件大小的讨论,请参阅 :ref:`bootloader-size`。
|
||||
|
||||
IRAM 二进制文件大小
|
||||
------------------------------------
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
.. list::
|
||||
|
||||
1. :ref:`first-stage-bootloader` 被固化在了 {IDF_TARGET_NAME} 内部的 ROM 中,它会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载二级引导程序至 RAM (IRAM & DRAM) 中。
|
||||
1. :ref:`first-stage-bootloader` 被固化在了 {IDF_TARGET_NAME} 内部的 ROM 中,它会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载二级引导加载程序至 RAM (IRAM & DRAM) 中。
|
||||
|
||||
2. :ref:`second-stage-bootloader` 从 flash 中加载分区表和主程序镜像至内存中,主程序中包含了 RAM 段和通过 flash 高速缓存映射的只读段。
|
||||
|
||||
@ -21,8 +21,8 @@
|
||||
|
||||
.. _first-stage-bootloader:
|
||||
|
||||
一级引导程序
|
||||
~~~~~~~~~~~~
|
||||
一级 (ROM) 引导加载程序
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES
|
||||
|
||||
@ -48,45 +48,45 @@
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
二级引导程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。如果正在使用 :doc:`/security/secure-boot-v1`,则 flash 的第一个 4 kB 扇区用于存储安全启动 IV 以及引导程序镜像的摘要,否则不使用该扇区。
|
||||
二级引导加载程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。如果正在使用 :doc:`/security/secure-boot-v1`,则 flash 的第一个 4 kB 扇区用于存储安全启动 IV 以及引导加载程序镜像的摘要,否则不使用该扇区。
|
||||
|
||||
.. only:: esp32s2
|
||||
|
||||
二级引导程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。该地址前面的 flash 4 kB 扇区未使用。
|
||||
二级引导加载程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。该地址前面的 flash 4 kB 扇区未使用。
|
||||
|
||||
.. only:: SOC_KEY_MANAGER_SUPPORTED
|
||||
|
||||
二级引导程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。该地址前面的 flash 8 kB 扇区将为密钥管理器保留,用于与 flash 加密 (AES-XTS) 相关的操作。
|
||||
二级引导加载程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。该地址前面的 flash 8 kB 扇区将为密钥管理器保留,用于与 flash 加密 (AES-XTS) 相关的操作。
|
||||
|
||||
.. only:: not (esp32 or esp32s2 or SOC_KEY_MANAGER_SUPPORTED)
|
||||
|
||||
二级引导程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。
|
||||
二级引导加载程序二进制镜像会从 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处加载。
|
||||
|
||||
.. TODO: describe application binary image format, describe optional flash configuration commands.
|
||||
|
||||
.. _second-stage-bootloader:
|
||||
|
||||
二级引导程序
|
||||
~~~~~~~~~~~~
|
||||
二级引导加载程序
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
在 ESP-IDF 中,存放在 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处的二进制镜像就是二级引导程序。二级引导程序的源码可以在 ESP-IDF 的 :idf:`components/bootloader` 目录下找到。ESP-IDF 使用二级引导程序可以增加 flash 分区的灵活性(使用分区表),并且方便实现 flash 加密,安全引导和空中升级 (OTA) 等功能。
|
||||
在 ESP-IDF 中,存放在 flash 的 {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} 偏移地址处的二进制镜像就是二级引导加载程序。二级引导加载程序的源码可以在 ESP-IDF 的 :idf:`components/bootloader` 目录下找到。ESP-IDF 使用二级引导加载程序可以增加 flash 分区的灵活性(使用分区表),并且方便实现 flash 加密,安全引导和空中升级 (OTA) 等功能。
|
||||
|
||||
当一级引导程序校验并加载完二级引导程序后,它会从二进制镜像的头部找到二级引导程序的入口点,并跳转过去运行。
|
||||
当一级 (ROM) 引导加载程序校验并加载完二级引导加载程序后,它会从二进制镜像的头部找到二级引导加载程序的入口点,并跳转过去运行。
|
||||
|
||||
二级引导程序默认从 flash 的 {IDF_TARGET_CONFIG_PARTITION_TABLE_OFFSET} 偏移地址处(:ref:`可配置的值 <CONFIG_PARTITION_TABLE_OFFSET>`)读取分区表。请参考 :doc:`分区表 <partition-tables>` 获取详细信息。引导程序会寻找工厂分区和 OTA 应用程序分区。如果在分区表中找到了 OTA 应用程序分区,引导程序将查询 ``otadata`` 分区以确定应引导哪个分区。更多信息请参考 :doc:`/api-reference/system/ota`。
|
||||
二级引导加载程序默认从 flash 的 {IDF_TARGET_CONFIG_PARTITION_TABLE_OFFSET} 偏移地址处(:ref:`可配置的值 <CONFIG_PARTITION_TABLE_OFFSET>`)读取分区表。请参考 :doc:`分区表 <partition-tables>` 获取详细信息。引导加载程序会寻找工厂分区和 OTA 应用程序分区。如果在分区表中找到了 OTA 应用程序分区,引导加载程序将查询 ``otadata`` 分区以确定应引导哪个分区。更多信息请参考 :doc:`/api-reference/system/ota`。
|
||||
|
||||
关于 ESP-IDF 引导程序可用的配置选项,请参考 :doc:`bootloader`。
|
||||
关于 ESP-IDF 引导加载程序可用的配置选项,请参考 :doc:`bootloader`。
|
||||
|
||||
对于选定的分区,二级引导程序将从 flash 逐段读取二进制镜像:
|
||||
对于选定的分区,二级引导加载程序将从 flash 逐段读取二进制镜像:
|
||||
|
||||
- 对于在内部 :ref:`iram` 或 :ref:`dram` 中具有加载地址的段,将把数据从 flash 复制到它们的加载地址处。
|
||||
- 对于一些加载地址位于 :ref:`drom` 或 :ref:`irom` 区域的段,通过配置 flash MMU,可为从 flash 到加载地址提供正确的映射。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
请注意,二级引导程序同时为 PRO CPU 和 APP CPU 配置 flash MMU,但仅使能 PRO CPU 的 flash MMU。原因是二级引导程序代码已加载到 APP CPU 的高速缓存使用的内存区域中。因此使能 APP CPU 高速缓存的任务就交给了应用程序。
|
||||
请注意,二级引导加载程序同时为 PRO CPU 和 APP CPU 配置 flash MMU,但仅使能 PRO CPU 的 flash MMU。原因是二级引导加载程序代码已加载到 APP CPU 的高速缓存使用的内存区域中。因此使能 APP CPU 高速缓存的任务就交给了应用程序。
|
||||
|
||||
一旦处理完所有段(即加载了代码并设置了 flash MMU),二级引导程序将验证应用程序的完整性,并从二进制镜像文件的头部寻找入口地址,然后跳转到该地址处运行。
|
||||
一旦处理完所有段(即加载了代码并设置了 flash MMU),二级引导加载程序将验证应用程序的完整性,并从二进制镜像文件的头部寻找入口地址,然后跳转到该地址处运行。
|
||||
|
||||
.. _application-startup:
|
||||
|
||||
@ -108,7 +108,7 @@
|
||||
|
||||
ESP-IDF 应用程序的入口是 :idf_file:`components/esp_system/port/cpu_start.c` 文件中的 ``call_start_cpu0`` 函数。这个函数由二级引导加载程序执行,并且从不返回。
|
||||
|
||||
该端口层的初始化功能会初始化基本的 C 运行环境 ("CRT"),并对 SoC 的内部硬件进行了初始配置。
|
||||
该端口层的初始化功能会初始化基本的 C 运行环境 ("CRT"),并对 SoC 的内部硬件进行了初始配置。
|
||||
|
||||
.. list::
|
||||
|
||||
@ -119,7 +119,7 @@ ESP-IDF 应用程序的入口是 :idf_file:`components/esp_system/port/cpu_start
|
||||
:SOC_SPIRAM_SUPPORTED: - 如果配置了 PSRAM,则使能 PSRAM。
|
||||
- 将 CPU 时钟设置为项目配置的频率。
|
||||
:SOC_MEMPROT_SUPPORTED: - 如果配置了内存保护,则初始化内存保护。
|
||||
:esp32: - 根据应用程序头部设置重新配置主 SPI flash,这是为了与 ESP-IDF V4.0 之前的引导程序版本兼容,请参考 :ref:`bootloader-compatibility`。
|
||||
:esp32: - 根据应用程序头部设置重新配置主 SPI flash,这是为了与 ESP-IDF V4.0 之前的引导加载程序版本兼容,请参考 :ref:`bootloader-compatibility`。
|
||||
:SOC_HP_CPU_HAS_MULTIPLE_CORES: - 如果应用程序被配置为在多个内核上运行,则启动另一个内核并等待其初始化(在类似的“端口层”初始化函数 ``call_start_cpu1`` 内)。
|
||||
|
||||
.. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES
|
||||
|
@ -250,7 +250,7 @@ uf2 二进制文件也可以通过 :ref:`idf.py uf2 <generate-uf2-binary>` 生
|
||||
|
||||
在 ESP 芯片上运行 `ESP USB Bridge <https://github.com/espressif/esp-usb-bridge>`_ 项目将创建一个 USB 大容量存储设备,用户可以将生成的 UF2 文件复制到该 USB 设备中,桥接 MCU 将使用该文件来烧录目标 MCU。这一操作十分简单,只需将文件复制(或“拖放”)到文件资源管理器访问的公开磁盘中即可。
|
||||
|
||||
如需仅为应用程序生成 UF2 二进制文件,即不包含加载引导程序和分区表,请使用 ``uf2-app`` 命令。
|
||||
如需仅为应用程序生成 UF2 二进制文件,即不包含引导加载程序和分区表,请使用 ``uf2-app`` 命令。
|
||||
|
||||
``idf.py uf2`` 命令在功能上与 :ref:`上述 <merging-binaries>` ``idf.py merge-bin -f uf2`` 命令等效。而将二进制文件合并为除 uf2 以外的各种格式时,``idf.py merge-bin`` 命令更具灵活性和可选性。
|
||||
|
||||
|
@ -85,7 +85,7 @@ GPIO 驱动提供了一个函数 :cpp:func:`gpio_dump_io_configuration` 用来
|
||||
|
||||
如果 IO 管脚通过 GPIO 交换矩阵连接到内部外设信号,输出信息打印中的外设信号 ID 定义可以在 :component_file:`soc/{IDF_TARGET_PATH_NAME}/include/soc/gpio_sig_map.h` 头文件中查看。``**RESERVED**`` 字样则表示此 IO 用于连接 SPI flash 或 PSRAM,强烈建议不要重新配置这些管脚用于其他功能。
|
||||
|
||||
请不要依赖技术参考手册中记录的 GPIO 默认配置状态,因为特殊用途的 GPIO 可能会在 app_main 之前被引导程序或应用程序启动阶段的代码更改。
|
||||
请不要依赖技术参考手册中记录的 GPIO 默认配置状态,因为特殊用途的 GPIO 可能会在 app_main 之前被引导加载程序或应用程序启动阶段的代码更改。
|
||||
|
||||
.. only:: esp32c3 or esp32c6 or esp32h2 or esp32p4 or esp32s2 or esp32s3 or esp32c5 or esp32c61
|
||||
|
||||
|
@ -118,7 +118,7 @@ SPI flash 容量
|
||||
|
||||
SPI flash 容量由引导加载程序镜像头部(烧录偏移量为 0x1000)的一个字段进行配置。
|
||||
|
||||
默认情况下,引导程序被写入 flash 时,``esptool.py`` 会自动检测 SPI flash 容量,同时使用正确容量更新引导程序的头部。也可以在工程配置中设置 :ref:`CONFIG_ESPTOOLPY_FLASHSIZE`,生成固定的 flash 容量。
|
||||
默认情况下,引导加载程序被写入 flash 时,``esptool.py`` 会自动检测 SPI flash 容量,同时使用正确容量更新引导加载程序的头部。也可以在工程配置中设置 :ref:`CONFIG_ESPTOOLPY_FLASHSIZE`,生成固定的 flash 容量。
|
||||
|
||||
如需在运行时覆盖已配置的 flash 容量,请配置 ``g_rom_flashchip`` 结构中的 ``chip_size``。``esp_flash_*`` 函数使用此容量(于软件和 ROM 中)进行边界检查。
|
||||
|
||||
|
@ -98,7 +98,7 @@ NVS 密钥分区
|
||||
# "Active security features detected, erasing flash is disabled as a safety measure. Use --force to override ..."
|
||||
parttool.py --esptool-erase-args=force --esptool-write-args encrypt --port PORT --partition-table-file=PARTITION_TABLE_FILE --partition-table-offset PARTITION_TABLE_OFFSET write_partition --partition-name="name of nvs_key partition" --input NVS_KEY_PARTITION_FILE
|
||||
|
||||
由于密钥分区被标记为 ``encrypted``,且 :doc:`../../security/flash-encryption` 已启用,引导程序会在首次启动时使用 flash 加密密钥对此分区进行加密。
|
||||
由于密钥分区被标记为 ``encrypted``,且 :doc:`../../security/flash-encryption` 已启用,引导加载程序会在首次启动时使用 flash 加密密钥对此分区进行加密。
|
||||
|
||||
一个应用程序可以使用不同的密钥对不同的 NVS 分区进行加密,从而拥有多个密钥分区。应用程序应为加密或解密操作提供正确的密钥分区和密钥信息。
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
分区表 API
|
||||
-------------------
|
||||
|
||||
ESP-IDF 工程使用分区表保存 SPI flash 各区信息,包括引导程序、各种应用程序二进制文件、数据及文件系统等。请参阅 :doc:`/api-guides/partition-tables`,查看详细信息。
|
||||
ESP-IDF 工程使用分区表保存 SPI flash 各区信息,包括引导加载程序、各种应用程序二进制文件、数据及文件系统等。请参阅 :doc:`/api-guides/partition-tables`,查看详细信息。
|
||||
|
||||
该组件在 ``esp_partition.h`` 中声明了一些 API 函数,用以枚举在分区表中找到的分区,并对这些分区执行操作:
|
||||
|
||||
|
@ -110,7 +110,7 @@ EFuse 块版本号与芯片版本号类似,但是它主要影响在 eFuse 中
|
||||
故障排除
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
1. 如果第二阶段引导加载程序所运行的芯片版本低于镜像(如软件镜像)中指定的最小版本,会发生重启并显示以下消息:
|
||||
1. 如果二级引导加载程序所运行的芯片版本低于镜像(如软件镜像)中指定的最小版本,会发生重启并显示以下消息:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
@ -132,13 +132,13 @@ EFuse 块版本号与芯片版本号类似,但是它主要影响在 eFuse 中
|
||||
二进制镜像的常见版本需求
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
芯片版本号检查主要根据二级引导程序和应用程序二进制镜像中包含的 :cpp:type:`esp_image_header_t` 标头,其中记录了可以运行该软件的芯片版本号。这一标头有 3 个与版本相关的字段:
|
||||
芯片版本号检查主要根据二级引导加载程序和应用程序二进制镜像中包含的 :cpp:type:`esp_image_header_t` 标头,其中记录了可以运行该软件的芯片版本号。这一标头有 3 个与版本相关的字段:
|
||||
|
||||
- ``min_chip_rev`` - 镜像所需芯片的最小主版本号(但对于 ESP32-C3,该字段指次版本号)。其值由 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` 确定。
|
||||
- ``min_chip_rev_full`` - 镜像所需芯片的最小版本号,格式为 ``major * 100 + minor``。其值由 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` 确定。
|
||||
- ``max_chip_rev_full`` - 镜像所需芯片的最大版本号,格式为 ``major * 100 + minor``。其值由 ``CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MAX_FULL`` 确定。用户无法对其进行修改,仅当 ESP-IDF 支持新版本时由乐鑫官方进行更改。
|
||||
|
||||
而 eFuse 块版本的要求则存储在 :cpp:type:`esp_app_desc_t` 结构体中。该结构体对象位于应用程序的二进制进项文件中。由于 eFuse 块版本信息主要影响 ADC 校准,而二级引导程序的镜像不涉及 ADC,因此我们只需要检查应用程序镜像的 eFuse 块版本信息。有 2 个与 eFuse 块版本相关的字段:
|
||||
而 eFuse 块版本的要求则存储在 :cpp:type:`esp_app_desc_t` 结构体中。该结构体对象位于应用程序的二进制进项文件中。由于 eFuse 块版本信息主要影响 ADC 校准,而二级引导加载程序的镜像不涉及 ADC,因此我们只需要检查应用程序镜像的 eFuse 块版本信息。有 2 个与 eFuse 块版本相关的字段:
|
||||
|
||||
- ``min_efuse_blk_rev_full`` - 镜像所需 eFuse 块的最小版本号,格式为 ``major * 100 + minor``。其值由 ``CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL`` 确定。
|
||||
- ``max_efuse_blk_rev_full`` - 镜像所需 eFuse 块的最大版本号,格式为 ``major * 100 + minor``。其值由 ``CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL`` 确定。它反映了当前 ESP-IDF 版本能支持的最大 eFuse 块版本号,不应由用户修改。
|
||||
@ -148,36 +148,36 @@ EFuse 块版本号与芯片版本号类似,但是它主要影响在 eFuse 中
|
||||
|
||||
应用启动过程中,检查最小和最大版本的顺序如下:
|
||||
|
||||
1. 在运行第 2 阶段引导启动程序前,第 1 阶段引导启动程序(ROM 引导启动程序)不会在 :cpp:type:`esp_image_header_t` 中检查最小和最大版本字段。
|
||||
1. 在运行二级引导加载程序前,一级 (ROM) 引导加载程序不会在 :cpp:type:`esp_image_header_t` 中检查最小和最大版本字段。
|
||||
|
||||
2. 在第 2 阶段引导启动程序的初始化阶段,会检查引导程序自身是否可以在此版本的芯片上启动。它从引导启动程序镜像的标头中读取最小版本,并与 eFuse 中的芯片版本进行比较。如果芯片版本低于最小版本,引导启动程序会拒绝启动并中止运行。此阶段不检查最大版本。
|
||||
2. 在二级引导加载程序的初始化阶段,会检查引导加载程序自身是否可以在此版本的芯片上启动。它从引导加载程序镜像的标头中读取最小版本,并与 eFuse 中的芯片版本进行比较。如果芯片版本低于最小版本,引导加载程序会拒绝启动并中止运行。此阶段不检查最大版本。
|
||||
|
||||
3. 然后,第 2 阶段引导启动程序会检查应用程序的版本要求。它从应用程序镜像的标头中读取支持的芯片最小和最大版本,以及从段的标头中读取 eFuse 块版本信息,并与 eFuse 中的芯片版本进行比较。如果该芯片版本或 eFuse 块版本低于各自的最小版本或高于最大版本,引导程序会拒绝启动并中止。然而,如果设置了忽略最大版本位,则可以忽略最大版本限制。软件确定可以使用此芯片版本时,用户可以自行设置忽略位。
|
||||
3. 然后,二级引导加载程序会检查应用程序的版本要求。它从应用程序镜像的标头中读取支持的芯片最小和最大版本,以及从段的标头中读取 eFuse 块版本信息,并与 eFuse 中的芯片版本进行比较。如果该芯片版本或 eFuse 块版本低于各自的最小版本或高于最大版本,引导加载程序会拒绝启动并中止。然而,如果设置了忽略最大版本位,则可以忽略最大版本限制。软件确定可以使用此芯片版本时,用户可以自行设置忽略位。
|
||||
|
||||
4. 在空中升级 (OTA) 阶段,运行中的应用程序会检查新软件是否与芯片版本及 eFuse 块版本相匹配。它会从新应用程序镜像的标头中提取最小和最大芯片版本,以及应用程序描述中提取最大和最小 eFuse 块版本,并与 eFuse 中的芯片版本和块版本进行比较。应用程序检查版本匹配的方式与引导启动程序相同,即芯片版本和 eFuse 块版本须处在最小和最大版本之间(忽略最大版本的逻辑也相同)。
|
||||
4. 在空中升级 (OTA) 阶段,运行中的应用程序会检查新软件是否与芯片版本及 eFuse 块版本相匹配。它会从新应用程序镜像的标头中提取最小和最大芯片版本,以及应用程序描述中提取最大和最小 eFuse 块版本,并与 eFuse 中的芯片版本和块版本进行比较。应用程序检查版本匹配的方式与引导加载程序相同,即芯片版本和 eFuse 块版本须处在最小和最大版本之间(忽略最大版本的逻辑也相同)。
|
||||
|
||||
向后兼容旧版 ESP-IDF 构建的引导启动程序
|
||||
向后兼容旧版 ESP-IDF 构建的引导加载程序
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. only:: esp32 or esp32c3 or esp32s2 or esp32s3
|
||||
|
||||
主要版本号和次版本号的 eFuse 位对于旧版引导启动程序(由早于 v5.0 版本的 ESP-IDF 进行构建)而言是未知的。旧版启动引导程序只使用一个 eFuse 位来表示芯片版本。
|
||||
主要版本号和次版本号的 eFuse 位对于旧版引导加载程序(由早于 v5.0 版本的 ESP-IDF 进行构建)而言是未知的。旧版引导加载程序只使用一个 eFuse 位来表示芯片版本。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
旧版引导启动程序不读取次版本号的 eFuse 位,且主版本号只能低于或等于 v3。这表明,旧版引导启动程序只能正确检测范围在 ``v0.0`` 至 ``v3.0`` 的芯片版本,其中,次版本号总是设置为 ``0``。
|
||||
旧版引导加载程序不读取次版本号的 eFuse 位,且主版本号只能低于或等于 v3。这表明,旧版引导加载程序只能正确检测范围在 ``v0.0`` 至 ``v3.0`` 的芯片版本,其中,次版本号总是设置为 ``0``。
|
||||
|
||||
.. only:: esp32c2
|
||||
|
||||
ESP-IDF v5.0 中添加了对 {IDF_TARGET_NAME} 芯片的支持。引导启动程序能够检测范围在 ``v0.0`` 至 ``v3.15`` 内的所有芯片版本。
|
||||
ESP-IDF v5.0 中添加了对 {IDF_TARGET_NAME} 芯片的支持。引导加载程序能够检测范围在 ``v0.0`` 至 ``v3.15`` 内的所有芯片版本。
|
||||
|
||||
.. only:: esp32c3
|
||||
|
||||
在 ESP-IDF v4.3 中添加了对 {IDF_TARGET_NAME} 芯片的支持。旧版引导启动程序无法读取晶圆版本 eFuse 的所有位,只能读取前 3 个最低有效位。因此,旧版引导启动程序无法正确检测芯片版本。具体而言,只能正确检测 ``v0.0`` 至 ``v0.8`` 范围内的芯片版本,其他芯片版本则会被错误识别为该范围内的某个版本。
|
||||
在 ESP-IDF v4.3 中添加了对 {IDF_TARGET_NAME} 芯片的支持。旧版引导加载程序无法读取晶圆版本 eFuse 的所有位,只能读取前 3 个最低有效位。因此,旧版引导加载程序无法正确检测芯片版本。具体而言,只能正确检测 ``v0.0`` 至 ``v0.8`` 范围内的芯片版本,其他芯片版本则会被错误识别为该范围内的某个版本。
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
在 ESP-IDF v4.2 中添加了对 {IDF_TARGET_NAME} 芯片的支持。 由于 ``Minimum Supported ESP32-S2 Revision`` Kconfig 选项未引入,{IDF_TARGET_NAME} 芯片在 :cpp:type:`esp_image_header_t` 头文件中将 ``rev_min`` 设置为 0。这表明旧版引导启动程序不会检查芯片版本。在 v0.0 至 v3.15 范围内,任何应用程序都可以通过此类引导加载程序加载。
|
||||
在 ESP-IDF v4.2 中添加了对 {IDF_TARGET_NAME} 芯片的支持。 由于 ``Minimum Supported ESP32-S2 Revision`` Kconfig 选项未引入,{IDF_TARGET_NAME} 芯片在 :cpp:type:`esp_image_header_t` 头文件中将 ``rev_min`` 设置为 0。这表明旧版引导加载程序不会检查芯片版本。在 v0.0 至 v3.15 范围内,任何应用程序都可以通过此类引导加载程序加载。
|
||||
|
||||
请使用 ``esptool chip_id`` 命令查看芯片版本。
|
||||
|
||||
|
@ -555,7 +555,7 @@ flash 加密测试
|
||||
|
||||
flash 加密是一项硬件功能,需要物理烧录 eFuse ``key`` 和 ``FLASH_CRYPT_CNT``。如果 flash 加密实际未启用,那么启用 :ref:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` 选项只是提供了测试的可能性,而不会加密 flash 中的任何内容,即使日志中显示了加密操作。
|
||||
|
||||
为此,可使用 :cpp:func:`bootloader_flash_write` 函数。但是,如果运行应用程序时芯片已启用 flash 加密,或者以 :ref:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` 选项创建了启动加载程序,则 flash 加密/解密操作会正常进行。这意味着数据写入加密 flash 分区时被加密,从加密分区读取时被解密。
|
||||
为此,可使用 :cpp:func:`bootloader_flash_write` 函数。但是,如果运行应用程序时芯片已启用 flash 加密,或者以 :ref:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` 选项创建了引导加载程序,则 flash 加密/解密操作会正常进行。这意味着数据写入加密 flash 分区时被加密,从加密分区读取时被解密。
|
||||
|
||||
``espefuse.py``
|
||||
^^^^^^^^^^^^^^^
|
||||
|
@ -9,7 +9,7 @@
|
||||
软件复位
|
||||
------------
|
||||
|
||||
函数 :cpp:func:`esp_restart` 用于执行芯片的软件复位。调用此函数时,程序停止执行,{IDF_TARGET_CPU_RESET_DES},应用程序由 bootloader 加载并重启。
|
||||
函数 :cpp:func:`esp_restart` 用于执行芯片的软件复位。调用此函数时,程序停止执行,{IDF_TARGET_CPU_RESET_DES},应用程序由引导加载程序加载并重启。
|
||||
|
||||
函数 :cpp:func:`esp_register_shutdown_handler` 用于注册复位前会自动调用的例程(复位过程由 :cpp:func:`esp_restart` 函数触发),这与 ``atexit`` POSIX 函数的功能类似。
|
||||
|
||||
|
@ -19,7 +19,7 @@ OTA 数据分区
|
||||
|
||||
所有使用 OTA 功能项目,其 :doc:`../../api-guides/partition-tables` 必须包含一个 OTA 数据分区(类型为 ``data``,子类型为 ``ota``)。
|
||||
|
||||
工厂启动设置下,OTA 数据分区中应没有数据(所有字节擦写成 0xFF)。如果分区表中有工厂应用程序,ESP-IDF 软件引导加载程序会启动工厂应用程序。如果分区表中没有工厂应用程序,则启动第一个可用的 OTA 分区(通常是 ``ota_0``)。
|
||||
工厂启动设置下,OTA 数据分区中应没有数据(所有字节擦写成 0xFF)。如果分区表中有工厂应用程序,ESP-IDF 二级引导加载程序会启动工厂应用程序。如果分区表中没有工厂应用程序,则启动第一个可用的 OTA 分区(通常是 ``ota_0``)。
|
||||
|
||||
第一次 OTA 升级后,OTA 数据分区更新,指定下一次启动哪个 OTA 应用程序分区。
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
.. note::
|
||||
|
||||
ESP-IDF 第二阶段引导加载程序在启动过程中启用的熵源会用熵来初始化内部 RNG 状态。但是,内部硬件 RNG 状态的大小并不足以提供连续的真随机数流。因此,在需要真随机数时必须启用连续的熵源。
|
||||
ESP-IDF 二级引导加载程序在启动过程中启用的熵源会用熵来初始化内部 RNG 状态。但是,内部硬件 RNG 状态的大小并不足以提供连续的真随机数流。因此,在需要真随机数时必须启用连续的熵源。
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -39,7 +39,7 @@ flash 加密功能用于加密与 {IDF_TARGET_NAME} 搭载使用的片外 flash
|
||||
|
||||
启用 flash 加密后,会默认加密以下类型的数据:
|
||||
|
||||
- :ref:`second-stage-bootloader` (固件引导加载程序)
|
||||
- :ref:`second-stage-bootloader`
|
||||
- 分区表
|
||||
- :ref:`nvs_encr_key_partition`
|
||||
- Otadata
|
||||
@ -48,7 +48,7 @@ flash 加密功能用于加密与 {IDF_TARGET_NAME} 搭载使用的片外 flash
|
||||
其他类型的数据将视情况进行加密:
|
||||
|
||||
- 分区表中标有 ``encrypted`` 标志的分区。如需了解详情,请参考 :ref:`encrypted-partition-flag`。
|
||||
- 如果启用了安全启动,则会对安全启动引导程序摘要进行加密(见下文)。
|
||||
- 如果启用了安全启动,则会对安全启动引导加载程序摘要进行加密(见下文)。
|
||||
|
||||
.. _flash-encryption-efuse:
|
||||
|
||||
@ -175,39 +175,39 @@ flash 加密操作由 {IDF_TARGET_NAME} 上的多个 eFuse 控制,具体 eFuse
|
||||
flash 的加密过程
|
||||
------------------
|
||||
|
||||
假设 eFuse 值处于默认状态,且固件的引导加载程序编译为支持 flash 加密,则 flash 加密的具体过程如下:
|
||||
假设 eFuse 值处于默认状态,且二级引导加载程序编译为支持 flash 加密,则 flash 加密的具体过程如下:
|
||||
|
||||
.. only:: not SOC_FLASH_ENCRYPTION_XTS_AES
|
||||
|
||||
1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。ROM 引导加载程序加载固件引导加载程序。
|
||||
1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。一级 (ROM) 引导加载程序加载二级引导加载程序。
|
||||
|
||||
2. 固件的引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b0000000``)。因为该值为 0(偶数位),固件的引导加载程序将配置并启用 flash 加密块,同时将 ``FLASH_CRYPT_CONFIG`` eFuse 的值编程为 0xF。关于 flash 加密块的更多信息,请参考 *{IDF_TARGET_NAME} 技术参考手册* > *eFuse 控制器 (eFuse)* > *flash 加密块* [`PDF <{IDF_TARGET_TRM_CN_URL}#efuse>`__]。
|
||||
2. 二级引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b0000000``)。因为该值为 0(偶数位),二级引导加载程序将配置并启用 flash 加密块,同时将 ``FLASH_CRYPT_CONFIG`` eFuse 的值编程为 0xF。关于 flash 加密块的更多信息,请参考 *{IDF_TARGET_NAME} 技术参考手册* > *eFuse 控制器 (eFuse)* > *flash 加密块* [`PDF <{IDF_TARGET_TRM_CN_URL}#efuse>`__]。
|
||||
|
||||
3. 固件引导加载程序首先检查 eFuse 中是否已经存在有效密钥(例如用 espefuse 工具烧写的密钥),如果存在,则会跳过密钥生成,并将该密钥用于 flash 加密过程。否则,固件引导加载程序会使用 RNG(随机数发生器)模块生成一个 AES-256 位密钥,并将其写入 ``flash_encryption`` eFuse 中。由于已设置了 ``flash_encryption`` eFuse 的读保护位和写保护位,因此无法通过软件访问密钥。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。
|
||||
3. 二级引导加载程序首先检查 eFuse 中是否已经存在有效密钥(例如用 espefuse 工具烧写的密钥),如果存在,则会跳过密钥生成,并将该密钥用于 flash 加密过程。否则,二级引导加载程序会使用 RNG(随机数发生器)模块生成一个 AES-256 位密钥,并将其写入 ``flash_encryption`` eFuse 中。由于已设置了 ``flash_encryption`` eFuse 的读保护位和写保护位,因此无法通过软件访问密钥。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。
|
||||
|
||||
4. flash 加密块将加密 flash 的内容(固件的引导加载程序、应用程序、以及标有 ``加密`` 标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。
|
||||
4. flash 加密块将加密 flash 的内容(二级引导加载程序、应用程序、以及标有 ``加密`` 标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。
|
||||
|
||||
5. 固件引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b0000001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数个比特位。
|
||||
5. 二级引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b0000001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数个比特位。
|
||||
|
||||
6. 对于 :ref:`flash-enc-development-mode`,固件引导加载程序仅设置 ``DISABLE_DL_DECRYPT`` 和 ``DISABLE_DL_CACHE`` 的 eFuse 位,以便 UART 引导加载程序重新烧录加密的二进制文件。此外, ``{IDF_TARGET_CRYPT_CNT}`` 的 eFuse 位不受写入保护。
|
||||
6. 对于 :ref:`flash-enc-development-mode`,二级引导加载程序仅设置 ``DISABLE_DL_DECRYPT`` 和 ``DISABLE_DL_CACHE`` 的 eFuse 位,以便 UART 引导加载程序重新烧录加密的二进制文件。此外, ``{IDF_TARGET_CRYPT_CNT}`` 的 eFuse 位不受写入保护。
|
||||
|
||||
7. 对于 :ref:`flash-enc-release-mode`,固件引导加载程序设置 ``DISABLE_DL_ENCRYPT``、``DISABLE_DL_DECRYPT`` 和 ``DISABLE_DL_CACHE`` 的 eFuse 位为 1,以防止 UART 引导加载程序解密 flash 内容。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。
|
||||
7. 对于 :ref:`flash-enc-release-mode`,二级引导加载程序设置 ``DISABLE_DL_ENCRYPT``、``DISABLE_DL_DECRYPT`` 和 ``DISABLE_DL_CACHE`` 的 eFuse 位为 1,以防止 UART 引导加载程序解密 flash 内容。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。
|
||||
|
||||
8. 重新启动设备以开始执行加密镜像。固件引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。
|
||||
8. 重新启动设备以开始执行加密镜像。二级引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。
|
||||
|
||||
.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_256
|
||||
|
||||
1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。ROM 引导加载程序加载固件引导加载程序。
|
||||
1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。一级 (ROM) 引导加载程序加载二级引导加载程序。
|
||||
|
||||
2. 固件的引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b000``)。因为该值为 0(偶数位),固件引导加载程序将配置并启用 flash 加密块。关于 flash 加密块的更多信息,请参考 *{IDF_TARGET_NAME} 技术参考手册* > *eFuse 控制器 (eFuse)* > *自动加密块* [`PDF <{IDF_TARGET_TRM_CN_URL}#efuse>`__]。
|
||||
2. 二级引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b000``)。因为该值为 0(偶数位),二级引导加载程序将配置并启用 flash 加密块。关于 flash 加密块的更多信息,请参考 *{IDF_TARGET_NAME} 技术参考手册* > *eFuse 控制器 (eFuse)* > *自动加密块* [`PDF <{IDF_TARGET_TRM_CN_URL}#efuse>`__]。
|
||||
|
||||
3. 固件引导加载程序首先检查 eFuse 中是否已经存在有效密钥(例如用 espefuse 工具烧写的密钥),如果存在,则会跳过密钥生成,并将该密钥用于 flash 加密过程。否则,固件引导加载程序使用 RNG(随机数发生器)模块生成一个 256 位或 512 位的密钥,具体位数取决于 :ref:`生成的 XTS-AES 密钥的大小 <CONFIG_SECURE_FLASH_ENCRYPTION_KEYSIZE>`,然后将其分别写入一个或两个 `BLOCK_KEYN` eFuse 中。软件也为存储密钥的块更新了 ``KEY_PURPOSE_N``。由于上述一个或两个 ``BLOCK_KEYN`` eFuse 已设置了读保护和写保护位,因此无法通过软件访问密钥。``KEY_PURPOSE_N`` 字段也受写保护。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。
|
||||
3. 二级引导加载程序首先检查 eFuse 中是否已经存在有效密钥(例如用 espefuse 工具烧写的密钥),如果存在,则会跳过密钥生成,并将该密钥用于 flash 加密过程。否则,二级引导加载程序使用 RNG(随机数发生器)模块生成一个 256 位或 512 位的密钥,具体位数取决于 :ref:`生成的 XTS-AES 密钥的大小 <CONFIG_SECURE_FLASH_ENCRYPTION_KEYSIZE>`,然后将其分别写入一个或两个 `BLOCK_KEYN` eFuse 中。软件也为存储密钥的块更新了 ``KEY_PURPOSE_N``。由于上述一个或两个 ``BLOCK_KEYN`` eFuse 已设置了读保护和写保护位,因此无法通过软件访问密钥。``KEY_PURPOSE_N`` 字段也受写保护。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。
|
||||
|
||||
4. flash 加密块将加密 flash 的内容(固件的引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。
|
||||
4. flash 加密块将加密 flash 的内容(二级引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。
|
||||
|
||||
5. 固件引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数位。
|
||||
5. 二级引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数位。
|
||||
|
||||
6. 对于 :ref:`flash-enc-development-mode`,固件引导加载程序允许 UART 引导加载程序重新烧录加密后的二进制文件。同时,``{IDF_TARGET_CRYPT_CNT}`` eFuse 位不受写入保护。此外,固件引导加载程序默认置位以下 eFuse 位:
|
||||
6. 对于 :ref:`flash-enc-development-mode`,二级引导加载程序允许 UART 引导加载程序重新烧录加密后的二进制文件。同时,``{IDF_TARGET_CRYPT_CNT}`` eFuse 位不受写入保护。此外,二级引导加载程序默认置位以下 eFuse 位:
|
||||
|
||||
.. list::
|
||||
|
||||
@ -217,45 +217,45 @@ flash 的加密过程
|
||||
- ``HARD_DIS_JTAG``
|
||||
- ``DIS_LEGACY_SPI_BOOT``
|
||||
|
||||
7. 对于 :ref:`flash-enc-release-mode`,固件引导加载程序设置所有在开发模式下设置的 eFuse 位。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。
|
||||
7. 对于 :ref:`flash-enc-release-mode`,二级引导加载程序设置所有在开发模式下设置的 eFuse 位。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。
|
||||
|
||||
8. 重新启动设备以开始执行加密镜像。固件引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。
|
||||
8. 重新启动设备以开始执行加密镜像。二级引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。
|
||||
|
||||
.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_128 and not SOC_FLASH_ENCRYPTION_XTS_AES_256 and not SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK
|
||||
|
||||
1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。ROM 引导加载程序加载固件引导加载程序。
|
||||
1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。一级 (ROM) 引导加载程序加载二级引导加载程序。
|
||||
|
||||
2. 固件的引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b000``)。因为该值为 0(偶数位),固件引导加载程序将配置并启用 flash 加密块。关于 flash 加密块的更多信息,请参考 `{IDF_TARGET_NAME} 技术参考手册 <{IDF_TARGET_TRM_CN_URL}>`_。
|
||||
2. 二级引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b000``)。因为该值为 0(偶数位),二级引导加载程序将配置并启用 flash 加密块。关于 flash 加密块的更多信息,请参考 `{IDF_TARGET_NAME} 技术参考手册 <{IDF_TARGET_TRM_CN_URL}>`_。
|
||||
|
||||
3. 固件的引导加载程序使用 RNG(随机数发生器)模块生成 256 位密钥,然后将其写入 `BLOCK_KEYN` eFuse。软件也为存储密钥的块更新了 ``KEY_PURPOSE_N``。由于 ``BLOCK_KEYN`` eFuse 已设置了读保护和写保护位,因此无法通过软件访问密钥。``KEY_PURPOSE_N`` 字段也受写保护。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。如果 eFuse 中已经存在有效密钥(例如用 espefuse 工具烧写的密钥),则会跳过密钥生成,并将该密钥用于 flash 加密过程。
|
||||
3. 二级引导加载程序使用 RNG(随机数发生器)模块生成 256 位密钥,然后将其写入 `BLOCK_KEYN` eFuse。软件也为存储密钥的块更新了 ``KEY_PURPOSE_N``。由于 ``BLOCK_KEYN`` eFuse 已设置了读保护和写保护位,因此无法通过软件访问密钥。``KEY_PURPOSE_N`` 字段也受写保护。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。如果 eFuse 中已经存在有效密钥(例如用 espefuse 工具烧写的密钥),则会跳过密钥生成,并将该密钥用于 flash 加密过程。
|
||||
|
||||
4. flash 加密块将加密 flash 的内容(固件的引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。
|
||||
4. flash 加密块将加密 flash 的内容(二级引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。
|
||||
|
||||
5. 固件引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数位。
|
||||
5. 二级引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数位。
|
||||
|
||||
6. 对于 :ref:`flash-enc-development-mode`,固件引导加载程序允许 UART 引导加载程序重新烧录加密后的二进制文件。同时,``{IDF_TARGET_CRYPT_CNT}`` eFuse 位不受写入保护。此外,默认情况下,固件引导加载程序设置 ``DIS_DOWNLOAD_ICACHE``、 ``DIS_PAD_JTAG``、 ``DIS_USB_JTAG`` 和 ``DIS_LEGACY_SPI_BOOT`` eFuse 位。
|
||||
6. 对于 :ref:`flash-enc-development-mode`,二级引导加载程序允许 UART 引导加载程序重新烧录加密后的二进制文件。同时,``{IDF_TARGET_CRYPT_CNT}`` eFuse 位不受写入保护。此外,默认情况下,二级引导加载程序设置 ``DIS_DOWNLOAD_ICACHE``、 ``DIS_PAD_JTAG``、 ``DIS_USB_JTAG`` 和 ``DIS_LEGACY_SPI_BOOT`` eFuse 位。
|
||||
|
||||
7. 对于 :ref:`flash-enc-release-mode`,固件引导加载程序设置所有在开发模式下设置的 eFuse 位以及 ``DIS_DOWNLOAD_MANUAL_ENCRYPT``。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。
|
||||
7. 对于 :ref:`flash-enc-release-mode`,二级引导加载程序设置所有在开发模式下设置的 eFuse 位以及 ``DIS_DOWNLOAD_MANUAL_ENCRYPT``。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。
|
||||
|
||||
8. 重新启动设备以开始执行加密镜像。固件引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。
|
||||
8. 重新启动设备以开始执行加密镜像。二级引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。
|
||||
|
||||
.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_128 and SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK
|
||||
|
||||
1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。ROM 引导加载程序加载固件引导加载程序。
|
||||
1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。ROM 引导加载程序加载二级引导加载程序。
|
||||
|
||||
2. 固件的引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b000``)。因为该值为 0(偶数位),固件引导加载程序将配置并启用 flash 加密块。关于 flash 加密块的更多信息,请参考 `{IDF_TARGET_NAME} 技术参考手册 <{IDF_TARGET_TRM_CN_URL}>`_。
|
||||
2. 二级引导加载程序将读取 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值 (``0b000``)。因为该值为 0(偶数位),二级引导加载程序将配置并启用 flash 加密块。关于 flash 加密块的更多信息,请参考 `{IDF_TARGET_NAME} 技术参考手册 <{IDF_TARGET_TRM_CN_URL}>`_。
|
||||
|
||||
3. 固件的引导加载程序使用 RNG(随机数发生器)模块生成 256 位或 128 位密钥(具体位数取决于 :ref:`生成的 XTS-AES 密钥大小 <CONFIG_SECURE_FLASH_ENCRYPTION_KEYSIZE>`),然后将其写入 `BLOCK_KEY0` eFuse。同时,根据所选选项,软件对 ``XTS_KEY_LENGTH_256`` 进行更新。由于 ``BLOCK_KEY0`` eFuse 已设置写保护和读保护位,故无法通过软件访问密钥。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。若使用 128 位 flash 加密密钥,则整个 eFuse 密钥块都受写保护,但只有低 128 位受读保护,高 128 位是可读的,以满足安全启动的需要。如果 flash 加密密钥是 256 位,那么 ``XTS_KEY_LENGTH_256`` 为 1,否则为 0。为防止意外将 eFuse 从 0 改为 1,为 RELEASE 模式设置了一个写保护位。如果 eFuse 中已经存在有效密钥(例如用 espefuse 工具烧写的密钥),则跳过密钥生成,并将该密钥用于 flash 加密过程。
|
||||
3. 二级引导加载程序使用 RNG(随机数发生器)模块生成 256 位或 128 位密钥(具体位数取决于 :ref:`生成的 XTS-AES 密钥大小 <CONFIG_SECURE_FLASH_ENCRYPTION_KEYSIZE>`),然后将其写入 `BLOCK_KEY0` eFuse。同时,根据所选选项,软件对 ``XTS_KEY_LENGTH_256`` 进行更新。由于 ``BLOCK_KEY0`` eFuse 已设置写保护和读保护位,故无法通过软件访问密钥。flash 加密操作完全在硬件中完成,无法通过软件访问密钥。若使用 128 位 flash 加密密钥,则整个 eFuse 密钥块都受写保护,但只有低 128 位受读保护,高 128 位是可读的,以满足安全启动的需要。如果 flash 加密密钥是 256 位,那么 ``XTS_KEY_LENGTH_256`` 为 1,否则为 0。为防止意外将 eFuse 从 0 改为 1,为 RELEASE 模式设置了一个写保护位。如果 eFuse 中已经存在有效密钥(例如用 espefuse 工具烧写的密钥),则跳过密钥生成,并将该密钥用于 flash 加密过程。
|
||||
|
||||
4. flash 加密块将加密 flash 的内容(固件的引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。
|
||||
4. flash 加密块将加密 flash 的内容(二级引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。
|
||||
|
||||
5. 固件引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数位。
|
||||
5. 二级引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数位。
|
||||
|
||||
6. 对于 :ref:`flash-enc-development-mode`,固件引导加载程序允许 UART 引导加载程序重新烧录加密后的二进制文件。同时,``{IDF_TARGET_CRYPT_CNT}`` eFuse 位不受写入保护。此外,默认情况下,固件引导加载程序设置 ``DIS_DOWNLOAD_ICACHE``、``DIS_PAD_JTAG`` 和 ``DIS_DIRECT_BOOT`` eFuse 位。
|
||||
6. 对于 :ref:`flash-enc-development-mode`,二级引导加载程序允许 UART 引导加载程序重新烧录加密后的二进制文件。同时,``{IDF_TARGET_CRYPT_CNT}`` eFuse 位不受写入保护。此外,默认情况下,二级引导加载程序设置 ``DIS_DOWNLOAD_ICACHE``、``DIS_PAD_JTAG`` 和 ``DIS_DIRECT_BOOT`` eFuse 位。
|
||||
|
||||
7. 对于 :ref:`flash-enc-release-mode`,固件引导加载程序设置所有在开发模式下设置的 eFuse 位以及 ``DIS_DOWNLOAD_MANUAL_ENCRYPT``。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。
|
||||
7. 对于 :ref:`flash-enc-release-mode`,二级引导加载程序设置所有在开发模式下设置的 eFuse 位以及 ``DIS_DOWNLOAD_MANUAL_ENCRYPT``。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。
|
||||
|
||||
8. 重新启动设备以开始执行加密镜像。固件引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。
|
||||
8. 重新启动设备以开始执行加密镜像。二级引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。
|
||||
|
||||
在开发阶段常需编写不同的明文 flash 镜像并测试 flash 的加密过程。这要求固件下载模式能够根据需求不断加载新的明文镜像。但是,在制造和生产过程中,出于安全考虑,固件下载模式不应有权限访问 flash 内容。
|
||||
|
||||
@ -316,7 +316,7 @@ flash 加密设置
|
||||
|
||||
这个命令不包括任何应该写入 flash 分区的用户文件。请在运行此命令前手动写入这些文件,否则在写入前应单独对这些文件进行加密。
|
||||
|
||||
该命令将向 flash 写入未加密的镜像:固件引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将复位。在下一次启动时,固件引导加载程序会加密:固件引导加载程序、应用程序分区和标记为“加密”的分区,然后复位。就地加密可能需要时间,对于大分区最多需要一分钟。之后,应用程序在运行时解密并执行命令。
|
||||
该命令将向 flash 写入未加密的镜像:二级引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将复位。在下一次启动时,二级引导加载程序会加密:二级引导加载程序、应用程序分区和标记为“加密”的分区,然后复位。就地加密可能需要时间,对于大分区最多需要一分钟。之后,应用程序在运行时解密并执行命令。
|
||||
|
||||
下面是启用 flash 加密后 {IDF_TARGET_NAME} 首次启动时的样例输出:
|
||||
|
||||
@ -486,7 +486,7 @@ flash 加密设置
|
||||
|
||||
这个命令不包括任何应该被写入 flash 上的分区的用户文件。请在运行此命令前手动写入这些文件,否则在写入前应单独对这些文件进行加密。
|
||||
|
||||
该命令将向 flash 写入未加密的镜像:固件引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将复位。在下一次启动时,固件引导加载程序会加密:固件引导加载程序、应用程序分区和标记为 ``加密`` 的分区,然后复位。就地加密可能需要时间,对于大的分区来说可能耗时一分钟。之后,应用程序在运行时被解密并执行。
|
||||
该命令将向 flash 写入未加密的镜像:二级引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将复位。在下一次启动时,二级引导加载程序会加密:二级引导加载程序、应用程序分区和标记为 ``加密`` 的分区,然后复位。就地加密可能需要时间,对于大的分区来说可能耗时一分钟。之后,应用程序在运行时被解密并执行。
|
||||
|
||||
如果使用开发模式,那么更新和重新烧录二进制文件最简单的方法是 :ref:`encrypt-partitions`。
|
||||
|
||||
@ -549,7 +549,7 @@ flash 加密设置
|
||||
|
||||
这个命令不包括任何应该被写入 flash 分区的用户文件。请在运行此命令前手动写入这些文件,否则在写入前应单独对这些文件进行加密。
|
||||
|
||||
该命令将向 flash 写入未加密的镜像:固件引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将复位。在下一次启动时,固件引导加载程序会加密:固件引导加载程序、应用程序分区和标记为 ``加密`` 的分区,然后复位。就地加密可能需要时间,对于大的分区来说可能耗时一分钟。之后,应用程序在运行时被解密并执行。
|
||||
该命令将向 flash 写入未加密的镜像:二级引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将复位。在下一次启动时,二级引导加载程序会加密:二级引导加载程序、应用程序分区和标记为 ``加密`` 的分区,然后复位。就地加密可能需要时间,对于大的分区来说可能耗时一分钟。之后,应用程序在运行时被解密并执行。
|
||||
|
||||
一旦在发布模式下启用 flash 加密,引导加载程序将写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse。
|
||||
|
||||
@ -576,14 +576,14 @@ flash 加密设置
|
||||
外部启用 flash 加密
|
||||
----------------------------------
|
||||
|
||||
在上述过程中,对与 flash 加密相关的 eFuse 是通过固件引导加载程序烧写的,或者,也可以借助 ``espefuse`` 工具烧写 eFuse。如需了解详情,请参考 :ref:`enable-flash-encryption-externally`。
|
||||
在上述过程中,对与 flash 加密相关的 eFuse 是通过二级引导加载程序烧写的,或者,也可以借助 ``espefuse`` 工具烧写 eFuse。如需了解详情,请参考 :ref:`enable-flash-encryption-externally`。
|
||||
|
||||
可能出现的错误
|
||||
-----------------
|
||||
|
||||
一旦启用 flash 加密,``{IDF_TARGET_CRYPT_CNT}`` 的 eFuse 值将设置为奇数位。这意味着所有标有加密标志的分区都会包含加密的密本。如果 {IDF_TARGET_NAME} 错误地加载了明文数据,则会出现以下三种典型的错误情况:
|
||||
|
||||
1. 如果通过 **明文固件引导加载程序镜像** 重新烧录了引导加载程序分区,则 ROM 加载器将无法加载固件引导加载程序,并会显示以下错误类型:
|
||||
1. 如果通过 **明文二级引导加载程序镜像** 重新烧录了引导加载程序分区,则 ROM 加载器将无法加载二级引导加载程序,并会显示以下错误类型:
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
@ -635,7 +635,7 @@ flash 加密设置
|
||||
|
||||
如果 flash 内容被擦除或损坏,也会出现这个错误。
|
||||
|
||||
2. 如果固件的引导加载程序已加密,但通过 **明文分区表镜像** 重新烧录了分区表,引导加载程序将无法读取分区表,从而出现以下错误:
|
||||
2. 如果二级引导加载程序已加密,但通过 **明文分区表镜像** 重新烧录了分区表,引导加载程序将无法读取分区表,从而出现以下错误:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@ -727,7 +727,7 @@ flash 加密范围
|
||||
- flash 中可执行的应用程序代码 (IROM)。
|
||||
- 所有存储于 flash 中的只读数据 (DROM)。
|
||||
- 通过函数 :cpp:func:`spi_flash_mmap` 访问的任意数据。
|
||||
- ROM 引导加载程序读取的固件引导加载程序镜像。
|
||||
- ROM 引导加载程序读取的二级引导加载程序镜像。
|
||||
|
||||
.. important::
|
||||
|
||||
@ -976,7 +976,7 @@ flash 加密的高级功能
|
||||
|
||||
``FLASH_CRYPT_CONFIG`` eFuse 决定 flash 加密密钥中随块偏移“调整”的位数。详情可参考 :ref:`flash-encryption-algorithm`。
|
||||
|
||||
首次启动固件引导加载程序时,该值始终设置为最大值 `0xF`。
|
||||
首次启动二级引导加载程序时,该值始终设置为最大值 `0xF`。
|
||||
|
||||
可手动写入这些 eFuse,并在首次启动前对其写保护,以便选择不同的调整值。但不推荐该操作。
|
||||
|
||||
|
@ -30,11 +30,11 @@
|
||||
|
||||
- 为理解安全启动过程,请熟悉标准 :doc:`../api-guides/startup`。
|
||||
|
||||
- 安全启动过程会验证启动过程的两个阶段,包括初始软件引导加载程序和随后的分区与应用加载,形成一条信任链。
|
||||
- 安全启动过程会验证启动过程的两个阶段,包括二级引导加载程序的加载和随后的分区与应用加载,形成一条信任链。
|
||||
|
||||
|
||||
安全启动过程概述
|
||||
----------------------------
|
||||
---------------------
|
||||
|
||||
以下是对安全启动过程的宏观概述,操作指南请参阅 :ref:`secure-boot-how-to`,进一步的技术细节请参阅 :ref:`secure-boot-technical-details`:
|
||||
|
||||
@ -42,18 +42,18 @@
|
||||
|
||||
2. 安全启动默认在构建过程中签名镜像和分区表数据。配置项 ``Secure boot private signing key`` 是指向 PEM 格式文件中 ECDSA 公钥/私钥对的文件路径。
|
||||
|
||||
3. 启用安全启动支持的 ESP-IDF 负责构建软件引导加载程序镜像,签名验证所需公钥已集成到引导加载程序镜像中。此软件引导加载程序镜像将刷写到 0x1000 偏移地址。
|
||||
3. 启用安全启动支持的 ESP-IDF 负责构建二级引导加载程序镜像,签名验证所需公钥已集成到该镜像中。此二级引导加载程序镜像将烧写到 0x1000 偏移地址。
|
||||
|
||||
4. 初次启动时,软件引导加载程序按以下方式启用安全启动:
|
||||
4. 初次启动时,二级引导加载程序按以下方式启用安全启动:
|
||||
|
||||
- 硬件安全启动支持生成设备安全引导加载程序密钥以及安全摘要。密钥借助硬件随机数生成,随后存储在 eFuse 中,受读写保护。硬件安全启动还支持生成安全摘要,摘要源自密钥、初始向量 (IV) 和引导加载程序镜像内容。
|
||||
- 硬件安全启动支持生成设备安全引导加载程序密钥以及安全摘要。密钥借助硬件随机数生成,随后存储在 eFuse 中,受读写保护。硬件安全启动还支持生成安全摘要,摘要源自密钥、初始向量 (IV) 和该引导加载程序镜像的内容。
|
||||
- 安全摘要将刷写到 flash 中的 0x0 偏移地址。
|
||||
- 根据安全启动配置,烧录 eFuse 以禁用 JTAG 和 ROM 基本解释器。**强烈建议** 禁用 JTAG 和 ROM 基本解释器。
|
||||
- 烧录 ABS_DONE_0 eFuse 后,引导加载程序将始终启用安全启动,软件引导加载程序也随之受到保护。此后,芯片只有在摘要匹配时才会启动引导加载程序镜像。
|
||||
- 烧录 ABS_DONE_0 eFuse 后,该二级引导加载程序将始终启用安全启动,并随之受到保护。此后,芯片只有在摘要匹配时才会启动引导加载程序镜像。
|
||||
|
||||
5. 在后续启动过程中,ROM 引导加载程序检测到安全启动 eFuse 已烧录,读取 0x0 处保存的摘要,然后使用硬件安全启动支持来将其与新计算的摘要进行对比。如果摘要不匹配,启动过程终止。摘要读取和对比完全由硬件完成,软件无法读取计算的摘要。更多技术详情,请参阅 :ref:`secure-boot-hardware-support`。
|
||||
5. 在后续启动过程中,一级 (ROM) 引导加载程序检测到安全启动 eFuse 已烧录,读取 0x0 处保存的摘要,然后使用硬件安全启动支持来将其与新计算的摘要进行对比。如果摘要不匹配,启动过程终止。摘要读取和对比完全由硬件完成,软件无法读取计算的摘要。更多技术详情,请参阅 :ref:`secure-boot-hardware-support`。
|
||||
|
||||
6. 在安全启动模式下运行时,软件引导加载程序使用安全启动签名密钥,该密钥的公钥已嵌入引导加载程序本身,并作为引导加载程序的一部分进行验证,以在启动前验证附加到所有后续分区表和应用程序镜像的签名。
|
||||
6. 在安全启动模式下运行时,二级引导加载程序使用安全启动签名密钥,该密钥的公钥已嵌入该引导加载程序本身,并作为该引导加载程序的一部分进行验证,以在启动前验证附加到所有后续分区表和应用程序镜像的签名。
|
||||
|
||||
|
||||
密钥
|
||||
@ -61,7 +61,7 @@
|
||||
|
||||
安全启动过程中使用以下密钥:
|
||||
|
||||
- 安全引导加载程序密钥是一个 256 位 AES 密钥,存储在 eFuse 块 2 中。引导加载程序可以使用内部硬件随机数生成器自行生成该密钥,无需手动提供。也可以选择提供该密钥,请参阅 :ref:`secure-boot-reflashable`。在启用安全启动之前,存储该密钥的 eFuse 受到读取和写入保护,防止软件访问。
|
||||
- 安全引导加载程序密钥是一个 256 位 AES 密钥,存储在 eFuse 块 2 中。安全引导加载程序可以使用内部硬件随机数生成器自行生成该密钥,无需手动提供。也可以选择提供该密钥,请参阅 :ref:`secure-boot-reflashable`。在启用安全启动之前,存储该密钥的 eFuse 受到读取和写入保护,防止软件访问。
|
||||
|
||||
- eFuse 块 2 默认编码方案为 ``None``,块中存储了一个 256 位密钥。在某些版本的 {IDF_TARGET_NAME} 上,编码方案设置为 ``3/4 Encoding``,CODING_SCHEME eFuse 值为 1,且块中必须存储一个 192 位密钥。
|
||||
|
||||
@ -73,9 +73,9 @@
|
||||
|
||||
- ``secure boot signing key`` 是标准的 ECDSA 公钥/私钥对,以 PEM 格式存储,请参阅 :ref:`secure-boot-image-signing-algorithm`。
|
||||
|
||||
- 该密钥对的公钥用于验证签名,但不用于创建签名。它编译到软件引导加载程序中,并在启动继续前验证启动过程的第二阶段,包括分区表和应用程序镜像。该公钥可以自由分发,无需保密。
|
||||
- 该密钥对的公钥仅用于验证签名,但不用于创建签名。它编译到二级引导加载程序中,并在启动继续前验证启动过程的第二阶段,包括分区表和应用程序镜像。该公钥可以自由分发,无需保密。
|
||||
|
||||
- 该密钥对的私钥必须严格保密。一旦持有该私钥,即可用它对配置了安全启动和匹配公钥的引导加载程序进行身份验证。
|
||||
- 该密钥对的私钥必须严格保密。一旦持有该私钥,即可用它对任何配置了安全启动和匹配公钥的引导加载程序进行身份验证。
|
||||
|
||||
|
||||
引导加载程序大小
|
||||
@ -117,7 +117,7 @@
|
||||
|
||||
如果启用了安全启动,``idf.py flash`` 不会烧录引导加载程序。
|
||||
|
||||
8. 重置 {IDF_TARGET_NAME} 以启动烧录的软件引导加载程序。该软件引导加载程序会在芯片上启用安全启动,验证应用程序镜像签名,并启动应用程序。请查看 {IDF_TARGET_NAME} 的串行控制器输出,确保已启用安全启动,且没有因构建配置发生错误。
|
||||
8. 重置 {IDF_TARGET_NAME} 以启动烧录的二级引导加载程序。该二级引导加载程序会在芯片上启用安全启动,验证应用程序镜像签名,并启动应用程序。请查看 {IDF_TARGET_NAME} 的串行控制器输出,确保已启用安全启动,且没有因构建配置发生错误。
|
||||
|
||||
.. note::
|
||||
|
||||
@ -127,12 +127,12 @@
|
||||
|
||||
如果在初次启动过程中重置或关闭了 {IDF_TARGET_NAME},它会在下次启动时重新开始上述步骤。
|
||||
|
||||
9. 在后续启动过程中,安全启动硬件将使用安全引导加载程序密钥验证软件引导加载程序是否更改,随后,软件引导加载程序将使用安全启动签名密钥的公钥部分来验证已签名的分区表和应用程序镜像。
|
||||
9. 在后续启动过程中,安全启动硬件将使用安全引导加载程序密钥验证二级引导加载程序是否更改,随后,二级引导加载程序将使用安全启动签名密钥的公钥部分来验证已签名的分区表和应用程序镜像。
|
||||
|
||||
|
||||
.. _secure-boot-reflashable:
|
||||
|
||||
可重复烧录的软件引导加载程序
|
||||
可重复烧录的二级引导加载程序
|
||||
-------------------------------
|
||||
|
||||
对于生产设备,推荐使用 ``Secure Boot: One-Time Flash`` 配置。该模式下,每个设备都对应拥有始终存储在设备内部的唯一密钥。
|
||||
@ -229,7 +229,7 @@
|
||||
安全启动硬件支持
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
安全启动验证的第一阶段为检查软件引导加载程序,该检查通过硬件完成。{IDF_TARGET_NAME} 的安全启动支持硬件提供以下三种基本操作:
|
||||
安全启动验证的第一阶段为检查二级引导加载程序,该检查通过硬件完成。{IDF_TARGET_NAME} 的安全启动支持硬件提供以下三种基本操作:
|
||||
|
||||
1. 通过硬件随机数生成器生成一系列随机字节。
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
芯片版本低于 v3.0 的 ESP32 安全启动请参阅 :doc:`secure-boot-v1`。如果当前芯片版本支持安全启动 v2,推荐使用此模式,相比安全启动 v1 更安全且灵活。
|
||||
|
||||
安全启动 v2 使用基于 {IDF_TARGET_SBV2_SCHEME} 的应用程序和引导加载程序 (bootloader) :ref:`second-stage-bootloader` 验证。若需要使用 {IDF_TARGET_SBV2_SCHEME} 方案对应用程序签名,且无需对 bootloader 签名,同样可以参考本文档。
|
||||
安全启动 v2 使用基于 {IDF_TARGET_SBV2_SCHEME} 的应用程序和 :ref:`second-stage-bootloader` 验证。若需要使用 {IDF_TARGET_SBV2_SCHEME} 方案对应用程序签名,且无需对引导加载程序签名,同样可以参考本文档。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
@ -49,7 +49,7 @@
|
||||
背景
|
||||
----------
|
||||
|
||||
安全启动通过检查每个启动的软件是否已签名来确保设备不会运行任何未经授权(即未签名)的代码。在 {IDF_TARGET_NAME} 上,这些软件包括第二阶段的 bootloader 和每个应用程序的二进制文件。注意,第一阶段的 bootloader 是无法更改的 ROM 代码,因此不需要签名。
|
||||
安全启动通过检查每个启动的软件是否已签名来确保设备不会运行任何未经授权(即未签名)的代码。在 {IDF_TARGET_NAME} 上,这些软件包括二级引导加载程序和每个应用程序的二进制文件。注意,一级 (ROM) 引导加载程序是无法更改的 ROM 代码,因此不需要签名。
|
||||
|
||||
.. only:: esp32 or (SOC_SECURE_BOOT_V2_RSA and not SOC_SECURE_BOOT_V2_ECC)
|
||||
|
||||
@ -65,9 +65,9 @@
|
||||
|
||||
{IDF_TARGET_NAME} 的安全启动包括以下步骤:
|
||||
|
||||
1. 第一阶段 bootloader (ROM boot) 仍处于 ROM 中,加载第二阶段 bootloader,并验证第二阶段 bootloader 的 {IDF_TARGET_SBV2_SCHEME} 签名。验证通过后方可进入第二阶段。
|
||||
1. 一级 (ROM) 引导加载程序加载二级引导加载程序,并验证二级引导加载程序的 {IDF_TARGET_SBV2_SCHEME} 签名。验证通过后,方可运行二级引导加载程序。
|
||||
|
||||
2. 第二阶段 bootloader 加载特定应用程序镜像时,会验证应用程序的 {IDF_TARGET_SBV2_SCHEME} 签名。若验证通过,则执行应用程序镜像。
|
||||
2. 二级引导加载程序加载特定应用程序镜像,并验证应用程序的 {IDF_TARGET_SBV2_SCHEME} 签名。若验证通过,则执行应用程序镜像。
|
||||
|
||||
|
||||
优势
|
||||
@ -85,10 +85,10 @@
|
||||
|
||||
- {IDF_TARGET_NAME} 支持永久撤销个别公钥,对此可以选择保守或激进的配置。
|
||||
|
||||
- 保守配置:在此情况下,只有在 bootloader 和应用程序成功迁移到新密钥后才会撤销旧密钥。
|
||||
- 激进配置:在此情况下,只要使用此密钥验证失败,就会立即撤销该密钥。
|
||||
- 保守配置:在此情况下,只有在引导加载程序和应用程序成功迁移到新密钥后才会注销旧密钥。
|
||||
- 激进配置:在此情况下,只要使用此密钥验证失败,就会立即注销该密钥。
|
||||
|
||||
- 应用程序和软件 bootloader 采用相同的镜像格式和签名验证方法。
|
||||
- 应用程序和二级引导加载程序采用相同的镜像格式和签名验证方法。
|
||||
|
||||
- 设备不存储任何机密信息,因此可以免受被动侧通道攻击的影响,如时序分析或功耗分析。
|
||||
|
||||
@ -98,39 +98,39 @@
|
||||
|
||||
以下为使用安全启动 v2 流程的概述。有关如何启用安全启动,请参阅 :ref:`secure-boot-v2-howto`。
|
||||
|
||||
安全启动 v2 使用专用的 *签名块* 验证 bootloader 镜像和应用程序二进制镜像,每个镜像末尾都附加了一个单独生成的签名块。
|
||||
安全启动 v2 使用专用的 *签名块* 验证引导加载程序镜像和应用程序二进制镜像,每个镜像末尾都附加了一个单独生成的签名块。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
在 ESP32 芯片版本 v3.0 中,bootloader 或应用程序镜像只能附加一个签名块。
|
||||
在 ESP32 芯片版本 v3.0 中,引导加载程序或应用程序镜像只能附加一个签名块。
|
||||
|
||||
.. only:: esp32c2
|
||||
|
||||
在 {IDF_TARGET_NAME} 中,bootloader 或应用程序镜像只能附加一个签名块。
|
||||
在 {IDF_TARGET_NAME} 中,引导加载程序或应用程序镜像只能附加一个签名块。
|
||||
|
||||
.. only:: SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS
|
||||
|
||||
在 {IDF_TARGET_NAME} 中,bootloader 或应用程序镜像至多可以附加三个签名块。
|
||||
在 {IDF_TARGET_NAME} 中,引导加载程序或应用程序镜像至多可以附加三个签名块。
|
||||
|
||||
每个签名块包含前一个镜像的签名和相应的 {IDF_TARGET_SBV2_KEY} 公钥。有关格式详情,请参阅 :ref:`signature-block-format`。{IDF_TARGET_SBV2_KEY} 公钥的摘要存储在 eFuse 中。
|
||||
|
||||
应用程序镜像不仅在每次启动时验证,也会在每次空中升级 (OTA) 时验证。如果当前所选 OTA 应用程序镜像无法验证,bootloader 将回退,并寻找其他正确签名的应用程序镜像。
|
||||
应用程序镜像不仅在每次启动时验证,也会在每次空中升级 (OTA) 时验证。如果当前所选 OTA 应用程序镜像无法验证,引导加载程序将回退,并寻找其他正确签名的应用程序镜像。
|
||||
|
||||
安全启动 v2 流程遵循以下步骤:
|
||||
|
||||
1. 启动时,ROM 代码检查 eFuse 中的安全启动 v2 位。如果禁用了安全启动,则执行普通启动;如果启用了安全启动,将继续以下步骤。
|
||||
|
||||
2. ROM 代码验证 bootloader 的签名块,请参阅 :ref:`verify_signature-block`。如果验证失败,启动过程将中止。
|
||||
2. ROM 代码验证引导加载程序的签名块,请参阅 :ref:`verify_signature-block`。如果验证失败,启动过程将中止。
|
||||
|
||||
3. ROM 代码使用原始镜像数据、相应的签名块以及 eFuse 验证 bootloader 镜像,请参阅 :ref:`verify_image`。如果验证失败,启动过程将中止。
|
||||
3. ROM 代码使用原始镜像数据、相应的签名块以及 eFuse 验证引导加载程序镜像,请参阅 :ref:`verify_image`。如果验证失败,启动过程将中止。
|
||||
|
||||
4. ROM 代码执行 bootloader 。
|
||||
4. ROM 代码执行引导加载程序。
|
||||
|
||||
5. bootloader 验证应用程序镜像的签名块,请参阅 :ref:`verify_signature-block`。如果验证失败,启动过程将中止。
|
||||
5. 引导加载程序验证应用程序镜像的签名块,请参阅 :ref:`verify_signature-block`。如果验证失败,启动过程将中止。
|
||||
|
||||
6. bootloader 使用原始镜像数据、相应的签名块以及 eFuse 验证 bootloader 镜像,请参阅 :ref:`verify_image`。如果验证失败,启动过程将中止。如果验证失败,但发现了其他应用程序镜像, bootloader 将使用步骤 5 到 7 验证另一个镜像。该过程将重复,直至找到有效镜像,或所有镜像验证完毕。
|
||||
6. 引导加载程序使用原始镜像数据、相应的签名块以及 eFuse 验证引导加载程序镜像,请参阅 :ref:`verify_image`。如果验证失败,启动过程将中止。如果验证失败,但发现了其他应用程序镜像,引导加载程序将使用步骤 5 到 7 验证另一个镜像。该过程将重复,直至找到有效镜像,或所有镜像验证完毕。
|
||||
|
||||
7. bootloader 执行经验证的应用程序镜像。
|
||||
7. 引导加载程序执行经验证的应用程序镜像。
|
||||
|
||||
|
||||
.. _signature-block-format:
|
||||
@ -313,29 +313,29 @@
|
||||
|
||||
如果存储在某个签名块中的公钥是适用于当前设备的有效公钥,且该签名块中存储的签名与从 flash 中读取的镜像数据计算出的签名匹配,则该镜像通过验证。
|
||||
|
||||
1. 将嵌入在 bootloader 签名块中的公钥生成的 SHA-256 哈希摘要与存储在 eFuse 中的摘要进行比较,如果公钥的哈希摘要无法与 eFuse 中的任何哈希摘要匹配,则验证失败。
|
||||
1. 将嵌入在引导加载程序签名块中的公钥生成的 SHA-256 哈希摘要与存储在 eFuse 中的摘要进行比较,如果公钥的哈希摘要无法与 eFuse 中的任何哈希摘要匹配,则验证失败。
|
||||
|
||||
2. 生成应用程序镜像摘要,将其与签名块中的镜像摘要进行匹配,如果无法匹配,则验证失败。
|
||||
|
||||
.. only:: esp32 or (SOC_SECURE_BOOT_V2_RSA and not SOC_SECURE_BOOT_V2_ECC)
|
||||
|
||||
3. 使用公钥,采用 RSA-PSS(RFC8017 的第 8.1.2 节)算法,验证 bootloader 镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。
|
||||
3. 使用公钥,采用 RSA-PSS(RFC8017 的第 8.1.2 节)算法,验证引导加载程序镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。
|
||||
|
||||
.. only:: SOC_SECURE_BOOT_V2_ECC and not SOC_SECURE_BOOT_V2_RSA
|
||||
|
||||
3. 使用公钥,采用 ECDSA(RFC6090 的第 5.3.3 节)算法,验证 bootloader 镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。
|
||||
3. 使用公钥,采用 ECDSA(RFC6090 的第 5.3.3 节)算法,验证引导加载程序镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。
|
||||
|
||||
.. only:: SOC_SECURE_BOOT_V2_ECC and SOC_SECURE_BOOT_V2_RSA
|
||||
|
||||
1. 使用公钥,采用 RSA-PSS(RFC8017 的第 8.1.2 节)算法或 ECDSA(RFC6090 的第 5.3.3 节)算法,验证 bootloader 镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。
|
||||
1. 使用公钥,采用 RSA-PSS(RFC8017 的第 8.1.2 节)算法或 ECDSA(RFC6090 的第 5.3.3 节)算法,验证引导加载程序镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。
|
||||
|
||||
|
||||
bootloader 大小
|
||||
------------------
|
||||
|
||||
启用安全启动和/或 flash 加密都会增加 bootloader 的大小,因此可能需要更新分区表偏移量,请参阅 :ref:`bootloader-size`。
|
||||
启用安全启动和/或 flash 加密都会增加引导加载程序的大小,因此可能需要更新分区表偏移量,请参阅 :ref:`bootloader-size`。
|
||||
|
||||
禁用 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 时,bootloader 将使用 ``esptool`` 的 ``elf2image`` 命令中的 ``--pad-to-size`` 选项进行扇区填充,每个扇区大小为 4 KB。
|
||||
禁用 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 时,引导加载程序将使用 ``esptool`` 的 ``elf2image`` 命令中的 ``--pad-to-size`` 选项进行扇区填充,每个扇区大小为 4 KB。
|
||||
|
||||
|
||||
.. _efuse-usage:
|
||||
@ -405,17 +405,17 @@ bootloader 大小
|
||||
|
||||
在生产环境下,建议使用 OpenSSL 或其他行业标准的加密程序生成密钥对,详情请参阅 :ref:`secure-boot-v2-generate-key`。
|
||||
|
||||
7. 运行 ``idf.py bootloader`` 构建启用了安全启动的 bootloader ,构建输出中会包含一个烧录命令的提示,使用 ``esptool.py write_flash`` 烧录。
|
||||
7. 运行 ``idf.py bootloader`` 构建启用了安全启动的引导加载程序,构建输出中会包含一个烧录命令的提示,使用 ``esptool.py write_flash`` 烧录。
|
||||
|
||||
8. 烧录 bootloader 前,请运行指定命令并等待烧录完成。注意,此处的指定命令需要手动输入,构建系统不会执行此过程。
|
||||
8. 烧录引导加载程序前,请运行指定命令并等待烧录完成。注意,此处的指定命令需要手动输入,构建系统不会执行此过程。
|
||||
|
||||
9. 运行 ``idf.py flash`` 构建并烧录分区表以及刚刚构建的应用程序镜像,该镜像使用步骤 6 中生成的签名密钥进行签名。
|
||||
|
||||
.. note::
|
||||
|
||||
如果启用了安全启动,``idf.py flash`` 不会烧录 bootloader。
|
||||
如果启用了安全启动,``idf.py flash`` 不会烧录引导加载程序。
|
||||
|
||||
10. 重置 {IDF_TARGET_NAME} 将启动烧录的软件 bootloader。该软件 bootloader 会在芯片上启用安全启动,然后验证应用程序镜像签名,并启动应用程序。请查看 {IDF_TARGET_NAME} 的串行控制器输出,确保已启用安全启动,且没有因构建配置发生错误。
|
||||
10. 重置 {IDF_TARGET_NAME},它将启动你烧录的二级引导加载程序。该二级引导加载程序会在芯片上启用安全启动,然后验证应用程序镜像签名,并启动应用程序。请查看 {IDF_TARGET_NAME} 的串行控制器输出,确保已启用安全启动,且没有因构建配置发生错误。
|
||||
|
||||
.. note::
|
||||
|
||||
@ -425,13 +425,13 @@ bootloader 大小
|
||||
|
||||
如果在初次启动过程中重置或关闭了 {IDF_TARGET_NAME},它会在下次启动时重新开始上述步骤。
|
||||
|
||||
11. 在后续启动过程中,安全启动硬件会验证软件 bootloader 是否更改,软件 bootloader 会使用其附加的签名块中经验证的公钥部分,验证已签名的应用程序镜像。
|
||||
11. 在后续启动过程中,安全启动硬件会验证二级引导加载程序是否更改,二级引导加载程序会使用其附加的签名块中经验证的公钥部分,验证已签名的应用程序镜像。
|
||||
|
||||
|
||||
启用安全启动后的限制
|
||||
-----------------------------------------
|
||||
|
||||
- 任何更新过的 bootloader 或应用程序都需要使用与已存储在 eFuse 中的摘要相匹配的密钥来签名。
|
||||
- 任何更新过的引导加载程序或应用程序都需要使用与已存储在 eFuse 中的摘要相匹配的密钥来签名。
|
||||
|
||||
- 注意,启用安全启动或 flash 加密会禁用 ROM 中的 USB-OTG USB 栈,阻止通过该端口进行串行仿真或设备固件更新 (DFU)。
|
||||
|
||||
@ -578,7 +578,7 @@ bootloader 大小
|
||||
* 在具备高质量熵源的系统上生成签名密钥。
|
||||
* 时刻对签名密钥保密,泄漏此密钥将危及安全启动系统。
|
||||
* 不允许第三方使用 ``idf.py secure-`` 命令来观察密钥生成或签名过程的任何细节,这两个过程都容易受到定时攻击或其他侧信道攻击的威胁。
|
||||
* 在安全启动配置中启用所有安全启动选项,包括 flash 加密、禁用 JTAG、禁用 BASIC ROM 解释器和禁用 UART bootloader 的加密 flash 访问。
|
||||
* 在安全启动配置中启用所有安全启动选项,包括 flash 加密、禁用 JTAG、禁用 BASIC ROM 解释器和禁用 UART 引导加载程序的加密 flash 访问。
|
||||
* 结合 :doc:`flash-encryption` 使用安全启动,防止本地读取 flash 内容。
|
||||
|
||||
.. only:: SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS
|
||||
@ -589,18 +589,18 @@ bootloader 大小
|
||||
* 应独立计算并分别存储 1 到 3 个 {IDF_TARGET_SBV2_KEY} 公钥对(密钥 #0, #1, #2)。
|
||||
* 完成烧录后,应设置 KEY_DIGEST eFuse 为写保护位。
|
||||
* 未使用的 KEY_DIGEST 槽必须烧录其相应的 KEY_REVOKE eFuse,以永久禁用。请在设备离开工厂前完成此操作。
|
||||
* 烧录 eFuse 可以由软件 bootloader 在首次从 menuconfig 启用 ``Secure Boot v2`` 后进行,也可以使用 ``espefuse.py``,后者与 ROM 中的串行 bootloader 通信。
|
||||
* 烧录 eFuse 可以由二级引导加载程序在首次从 menuconfig 启用 ``Secure Boot v2`` 后进行,也可以使用 ``espefuse.py``,后者与 ROM 中的串行引导加载程序通信。
|
||||
* KEY_DIGEST 应从密钥摘要 #0 开始,按顺序编号。如果使用了密钥摘要 #1,则必须使用密钥摘要 #0。如果使用了密钥摘要 #2,则必须使用密钥摘要 #0 和 #1。
|
||||
* 软件 bootloader 不支持 OTA 升级,它将至少由一个私钥签名,也可能使用全部三个私钥,并在工厂内烧录。
|
||||
* 应用程序应仅由单个私钥签名,其他私钥应妥善保管。但如果需要撤销某些私钥,也可以使用多个签名私钥,请参阅下文的 :ref:`secure-boot-v2-key-revocation`。
|
||||
* 二级引导加载程序不支持 OTA 升级,它将至少由一个私钥签名,也可能使用全部三个私钥,并在工厂内烧录。
|
||||
* 应用程序应仅由单个私钥签名,其他私钥应妥善保管。但如果需要注销某些私钥,也可以使用多个签名私钥,请参阅下文的 :ref:`secure-boot-v2-key-revocation`。
|
||||
|
||||
|
||||
多个密钥管理
|
||||
-------------
|
||||
|
||||
* 在烧录 bootloader 之前,应使用设备整个生命周期所需的所有私钥对 bootloader 签名。
|
||||
* 构建系统每次只能使用一个私钥签名,如果需要,必须手动运行命令以附加更多签名。
|
||||
* 可以使用 ``idf.py secure-sign-data`` 的附加功能,此命令也将在启用安全启动 v2 的 bootloader 编译的末尾显示。
|
||||
* 在烧录引导加载程序之前,应使用设备整个生命周期所需的所有私钥对引导加载程序签名。
|
||||
* 构建系统每次只能使用一个私钥签名,如果需要,你必须手动运行命令以附加更多签名。
|
||||
* 你可以使用 ``idf.py secure-sign-data`` 的附加功能,此命令也将在启用安全启动 v2 的引导加载程序编译的末尾显示。
|
||||
|
||||
.. code-block::
|
||||
|
||||
@ -621,13 +621,13 @@ bootloader 大小
|
||||
* 密钥按线性顺序处理,即密钥 #0、密钥 #1、密钥 #2。
|
||||
* 撤销一个密钥后,其余未被撤销的密钥仍可用于应用程序签名。例如,如密钥 #1 被撤销,仍然可以使用密钥 #0 和密钥 #2 给应用程序签名。
|
||||
* 应用程序每次应只使用一个密钥签名,尽量避免暴露未使用的私钥。
|
||||
* bootloader 可以使用来自工厂的多个函数签名。
|
||||
* 引导加载程序可以使用来自工厂的多个函数签名。
|
||||
|
||||
.. note::
|
||||
|
||||
请注意,启用配置 :ref:`CONFIG_SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS` 只能确保 **应用程序** 不会撤销未使用的摘要槽。
|
||||
若想在设备首次启动时启用安全启动,那么即使启用了上述配置,bootloader 也会在启用安全启动时撤销未使用的摘要槽,因为保留未使用的密钥槽会构成安全隐患。
|
||||
如果在开发流程中需要保留未使用摘要槽,则应从外部启用安全启动 (:ref:`enable-secure-boot-v2-externally`),而不是在启动设备时启用安全启动,这样 bootloader 就无需启用安全启动,从而避免安全隐患。
|
||||
若想在设备首次启动时启用安全启动,那么即使启用了上述配置,引导加载程序也会在启用安全启动时撤销未使用的摘要槽,因为保留未使用的密钥槽会构成安全隐患。
|
||||
如果在开发流程中需要保留未使用摘要槽,则应从外部启用安全启动 (:ref:`enable-secure-boot-v2-externally`),而不是在启动设备时启用安全启动,这样引导加载程序就无需启用安全启动,从而避免安全隐患。
|
||||
|
||||
保守方法
|
||||
~~~~~~~~~~~~
|
||||
@ -638,11 +638,11 @@ bootloader 大小
|
||||
2. 新的 OTA 更新写入未使用的 OTA 应用程序分区。
|
||||
3. 验证新应用程序的签名块。对比公钥与 eFuse 中烧录的摘要,并使用已验证的公钥验证应用程序。
|
||||
4. 将活动分区设置为新的 OTA 应用程序分区。
|
||||
5. 设备重置并加载使用密钥 #N-1 验证的 bootloader ,随后启动使用密钥 #N 验证的新应用程序。
|
||||
6. 新应用程序使用密钥 #N 验证 bootloader ,这是最后的检查,然后运行代码撤销密钥 #N-1,即设置 KEY_REVOKE eFuse 位。
|
||||
7. 可以使用 API :cpp:func:`esp_ota_revoke_secure_boot_public_key` 撤销密钥 #N-1。
|
||||
5. 设备重置并加载使用密钥 #N-1 验证的引导加载程序,随后启动使用密钥 #N 验证的新应用程序。
|
||||
6. 新应用程序使用密钥 #N 验证引导加载程序,这是最后的检查,然后运行代码注销密钥 #N-1,即设置 KEY_REVOKE eFuse 位。
|
||||
7. 可以使用 API `esp_ota_revoke_secure_boot_public_key()` 注销密钥 #N-1。
|
||||
|
||||
* 类似的方法也可以用于物理重新烧录,以使用新的密钥,还可以同时更改 bootloader 的内容。
|
||||
* 类似的方法也可以用于物理重新烧录,以使用新的密钥,还可以同时更改引导加载程序的内容。
|
||||
|
||||
.. note::
|
||||
|
||||
@ -668,17 +668,16 @@ bootloader 大小
|
||||
技术细节
|
||||
-----------------
|
||||
|
||||
以下章节包含安全启动元件的详细参考描述:
|
||||
以下章节包含安全启动元件的详细参考描述。
|
||||
|
||||
安全启动已集成到 ESP-IDF 构建系统中,因此 ``idf.py build`` 将进行应用程序镜像签名。启用 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 后,``idf.py bootloader`` 将生成一个已签名的引导加载程序。
|
||||
|
||||
手动命令
|
||||
~~~~~~~~~~~~~~~
|
||||
另外,也可以使用 ``idf.py`` 或 ``openssl`` 工具生成独立签名并进行验证。建议使用 ``idf.py``,但如果需在非 ESP-IDF 环境中生成或验证签名,也可以使用 ``openssl`` 命令,因为安全引导 v2 生成签名符合标准的签名算法。
|
||||
|
||||
安全启动已集成到 ESP-IDF 构建系统中,因此 ``idf.py build`` 将进行应用程序镜像签名。启用 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 后,``idf.py bootloader`` 将生成一个已签名的 bootloader 。
|
||||
用 ``idf.py`` 生成和验证签名
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
然而,也可以使用 ``idf.py`` 工具生成独立的签名和摘要。
|
||||
|
||||
二进制镜像签名:
|
||||
1. 二进制镜像签名:
|
||||
|
||||
.. code-block::
|
||||
|
||||
@ -686,6 +685,79 @@ bootloader 大小
|
||||
|
||||
Keyfile 是包含 {IDF_TARGET_SBV2_KEY} 签名私钥的 PEM 文件。
|
||||
|
||||
2. 验证签名的二进制镜像:
|
||||
|
||||
.. code-block::
|
||||
|
||||
idf.py secure-verify-signature --keyfile ./my_signing_key.pem image_signed.bin
|
||||
|
||||
Keyfile 是包含 {IDF_TARGET_SBV2_KEY} 公钥/私钥签名的 PEM 文件。
|
||||
|
||||
用 OpenSSL 生成和验证签名
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
最好使用 ``idf.py`` 工具生成和验证签名,但如果需要使用 OpenSSL 执行这些操作,可参考以下命令:
|
||||
|
||||
1. 生成需要计算签名的二进制文件镜像的摘要。
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
openssl dgst -sha256 -binary BINARY_FILE > DIGEST_BINARY_FILE
|
||||
|
||||
2. 使用上一步计算出的摘要生成该镜像的签名。
|
||||
|
||||
.. only:: SOC_SECURE_BOOT_V2_RSA
|
||||
|
||||
用于生成 RSA-PSS 签名:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
openssl pkeyutl -sign \
|
||||
-in DIGEST_BINARY_FILE \
|
||||
-inkey PRIVATE_SIGNING_KEY \
|
||||
-out SIGNATURE_FILE \
|
||||
-pkeyopt digest:sha256 \
|
||||
-pkeyopt rsa_padding_mode:pss \
|
||||
-pkeyopt rsa_pss_saltlen:32
|
||||
|
||||
.. only:: SOC_SECURE_BOOT_V2_ECC
|
||||
|
||||
用于生成 ECDSA 签名:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
openssl pkeyutl -sign \
|
||||
-in DIGEST_BINARY_FILE \
|
||||
-inkey PRIVATE_SIGNING_KEY \
|
||||
-out SIGNATURE_FILE
|
||||
|
||||
3. 验证生成的签名。
|
||||
|
||||
.. only:: SOC_SECURE_BOOT_V2_RSA
|
||||
|
||||
For verifying an RSA-PSS signature:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
openssl pkeyutl -verify \
|
||||
-in DIGEST_BINARY_FILE \
|
||||
-pubin -inkey PUBLIC_SIGNING_KEY \
|
||||
-sigfile SIGNATURE_FILE \
|
||||
-pkeyopt rsa_padding_mode:pss \
|
||||
-pkeyopt rsa_pss_saltlen:32 \
|
||||
-pkeyopt digest:sha256
|
||||
|
||||
.. only:: SOC_SECURE_BOOT_V2_ECC
|
||||
|
||||
用于验证 ECDSA 签名:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
openssl pkeyutl -verify \
|
||||
-in DIGEST_BINARY_FILE \
|
||||
-pubin -inkey PUBLIC_SIGNING_KEY \
|
||||
-sigfile SIGNATURE_FILE
|
||||
|
||||
|
||||
.. _secure-boot-v2-and-flash-encr:
|
||||
|
||||
@ -708,7 +780,7 @@ Keyfile 是包含 {IDF_TARGET_SBV2_KEY} 签名私钥的 PEM 文件。
|
||||
|
||||
无需启用硬件安全启动选项,即可在 OTA 更新时验证应用程序的安全启动 v2 签名。这种方法采用了与安全启动 v2 相同的应用程序签名方案,但不同于硬件安全启动,软件安全启动无法阻止能够写入 flash 的攻击者绕过签名验证。
|
||||
|
||||
如果在启动时无法接受安全启动验证的延迟,和/或威胁模型不包括物理访问或攻击者在 flash 中写入 bootloader 或应用程序分区,则适合使用未启用硬件安全启动的验证。
|
||||
如果在启动时无法接受安全启动验证的延迟,和/或威胁模型不包括物理访问或攻击者在 flash 中写入引导加载程序或应用程序分区,则适合使用未启用硬件安全启动的验证。
|
||||
|
||||
在此模式下,当前运行的应用程序签名块中的公钥将用于验证新更新的应用程序签名。更新时,不会验证运行中的应用程序签名,而是假定它有效。通过这种方式,系统建立了从当前运行的应用程序到新更新的应用程序之间的信任链。
|
||||
|
||||
@ -764,6 +836,6 @@ Keyfile 是包含 {IDF_TARGET_SBV2_KEY} 签名私钥的 PEM 文件。
|
||||
JTAG 调试
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
启用安全启动模式时,eFuse 会默认禁用 JTAG。初次启动时,bootloader 即禁用 JTAG 调试功能,并启用安全启动模式。
|
||||
启用安全启动模式时,eFuse 会默认禁用 JTAG。初次启动时,引导加载程序即禁用 JTAG 调试功能,并启用安全启动模式。
|
||||
|
||||
有关在启用安全启动或已签名应用程序验证的情况下使用 JTAG 调试的更多信息,请参阅 :ref:`jtag-debugging-security-features`。
|
||||
|
@ -30,7 +30,7 @@
|
||||
#. 用逐步指令简化启用安全功能的传统工作流程。
|
||||
#. 设计比基于固件的传统工作流更加灵活的工作流。
|
||||
#. 将工作流划分为多个小操作,从而提高可靠性。
|
||||
#. 消除对 :ref:`second-stage-bootloader` (固件引导加载程序)的依赖。
|
||||
#. 消除对 :ref:`second-stage-bootloader` 的依赖。
|
||||
|
||||
准备工作
|
||||
--------
|
||||
@ -302,7 +302,7 @@
|
||||
:esp32: - :ref:`选择 UART ROM 下载模式(永久禁用(推荐))<CONFIG_SECURE_UART_ROM_DL_MODE>` (注意,此选项仅在 :ref:`CONFIG_ESP32_REV_MIN` 设为 3 (ESP32 V3) 时可用)。UART ROM 下载模式在默认设置中自动启用,但建议永久禁用此模式以减少攻击者可用的选项。
|
||||
:not esp32: - :ref:`选择发布模式 <CONFIG_SECURE_FLASH_ENCRYPTION_MODE>` (注意,若选择发布模式,则将烧录 ``EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT`` eFuse 位,ROM 下载模式下 flash 加密硬件将被禁用)。
|
||||
:not esp32: - :ref:`选择 UART ROM 下载模式(永久切换到安全模式(推荐))<CONFIG_SECURE_UART_ROM_DL_MODE>`。这是推荐的默认选项,如果不需要,也可将其更改为永久禁用 UART ROM 下载模式。
|
||||
- :ref:`选择适当的引导程序日志级别 <CONFIG_BOOTLOADER_LOG_LEVEL>`。
|
||||
- :ref:`选择适当的引导加载程序日志级别 <CONFIG_BOOTLOADER_LOG_LEVEL>`。
|
||||
- 保存配置并退出。
|
||||
|
||||
7. 构建、加密并烧录二进制文件
|
||||
@ -329,7 +329,7 @@
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
如果 ESP32 在 eFuse 中使用非默认的 :ref:`FLASH_CRYPT_CONFIG 值 <setting-flash-crypt-config>`,需要将 ``--flash_crypt_conf`` 参数传递给 ``espsecure.py`` 以设置匹配值。如果设备自行配置 flash 加密,则不会发生这种情况,但是如果手动烧录了 eFuses 启用 flash 加密,就有可能发生。
|
||||
如果 ESP32 在 eFuse 中使用非默认的 :ref:`FLASH_CRYPT_CONFIG 值 <setting-flash-crypt-config>`,需要将 ``--flash_crypt_conf`` 参数传递给 ``espsecure.py`` 以设置匹配值。如果通过二级引导加载程序配置 flash 加密,则不会发生这种情况,但是如果手动烧录了 eFuses 启用 flash 加密,就有可能发生。
|
||||
|
||||
使用 ``espsecure.py decrypt_flash_data`` 命令时,可以用相同的选项(和不同的输入或输出文件)来解密密文 flash 或之前加密的文件。
|
||||
|
||||
@ -523,7 +523,7 @@ flash 加密指南
|
||||
|
||||
6. 构建二进制文件
|
||||
|
||||
默认情况下,ROM 引导加载程序只会验证 :ref:`second-stage-bootloader` (固件引导加载程序)。只有在启用 :ref:`CONFIG_SECURE_BOOT` 选项(并将 :ref:`CONFIG_SECURE_BOOT_VERSION` 设置为 ``SECURE_BOOT_V2_ENABLED``)时,固件引导加载程序才会在构建引导加载程序时验证应用程序分区。
|
||||
默认情况下,一级 (ROM) 引导加载程序只会验证 :ref:`second-stage-bootloader`。只有在启用 :ref:`CONFIG_SECURE_BOOT` 选项(并将 :ref:`CONFIG_SECURE_BOOT_VERSION` 设置为 ``SECURE_BOOT_V2_ENABLED``)时,二级引导加载程序才会在构建引导加载程序时验证应用程序分区。
|
||||
|
||||
A) 打开 :ref:`project-configuration-menu`,在 ``Security features`` 中设置 ``Enable hardware Secure Boot in bootloader`` 启用 Secure Boot。
|
||||
|
||||
|
@ -125,7 +125,7 @@ ESP-IDF 的每个主要版本和次要版本(V4.1、V4.2 等)的支持期限
|
||||
|
||||
idf.py --version
|
||||
|
||||
此外,由于 ESP-IDF 的版本也已编译至固件中,因此你也可以使用宏 ``IDF_VER`` 查看 ESP-IDF 的版本(以字符串的格式)。ESP-IDF 默认引导程序会在设备启动时打印 ESP-IDF 的版本。请注意,在 GitHub 仓库中的代码更新时,代码中的版本信息仅会在源代码重新编译或在清除编译时才会更新,因此打印出来的版本可能并不是最新的。
|
||||
此外,由于 ESP-IDF 的版本也已编译至固件中,因此你也可以使用宏 ``IDF_VER`` 查看 ESP-IDF 的版本(以字符串的格式)。ESP-IDF 默认引导加载程序会在设备启动时打印 ESP-IDF 的版本。请注意,在 GitHub 仓库中的代码更新时,代码中的版本信息仅会在源代码重新编译或在清除编译时才会更新,因此打印出来的版本可能并不是最新的。
|
||||
|
||||
如果编写的代码需要支持多个 ESP-IDF 版本,可以在编译时使用 :ref:`compile-time macros<idf-version-h>` 检查版本。
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user