Files
esp-idf/components/efuse/src/esp_efuse_api_key_esp32.c
T
KonstantinKondrashov 90f2d3199a secure_boot: Checks secure boot efuses
ESP32 V1 and V2 - protection bits.
ESP32xx V2: revoke bits, protection bits

- refactor efuse component
- adds some APIs for esp32 chips as well as for esp32xx chips
2021-02-23 03:56:21 +08:00

149 lines
4.6 KiB
C

// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#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"
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_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_RD_DIS_BLK1, ESP_EFUSE_WR_DIS_BLK1},
{ESP_EFUSE_RD_DIS_BLK2, ESP_EFUSE_WR_DIS_BLK2},
{ESP_EFUSE_RD_DIS_BLK3, ESP_EFUSE_WR_DIS_BLK3},
};
// Sets a write protection for the whole block.
esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk)
{
if (blk == EFUSE_BLK0 || blk >= EFUSE_BLK_MAX) {
return ESP_ERR_NOT_SUPPORTED;
}
unsigned idx = blk - EFUSE_BLK1;
return esp_efuse_write_field_cnt(s_table[idx].key_wr_dis, 1);
}
// read protect for blk.
esp_err_t esp_efuse_set_read_protect(esp_efuse_block_t blk)
{
if (blk == EFUSE_BLK0 || blk >= EFUSE_BLK_MAX) {
return ESP_ERR_NOT_SUPPORTED;
}
unsigned idx = blk - EFUSE_BLK1;
return esp_efuse_write_field_cnt(s_table[idx].key_rd_dis, 1);
}
// 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 {
uint32_t coding_scheme = REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_CODING_SCHEME);
if (coding_scheme == EFUSE_CODING_SCHEME_VAL_NONE ||
coding_scheme == (EFUSE_CODING_SCHEME_VAL_34 | EFUSE_CODING_SCHEME_VAL_REPEAT)) {
scheme = EFUSE_CODING_SCHEME_NONE;
} else if (coding_scheme == EFUSE_CODING_SCHEME_VAL_34) {
scheme = EFUSE_CODING_SCHEME_3_4;
} else {
scheme = EFUSE_CODING_SCHEME_REPEAT;
}
}
return scheme;
}
bool esp_efuse_block_is_empty(esp_efuse_block_t block)
{
unsigned blk_len_bit = 256;
uint32_t key[8];
if (esp_efuse_get_coding_scheme(block) == EFUSE_CODING_SCHEME_3_4) {
blk_len_bit = 192;
}
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;
return esp_efuse_read_field_bit(s_table[idx].key_rd_dis);
}
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;
}
unsigned idx = block - EFUSE_BLK_KEY0;
const uint8_t one = 1;
return esp_efuse_write_field_blob(s_table[idx].key_rd_dis, &one, 1);
}
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;
const uint8_t one = 1;
return esp_efuse_write_field_blob(s_table[idx].key_wr_dis, &one, 1);
}
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
}