efuse(esp32c2): Support eFuse key APIs
This commit is contained in:
@@ -11,6 +11,11 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_efuse_table.h"
|
||||
|
||||
/*
|
||||
* Each eFuse key block has a special field that defines the purpose of this block.
|
||||
* This special field is called key_purpose.
|
||||
*/
|
||||
|
||||
const static char *TAG = "efuse";
|
||||
|
||||
/**
|
||||
@@ -31,9 +36,6 @@ typedef struct {
|
||||
} esp_efuse_revokes_t;
|
||||
|
||||
const esp_efuse_keys_t s_table[EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0] = {
|
||||
#if CONFIG_IDF_TARGET_ESP32C2
|
||||
{ESP_EFUSE_KEY0, NULL, ESP_EFUSE_RD_DIS_KEY0, ESP_EFUSE_WR_DIS_KEY0, NULL},
|
||||
#else
|
||||
{ESP_EFUSE_KEY0, ESP_EFUSE_KEY_PURPOSE_0, ESP_EFUSE_RD_DIS_KEY0, ESP_EFUSE_WR_DIS_KEY0, ESP_EFUSE_WR_DIS_KEY0_PURPOSE},
|
||||
{ESP_EFUSE_KEY1, ESP_EFUSE_KEY_PURPOSE_1, ESP_EFUSE_RD_DIS_KEY1, ESP_EFUSE_WR_DIS_KEY1, ESP_EFUSE_WR_DIS_KEY1_PURPOSE},
|
||||
{ESP_EFUSE_KEY2, ESP_EFUSE_KEY_PURPOSE_2, ESP_EFUSE_RD_DIS_KEY2, ESP_EFUSE_WR_DIS_KEY2, ESP_EFUSE_WR_DIS_KEY2_PURPOSE},
|
||||
@@ -43,7 +45,6 @@ const esp_efuse_keys_t s_table[EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0] = {
|
||||
#if 0
|
||||
{ESP_EFUSE_KEY6, ESP_EFUSE_KEY_PURPOSE_6, ESP_EFUSE_RD_DIS_KEY6, ESP_EFUSE_WR_DIS_KEY6, ESP_EFUSE_WR_DIS_KEY6_PURPOSE},
|
||||
#endif
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32C2
|
||||
};
|
||||
|
||||
#if SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY
|
||||
@@ -76,7 +77,6 @@ bool esp_efuse_block_is_empty(esp_efuse_block_t block)
|
||||
// Sets a write protection for the whole block.
|
||||
esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk)
|
||||
{
|
||||
#if !CONFIG_IDF_TARGET_ESP32C2
|
||||
if (blk == EFUSE_BLK1) {
|
||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_BLK1, 1);
|
||||
} else if (blk == EFUSE_BLK2) {
|
||||
@@ -89,8 +89,7 @@ esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk)
|
||||
unsigned idx = blk - EFUSE_BLK_KEY0;
|
||||
return esp_efuse_write_field_cnt(s_table[idx].key_wr_dis, 1);
|
||||
}
|
||||
#endif
|
||||
return ESP_ERR_NOT_SUPPORTED; // IDF-3818
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
// read protect for blk.
|
||||
@@ -100,11 +99,9 @@ esp_err_t esp_efuse_set_read_protect(esp_efuse_block_t blk)
|
||||
unsigned idx = blk - EFUSE_BLK_KEY0;
|
||||
return esp_efuse_write_field_cnt(s_table[idx].key_rd_dis, 1);
|
||||
}
|
||||
#if !CONFIG_IDF_TARGET_ESP32C2 // IDF-3818
|
||||
else if (blk == EFUSE_BLK10) {
|
||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_SYS_DATA_PART2, 1);
|
||||
}
|
||||
#endif
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
|
||||
}
|
||||
@@ -171,7 +168,6 @@ esp_err_t esp_efuse_set_key_dis_write(esp_efuse_block_t block)
|
||||
return esp_efuse_write_field_bit(s_table[idx].key_wr_dis);
|
||||
}
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C2 // cause esp32c2 efuse has no purpose region
|
||||
esp_efuse_purpose_t esp_efuse_get_key_purpose(esp_efuse_block_t block)
|
||||
{
|
||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||
@@ -194,7 +190,6 @@ esp_err_t esp_efuse_set_key_purpose(esp_efuse_block_t block, esp_efuse_purpose_t
|
||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||
return esp_efuse_write_field_blob(s_table[idx].keypurpose, &purpose, s_table[idx].keypurpose[0]->bit_count);
|
||||
}
|
||||
#endif //CONFIG_IDF_TARGET_ESP32C2
|
||||
|
||||
bool esp_efuse_get_keypurpose_dis_write(esp_efuse_block_t block)
|
||||
{
|
||||
@@ -256,11 +251,8 @@ bool esp_efuse_key_block_unused(esp_efuse_block_t block)
|
||||
return false; // Not a key block
|
||||
}
|
||||
|
||||
if (
|
||||
#if !CONFIG_IDF_TARGET_ESP32C2
|
||||
esp_efuse_get_key_purpose(block) != ESP_EFUSE_KEY_PURPOSE_USER ||
|
||||
if (esp_efuse_get_key_purpose(block) != ESP_EFUSE_KEY_PURPOSE_USER ||
|
||||
esp_efuse_get_keypurpose_dis_write(block) ||
|
||||
#endif
|
||||
esp_efuse_get_key_dis_read(block) ||
|
||||
esp_efuse_get_key_dis_write(block)) {
|
||||
return false; // Block in use!
|
||||
@@ -277,15 +269,9 @@ esp_err_t esp_efuse_write_key(esp_efuse_block_t block, esp_efuse_purpose_t purpo
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C2
|
||||
if (block != EFUSE_BLK_KEY0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#else
|
||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX || key_size_bytes > 32 || purpose >= ESP_EFUSE_KEY_PURPOSE_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_efuse_batch_write_begin();
|
||||
|
||||
@@ -296,7 +282,6 @@ esp_err_t esp_efuse_write_key(esp_efuse_block_t block, esp_efuse_purpose_t purpo
|
||||
ESP_EFUSE_CHK(esp_efuse_write_field_blob(s_table[idx].key, key, key_size_bytes * 8));
|
||||
ESP_EFUSE_CHK(esp_efuse_set_key_dis_write(block));
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C2
|
||||
if (purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY ||
|
||||
#ifdef SOC_FLASH_ENCRYPTION_XTS_AES_256
|
||||
purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1 ||
|
||||
@@ -310,7 +295,6 @@ esp_err_t esp_efuse_write_key(esp_efuse_block_t block, esp_efuse_purpose_t purpo
|
||||
}
|
||||
ESP_EFUSE_CHK(esp_efuse_set_key_purpose(block, purpose));
|
||||
ESP_EFUSE_CHK(esp_efuse_set_keypurpose_dis_write(block));
|
||||
#endif //#if !CONFIG_IDF_TARGET_ESP32C2
|
||||
return esp_efuse_batch_write_commit();
|
||||
}
|
||||
err_exit:
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_efuse_utility.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "assert.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_efuse_table.h"
|
||||
|
||||
/*
|
||||
* The chip has only one eFuse key block.
|
||||
* There are no eFuse key purpose fields (added only virtual key purposes to support key APIs).
|
||||
* Flash Encryption key and Secure Boot key reside in one eFuse block.
|
||||
* To burn the FE key and the SB key need to use the batch mode to do it at once.
|
||||
*/
|
||||
|
||||
static esp_err_t esp_efuse_set_key_purpose(esp_efuse_block_t block, esp_efuse_purpose_t purpose);
|
||||
|
||||
static __attribute__((unused)) const char *TAG = "efuse";
|
||||
|
||||
/**
|
||||
* @brief Keys and their attributes are packed into a structure
|
||||
*/
|
||||
typedef struct {
|
||||
const esp_efuse_desc_t** key; /**< Key */
|
||||
esp_efuse_purpose_t purpose; /**< purpose of block */
|
||||
const esp_efuse_desc_t** key_rd_dis; /**< Read protection of a key */
|
||||
const esp_efuse_desc_t** key_wr_dis; /**< Write protection of a key*/
|
||||
} esp_efuse_keys_t;
|
||||
|
||||
const esp_efuse_keys_t s_table[EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0] = {
|
||||
{ESP_EFUSE_KEY0, ESP_EFUSE_KEY_PURPOSE_USER, ESP_EFUSE_RD_DIS_KEY0, ESP_EFUSE_WR_DIS_KEY0}, // EFUSE_BLK_KEY0
|
||||
};
|
||||
|
||||
// Sets a write protection for the whole block.
|
||||
esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk)
|
||||
{
|
||||
if (blk < EFUSE_BLK_KEY0 || blk >= EFUSE_BLK_KEY_MAX) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
unsigned idx = blk - EFUSE_BLK_KEY0;
|
||||
return esp_efuse_write_field_cnt(s_table[idx].key_wr_dis, s_table[idx].key_wr_dis[0]->bit_count);
|
||||
}
|
||||
|
||||
// Sets a read protection for the whole block.
|
||||
esp_err_t esp_efuse_set_read_protect(esp_efuse_block_t blk)
|
||||
{
|
||||
if (blk < EFUSE_BLK_KEY0 || blk >= EFUSE_BLK_KEY_MAX) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
unsigned idx = blk - EFUSE_BLK_KEY0;
|
||||
return esp_efuse_write_field_cnt(s_table[idx].key_rd_dis, s_table[idx].key_rd_dis[0]->bit_count);
|
||||
}
|
||||
|
||||
// get efuse coding_scheme.
|
||||
esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk)
|
||||
{
|
||||
esp_efuse_coding_scheme_t scheme;
|
||||
if (blk == EFUSE_BLK0) {
|
||||
scheme = EFUSE_CODING_SCHEME_NONE;
|
||||
} else {
|
||||
scheme = EFUSE_CODING_SCHEME_RS;
|
||||
}
|
||||
return scheme;
|
||||
}
|
||||
|
||||
bool esp_efuse_block_is_empty(esp_efuse_block_t block)
|
||||
{
|
||||
assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
|
||||
const unsigned blk_len_bit = 256;
|
||||
uint32_t key[8];
|
||||
esp_err_t err = esp_efuse_read_block(block, &key, 0, blk_len_bit);
|
||||
if (err != ESP_OK) {
|
||||
return false;
|
||||
}
|
||||
unsigned zeros = 0;
|
||||
for (unsigned i = 0; i < blk_len_bit / 32; ++i) {
|
||||
if (key[i] == 0) {
|
||||
++zeros;
|
||||
}
|
||||
}
|
||||
if (zeros == blk_len_bit / 32) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool esp_efuse_get_key_dis_read(esp_efuse_block_t block)
|
||||
{
|
||||
assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
|
||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||
if (esp_efuse_get_key_purpose(block) == ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY) {
|
||||
uint8_t value = 0;
|
||||
esp_err_t err = esp_efuse_read_field_blob(s_table[idx].key_rd_dis, &value, s_table[idx].key_rd_dis[0]->bit_count);
|
||||
assert(err == ESP_OK);
|
||||
return (err == ESP_OK) && (value == ((1 << s_table[idx].key_rd_dis[0]->bit_count) - 1));
|
||||
}
|
||||
return esp_efuse_read_field_bit(ESP_EFUSE_RD_DIS_KEY0_LOW);
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_set_key_dis_read(esp_efuse_block_t block)
|
||||
{
|
||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (esp_efuse_get_key_purpose(block) == ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY) {
|
||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||
uint8_t value = (1 << s_table[idx].key_rd_dis[0]->bit_count) - 1;
|
||||
return esp_efuse_write_field_blob(s_table[idx].key_rd_dis, &value, s_table[idx].key_rd_dis[0]->bit_count);
|
||||
}
|
||||
return esp_efuse_write_field_bit(ESP_EFUSE_RD_DIS_KEY0_LOW);
|
||||
}
|
||||
|
||||
bool esp_efuse_get_key_dis_write(esp_efuse_block_t block)
|
||||
{
|
||||
assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
|
||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||
return esp_efuse_read_field_bit(s_table[idx].key_wr_dis);
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_set_key_dis_write(esp_efuse_block_t block)
|
||||
{
|
||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||
return esp_efuse_write_field_bit(s_table[idx].key_wr_dis);
|
||||
}
|
||||
|
||||
bool esp_efuse_key_block_unused(esp_efuse_block_t block)
|
||||
{
|
||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||
return false; // Not a key block
|
||||
}
|
||||
|
||||
if (esp_efuse_get_key_dis_read(block) || esp_efuse_get_key_dis_write(block) ||
|
||||
!esp_efuse_block_is_empty(block)) {
|
||||
return false; // Block in use!
|
||||
}
|
||||
|
||||
return true; // Unused
|
||||
}
|
||||
|
||||
esp_efuse_purpose_t esp_efuse_get_key_purpose(esp_efuse_block_t block)
|
||||
{
|
||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||
return ESP_EFUSE_KEY_PURPOSE_MAX;
|
||||
}
|
||||
if (esp_efuse_read_field_bit(ESP_EFUSE_XTS_KEY_LENGTH_256)) {
|
||||
return ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY;
|
||||
}
|
||||
return ESP_EFUSE_KEY_PURPOSE_XTS_AES_64_KEY;
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t esp_efuse_set_key_purpose(esp_efuse_block_t block, esp_efuse_purpose_t purpose)
|
||||
{
|
||||
(void)block;
|
||||
if (purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY) {
|
||||
return esp_efuse_write_field_bit(ESP_EFUSE_XTS_KEY_LENGTH_256);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool esp_efuse_get_keypurpose_dis_write(esp_efuse_block_t block)
|
||||
{
|
||||
(void)block;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool esp_efuse_find_purpose(esp_efuse_purpose_t purpose, esp_efuse_block_t *block)
|
||||
{
|
||||
(void)purpose;
|
||||
esp_efuse_block_t dummy;
|
||||
if (block == NULL) {
|
||||
block = &dummy;
|
||||
}
|
||||
*block = EFUSE_BLK_KEY0;
|
||||
return true;
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_write_key(esp_efuse_block_t block, esp_efuse_purpose_t purpose, const void *key, size_t key_size_bytes)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX || key_size_bytes > 32 || purpose >= ESP_EFUSE_KEY_PURPOSE_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if ((purpose == ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_V2 || purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_64_KEY) && (key_size_bytes != 16)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_efuse_batch_write_begin();
|
||||
|
||||
if (!esp_efuse_key_block_unused(block)) {
|
||||
err = ESP_ERR_INVALID_STATE;
|
||||
} else {
|
||||
size_t offset_in_bits = (purpose == ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_V2) ? 16 * 8 : 0;
|
||||
ESP_EFUSE_CHK(esp_efuse_write_block(block, key, offset_in_bits, key_size_bytes * 8));
|
||||
if (purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY) {
|
||||
ESP_EFUSE_CHK(esp_efuse_set_key_purpose(block, purpose));
|
||||
}
|
||||
if (purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY || purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_64_KEY) {
|
||||
ESP_EFUSE_CHK(esp_efuse_set_key_dis_read(block));
|
||||
}
|
||||
ESP_EFUSE_CHK(esp_efuse_set_key_dis_write(block));
|
||||
return esp_efuse_batch_write_commit();
|
||||
}
|
||||
err_exit:
|
||||
esp_efuse_batch_write_cancel();
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_write_keys(const esp_efuse_purpose_t purposes[], uint8_t keys[][32], unsigned number_of_keys)
|
||||
{
|
||||
esp_err_t err = ESP_FAIL;
|
||||
if (number_of_keys == 0 || number_of_keys > 2 || keys == NULL || purposes == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_efuse_purpose_t purpose = 0;
|
||||
|
||||
esp_efuse_batch_write_begin();
|
||||
for (unsigned i_key = 0; i_key < number_of_keys; i_key++) {
|
||||
purpose = purposes[i_key];
|
||||
ESP_LOGI(TAG, "Writing EFUSE_BLK_KEY0 with purpose %d", purpose);
|
||||
size_t key_size = (purpose == ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_V2 || purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_64_KEY) ? 16 : 32;
|
||||
ESP_EFUSE_CHK(esp_efuse_write_key(EFUSE_BLK_KEY0, purpose, keys[i_key], key_size));
|
||||
}
|
||||
return esp_efuse_batch_write_commit();
|
||||
err_exit:
|
||||
ESP_LOGE(TAG, "Failed to write EFUSE_BLK_KEY0 with purpose %d. Can't continue.", purpose);
|
||||
esp_efuse_batch_write_cancel();
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_read_key_digests(ets_secure_boot_key_digests_t *trusted_keys)
|
||||
{
|
||||
if (trusted_keys == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
trusted_keys->key_digests[0] = (const void *)(esp_efuse_utility_get_read_register_address(EFUSE_BLK_KEY0) + 16);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -11,6 +11,13 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_efuse_table.h"
|
||||
|
||||
/*
|
||||
* FE uses eFuse block1.
|
||||
* SB uses eFuse block2.
|
||||
* Block3 can be used by customer.
|
||||
* There are no eFuse key purpose fields (added only virtual key purposes to support key APIs).
|
||||
*/
|
||||
|
||||
static __attribute__((unused)) const char *TAG = "efuse";
|
||||
|
||||
/**
|
||||
@@ -24,7 +24,7 @@ static __attribute__((unused)) const char *TAG = "efuse";
|
||||
#ifdef CONFIG_BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD
|
||||
#define APP_SEC_VER_SIZE_EFUSE_FIELD CONFIG_BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD
|
||||
#else
|
||||
#define APP_SEC_VER_SIZE_EFUSE_FIELD 16 // smallest possible size for all chips
|
||||
#define APP_SEC_VER_SIZE_EFUSE_FIELD 4 // smallest possible size for all chips
|
||||
#endif
|
||||
|
||||
// Reset efuse write registers
|
||||
@@ -33,8 +33,6 @@ void esp_efuse_reset(void)
|
||||
esp_efuse_utility_reset();
|
||||
}
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C2
|
||||
// IDF-3818
|
||||
uint32_t esp_efuse_read_secure_version(void)
|
||||
{
|
||||
uint32_t secure_version = 0;
|
||||
@@ -85,4 +83,3 @@ esp_err_t esp_efuse_update_secure_version(uint32_t secure_version)
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user