feat(bootloader): support to check efuse block revision

change(bootloader): remove ignore efuse check flag (temp)

change(bootloader): use int for the minimum efuse blk rev (temp)
This commit is contained in:
laokaiyao
2024-08-14 19:02:59 +08:00
parent f3879f7615
commit 1c2f8b8ce0
23 changed files with 288 additions and 36 deletions
@@ -27,7 +27,7 @@
#include "esp_rom_caps.h"
#define ESP_PARTITION_HASH_LEN 32 /* SHA-256 digest length */
#define IS_MAX_REV_SET(max_chip_rev_full) (((max_chip_rev_full) != 65535) && ((max_chip_rev_full) != 0))
#define IS_FIELD_SET(rev_full) (((rev_full) != 65535) && ((rev_full) != 0))
static const char* TAG = "boot_comm";
@@ -57,6 +57,31 @@ int bootloader_common_get_active_otadata(esp_ota_select_entry_t *two_otadata)
return bootloader_common_select_otadata(two_otadata, valid_two_otadata, true);
}
#if !CONFIG_IDF_TARGET_ESP32
esp_err_t bootloader_common_check_efuse_blk_validity(uint32_t min_rev_full, uint32_t max_rev_full)
{
esp_err_t err = ESP_OK;
#ifndef CONFIG_IDF_ENV_FPGA
// Check whether the efuse block version satisfy the requirements of current image.
uint32_t revision = efuse_hal_blk_version();
uint32_t major_rev = revision / 100;
uint32_t minor_rev = revision % 100;
if (IS_FIELD_SET(min_rev_full) && !ESP_EFUSE_BLK_REV_ABOVE(revision, min_rev_full)) {
ESP_LOGE(TAG, "Image requires efuse blk rev >= v%"PRIu32".%"PRIu32", but chip is v%"PRIu32".%"PRIu32,
min_rev_full / 100, min_rev_full % 100, major_rev, minor_rev);
err = ESP_FAIL;
}
// If burnt `disable_blk_version_major` bit, skip the max version check
if ((IS_FIELD_SET(max_rev_full) && (revision > max_rev_full) && !efuse_hal_get_disable_blk_version_major())) {
ESP_LOGE(TAG, "Image requires efuse blk rev <= v%"PRIu32".%"PRIu32", but chip is v%"PRIu32".%"PRIu32,
max_rev_full / 100, max_rev_full % 100, major_rev, minor_rev);
err = ESP_FAIL;
}
#endif
return err;
}
#endif // !CONFIG_IDF_TARGET_ESP32
esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hdr, esp_image_type type)
{
esp_err_t err = ESP_OK;
@@ -80,7 +105,7 @@ esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hd
}
if (type == ESP_IMAGE_APPLICATION) {
unsigned max_rev = img_hdr->max_chip_rev_full;
if ((IS_MAX_REV_SET(max_rev) && (revision > max_rev) && !efuse_hal_get_disable_wafer_version_major())) {
if ((IS_FIELD_SET(max_rev) && (revision > max_rev) && !efuse_hal_get_disable_wafer_version_major())) {
ESP_LOGE(TAG, "Image requires chip rev <= v%d.%d, but chip is v%d.%d",
max_rev / 100, max_rev % 100,
major_rev, minor_rev);
@@ -43,10 +43,17 @@ esp_err_t bootloader_read_bootloader_header(void)
esp_err_t bootloader_check_bootloader_validity(void)
{
unsigned int revision = efuse_hal_chip_revision();
unsigned int major = revision / 100;
unsigned int minor = revision % 100;
ESP_EARLY_LOGI(TAG, "chip revision: v%d.%d", major, minor);
unsigned int chip_revision = efuse_hal_chip_revision();
unsigned int chip_major_rev = chip_revision / 100;
unsigned int chip_minor_rev = chip_revision % 100;
ESP_EARLY_LOGI(TAG, "chip revision: v%d.%d", chip_major_rev, chip_minor_rev);
/* ESP32 doesn't have more memory and more efuse bits for block major version. */
#if !CONFIG_IDF_TARGET_ESP32
unsigned int efuse_revision = efuse_hal_blk_version();
unsigned int efuse_major_rev = efuse_revision / 100;
unsigned int efuse_minor_rev = efuse_revision % 100;
ESP_EARLY_LOGI(TAG, "efuse block revision: v%d.%d", efuse_major_rev, efuse_minor_rev);
#endif // !CONFIG_IDF_TARGET_ESP32
/* compare with the one set in bootloader image header */
if (bootloader_common_check_chip_validity(&bootloader_image_hdr, ESP_IMAGE_BOOTLOADER) != ESP_OK) {
return ESP_FAIL;
@@ -691,19 +691,28 @@ static esp_err_t process_segment_data(int segment, intptr_t load_addr, uint32_t
const uint32_t *src = data;
#if CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
// Case I: Bootloader verifying application
// Case II: Bootloader verifying bootloader
// Anti-rollback check should handle only Case I from above.
// The esp_app_desc_t structure is located in DROM and is always in segment #0.
// Anti-rollback check and efuse block version check should handle only Case I from above.
if (segment == 0 && metadata->start_addr != ESP_BOOTLOADER_OFFSET) {
/* ESP32 doesn't have more memory and more efuse bits for block major version. */
#if !CONFIG_IDF_TARGET_ESP32
const esp_app_desc_t *app_desc = (const esp_app_desc_t *)src;
esp_err_t ret = bootloader_common_check_efuse_blk_validity(app_desc->min_efuse_blk_rev_full, app_desc->max_efuse_blk_rev_full);
if (ret != ESP_OK) {
bootloader_munmap(data);
return ret;
}
#endif // !CONFIG_IDF_TARGET_ESP32
#if CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
ESP_LOGD(TAG, "additional anti-rollback check 0x%"PRIx32, data_addr);
// The esp_app_desc_t structure is located in DROM and is always in segment #0.
size_t len = process_esp_app_desc_data(src, sha_handle, checksum, metadata);
data_len -= len;
src += len / 4;
// In BOOTLOADER_BUILD, for DROM (segment #0) we do not load it into dest (only map it), do_load = false.
}
#endif // CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
}
for (size_t i = 0; i < data_len; i += 4) {
int w_i = i / 4; // Word index