mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-06 13:18:07 +00:00
499 lines
17 KiB
C
499 lines
17 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#include <stdarg.h>
|
|
|
|
#include "esp_err.h"
|
|
#include "esp_random.h"
|
|
|
|
#include "hal/sha_types.h"
|
|
#include "hal/sha_hal.h"
|
|
#include "rom/digital_signature.h"
|
|
#include "hal/mmu_types.h"
|
|
#include "hal/wdt_hal.h"
|
|
#include "hal/spi_flash_types.h"
|
|
#include "esp_hmac.h"
|
|
#include "esp_ds.h"
|
|
#include "esp_crypto_lock.h"
|
|
#include "esp_flash.h"
|
|
|
|
#include "soc/soc_caps.h"
|
|
#include "sdkconfig.h"
|
|
|
|
#include "esp_tee.h"
|
|
#include "secure_service_num.h"
|
|
|
|
/* ---------------------------------------------- Interrupts ------------------------------------------------- */
|
|
|
|
void IRAM_ATTR __wrap_esp_rom_route_intr_matrix(int cpu_no, uint32_t model_num, uint32_t intr_num)
|
|
{
|
|
esp_tee_service_call(4, SS_ESP_ROM_ROUTE_INTR_MATRIX, cpu_no, model_num, intr_num);
|
|
}
|
|
|
|
#if SOC_INT_CLIC_SUPPORTED
|
|
void IRAM_ATTR __wrap_esprv_int_set_vectored(int rv_int_num, bool vectored)
|
|
{
|
|
esp_tee_service_call(3, SS_ESPRV_INT_SET_VECTORED, rv_int_num, vectored);
|
|
}
|
|
#endif
|
|
|
|
/* ---------------------------------------------- RTC_WDT ------------------------------------------------- */
|
|
|
|
void __wrap_wdt_hal_init(wdt_hal_context_t *hal, wdt_inst_t wdt_inst, uint32_t prescaler, bool enable_intr)
|
|
{
|
|
esp_tee_service_call(5, SS_WDT_HAL_INIT, hal, wdt_inst, prescaler, enable_intr);
|
|
}
|
|
|
|
void __wrap_wdt_hal_deinit(wdt_hal_context_t *hal)
|
|
{
|
|
esp_tee_service_call(2, SS_WDT_HAL_DEINIT, hal);
|
|
}
|
|
|
|
/* ---------------------------------------------- AES ------------------------------------------------- */
|
|
|
|
typedef struct {
|
|
uint8_t key_bytes;
|
|
volatile uint8_t key_in_hardware; /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
|
|
uint8_t key[32];
|
|
} esp_aes_context;
|
|
|
|
int __wrap_esp_aes_intr_alloc(void)
|
|
{
|
|
return esp_tee_service_call(1, SS_ESP_AES_INTR_ALLOC);
|
|
}
|
|
|
|
int __wrap_esp_aes_crypt_cbc(esp_aes_context *ctx,
|
|
int mode,
|
|
size_t length,
|
|
unsigned char iv[16],
|
|
const unsigned char *input,
|
|
unsigned char *output)
|
|
{
|
|
esp_crypto_sha_aes_lock_acquire();
|
|
esp_err_t err = esp_tee_service_call(7, SS_ESP_AES_CRYPT_CBC, ctx, mode, length, iv, input, output);
|
|
esp_crypto_sha_aes_lock_release();
|
|
return err;
|
|
}
|
|
|
|
int __wrap_esp_aes_crypt_cfb128(esp_aes_context *ctx,
|
|
int mode,
|
|
size_t length,
|
|
size_t *iv_off,
|
|
unsigned char iv[16],
|
|
const unsigned char *input,
|
|
unsigned char *output)
|
|
{
|
|
esp_crypto_sha_aes_lock_acquire();
|
|
esp_err_t err = esp_tee_service_call(8, SS_ESP_AES_CRYPT_CFB128, (uint32_t)ctx,
|
|
mode, length, iv_off, iv, (uint32_t)input, (uint32_t)output);
|
|
esp_crypto_sha_aes_lock_release();
|
|
return err;
|
|
}
|
|
|
|
int __wrap_esp_aes_crypt_cfb8(esp_aes_context *ctx,
|
|
int mode,
|
|
size_t length,
|
|
unsigned char iv[16],
|
|
const unsigned char *input,
|
|
unsigned char *output)
|
|
{
|
|
esp_crypto_sha_aes_lock_acquire();
|
|
esp_err_t err = esp_tee_service_call(7, SS_ESP_AES_CRYPT_CFB8, ctx,
|
|
mode, length, iv, input, output);
|
|
esp_crypto_sha_aes_lock_release();
|
|
return err;
|
|
}
|
|
|
|
int __wrap_esp_aes_crypt_ctr(esp_aes_context *ctx,
|
|
size_t length,
|
|
size_t *nc_off,
|
|
unsigned char nonce_counter[16],
|
|
unsigned char stream_block[16],
|
|
const unsigned char *input,
|
|
unsigned char *output)
|
|
{
|
|
esp_crypto_sha_aes_lock_acquire();
|
|
esp_err_t err = esp_tee_service_call(8, SS_ESP_AES_CRYPT_CTR, ctx, length, nc_off, nonce_counter, stream_block, input, output);
|
|
esp_crypto_sha_aes_lock_release();
|
|
return err;
|
|
}
|
|
|
|
int __wrap_esp_aes_crypt_ecb(esp_aes_context *ctx,
|
|
int mode,
|
|
const unsigned char input[16],
|
|
unsigned char output[16])
|
|
{
|
|
esp_crypto_sha_aes_lock_acquire();
|
|
esp_err_t err = esp_tee_service_call(5, SS_ESP_AES_CRYPT_ECB,
|
|
(uint32_t)ctx, (uint32_t)mode,
|
|
(uint32_t)input, (uint32_t)output);
|
|
esp_crypto_sha_aes_lock_release();
|
|
return err;
|
|
}
|
|
|
|
int __wrap_esp_aes_crypt_ofb(esp_aes_context *ctx,
|
|
size_t length,
|
|
size_t *iv_off,
|
|
unsigned char iv[16],
|
|
const unsigned char *input,
|
|
unsigned char *output)
|
|
{
|
|
esp_crypto_sha_aes_lock_acquire();
|
|
esp_err_t err = esp_tee_service_call(7, SS_ESP_AES_CRYPT_OFB, (uint32_t)ctx, length,
|
|
iv_off, iv, (uint32_t)input, (uint32_t)output);
|
|
esp_crypto_sha_aes_lock_release();
|
|
return err;
|
|
}
|
|
|
|
/* ---------------------------------------------- SHA ------------------------------------------------- */
|
|
|
|
typedef enum {
|
|
ESP_SHA1_STATE_INIT,
|
|
ESP_SHA1_STATE_IN_PROCESS
|
|
} esp_sha1_state;
|
|
|
|
typedef enum {
|
|
ESP_SHA256_STATE_INIT,
|
|
ESP_SHA256_STATE_IN_PROCESS
|
|
} esp_sha256_state;
|
|
|
|
typedef enum {
|
|
ESP_SHA512_STATE_INIT,
|
|
ESP_SHA512_STATE_IN_PROCESS
|
|
} esp_sha512_state;
|
|
|
|
typedef struct {
|
|
uint32_t total[2]; /*!< number of bytes processed */
|
|
uint32_t state[5]; /*!< intermediate digest state */
|
|
unsigned char buffer[64]; /*!< data block being processed */
|
|
int first_block; /*!< if first then true else false */
|
|
esp_sha_type mode;
|
|
esp_sha1_state sha_state;
|
|
} esp_sha1_context;
|
|
|
|
typedef struct {
|
|
uint32_t total[2]; /*!< number of bytes processed */
|
|
uint32_t state[8]; /*!< intermediate digest state */
|
|
unsigned char buffer[64]; /*!< data block being processed */
|
|
int first_block; /*!< if first then true, else false */
|
|
esp_sha_type mode;
|
|
esp_sha256_state sha_state;
|
|
} esp_sha256_context;
|
|
|
|
typedef struct {
|
|
uint64_t total[2]; /*!< number of bytes processed */
|
|
uint64_t state[8]; /*!< intermediate digest state */
|
|
unsigned char buffer[128]; /*!< data block being processed */
|
|
int first_block;
|
|
esp_sha_type mode;
|
|
uint32_t t_val; /*!< t_val for 512/t mode */
|
|
esp_sha512_state sha_state;
|
|
} esp_sha512_context;
|
|
|
|
void __wrap_esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output)
|
|
{
|
|
esp_tee_service_call(5, SS_ESP_SHA,
|
|
(uint32_t)sha_type, (uint32_t)input,
|
|
(uint32_t)ilen, (uint32_t)output);
|
|
}
|
|
|
|
int __wrap_esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen,
|
|
const void *buf, uint32_t buf_len, bool is_first_block)
|
|
{
|
|
return esp_tee_service_call(7, SS_ESP_SHA_DMA, sha_type, input, ilen, buf, buf_len, is_first_block);
|
|
}
|
|
|
|
int __wrap_esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block)
|
|
{
|
|
return esp_tee_service_call(4, SS_ESP_SHA_BLOCK, sha_type, data_block, is_first_block);
|
|
}
|
|
|
|
void __wrap_esp_sha_set_mode(esp_sha_type sha_type)
|
|
{
|
|
esp_tee_service_call(2, SS_ESP_SHA_SET_MODE, sha_type);
|
|
}
|
|
|
|
void __wrap_esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state)
|
|
{
|
|
esp_tee_service_call(3, SS_ESP_SHA_READ_DIGEST_STATE, sha_type, digest_state);
|
|
}
|
|
|
|
void __wrap_esp_sha_write_digest_state(esp_sha_type sha_type, void *digest_state)
|
|
{
|
|
esp_tee_service_call(3, SS_ESP_SHA_WRITE_DIGEST_STATE, sha_type, digest_state);
|
|
}
|
|
|
|
void __wrap_esp_crypto_sha_enable_periph_clk(bool enable)
|
|
{
|
|
esp_tee_service_call(2, SS_ESP_CRYPTO_SHA_ENABLE_PERIPH_CLK, enable);
|
|
}
|
|
|
|
#if SOC_SHA_SUPPORT_SHA512_T
|
|
int __wrap_esp_sha_512_t_init_hash(uint16_t t)
|
|
{
|
|
return esp_tee_service_call(2, SS_ESP_SHA_512_T_INIT_HASH, t);
|
|
}
|
|
#endif
|
|
|
|
/* ---------------------------------------------- HMAC ------------------------------------------------- */
|
|
|
|
esp_err_t __wrap_esp_hmac_calculate(hmac_key_id_t key_id, const void *message, size_t message_len, uint8_t *hmac)
|
|
{
|
|
esp_crypto_hmac_lock_acquire();
|
|
esp_err_t err = esp_tee_service_call(5, SS_ESP_HMAC_CALCULATE, key_id, message, message_len, hmac);
|
|
esp_crypto_hmac_lock_release();
|
|
return err;
|
|
}
|
|
|
|
esp_err_t __wrap_esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token)
|
|
{
|
|
esp_crypto_hmac_lock_acquire();
|
|
esp_err_t err = esp_tee_service_call(3, SS_ESP_HMAC_JTAG_ENABLE, key_id, token);
|
|
esp_crypto_hmac_lock_release();
|
|
return err;
|
|
}
|
|
|
|
esp_err_t __wrap_esp_hmac_jtag_disable(void)
|
|
{
|
|
esp_crypto_hmac_lock_acquire();
|
|
esp_err_t err = esp_tee_service_call(1, SS_ESP_HMAC_JTAG_DISABLE);
|
|
esp_crypto_hmac_lock_release();
|
|
return err;
|
|
}
|
|
|
|
/* ---------------------------------------------- DS ------------------------------------------------- */
|
|
|
|
esp_err_t __wrap_esp_ds_sign(const void *message,
|
|
const esp_ds_data_t *data,
|
|
hmac_key_id_t key_id,
|
|
void *signature)
|
|
{
|
|
esp_crypto_ds_lock_acquire();
|
|
esp_err_t err = esp_tee_service_call(5, SS_ESP_DS_SIGN, message, data, key_id, signature);
|
|
esp_crypto_ds_lock_release();
|
|
return err;
|
|
}
|
|
|
|
esp_err_t __wrap_esp_ds_start_sign(const void *message,
|
|
const esp_ds_data_t *data,
|
|
hmac_key_id_t key_id,
|
|
esp_ds_context_t **esp_ds_ctx)
|
|
{
|
|
esp_crypto_ds_lock_acquire();
|
|
if (esp_ds_ctx != NULL) {
|
|
*esp_ds_ctx = malloc(sizeof(esp_ds_context_t));
|
|
if (!*esp_ds_ctx) {
|
|
return ESP_ERR_NO_MEM;
|
|
}
|
|
}
|
|
return esp_tee_service_call(5, SS_ESP_DS_START_SIGN, message, data, key_id, esp_ds_ctx);
|
|
}
|
|
|
|
bool __wrap_esp_ds_is_busy(void)
|
|
{
|
|
return esp_tee_service_call(1, SS_ESP_DS_IS_BUSY);
|
|
}
|
|
|
|
esp_err_t __wrap_esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
|
|
{
|
|
esp_err_t err = esp_tee_service_call(3, SS_ESP_DS_FINISH_SIGN, signature, esp_ds_ctx);
|
|
if (err != ESP_ERR_INVALID_ARG) {
|
|
free(esp_ds_ctx);
|
|
}
|
|
esp_crypto_ds_lock_release();
|
|
return err;
|
|
}
|
|
|
|
esp_err_t __wrap_esp_ds_encrypt_params(esp_ds_data_t *data,
|
|
const void *iv,
|
|
const esp_ds_p_data_t *p_data,
|
|
const void *key)
|
|
{
|
|
esp_crypto_sha_aes_lock_acquire();
|
|
esp_err_t err = esp_tee_service_call(5, SS_ESP_DS_ENCRYPT_PARAMS, data, iv, p_data, key);
|
|
esp_crypto_sha_aes_lock_release();
|
|
return err;
|
|
}
|
|
|
|
/* ---------------------------------------------- MPI ------------------------------------------------- */
|
|
|
|
void __wrap_esp_crypto_mpi_enable_periph_clk(bool enable)
|
|
{
|
|
esp_tee_service_call(2, SS_ESP_CRYPTO_MPI_ENABLE_PERIPH_CLK, enable);
|
|
}
|
|
|
|
/* ---------------------------------------------- ECC ------------------------------------------------- */
|
|
|
|
#define P256_LEN (256/8)
|
|
#define P192_LEN (192/8)
|
|
|
|
typedef struct {
|
|
uint8_t x[P256_LEN]; /* Little endian order */
|
|
uint8_t y[P256_LEN]; /* Little endian order */
|
|
unsigned len; /* P192_LEN or P256_LEN */
|
|
} ecc_point_t;
|
|
|
|
int __wrap_esp_ecc_point_multiply(const ecc_point_t *point, const uint8_t *scalar, ecc_point_t *result, bool verify_first)
|
|
{
|
|
esp_crypto_ecc_lock_acquire();
|
|
esp_err_t err = esp_tee_service_call(5, SS_ESP_ECC_POINT_MULTIPLY, point, scalar, result, verify_first);
|
|
esp_crypto_ecc_lock_release();
|
|
return err;
|
|
}
|
|
|
|
int __wrap_esp_ecc_point_verify(const ecc_point_t *point)
|
|
{
|
|
esp_crypto_ecc_lock_acquire();
|
|
esp_err_t err = esp_tee_service_call(2, SS_ESP_ECC_POINT_VERIFY, point);
|
|
esp_crypto_ecc_lock_release();
|
|
return err;
|
|
}
|
|
|
|
#if SOC_ECDSA_SUPPORTED
|
|
void __wrap_esp_crypto_ecc_enable_periph_clk(bool enable)
|
|
{
|
|
esp_tee_service_call(2, SS_ESP_CRYPTO_ECC_ENABLE_PERIPH_CLK, enable);
|
|
}
|
|
#endif
|
|
|
|
/* ---------------------------------------------- MMU HAL ------------------------------------------------- */
|
|
|
|
void IRAM_ATTR __wrap_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vaddr, uint32_t paddr, uint32_t len, uint32_t *out_len)
|
|
{
|
|
esp_tee_service_call(7, SS_MMU_HAL_MAP_REGION, mmu_id, mem_type, vaddr, paddr, len, out_len);
|
|
}
|
|
|
|
void IRAM_ATTR __wrap_mmu_hal_unmap_region(uint32_t mmu_id, uint32_t vaddr, uint32_t len)
|
|
{
|
|
esp_tee_service_call(4, SS_MMU_HAL_UNMAP_REGION, mmu_id, vaddr, len);
|
|
}
|
|
|
|
bool IRAM_ATTR __wrap_mmu_hal_vaddr_to_paddr(uint32_t mmu_id, uint32_t vaddr, uint32_t *out_paddr, mmu_target_t *out_target)
|
|
{
|
|
return esp_tee_service_call(5, SS_MMU_HAL_VADDR_TO_PADDR, mmu_id, vaddr, out_paddr, out_target);
|
|
}
|
|
|
|
bool IRAM_ATTR __wrap_mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mmu_target_t target, mmu_vaddr_t type, uint32_t *out_vaddr)
|
|
{
|
|
return esp_tee_service_call(6, SS_MMU_HAL_PADDR_TO_VADDR, mmu_id, paddr, target, type, out_vaddr);
|
|
}
|
|
|
|
/**
|
|
* NOTE: This ROM-provided API is intended to configure the Cache MMU size for
|
|
* instruction (irom) and rodata (drom) sections in flash.
|
|
*
|
|
* On ESP32-C5, it also sets the start pages for flash irom and drom sections,
|
|
* which involves accessing MMU registers directly.
|
|
*
|
|
* However, these MMU registers are protected by the APM and direct access
|
|
* from the REE results in a fault.
|
|
*
|
|
* To prevent this, we wrap this function to be routed as a TEE service call.
|
|
*/
|
|
#if CONFIG_IDF_TARGET_ESP32C5
|
|
void IRAM_ATTR __wrap_Cache_Set_IDROM_MMU_Size(uint32_t irom_size, uint32_t drom_size)
|
|
{
|
|
esp_tee_service_call(3, SS_CACHE_SET_IDROM_MMU_SIZE, irom_size, drom_size);
|
|
}
|
|
#endif
|
|
|
|
#if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1
|
|
/* ---------------------------------------------- SPI Flash HAL ------------------------------------------------- */
|
|
|
|
uint32_t IRAM_ATTR __wrap_spi_flash_hal_check_status(spi_flash_host_inst_t *host)
|
|
{
|
|
return esp_tee_service_call(2, SS_SPI_FLASH_HAL_CHECK_STATUS, host);
|
|
}
|
|
|
|
esp_err_t IRAM_ATTR __wrap_spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_trans_t *trans)
|
|
{
|
|
return esp_tee_service_call(3, SS_SPI_FLASH_HAL_COMMON_COMMAND, host, trans);
|
|
}
|
|
|
|
esp_err_t IRAM_ATTR __wrap_spi_flash_hal_device_config(spi_flash_host_inst_t *host)
|
|
{
|
|
return esp_tee_service_call(2, SS_SPI_FLASH_HAL_DEVICE_CONFIG, host);
|
|
}
|
|
|
|
void IRAM_ATTR __wrap_spi_flash_hal_erase_block(spi_flash_host_inst_t *host, uint32_t start_address)
|
|
{
|
|
esp_tee_service_call(3, SS_SPI_FLASH_HAL_ERASE_BLOCK, host, start_address);
|
|
}
|
|
|
|
void IRAM_ATTR __wrap_spi_flash_hal_erase_chip(spi_flash_host_inst_t *host)
|
|
{
|
|
esp_tee_service_call(2, SS_SPI_FLASH_HAL_ERASE_CHIP, host);
|
|
}
|
|
|
|
void IRAM_ATTR __wrap_spi_flash_hal_erase_sector(spi_flash_host_inst_t *host, uint32_t start_address)
|
|
{
|
|
esp_tee_service_call(3, SS_SPI_FLASH_HAL_ERASE_SECTOR, host, start_address);
|
|
}
|
|
|
|
void IRAM_ATTR __wrap_spi_flash_hal_program_page(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length)
|
|
{
|
|
esp_tee_service_call(5, SS_SPI_FLASH_HAL_PROGRAM_PAGE, host, buffer, address, length);
|
|
}
|
|
|
|
esp_err_t IRAM_ATTR __wrap_spi_flash_hal_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len)
|
|
{
|
|
return esp_tee_service_call(5, SS_SPI_FLASH_HAL_READ, host, buffer, address, read_len);
|
|
}
|
|
|
|
void IRAM_ATTR __wrap_spi_flash_hal_resume(spi_flash_host_inst_t *host)
|
|
{
|
|
esp_tee_service_call(2, SS_SPI_FLASH_HAL_RESUME, host);
|
|
}
|
|
|
|
esp_err_t IRAM_ATTR __wrap_spi_flash_hal_set_write_protect(spi_flash_host_inst_t *host, bool wp)
|
|
{
|
|
return esp_tee_service_call(3, SS_SPI_FLASH_HAL_SET_WRITE_PROTECT, host, wp);
|
|
}
|
|
|
|
esp_err_t IRAM_ATTR __wrap_spi_flash_hal_setup_read_suspend(spi_flash_host_inst_t *host, const spi_flash_sus_cmd_conf *sus_conf)
|
|
{
|
|
return esp_tee_service_call(6, SS_SPI_FLASH_HAL_SETUP_READ_SUSPEND, host, sus_conf);
|
|
}
|
|
|
|
bool IRAM_ATTR __wrap_spi_flash_hal_supports_direct_read(spi_flash_host_inst_t *host, const void *p)
|
|
{
|
|
return esp_tee_service_call(3, SS_SPI_FLASH_HAL_SUPPORTS_DIRECT_READ, host, p);
|
|
}
|
|
|
|
bool IRAM_ATTR __wrap_spi_flash_hal_supports_direct_write(spi_flash_host_inst_t *host, const void *p)
|
|
{
|
|
return esp_tee_service_call(3, SS_SPI_FLASH_HAL_SUPPORTS_DIRECT_WRITE, host, p);
|
|
}
|
|
|
|
void IRAM_ATTR __wrap_spi_flash_hal_suspend(spi_flash_host_inst_t *host)
|
|
{
|
|
esp_tee_service_call(2, SS_SPI_FLASH_HAL_SUSPEND, host);
|
|
}
|
|
|
|
/* ---------------------------------------------- SPI Flash Extras ------------------------------------------------- */
|
|
|
|
uint32_t IRAM_ATTR __wrap_bootloader_flash_execute_command_common(
|
|
uint8_t command,
|
|
uint32_t addr_len, uint32_t address,
|
|
uint8_t dummy_len,
|
|
uint8_t mosi_len, uint32_t mosi_data,
|
|
uint8_t miso_len)
|
|
{
|
|
return esp_tee_service_call(8, SS_BOOTLOADER_FLASH_EXECUTE_COMMAND_COMMON,
|
|
command, addr_len, address, dummy_len, mosi_len,
|
|
mosi_data, miso_len);
|
|
}
|
|
|
|
esp_err_t IRAM_ATTR __wrap_memspi_host_flush_cache(spi_flash_host_inst_t *host, uint32_t addr, uint32_t size)
|
|
{
|
|
return esp_tee_service_call(4, SS_MEMSPI_HOST_FLUSH_CACHE, host, addr, size);
|
|
}
|
|
|
|
esp_err_t IRAM_ATTR __wrap_spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint32_t flags)
|
|
{
|
|
return esp_tee_service_call(3, SS_SPI_FLASH_CHIP_GENERIC_CONFIG_HOST_IO_MODE, chip, flags);
|
|
}
|
|
#endif
|