This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 438eadd880a366609e5e7c1f565e1fe48113dbad Author: Jukka Laitinen <[email protected]> AuthorDate: Tue Sep 1 15:17:48 2026 +0300 arch/arm/imxrt: Port the imx93 ELE driver for iMXRT118x iMXRT118x uses the same security element as the imx93. Just add iMXRT specific register definitions and port over the driver code. Signed-off-by: Jukka Laitinen <[email protected]> --- arch/arm/src/imxrt/CMakeLists.txt | 4 + arch/arm/src/imxrt/Kconfig | 9 + arch/arm/src/imxrt/Make.defs | 4 + arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ele.h | 125 ++++ arch/arm/src/imxrt/imxrt118x_ele.c | 640 +++++++++++++++++++++ arch/arm/src/imxrt/imxrt118x_ele.h | 367 ++++++++++++ 6 files changed, 1149 insertions(+) diff --git a/arch/arm/src/imxrt/CMakeLists.txt b/arch/arm/src/imxrt/CMakeLists.txt index 741a486bb68..b17af15dd10 100644 --- a/arch/arm/src/imxrt/CMakeLists.txt +++ b/arch/arm/src/imxrt/CMakeLists.txt @@ -155,4 +155,8 @@ if(CONFIG_IMXRT_TRDC) list(APPEND SRCS imxrt118x_trdc.c) endif() +if(CONFIG_IMXRT_ELE) + list(APPEND SRCS imxrt118x_ele.c) +endif() + target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/arm/src/imxrt/Kconfig b/arch/arm/src/imxrt/Kconfig index 1ecb4ea7c77..fd46a6dc4a7 100644 --- a/arch/arm/src/imxrt/Kconfig +++ b/arch/arm/src/imxrt/Kconfig @@ -126,6 +126,7 @@ config ARCH_CHIP_MIMXRT1189CVM8C_CM33 select ARCH_CORTEXM33 select ARMV8M_HAVE_STACKCHECK select IMXRT_TRDC + select IMXRT_ELE ---help--- Target the Cortex-M33 core on the RT1189 SoC. Used to build a NuttX bootloader / minimal application that runs on the M33 out @@ -424,6 +425,14 @@ config IMXRT_TRDC (arch/arm/src/imxrt/imxrt118x_trdc.c). Present on RT118x-class SoCs. +config IMXRT_ELE + bool + default n + ---help--- + Enable the NXP EdgeLock Enclave (ELE) messaging driver + (arch/arm/src/imxrt/imxrt118x_ele.c). Present on RT118x-class + SoCs. + menu "i.MX RT Peripheral Selection" config IMXRT_EDMA diff --git a/arch/arm/src/imxrt/Make.defs b/arch/arm/src/imxrt/Make.defs index edf5683e17b..ab93227b025 100644 --- a/arch/arm/src/imxrt/Make.defs +++ b/arch/arm/src/imxrt/Make.defs @@ -150,3 +150,7 @@ endif ifeq ($(CONFIG_IMXRT_TRDC),y) CHIP_CSRCS += imxrt118x_trdc.c endif + +ifeq ($(CONFIG_IMXRT_ELE),y) +CHIP_CSRCS += imxrt118x_ele.c +endif diff --git a/arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ele.h b/arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ele.h new file mode 100644 index 00000000000..ed050eac0d1 --- /dev/null +++ b/arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ele.h @@ -0,0 +1,125 @@ +/**************************************************************************** + * arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ele.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_IMXRT_HARDWARE_RT118X_IMXRT118X_ELE_H +#define __ARCH_ARM_SRC_IMXRT_HARDWARE_RT118X_IMXRT118X_ELE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "hardware/imxrt_memorymap.h" +#include <stdint.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ELE_MAX_MSG 255U + +#define ELE_CMD_TAG 0x17 +#define ELE_VERSION 0x6 +#define ELE_VERSION_FW 0x7 +#define ELE_RESP_TAG 0xe1 +#define ELE_OK 0xd6 + +/* ELE commands. */ + +#define ELE_LOAD_FW_REQ 0x02 +#define ELE_ENABLE_APC_REQ 0xd2 +#define ELE_RELEASE_RDC_REQ 0xc4 +#define ELE_GET_FW_VERSION_REQ 0x9d +#define ELE_DERIVE_KEY_REQ 0xa9 +#define ELE_GET_EVENTS_REQ 0xa2 +#define ELE_GET_TRNG_STATE_REQ 0xa4 +#define ELE_GET_RNG_REQ 0xcd +#define ELE_FWD_LIFECYCLE_UP_REQ 0x95 +#define ELE_OEM_CNTN_AUTH_REQ 0x87 +#define ELE_READ_FUSE_REQ 0x97 +#define ELE_RELEASE_CONTAINER_REQ 0x89 +#define ELE_START_RNG_REQ 0xa3 +#define ELE_VERIFY_IMAGE_REQ 0x88 +#define ELE_COMMIT_REQ 0xa8 +#define ELE_GET_INFO_REQ 0xda +#define ELE_VOLTAGE_CHANGE_START_REQ 0x12 +#define ELE_VOLTAGE_CHANGE_FINISH_REQ 0x13 + +/* RT118x RDC identifiers used by ELE_RELEASE_RDC_REQ, from NXP + * MCUXpresso SDK examples/_boards/evkmimxrt1180/board.c. + */ + +#define ELE_TRDC_AON_ID 0x74 +#define ELE_TRDC_WAKEUP_ID 0x78 +#define ELE_TRDC_MEGA_ID 0x82 + +#define ELE_CORE_CM33_ID 0x1 +#define ELE_CORE_CM7_ID 0x2 + +/* GET_INFO returned data. */ + +#define ELE_GET_INFO_BYTES 160 +#define ELE_GET_INFO_LC_WORD 2 +#define ELE_GET_INFO_LC_MASK 0xffff + +/* System 3 Messaging Unit A (IMXRT1180RM Ch. 65). + * The CM33 boots in Secure state and NXP's own SDK uses the Secure alias + * (0x57540000) rather than the Non-secure alias (0x47540000) for all ELE + * traffic — writes via the Non-secure alias may not reach the enclave + * even though reads mirror the same peripheral. + */ + +#define ELE_MU_TCR (IMXRT_S3MUA_BASE + 0x120) +#define ELE_MU_TSR (IMXRT_S3MUA_BASE + 0x124) +#define ELE_MU_RCR (IMXRT_S3MUA_BASE + 0x128) +#define ELE_MU_RSR (IMXRT_S3MUA_BASE + 0x12c) + +#define ELE_RR_NUM 4 +#define ELE_TR_NUM 8 +#define ELE_MU_TR(i) (IMXRT_S3MUA_BASE + 0x200 + (i) * 4) +#define ELE_MU_RR(i) (IMXRT_S3MUA_BASE + 0x280 + (i) * 4) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct ele_header_t +{ + union + { + uint32_t data; + struct + { + uint32_t version : 8; + uint32_t size : 8; + uint32_t command : 8; + uint32_t tag : 8; + }; + }; +}; + +struct ele_msg +{ + struct ele_header_t header; + uint32_t data[(ELE_MAX_MSG - 1)]; +}; + +#endif /* __ARCH_ARM_SRC_IMXRT_HARDWARE_RT118X_IMXRT118X_ELE_H */ diff --git a/arch/arm/src/imxrt/imxrt118x_ele.c b/arch/arm/src/imxrt/imxrt118x_ele.c new file mode 100644 index 00000000000..77eaf8cfc01 --- /dev/null +++ b/arch/arm/src/imxrt/imxrt118x_ele.c @@ -0,0 +1,640 @@ +/**************************************************************************** + * arch/arm/src/imxrt/imxrt118x_ele.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/nuttx.h> + +#include <sys/types.h> +#include <stdint.h> +#include <inttypes.h> +#include <unistd.h> +#include <errno.h> +#include <debug.h> + +#include "arm_internal.h" +#include "hardware/rt118x/imxrt118x_memorymap.h" +#include "imxrt118x_ele.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The M7 core is Armv7-M and the M33 core is Armv8-M; pick whichever + * D-Cache line size macro chip.h provided for the core we're building + * for. + */ + +#if defined(ARMV8M_DCACHE_LINESIZE) +# define DCACHE_LINESIZE ARMV8M_DCACHE_LINESIZE +#else +# define DCACHE_LINESIZE ARMV7M_DCACHE_LINESIZE +#endif + +#define upper_32_bits(n) ((uint32_t)(((n) >> 16) >> 16)) +#define lower_32_bits(n) ((uint32_t)(n)) + +#define ELE_RNG_TIMEOUT_US 5000 +#define ELE_RNG_SLEEP_US 100 +#define ELE_TRNG_STATUS_READY 0x3 +#define ELE_CSAL_STATUS_READY 0x2 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct ele_trng_state +{ + uint8_t trng_state; + uint8_t csal_state; + uint16_t reserved; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct ele_msg g_msg; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imxrt118x_ele_sendmsg + * + * Description: + * Send a message to the EdgeLock Enclave over the System 3 Message Unit A. + * + ****************************************************************************/ + +static void imxrt118x_ele_sendmsg(struct ele_msg *msg_ptr) +{ + /* Check that ele is ready to receive */ + + while (!((1) & getreg32(ELE_MU_TSR))); + + /* write header to slot 0 */ + + putreg32(msg_ptr->header.data, ELE_MU_TR(0)); + + /* write data */ + + for (int i = 1; i < msg_ptr->header.size; i++) + { + int tx_channel; + + tx_channel = i % ELE_TR_NUM; + while (!((1 << tx_channel) & getreg32(ELE_MU_TSR))); + + /* Write data */ + + putreg32(msg_ptr->data[i - 1], ELE_MU_TR(tx_channel)); + } +} + +/**************************************************************************** + * Name: imxrt118x_ele_receivemsg + * + * Description: + * Receive a response message from the EdgeLock Enclave. + * + ****************************************************************************/ + +static void imxrt118x_ele_receivemsg(struct ele_msg *msg_ptr) +{ + /* Check if data ready */ + + while (!((1) & getreg32(ELE_MU_RSR))); + + /* Read Header from slot 0 */ + + msg_ptr->header.data = getreg32(ELE_MU_RR(0)); + + for (int i = 1; i < msg_ptr->header.size; i++) + { + /* Check if empty */ + + int rx_channel = (i) % ELE_RR_NUM; + + while (!((1 << rx_channel) & getreg32(ELE_MU_RSR))); + + /* Read data */ + + msg_ptr->data[i - 1] = getreg32(ELE_MU_RR(rx_channel)); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void imxrt118x_ele_init(void) +{ + putreg32(0, ELE_MU_TCR); + putreg32(0, ELE_MU_RCR); + + imxrt118x_ele_check_fw_version(); +} + +int imxrt118x_ele_load_fw(uint32_t fw_addr) +{ + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 4; + g_msg.header.command = ELE_LOAD_FW_REQ; + g_msg.data[0] = fw_addr; + g_msg.data[1] = 0; + g_msg.data[2] = fw_addr; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + return 0; + } + + return -EIO; +} + +int imxrt118x_ele_release_rdc(uint32_t rdc_id) +{ + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 2; + g_msg.header.command = ELE_RELEASE_RDC_REQ; + g_msg.data[0] = rdc_id; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + return 0; + } + + return -EIO; +} + +uint32_t imxrt118x_ele_read_common_fuse(uint32_t fuse_id) +{ + uint32_t value = 0; + + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 2; + g_msg.header.command = ELE_READ_FUSE_REQ; + g_msg.data[0] = fuse_id; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + value = g_msg.data[1]; + } + + return value; +} + +int imxrt118x_ele_get_key(uint8_t *key, size_t key_size, + uint8_t *ctx, size_t ctx_size) +{ + if (!key) + { + _err("Invalid key parameter\n"); + return -EINVAL; + } + + if (!ctx) + { + _err("Invalid context parameter\n"); + return -EINVAL; + } + + if ((key_size != 16) && (key_size != 32)) + { + _err("Invalid key size\n"); + return -EINVAL; + } + + if (!IS_ALIGNED((uintptr_t)key, DCACHE_LINESIZE)) + { + _err("Invalid key alignment\n"); + return -EINVAL; + } + + if (!IS_ALIGNED((uintptr_t)ctx, DCACHE_LINESIZE)) + { + _err("Invalid context alignment\n"); + return -EINVAL; + } + + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 7; + g_msg.header.command = ELE_DERIVE_KEY_REQ; + g_msg.data[0] = upper_32_bits((uintptr_t)key); + g_msg.data[1] = lower_32_bits((uintptr_t)key); + g_msg.data[2] = upper_32_bits((uintptr_t)ctx); + g_msg.data[3] = lower_32_bits((uintptr_t)ctx); + g_msg.data[4] = ((ctx_size << 16) | key_size); + + uint32_t crc = g_msg.header.data; + + for (uint32_t i = 0; i < g_msg.header.size - 2; i++) + { + crc ^= g_msg.data[i]; + } + + g_msg.data[5] = crc; + + up_flush_dcache((uintptr_t)ctx, (uintptr_t)(ctx + ctx_size)); + up_invalidate_dcache((uintptr_t)key, (uintptr_t)(key + key_size)); + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + up_invalidate_dcache((uintptr_t)key, (uintptr_t)(key + key_size)); + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + return 0; + } + + return -EIO; +} + +int imxrt118x_ele_get_events(uint32_t *buffer, size_t buffer_size) +{ + size_t events_num; + size_t i; + + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 1; + g_msg.header.command = ELE_GET_EVENTS_REQ; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + events_num = g_msg.data[1] & 0xffff; + if (buffer) + { + for (i = 0; (i < buffer_size) && (i < events_num); i++) + { + buffer[i] = g_msg.data[i + 2]; + } + + return (int)i; + } + else + { + return (int)events_num; + } + } + + return -EIO; +} + +int imxrt118x_ele_close_device(void) +{ + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 2; + g_msg.header.command = ELE_FWD_LIFECYCLE_UP_REQ; + g_msg.data[0] = 0x08; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + return 0; + } + + return -EIO; +} + +uint32_t imxrt118x_ele_get_lifecycle(void) +{ + static uint8_t info[ELE_GET_INFO_BYTES] + aligned_data(DCACHE_LINESIZE); + + uint32_t addr = (uint32_t)(uintptr_t)info; + + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 4; + g_msg.header.command = ELE_GET_INFO_REQ; + g_msg.data[0] = upper_32_bits(addr); + g_msg.data[1] = lower_32_bits(addr); + g_msg.data[2] = sizeof(info); + + up_invalidate_dcache(addr, addr + sizeof(info)); + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if ((g_msg.data[0] & 0xff) != ELE_OK) + { + return 0; + } + + up_invalidate_dcache(addr, addr + sizeof(info)); + + return ((uint32_t *)info)[ELE_GET_INFO_LC_WORD] & ELE_GET_INFO_LC_MASK; +} + +int imxrt118x_ele_auth_oem_ctnr(unsigned long ctnr_addr, uint32_t *response) +{ + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 3; + g_msg.header.command = ELE_OEM_CNTN_AUTH_REQ; + g_msg.data[0] = upper_32_bits(ctnr_addr); + g_msg.data[1] = lower_32_bits(ctnr_addr); + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + if (response) + { + *response = g_msg.data[0]; + } + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + return 0; + } + + return -EIO; +} + +int imxrt118x_ele_release_container(uint32_t *response) +{ + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 1; + g_msg.header.command = ELE_RELEASE_CONTAINER_REQ; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if (response) + { + *response = g_msg.data[0]; + } + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + return 0; + } + + return -EIO; +} + +int imxrt118x_ele_verify_image(uint32_t img_id, uint32_t *response) +{ + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 2; + g_msg.header.command = ELE_VERIFY_IMAGE_REQ; + g_msg.data[0] = 1 << img_id; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if (response) + { + *response = g_msg.data[0]; + } + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + return 0; + } + + return -EIO; +} + +int imxrt118x_ele_start_rng(void) +{ + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 1; + g_msg.header.command = ELE_START_RNG_REQ; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + return 0; + } + + return -EIO; +} + +int imxrt118x_ele_get_trng_state(void) +{ + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 1; + g_msg.header.command = ELE_GET_TRNG_STATE_REQ; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + struct ele_trng_state *ele_trng = + (struct ele_trng_state *)(g_msg.data + 1); + + if (ele_trng->trng_state != ELE_TRNG_STATUS_READY || + ele_trng->csal_state != ELE_CSAL_STATUS_READY) + { + /* Ensure imxrt118x_ele_start_rng() was called earlier or we + * will end up here. + */ + + return -EBUSY; + } + else + { + return 0; + } + } + + return -EIO; +} + +int imxrt118x_ele_get_random(uint32_t paddr, size_t len) +{ + uint16_t counter = 0; + uint16_t max_tries = ELE_RNG_TIMEOUT_US / ELE_RNG_SLEEP_US; + + if (paddr == 0 || len == 0) + { + _err("Wrong input parameters!\n"); + return -EINVAL; + } + + while ((imxrt118x_ele_get_trng_state() != 0)) + { + if (counter > max_tries) + { + _err("Timed out after %hu iterations!\n", counter); + return -EBUSY; + } + + usleep(ELE_RNG_SLEEP_US); + counter++; + } + + /* Flush the cache before sending the request to ELE. */ + + up_flush_dcache((uintptr_t)paddr, (uintptr_t)(paddr + len)); + + g_msg.header.version = ELE_VERSION_FW; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 4; + g_msg.header.command = ELE_GET_RNG_REQ; + g_msg.data[0] = 0; + g_msg.data[1] = paddr; + g_msg.data[2] = len; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + /* Invalidate the cache so we can read the result from RAM. */ + + up_invalidate_dcache((uintptr_t)paddr, + (uintptr_t)(paddr + len)); + return 0; + } + + return -EIO; +} + +int imxrt118x_ele_commit(uint32_t info, uint32_t *response) +{ + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 2; + g_msg.header.command = ELE_COMMIT_REQ; + g_msg.data[0] = info; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if (response) + { + *response = g_msg.data[0]; + } + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + return 0; + } + + return -EIO; +} + +int imxrt118x_ele_enable_apc(void) +{ + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 1; + g_msg.header.command = ELE_ENABLE_APC_REQ; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + return 0; + } + + return -EIO; +} + +int imxrt118x_ele_voltage_change_start(void) +{ + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 1; + g_msg.header.command = ELE_VOLTAGE_CHANGE_START_REQ; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + return 0; + } + + return -EIO; +} + +int imxrt118x_ele_voltage_change_finish(void) +{ + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 1; + g_msg.header.command = ELE_VOLTAGE_CHANGE_FINISH_REQ; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if ((g_msg.data[0] & 0xff) == ELE_OK) + { + return 0; + } + + return -EIO; +} + +int imxrt118x_ele_check_fw_version(void) +{ + g_msg.header.version = ELE_VERSION; + g_msg.header.tag = ELE_CMD_TAG; + g_msg.header.size = 1; + g_msg.header.command = ELE_GET_FW_VERSION_REQ; + + imxrt118x_ele_sendmsg(&g_msg); + imxrt118x_ele_receivemsg(&g_msg); + + if ((g_msg.data[0] & 0xff) != ELE_OK) + { + return -EIO; + } + + return 0; +} diff --git a/arch/arm/src/imxrt/imxrt118x_ele.h b/arch/arm/src/imxrt/imxrt118x_ele.h new file mode 100644 index 00000000000..d2e443050f7 --- /dev/null +++ b/arch/arm/src/imxrt/imxrt118x_ele.h @@ -0,0 +1,367 @@ +/**************************************************************************** + * arch/arm/src/imxrt/imxrt118x_ele.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_IMXRT_IMXRT118X_ELE_H +#define __ARCH_ARM_SRC_IMXRT_IMXRT118X_ELE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/types.h> +#include <stdint.h> + +#include "hardware/rt118x/imxrt118x_ele.h" + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: imxrt118x_ele_init + * + * Description: + * Bring the EdgeLock Enclave up. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void imxrt118x_ele_init(void); + +/**************************************************************************** + * Name: imxrt118x_ele_load_fw + * + * Description: + * Load the EdgeLock Enclave firmware. + * + * Input Parameters: + * fw_addr - Address of the ELE firmware container. + * + * Returned Value: + * OK on success, a negated errno value otherwise. + * + ****************************************************************************/ + +int imxrt118x_ele_load_fw(uint32_t fw_addr); + +/**************************************************************************** + * Name: imxrt118x_ele_release_rdc + * + * Description: + * Request ownership of one TRDC. + * + * Input Parameters: + * rdc_id - Packed TRDC and core identifier. + * + * Returned Value: + * OK on success, a negated errno value otherwise. + * + ****************************************************************************/ + +int imxrt118x_ele_release_rdc(uint32_t rdc_id); + +/**************************************************************************** + * Name: imxrt118x_ele_read_common_fuse + * + * Description: + * Read a common fuse value. + * + * Input Parameters: + * fuse_id - Fuse ID + * + * Returned Value: + * Fuse value. Returns zero if read failed. + * + ****************************************************************************/ + +uint32_t imxrt118x_ele_read_common_fuse(uint32_t fuse_id); + +/**************************************************************************** + * Name: imxrt118x_ele_get_key + * + * Description: + * Return HW unique key value. + * + * Input Parameters: + * key - Key buffer, must be cache line aligned + * key_size - Key size in bytes, must be 16 or 32 + * ctx - Context buffer, must be cache line aligned + * ctx_size - Context buffer size + * + * Returned Value: + * OK on success, a negated errno value otherwise. + * + ****************************************************************************/ + +int imxrt118x_ele_get_key(uint8_t *key, size_t key_size, + uint8_t *ctx, size_t ctx_size); + +/**************************************************************************** + * Name: imxrt118x_ele_get_events + * + * Description: + * Return ELE events. + * + * Input Parameters: + * buffer - Event buffer + * buffer_size - Event buffer size + * + * Returned Value: + * Zero (OK) is returned if no events. A negated errno value is returned + * on failure. Positive value is number of events read. + * + ****************************************************************************/ + +int imxrt118x_ele_get_events(uint32_t *buffer, size_t buffer_size); + +/**************************************************************************** + * Name: imxrt118x_ele_close_device + * + * Description: + * Set device to OEM close state. This operation is irreversible. + * + * Returned Value: + * OK on success, a negated errno value otherwise. + * + ****************************************************************************/ + +int imxrt118x_ele_close_device(void); + +/**************************************************************************** + * Name: imxrt118x_ele_get_lifecycle + * + * Description: + * Return the device's lifecycle value, queried from the ELE via + * GET_INFO (RT118x has no i.MX9-style FSB lifecycle register). + * + * Returned Value: + * Lifecycle value. + * + ****************************************************************************/ + +uint32_t imxrt118x_ele_get_lifecycle(void); + +/**************************************************************************** + * Name: imxrt118x_ele_auth_oem_ctnr + * + * Description: + * Authenticate container header. + * + * Input Parameters: + * ctnr_addr - Address of the container header. + * + * Output Parameters: + * response - ELE response, can be used for debugging. + * + * Returned Value: + * OK on success, a negated errno value otherwise. + * + ****************************************************************************/ + +int imxrt118x_ele_auth_oem_ctnr(unsigned long ctnr_addr, uint32_t *response); + +/**************************************************************************** + * Name: imxrt118x_ele_release_container + * + * Description: + * Release the container from the ELE, used after + * imxrt118x_ele_auth_oem_ctnr(). + * + * Output Parameters: + * response - ELE response, can be used for debugging. + * + * Returned Value: + * OK on success, a negated errno value otherwise. + * + ****************************************************************************/ + +int imxrt118x_ele_release_container(uint32_t *response); + +/**************************************************************************** + * Name: imxrt118x_ele_verify_image + * + * Description: + * Verify the specified image, for the current container. + * + * Input Parameters: + * img_id - The id of the image in the context of the current container. + * + * Output Parameters: + * response - ELE response, can be used for debugging. + * + * Returned Value: + * OK on success, a negated errno value otherwise. + * + ****************************************************************************/ + +int imxrt118x_ele_verify_image(uint32_t img_id, uint32_t *response); + +/**************************************************************************** + * Name: imxrt118x_ele_start_rng + * + * Description: + * Sends command to initialize the ELE RNG context. + * + * Returned Value: + * OK on success, a negated errno value otherwise. + * + ****************************************************************************/ + +int imxrt118x_ele_start_rng(void); + +/**************************************************************************** + * Name: imxrt118x_ele_get_trng_state + * + * Description: + * Query the state of the True Random Number Generator. + * + * Returned Value: + * Zero is returned if the Random Number Generator (RNG) is ready for + * use. A negated errno value (-EBUSY) or another is returned on + * failure. + * + ****************************************************************************/ + +int imxrt118x_ele_get_trng_state(void); + +/**************************************************************************** + * Name: imxrt118x_ele_get_random + * + * Description: + * Request from the ELE the generation of a random number of specified + * length. + * + * Input Parameters: + * paddr - 32bit physical address to store the random number. + * len - Length in bytes of the random number. + * + * Returned Value: + * Zero is returned if ELE successfully generated the random number. + * A negated errno value (-EBUSY) or another is returned on failure. + * + ****************************************************************************/ + +int imxrt118x_ele_get_random(uint32_t paddr, size_t len); + +/**************************************************************************** + * Name: imxrt118x_ele_commit + * + * Description: + * Sends commit command to the ELE. + * + * Input Parameters: + * info - Information type to be committed + * + * Output Parameters: + * response - ELE response, can be used for debugging. + * + * Returned Value: + * OK on success, a negated errno value otherwise. + * + ****************************************************************************/ + +int imxrt118x_ele_commit(uint32_t info, uint32_t *response); + +/**************************************************************************** + * Name: imxrt118x_ele_enable_apc + * + * Description: + * Enable Access Permission Control for the M7. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success, a negated errno value otherwise. + * + ****************************************************************************/ + +int imxrt118x_ele_enable_apc(void); + +/**************************************************************************** + * Name: imxrt118x_ele_voltage_change_start + * + * Description: + * Begin an ELE-guarded VDD1P0 voltage change (VOLTAGE_CHANGE_START, + * 0x12). When the digital glitch detector (GDET) is enabled, the DCDC + * target must only be reprogrammed between this command and + * imxrt118x_ele_voltage_change_finish(); otherwise the glitch detector + * can trip on the transition and put the SoC into an unpredictable + * (lockup/reset) state. While the change is in progress the ELE accepts + * no other command and aborts if FINISH is not issued within 50 ms. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success, a negated errno value otherwise. ELE firmware that + * does not implement the command simply rejects it, in which case the + * caller may proceed with the (unguarded) voltage change. + * + ****************************************************************************/ + +int imxrt118x_ele_voltage_change_start(void); + +/**************************************************************************** + * Name: imxrt118x_ele_voltage_change_finish + * + * Description: + * Complete an ELE-guarded VDD1P0 voltage change (VOLTAGE_CHANGE_FINISH, + * 0x13), removing the GDET isolation started by + * imxrt118x_ele_voltage_change_start(). Must be issued within 50 ms of + * the START command. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success, a negated errno value otherwise. + * + ****************************************************************************/ + +int imxrt118x_ele_voltage_change_finish(void); + +/**************************************************************************** + * Name: imxrt118x_ele_check_fw_version + * + * Description: + * Query the EdgeLock Enclave firmware version (GET_FW_VERSION) and log + * it, so it can be verified that the intended ELE firmware is active. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success, a negated errno value otherwise. + * + ****************************************************************************/ + +int imxrt118x_ele_check_fw_version(void); + +#endif /* __ARCH_ARM_SRC_IMXRT_IMXRT118X_ELE_H */
