Skip to content

Commit

Permalink
Add chip revision into image header
Browse files Browse the repository at this point in the history
Check chip id and chip revision before boot app image

Closes #4000
  • Loading branch information
suda-morris committed Sep 16, 2019
1 parent a70c336 commit dd248ff
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 15 deletions.
4 changes: 4 additions & 0 deletions Kconfig
Expand Up @@ -29,6 +29,10 @@ mainmenu "Espressif IoT Development Framework Configuration"
default "IDF_TARGET_NOT_SET" if IDF_TARGET_ENV=""
default IDF_TARGET_ENV

config IDF_FIRMWARE_CHIP_ID
hex
default 0x0000 if IDF_TARGET="esp32"
default 0xFFFF

menu "SDK tool configuration"
config SDK_TOOLPREFIX
Expand Down
4 changes: 2 additions & 2 deletions components/app_update/esp_ota_ops.c
Expand Up @@ -42,7 +42,7 @@
#include "esp_efuse.h"


#define SUB_TYPE_ID(i) (i & 0x0F)
#define SUB_TYPE_ID(i) (i & 0x0F)

typedef struct ota_ops_entry_ {
uint32_t handle;
Expand Down Expand Up @@ -200,7 +200,7 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
// must erase the partition before writing to it
assert(it->erased_size > 0 && "must erase the partition before writing to it");
if (it->wrote_size == 0 && it->partial_bytes == 0 && size > 0 && data_bytes[0] != ESP_IMAGE_HEADER_MAGIC) {
ESP_LOGE(TAG, "OTA image has invalid magic byte (expected 0xE9, saw 0x%02x", data_bytes[0]);
ESP_LOGE(TAG, "OTA image has invalid magic byte (expected 0xE9, saw 0x%02x)", data_bytes[0]);
return ESP_ERR_OTA_VALIDATE_FAILED;
}

Expand Down
13 changes: 12 additions & 1 deletion components/bootloader_support/include/bootloader_common.h
Expand Up @@ -15,6 +15,7 @@
#pragma once
#include "esp_flash_partitions.h"
#include "esp_image_format.h"
#include "esp_app_format.h"

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -129,7 +130,7 @@ int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata,

/**
* @brief Returns esp_app_desc structure for app partition. This structure includes app version.
*
*
* Returns a description for the requested app partition.
* @param[in] partition App partition description.
* @param[out] app_desc Structure of info about app.
Expand All @@ -141,6 +142,16 @@ int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata,
*/
esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc);

/**
* @brief Check if the image (bootloader and application) has valid chip ID and revision
*
* @param img_hdr: image header
* @return
* - ESP_OK: image and chip are matched well
* - ESP_FAIL: image doesn't match to the chip
*/
esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hdr);

/**
* @brief Configure VDDSDIO, call this API to rise VDDSDIO to 1.9V when VDDSDIO regulator is enabled as 1.8V mode.
*/
Expand Down
17 changes: 16 additions & 1 deletion components/bootloader_support/include/esp_app_format.h
Expand Up @@ -13,6 +13,19 @@
// limitations under the License.
#pragma once

/**
* @brief ESP chip ID
*
*/
typedef enum {
ESP_CHIP_ID_ESP32 = 0x0000, /*!< chip ID: ESP32 */
ESP_CHIP_ID_INVALID = 0xFFFF /*!< Invalid chip ID (we defined it to make sure the esp_chip_id_t is 2 bytes size) */
} __attribute__((packed)) esp_chip_id_t;

/** @cond */
_Static_assert(sizeof(esp_chip_id_t) == 2, "esp_chip_id_t should be 16 bit");
/** @endcond */

/**
* @brief SPI flash mode, used in esp_image_header_t
*/
Expand Down Expand Up @@ -63,7 +76,9 @@ typedef struct {
* the IDF bootloader uses software to configure the WP
* pin and sets this field to 0xEE=disabled) */
uint8_t spi_pin_drv[3]; /*!< Drive settings for the SPI flash pins (read by ROM bootloader) */
uint8_t reserved[11]; /*!< Reserved bytes in ESP32 additional header space, currently unused */
esp_chip_id_t chip_id; /*!< Chip identification number */
uint8_t min_chip_rev; /*!< Minimum chip revision supported by image */
uint8_t reserved[8]; /*!< Reserved bytes in additional header space, currently unused */
uint8_t hash_appended; /*!< If 1, a SHA256 digest "simple hash" (of the entire image) is appended after the checksum.
* Included in image length. This digest
* is separate to secure boot and only used for detecting corruption.
Expand Down
22 changes: 21 additions & 1 deletion components/bootloader_support/src/bootloader_common.c
Expand Up @@ -28,6 +28,7 @@
#include "esp_image_format.h"
#include "bootloader_sha.h"
#include "sys/param.h"
#include "esp_efuse.h"

#define ESP_PARTITION_HASH_LEN 32 /* SHA-256 digest length */

Expand Down Expand Up @@ -271,6 +272,25 @@ void bootloader_common_vddsdio_configure(void)
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
}

esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hdr)
{
esp_err_t err = ESP_OK;
esp_chip_id_t chip_id = CONFIG_IDF_FIRMWARE_CHIP_ID;
if (chip_id != img_hdr->chip_id) {
ESP_LOGE(TAG, "image has invalid chip ID, expected at least %d, found %d", chip_id, img_hdr->chip_id);
err = ESP_FAIL;
}
uint8_t revision = esp_efuse_get_chip_ver();
if (revision < img_hdr->min_chip_rev) {
ESP_LOGE(TAG, "image has invalid chip revision, expected at least %d, found %d", revision, img_hdr->min_chip_rev);
err = ESP_FAIL;
} else if (revision != img_hdr->min_chip_rev) {
ESP_LOGI(TAG, "This chip is revision %d but project was configured for minimum revision %d. "\
"Suggest setting project minimum revision to %d if safe to do so.",
revision, img_hdr->min_chip_rev, revision);
}
return err;
}

#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )

Expand Down Expand Up @@ -332,4 +352,4 @@ rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void)
{
return rtc_retain_mem;
}
#endif
#endif
9 changes: 9 additions & 0 deletions components/bootloader_support/src/bootloader_init.c
Expand Up @@ -41,6 +41,7 @@
#include "soc/spi_periph.h"

#include "sdkconfig.h"
#include "esp_efuse.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp_flash_encrypt.h"
Expand Down Expand Up @@ -128,6 +129,14 @@ static esp_err_t bootloader_main(void)
ESP_LOGE(TAG, "failed to load bootloader header!");
return ESP_FAIL;
}

/* Check chip ID and minimum chip revision that supported by this image */
uint8_t revision = esp_efuse_get_chip_ver();
ESP_LOGI(TAG, "Chip Revision: %d", revision);
if (bootloader_common_check_chip_validity(&fhdr) != ESP_OK) {
return ESP_FAIL;
}

bootloader_init_flash_configure(&fhdr);
#if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240)
//Check if ESP32 is rated for a CPU frequency of 160MHz only
Expand Down
4 changes: 4 additions & 0 deletions components/bootloader_support/src/esp_image_format.c
Expand Up @@ -24,6 +24,7 @@
#include <bootloader_random.h>
#include <bootloader_sha.h>
#include "bootloader_util.h"
#include "bootloader_common.h"

/* Checking signatures as part of verifying images is necessary:
- Always if secure boot is enabled
Expand Down Expand Up @@ -299,6 +300,9 @@ static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t
}
err = ESP_ERR_IMAGE_INVALID;
}
if (bootloader_common_check_chip_validity(image) != ESP_OK) {
err = ESP_ERR_IMAGE_INVALID;
}
if (!silent) {
if (image->spi_mode > ESP_IMAGE_SPI_MODE_SLOW_READ) {
ESP_LOGW(TAG, "image at 0x%x has invalid SPI mode %d", src_addr, image->spi_mode);
Expand Down
9 changes: 0 additions & 9 deletions components/esp32/cpu_start.c
Expand Up @@ -401,15 +401,6 @@ void start_cpu0_default(void)
assert(flash_ret == ESP_OK);
#endif

uint8_t revision = esp_efuse_get_chip_ver();
ESP_LOGI(TAG, "Chip Revision: %d", revision);
if (revision > CONFIG_ESP32_REV_MIN) {
ESP_LOGW(TAG, "Chip revision is higher than the one configured in menuconfig. Suggest to upgrade it.");
} else if(revision != CONFIG_ESP32_REV_MIN) {
ESP_LOGE(TAG, "ESP-IDF can't support this chip revision. Modify minimum supported revision in menuconfig");
abort();
}

#ifdef CONFIG_PM_ENABLE
esp_pm_impl_init();
#ifdef CONFIG_PM_DFS_INIT_AUTO
Expand Down
4 changes: 4 additions & 0 deletions components/esptool_py/Makefile.projbuild
Expand Up @@ -31,6 +31,10 @@ endif

ESPTOOL_ELF2IMAGE_OPTIONS :=

ifdef CONFIG_ESP32_REV_MIN
ESPTOOL_ELF2IMAGE_OPTIONS += --min-rev $(CONFIG_ESP32_REV_MIN)
endif

ifdef CONFIG_SECURE_BOOT_ENABLED
ifndef CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION
ifndef IS_BOOTLOADER_BUILD
Expand Down
2 changes: 1 addition & 1 deletion components/esptool_py/esptool
Submodule esptool updated 4 files
+97 −68 espefuse.py
+44 −10 esptool.py
+1 −1 setup.cfg
+3 −2 test/test_imagegen.py
4 changes: 4 additions & 0 deletions components/esptool_py/project_include.cmake
Expand Up @@ -52,6 +52,10 @@ if(CONFIG_SECURE_BOOT_ENABLED AND
set(ESPTOOLPY_ELF2IMAGE_OPTIONS ${ESPTOOLPY_ELF2IMAGE_OPTIONS} --secure-pad)
endif()

if(CONFIG_ESP32_REV_MIN)
set(ESPTOOLPY_ELF2IMAGE_OPTIONS ${ESPTOOLPY_ELF2IMAGE_OPTIONS} --min-rev ${CONFIG_ESP32_REV_MIN})
endif()

if(CONFIG_ESPTOOLPY_FLASHSIZE_DETECT)
# Set ESPFLASHSIZE to 'detect' *after* elf2image options are generated,
# as elf2image can't have 'detect' as an option...
Expand Down

0 comments on commit dd248ff

Please sign in to comment.