diff --git a/components/efuse/src/esp_efuse_fields.c b/components/efuse/src/esp_efuse_fields.c index 52b7d273956..b4f53dc96be 100644 --- a/components/efuse/src/esp_efuse_fields.c +++ b/components/efuse/src/esp_efuse_fields.c @@ -81,11 +81,11 @@ esp_err_t esp_efuse_update_secure_version(uint32_t secure_version) uint32_t sec_ver_hw = esp_efuse_read_secure_version(); // If secure_version is the same as in eFuse field than it is ok just go out. if (sec_ver_hw < secure_version) { - uint32_t num_bit_hw = (1ULL << sec_ver_hw) - 1; - uint32_t num_bit_app = (1ULL << secure_version) - 1; - // Repeated programming of programmed bits is strictly forbidden - uint32_t new_bits = num_bit_app - num_bit_hw; // get only new bits - esp_efuse_write_field_blob(ESP_EFUSE_SECURE_VERSION, &new_bits, size); + esp_err_t err = esp_efuse_write_field_cnt(ESP_EFUSE_SECURE_VERSION, secure_version - sec_ver_hw); + if (err != ESP_OK || esp_efuse_read_secure_version() < secure_version) { + ESP_LOGE(TAG, "Failed to update secure version in eFuse"); + return ESP_FAIL; + } ESP_LOGI(TAG, "Anti-rollback is set. eFuse field is updated(%"PRIu32").", secure_version); } else if (sec_ver_hw > secure_version) { ESP_LOGE(TAG, "Anti-rollback is not set. secure_version of app is lower that eFuse field(%"PRIu32").", sec_ver_hw); diff --git a/components/efuse/test_apps/main/test_efuse.c b/components/efuse/test_apps/main/test_efuse.c index c07f4f2b618..8c6cd6e742f 100644 --- a/components/efuse/test_apps/main/test_efuse.c +++ b/components/efuse/test_apps/main/test_efuse.c @@ -282,6 +282,27 @@ TEST_CASE("efuse test write_field_cnt", "[efuse]") test_write_cnt(); } +TEST_CASE("secure version update handles sparse efuse field", "[efuse]") +{ + const uint32_t sparse_secure_version = 1U << 2; + const uint32_t expected_secure_version = 3; + size_t field_size = esp_efuse_get_field_size(ESP_EFUSE_SECURE_VERSION); + + // Preload a non-sequential state that may remain after an earlier incomplete update: + // initial: bitmap 0b100, secure version 1; + esp_efuse_utility_erase_virt_blocks(); + TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_SECURE_VERSION, &sparse_secure_version, field_size)); + TEST_ASSERT_EQUAL_UINT32(1, esp_efuse_read_secure_version()); + + // update to 3: bitmap 0b111, secure version 3; + TEST_ESP_OK(esp_efuse_update_secure_version(expected_secure_version)); + TEST_ASSERT_EQUAL_UINT32(expected_secure_version, esp_efuse_read_secure_version()); + + // repeated update: bitmap 0b111, secure version 3 (no change). + TEST_ESP_OK(esp_efuse_update_secure_version(expected_secure_version)); + TEST_ASSERT_EQUAL_UINT32(expected_secure_version, esp_efuse_read_secure_version()); +} + TEST_CASE("efuse test single bit functions", "[efuse]") { esp_efuse_utility_erase_virt_blocks();