From 79923d01992566626cb4a09156d2ec4f299e1d73 Mon Sep 17 00:00:00 2001 From: suda-morris <362953310@qq.com> Date: Mon, 16 Sep 2019 11:47:23 +0800 Subject: [PATCH 1/2] Add chip revision into image header Check chip id and chip revision before boot app image Closes https://github.com/espressif/esp-idf/issues/4000 --- Kconfig | 4 ++++ components/app_update/esp_ota_ops.c | 4 ++-- .../include/bootloader_common.h | 13 +++++++++++- .../include/esp_app_format.h | 17 ++++++++++++++- .../src/bootloader_common.c | 21 +++++++++++++++++++ .../bootloader_support/src/bootloader_init.c | 9 ++++++++ .../bootloader_support/src/esp_image_format.c | 4 ++++ components/esp32/cpu_start.c | 9 -------- components/esptool_py/Makefile.projbuild | 4 ++++ components/esptool_py/esptool | 2 +- components/esptool_py/project_include.cmake | 4 ++++ 11 files changed, 77 insertions(+), 14 deletions(-) diff --git a/Kconfig b/Kconfig index ad049f5dbf..b6351a86c8 100644 --- a/Kconfig +++ b/Kconfig @@ -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 diff --git a/components/app_update/esp_ota_ops.c b/components/app_update/esp_ota_ops.c index df6d8a9066..5f53566cb2 100644 --- a/components/app_update/esp_ota_ops.c +++ b/components/app_update/esp_ota_ops.c @@ -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; @@ -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; } diff --git a/components/bootloader_support/include/bootloader_common.h b/components/bootloader_support/include/bootloader_common.h index 2475d842a5..47733210ef 100644 --- a/components/bootloader_support/include/bootloader_common.h +++ b/components/bootloader_support/include/bootloader_common.h @@ -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" { @@ -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. @@ -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. */ diff --git a/components/bootloader_support/include/esp_app_format.h b/components/bootloader_support/include/esp_app_format.h index 4917dd0f7b..c7edaebd2d 100644 --- a/components/bootloader_support/include/esp_app_format.h +++ b/components/bootloader_support/include/esp_app_format.h @@ -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 */ @@ -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. diff --git a/components/bootloader_support/src/bootloader_common.c b/components/bootloader_support/src/bootloader_common.c index ed0169a960..7d97221400 100644 --- a/components/bootloader_support/src/bootloader_common.c +++ b/components/bootloader_support/src/bootloader_common.c @@ -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 */ @@ -270,3 +271,23 @@ void bootloader_common_vddsdio_configure() } #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; +} diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index 67ec3626c9..6239d3c920 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -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" @@ -127,6 +128,14 @@ static esp_err_t bootloader_main() 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 diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index a0f6c4698e..36afe923c0 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -24,6 +24,7 @@ #include #include #include "bootloader_util.h" +#include "bootloader_common.h" /* Checking signatures as part of verifying images is necessary: - Always if secure boot is enabled @@ -278,6 +279,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); diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index b55753a6dc..1f7fb0eb18 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -400,15 +400,6 @@ void start_cpu0_default(void) esp_err_t flash_ret = esp_flash_init_default_chip(); assert(flash_ret == ESP_OK); - 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 diff --git a/components/esptool_py/Makefile.projbuild b/components/esptool_py/Makefile.projbuild index 8292c06ecd..a351e8282f 100644 --- a/components/esptool_py/Makefile.projbuild +++ b/components/esptool_py/Makefile.projbuild @@ -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 diff --git a/components/esptool_py/esptool b/components/esptool_py/esptool index 1a7dbf787e..4f1e825d2d 160000 --- a/components/esptool_py/esptool +++ b/components/esptool_py/esptool @@ -1 +1 @@ -Subproject commit 1a7dbf787e7e504acdeaea074d15a5ccaf87e9e8 +Subproject commit 4f1e825d2d1ee33b896b3977905fb29ac6cc0794 diff --git a/components/esptool_py/project_include.cmake b/components/esptool_py/project_include.cmake index 78dc03cbb0..af676a626b 100644 --- a/components/esptool_py/project_include.cmake +++ b/components/esptool_py/project_include.cmake @@ -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... From bcd496be49bb180b10f4ebd010912db0eb57e3c8 Mon Sep 17 00:00:00 2001 From: suda-morris <362953310@qq.com> Date: Fri, 27 Sep 2019 10:58:30 +0800 Subject: [PATCH 2/2] bootloader: shrink bin size 1. write a bootloader version of "getting chip revision" function. 2. reduce wordy log. --- .../include/bootloader_common.h | 7 +++ .../src/bootloader_common.c | 43 ++++++++++++++++--- .../bootloader_support/src/bootloader_init.c | 3 +- components/efuse/src/esp_efuse_fields.c | 2 +- 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/components/bootloader_support/include/bootloader_common.h b/components/bootloader_support/include/bootloader_common.h index 47733210ef..e9577c83e7 100644 --- a/components/bootloader_support/include/bootloader_common.h +++ b/components/bootloader_support/include/bootloader_common.h @@ -142,6 +142,13 @@ 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 Get chip revision + * + * @return Chip revision number + */ +uint8_t bootloader_common_get_chip_revision(void); + /** * @brief Check if the image (bootloader and application) has valid chip ID and revision * diff --git a/components/bootloader_support/src/bootloader_common.c b/components/bootloader_support/src/bootloader_common.c index 7d97221400..9251331e76 100644 --- a/components/bootloader_support/src/bootloader_common.c +++ b/components/bootloader_support/src/bootloader_common.c @@ -25,10 +25,11 @@ #include "bootloader_common.h" #include "soc/gpio_periph.h" #include "soc/rtc.h" +#include "soc/efuse_reg.h" +#include "soc/apb_ctrl_reg.h" #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 */ @@ -272,22 +273,50 @@ void bootloader_common_vddsdio_configure() #endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST } +#ifdef CONFIG_IDF_TARGET_ESP32 +uint8_t bootloader_common_get_chip_revision(void) +{ + uint8_t eco_bit0, eco_bit1, eco_bit2; + eco_bit0 = (REG_READ(EFUSE_BLK0_RDATA3_REG) & 0xF000) >> 15; + eco_bit1 = (REG_READ(EFUSE_BLK0_RDATA5_REG) & 0x100000) >> 20; + eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 0x80000000) >> 31; + uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0; + uint8_t chip_ver = 0; + switch (combine_value) { + case 0: + chip_ver = 0; + break; + case 1: + chip_ver = 1; + break; + case 3: + chip_ver = 2; + break; + case 7: + chip_ver = 3; + break; + default: + chip_ver = 0; + break; + } + return chip_ver; +} +#endif + 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); + ESP_LOGE(TAG, "mismatch chip ID, expect %d, found %d", chip_id, img_hdr->chip_id); err = ESP_FAIL; } - uint8_t revision = esp_efuse_get_chip_ver(); + uint8_t revision = bootloader_common_get_chip_revision(); 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); + ESP_LOGE(TAG, "can't run on lower chip revision, expect %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); + ESP_LOGI(TAG, "mismatch chip revision, expect %d, found %d", revision, img_hdr->min_chip_rev); } return err; } diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index 6239d3c920..5c61122fc5 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -41,7 +41,6 @@ #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" @@ -130,7 +129,7 @@ static esp_err_t bootloader_main() } /* Check chip ID and minimum chip revision that supported by this image */ - uint8_t revision = esp_efuse_get_chip_ver(); + uint8_t revision = bootloader_common_get_chip_revision(); ESP_LOGI(TAG, "Chip Revision: %d", revision); if (bootloader_common_check_chip_validity(&fhdr) != ESP_OK) { return ESP_FAIL; diff --git a/components/efuse/src/esp_efuse_fields.c b/components/efuse/src/esp_efuse_fields.c index 39a38f2744..8e3cdc7992 100644 --- a/components/efuse/src/esp_efuse_fields.c +++ b/components/efuse/src/esp_efuse_fields.c @@ -35,7 +35,7 @@ uint8_t esp_efuse_get_chip_ver(void) uint8_t eco_bit0, eco_bit1, eco_bit2; esp_efuse_read_field_blob(ESP_EFUSE_CHIP_VER_REV1, &eco_bit0, 1); esp_efuse_read_field_blob(ESP_EFUSE_CHIP_VER_REV2, &eco_bit1, 1); - eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 80000000) >> 31; + eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 0x80000000) >> 31; uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0; uint8_t chip_ver = 0; switch (combine_value) {