From 1dd5a4dba4e0758c3336767ef39e744826a33c4a Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sat, 25 Apr 2020 14:58:30 +1000 Subject: [PATCH] efuse: Add new esp_efuse_write_field_bit() convenience function --- .../src/esp32s2/flash_encrypt.c | 8 +++---- .../bootloader_support/src/flash_encrypt.c | 10 ++------- components/efuse/include/esp_efuse.h | 17 +++++++++++++++ components/efuse/src/esp_efuse_api.c | 19 +++++++++++++++++ components/efuse/test/test_efuse.c | 21 +++++++++++++++++++ 5 files changed, 63 insertions(+), 12 deletions(-) diff --git a/components/bootloader_support/src/esp32s2/flash_encrypt.c b/components/bootloader_support/src/esp32s2/flash_encrypt.c index 797a495517..9d9acf754f 100644 --- a/components/bootloader_support/src/esp32s2/flash_encrypt.c +++ b/components/bootloader_support/src/esp32s2/flash_encrypt.c @@ -188,22 +188,22 @@ static esp_err_t initialise_flash_encryption(void) #ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC ESP_LOGI(TAG, "Disable UART bootloader encryption..."); - esp_efuse_write_field_cnt(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT, 1); + esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT); #else ESP_LOGW(TAG, "Not disabling UART bootloader encryption"); #endif #ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE ESP_LOGI(TAG, "Disable UART bootloader cache..."); - esp_efuse_write_field_cnt(ESP_EFUSE_DIS_DOWNLOAD_DCACHE, 1); - esp_efuse_write_field_cnt(ESP_EFUSE_DIS_DOWNLOAD_ICACHE, 1); + esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_DCACHE); + esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE); #else ESP_LOGW(TAG, "Not disabling UART bootloader cache - SECURITY COMPROMISED"); #endif #ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG ESP_LOGI(TAG, "Disable JTAG..."); - esp_efuse_write_field_cnt(ESP_EFUSE_HARD_DIS_JTAG, 1); + esp_efuse_write_field_bit(ESP_EFUSE_HARD_DIS_JTAG); #else ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED"); #endif diff --git a/components/bootloader_support/src/flash_encrypt.c b/components/bootloader_support/src/flash_encrypt.c index cf817e9a1f..a503e6bad9 100644 --- a/components/bootloader_support/src/flash_encrypt.c +++ b/components/bootloader_support/src/flash_encrypt.c @@ -76,13 +76,7 @@ void esp_flash_encryption_init_checks() void esp_flash_write_protect_crypt_cnt(void) { - uint8_t flash_crypt_cnt_wr_dis = 0; - - esp_efuse_read_field_blob(WR_DIS_CRYPT_CNT, &flash_crypt_cnt_wr_dis, 1); - - if (!flash_crypt_cnt_wr_dis) { - esp_efuse_write_field_cnt(WR_DIS_CRYPT_CNT, 1); - } + esp_efuse_write_field_bit(WR_DIS_CRYPT_CNT); } esp_flash_enc_mode_t esp_get_flash_encryption_mode(void) @@ -121,7 +115,7 @@ esp_flash_enc_mode_t esp_get_flash_encryption_mode(void) if (dis_dl_enc && dis_dl_icache && dis_dl_dcache) { mode = ESP_FLASH_ENC_MODE_RELEASE; } -#endif +#endif } } else { mode = ESP_FLASH_ENC_MODE_DISABLED; diff --git a/components/efuse/include/esp_efuse.h b/components/efuse/include/esp_efuse.h index 47eb1d1598..c50c86c64a 100644 --- a/components/efuse/include/esp_efuse.h +++ b/components/efuse/include/esp_efuse.h @@ -114,6 +114,23 @@ esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void */ esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt); +/** + * @brief Write a single bit eFuse field to 1 + * + * For use with eFuse fields that are a single bit. This function will write the bit to value 1 if + * it is not already set, or does nothing if the bit is already set. + * + * This is equivalent to calling esp_efuse_write_field_cnt() with the cnt parameter equal to 1, + * except that it will return ESP_OK if the field is already set to 1. + * + * @param[in] field Pointer to the structure describing the efuse field. + * + * @return + * - ESP_OK: The operation was successfully completed, or the bit was already set to value 1. + * - ESP_ERR_INVALID_ARG: Error in the passed arugments, including if the efuse field is not 1 bit wide. + */ +esp_err_t esp_efuse_write_field_bit(const esp_efuse_desc_t* field[]); + /** * @brief Sets a write protection for the whole block. * diff --git a/components/efuse/src/esp_efuse_api.c b/components/efuse/src/esp_efuse_api.c index 6ed5399add..361b8cd578 100644 --- a/components/efuse/src/esp_efuse_api.c +++ b/components/efuse/src/esp_efuse_api.c @@ -131,6 +131,25 @@ esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt) return err; } +esp_err_t esp_efuse_write_field_bit(const esp_efuse_desc_t* field[]) +{ + esp_err_t err; + uint8_t existing = 0; + const uint8_t one = 1; + + if (field == NULL || field[0]->bit_count != 1) { + return ESP_ERR_INVALID_ARG; + } + + /* Check existing value. esp_efuse_write_field_blob() also checks this, but will log an error */ + err = esp_efuse_read_field_blob(field, &existing, 1); + if (err != ESP_OK || existing) { + return err; // Error reading, or the bit is already written and we can no-op this + } + + return esp_efuse_write_field_blob(field, &one, 1); +} + // get the length of the field in bits int esp_efuse_get_field_size(const esp_efuse_desc_t* field[]) { diff --git a/components/efuse/test/test_efuse.c b/components/efuse/test/test_efuse.c index 6aa0b879a8..54a7b8af4c 100644 --- a/components/efuse/test/test_efuse.c +++ b/components/efuse/test/test_efuse.c @@ -267,6 +267,27 @@ TEST_CASE("efuse test write_field_cnt", "[efuse]") test_write_cnt(); } +TEST_CASE("efuse test write_field_bit", "[efuse]") +{ + esp_efuse_utility_erase_virt_blocks(); + esp_efuse_utility_debug_dump_blocks(); + + uint8_t test_bit; + TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test_bit, 1)); + TEST_ASSERT_EQUAL_HEX8(0, test_bit); + + TEST_ESP_OK(esp_efuse_write_field_bit(ESP_EFUSE_TEST5_LEN_1)); + TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test_bit, 1)); + TEST_ASSERT_EQUAL_HEX8(1, test_bit); + + // Can write the bit again and it's a no-op + TEST_ESP_OK(esp_efuse_write_field_bit(ESP_EFUSE_TEST5_LEN_1)); + TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test_bit, 1)); + TEST_ASSERT_EQUAL_HEX8(1, test_bit); + + esp_efuse_utility_debug_dump_blocks(); +} + void cut_tail_arr(uint8_t *arr, int num_used_bits, size_t count_bits) { if ((num_used_bits + count_bits) % 8) {