diff --git a/.gitignore b/.gitignore index 2a5f747072b..0d2b81f32c3 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,8 @@ !.gitignore !.github !.devcontainer +.cproject +cscope.* +.project +*.swp +.vscode diff --git a/core/arch/arm/include/sm/optee_smc.h b/core/arch/arm/include/sm/optee_smc.h index a43cfc4426b..ae3ed0e24ad 100644 --- a/core/arch/arm/include/sm/optee_smc.h +++ b/core/arch/arm/include/sm/optee_smc.h @@ -132,6 +132,9 @@ #define OPTEE_SMC_CALL_GET_OS_REVISION \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_REVISION) +/* Config to request getting the R-Car Software revision of optee_os */ +#define OPTEE_SMC_GET_RCAR_REVISION 1 + /* * Call with struct optee_msg_arg as argument * diff --git a/core/arch/arm/kernel/boot.c b/core/arch/arm/kernel/boot.c index 77cbeca1c0b..e40d9962d2b 100644 --- a/core/arch/arm/kernel/boot.c +++ b/core/arch/arm/kernel/boot.c @@ -45,6 +45,7 @@ #include #include +#include #if !defined(CFG_WITH_ARM_TRUSTED_FW) #include @@ -1044,6 +1045,7 @@ void __weak boot_init_primary_runtime(void) { thread_init_primary(); IMSG("OP-TEE version: %s", core_v_str); + IMSG("OPTEE_OS RCar BSP Revision: %s", VERSION_OF_RENESAS); if (IS_ENABLED(CFG_INSECURE)) { IMSG("WARNING: This OP-TEE configuration might be insecure!"); IMSG("WARNING: Please check https://optee.readthedocs.io/en/latest/architecture/porting_guidelines.html"); diff --git a/core/arch/arm/plat-rcar_gen5/conf.mk b/core/arch/arm/plat-rcar_gen5/conf.mk new file mode 100644 index 00000000000..809694a5ed1 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/conf.mk @@ -0,0 +1,91 @@ +PLATFORM_FLAVOR ?= X5H +include core/arch/arm/cpu/cortex-armv8-0.mk + +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_GIC,y) +$(call force,CFG_CORE_LARGE_PHYS_ADDR,y) +$(call force,CFG_CORE_ARM64_PA_BITS,36) +$(call force,CFG_LPAE_ADDR_SPACE_BITS,36) + +# Use the runtime HW PARange (ID_AA64MMFR0_EL1) instead of the hard-coded +# 36-bit (64GB) limit, so OP-TEE can address and map dynamic SHM in the +# DRAM banks above 64GB where Xen places guest RAM. Same approach as +# plat-vexpress (virtualization). +CFG_AUTO_MAX_PA_BITS ?= y +# Disable core ASLR for two reasons: +# 1. There is no source for ALSR seed, as Rcar platform +# does not provide DTB to OP-TEE. Also, there is no +# publically available documentation on integrated +# hardware RNG, so we can't use it either. +# 2. OP-TEE crashes during boot with enabled CFG_CORE_ASLR. +$(call force,CFG_CORE_ASLR,n) +$(call force,CFG_ARM64_core,y) +$(call force,CFG_WITH_LPAE,y) +ifeq ($(PLATFORM_FLAVOR), X5H) +$(call force,CFG_RCAR_GEN5, y) +endif + +CFG_ARM_GICV3 ?= y +CFG_CRYPTO_WITH_CE ?= n +CFG_TZDRAM_START ?= 0x8C400000 +CFG_TZDRAM_SIZE ?= 0x02000000 +CFG_TEE_RAM_VA_SIZE ?= 0x100000 +supported-ta-targets = ta_arm64 +CFG_DT ?= n +CFG_WITH_SOFTWARE_PRNG ?= y +CFG_TEE_CORE_DEBUG ?= n + +ifeq ($(CFG_RCAR_GEN5), y) +# 1xx - for SCIFxx +# 2xx - for HSCIFxx +CFG_RCAR_UART ?= 200 +$(call force,CFG_CORE_CLUSTER_SHIFT,2) #log2(2) = 4 --> 4(cores/per cluster) +$(call force,CFG_TEE_CORE_NB_CORE,32) + +# One OP-TEE thread per physical core makes no sense under +# CFG_NS_VIRTUALIZATION: threads are allocated per guest by +# virt_guest_created() -> thread_init_threads(), the callers are guest +# vCPUs rather than physical cores, and each thread costs 1792 B of guest +# heap, 8 KiB + a guard page of guest physical memory and two PGT cache +# entries. Upstream default is 2. +CFG_NUM_THREADS ?= 8 +CFG_MMAP_REGIONS ?= 21 +endif + +# For logging function +# Compiler switch - Debug log(Linux terminal log) +RCAR_DEBUG_LOG ?= 0 +ifneq ($(RCAR_DEBUG_LOG),0) +core-platform-cflags += -DRCAR_DEBUG_LOG +endif + +# For virtualization +ifeq ($(CFG_NS_VIRTUALIZATION),y) +CFG_VIRT_GUEST_COUNT ?= 3 +CFG_RCAR_MUTEX_DELAY ?= 1 +core-platform-cflags += -DCFG_RCAR_MUTEX_DELAY=$(CFG_RCAR_MUTEX_DELAY) +CFG_CORE_RESERVED_SHM ?= n +endif + +# For Direct mapping function +core-platform-cflags += -DRCAR_MMU_DIRECT_MAPPING + +# For using the rsipm functions +RCAR_TRNG_BY_RSIPM_HWENGINE ?= n +CFG_RSIPM_FW_SERVICE ?= n +ifeq ($(CFG_RSIPM_FW_SERVICE), y) +RCAR_TRNG_BY_RSIPM_HWENGINE = y +core-platform-cflags += -DRCAR_TRNG_BY_RSIPM_HWENGINE +endif + +# For Dynamic TA Authentication +CFG_DYNAMIC_TA_AUTH_BY_HWENGINE ?= n +ifeq ($(CFG_DYNAMIC_TA_AUTH_BY_HWENGINE),y) +core-platform-cflags += -DRCAR_DYNAMIC_TA_AUTH_BY_HWENGINE +endif + +# For MFIS mutex lock/unlock by HSCIF0 +ifeq ($(CFG_SCIF),y) +CFG_MFIS_DRV = y +endif diff --git a/core/arch/arm/plat-rcar_gen5/drivers/comm.c b/core/arch/arm/plat-rcar_gen5/drivers/comm.c new file mode 100644 index 00000000000..d04057f590f --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/drivers/comm.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2025, Renesas Electronics Corporation. + */ + +#include +#include +#include +#include "comm_shared.h" +#include "comm.h" +#include "platform_config.h" + +/* + * Function name: r_comm_trigger_secure + * Description : Trigger secure CPU processing by setting shared flags + and waiting for completion. + * Arguments : p_sevice_param : Pointer to the input parameters + * param_size : Size of the input parameters + * Return Value : None + */ + +void r_comm_trigger_secure(const void *p_sevice_param, size_t param_size) +{ + while (p_shared_flag->flag != REQ_STATE_NONE) + ; /* Wait */ + + p_shared_payload->p_data = (void *)p_sevice_param; + p_shared_payload->data_len = param_size; + p_shared_flag->flag = REQ_STATE_REQUEST; + + /* Wait until the flag changes to REQ_STATE_COMPLETE + * on the SECURE_CPU side + */ + while (p_shared_flag->flag != REQ_STATE_COMPLETE) + ; /* Wait */ + + /* After the service is completed, + * set the flag to REQ_STATE_GET_RESULT + */ + p_shared_flag->flag = REQ_STATE_GET_RESULT; +} + +/* + * Function name: r_comm_main_init + * Description : Initialize shared memory for communication with secure CPU. + * Arguments : + * (IN) base_share: the base address of shared memory + for communicating with secure core + * Return Value : None + */ +void r_comm_main_init(uint32_t base_shared_mem) +{ + p_shared_flag = (volatile void *)(uintptr_t)base_shared_mem; + p_shared_payload = (volatile void *)(uintptr_t)(base_shared_mem + + SHARED_FLAG_SIZE); + p_shared_data = (volatile void *)(uintptr_t)(base_shared_mem + + SHARED_FLAG_SIZE + SHARED_PAYLOAD_SIZE); + + p_shared_flag->flag = REQ_STATE_NONE; +} + +/* + * Function name: r_comm_wait_secure_cpu_init + * Description : Wait until the secure CPU sets the READY bit in shared status. + * Arguments : + * (IN) completed_state: the initial state of CPU + * + MAIN_CPU_INIT_DONE for main CPU + * + SECURE_CPU_INIT_DONE for secure CPU + * Return Value : None + */ +void r_comm_wait_secure_cpu_init(uint32_t cpu_completed_state) +{ + while ((p_shared_flag->status_sec_to_main & cpu_completed_state) + != cpu_completed_state) + ; /* Wait */ +} + +/* + * Function name: r_comm_set_status_main_to_sec + * Description : Set or clear the status bits from Main to Secure CPU. + * Arguments : infor : Bit(s) to set or clear + * set_value : 1 to set, 0 to clear the bit(s) + * Return Value : None + */ +void r_comm_set_status_main_to_sec(uint32_t infor, uint32_t set_value) +{ + if (set_value == 1) + p_shared_flag->status_main_to_sec |= infor; + else + p_shared_flag->status_main_to_sec &= ~infor; +} + +/* End of file */ diff --git a/core/arch/arm/plat-rcar_gen5/drivers/comm.h b/core/arch/arm/plat-rcar_gen5/drivers/comm.h new file mode 100644 index 00000000000..94375e4a942 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/drivers/comm.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2025, Renesas Electronics Corporation. + */ + +#include "comm_shared.h" + +void r_comm_trigger_secure(const void *p_sevice_param, size_t param_size); +void r_comm_main_init(uint32_t base_shared_mem); +void r_comm_wait_secure_cpu_init(uint32_t cpu_completed_state); +void r_comm_set_status_main_to_sec(uint32_t infor, uint32_t set_value); + +/* End of file */ diff --git a/core/arch/arm/plat-rcar_gen5/drivers/comm_shared.h b/core/arch/arm/plat-rcar_gen5/drivers/comm_shared.h new file mode 100644 index 00000000000..c3b17825ed5 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/drivers/comm_shared.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2025, Renesas Electronics Corporation. + */ + +#if !defined(SHARED_H) +#define SHARED_H + +#include + +#define INTER_CORE_COMM_SHARED_MEM_ADDR (0x185C0000uL) + +#define SHARED_FLAG_SIZE (16U) +#define SHARED_DATA_SIZE (104U) +#define SHARED_PAYLOAD_SIZE (76U) + +#define REQ_STATE_NONE (0xA5A5A500u) +#define REQ_STATE_REQUEST (0xA5A5A505u) /* Trigger request */ +#define REQ_STATE_EXECUTE (0xA5A5A506u) /* Request executing */ +#define REQ_STATE_COMPLETE (0xA5A5A507u) /* Request Completed */ +#define REQ_STATE_GET_RESULT (0xA5A5A508u) /* Result acquisition completed */ + +#define MAIN_CPU_INIT_DONE (0x10000000u) +#define SECURE_CPU_INIT_DONE (0x10000000u) +#define SB_IMAGE_HASH_WORD_SIZE (0x8u) /* Image hash WORD size */ + +/* + * Typedef definitions + */ + +typedef enum { + ALL_OK = 0, + NG, + UNKNOWN_TYPE, +} result_t; + +typedef struct { + uint32_t flag; + uint32_t status_main_to_sec; /* For notification from the Main CPU + * to the Secure CPU + */ + uint32_t status_sec_to_main; /* For notification from the Secure CPU + * to the Main CPU + */ +} shared_flag_t; + +typedef struct { + uint8_t service_id; + uint32_t param[100]; +} generic_data_t; + +typedef struct { + uint32_t notify_type; /* Communication notification type */ + uint16_t service_type; /* The type of request to process */ + uint32_t service_result; /* Request processing status */ + uint32_t data_len; /* Data Length */ + void *p_data; /* A pointer where the actual data is stored */ +} r_lsc_comm_payload_t; + +extern volatile shared_flag_t *p_shared_flag; +extern volatile r_lsc_comm_payload_t *p_shared_payload; +extern volatile void *p_shared_data; + +#endif /* SHARED_H */ + +/* End of file */ diff --git a/core/arch/arm/plat-rcar_gen5/drivers/mfis.c b/core/arch/arm/plat-rcar_gen5/drivers/mfis.c new file mode 100644 index 00000000000..3a0f99ee2be --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/drivers/mfis.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2026, Renesas Electronics Corporation. All rights reserved. + * + */ + +/******************************************************************************/ +/* Header file */ +/******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "rcar-common.h" + +/******************************************************************************/ +/* Variable */ +/******************************************************************************/ +/* MFIS locks are used base on convention as below order. + * The 5th MFIS lock is dedicated to protect exclusive + * control for serial console. + */ +static const uint32_t mfis_mfislckr_table[] = { +/* + * MFIS_MFISLCKR0, MFIS_RPC + * MFIS_MFISLCKR1, Reserved + * MFIS_MFISLCKR2, MFIS_UFS + * MFIS_MFISLCKR3, MFIS_OVERLAP_CHECK + * MFIS_MFISLCKR4, MFIS_MEASUREMENT + */ + MFIS_MFISLCKR5 /* MFIS_TARGET_HSCIF */ +}; + +/******************************************************************************/ +/* Function */ +/******************************************************************************/ +void rcar_mfis_init(void) +{ + uint32_t register_value; + + /* Write Protection Control Register */ + /* Disable write protection setting */ + register_value = (MFISWPCNTR_CODEVALUE_SET | MFISWPCNTR_WPD_SET); + io_write32(MFIS_MFISWPCNTR, register_value); +} + +void rcar_mfis_lock(mfis_target_t target) +{ + uintptr_t lock_reg; + uint32_t val; + uint32_t i; + bool mmu_enabled = cpu_mmu_enabled(); + + if (mmu_enabled) + lock_reg = (uintptr_t)(p2v_ioadr(mfis_mfislckr_table[target], + MEMORY8_PA_END - (mfis_mfislckr_table[target]))); + else + lock_reg = mfis_mfislckr_table[target]; + + /* Wait until acquired (with timeout to avoid hang) */ + for (i = 0; i < MFIS_LOCK_TIMEOUT; i++) { + val = io_read32(lock_reg); + if ((val & MFISLCKR_LCK_MASK) == + MFISLCKR_LCK_NOT_ACQUIRED_CHECK) { + return; + } + } +} + +void rcar_mfis_unlock(mfis_target_t target) +{ + uint32_t register_value_mfis_mfislckr; + bool mmu_enabled = cpu_mmu_enabled(); + vaddr_t address = p2v_ioadr(mfis_mfislckr_table[target], + MEMORY8_PA_END - (mfis_mfislckr_table[target])); + + if (mmu_enabled) { + register_value_mfis_mfislckr = io_read32(address); + register_value_mfis_mfislckr &= (~(MFISLCKR_LCK_MASK)); + register_value_mfis_mfislckr |= MFISLCKR_LCK_RELEASE_SET; + /* MFIS Lock Register [j] (MFISLCKR[j]) */ + io_write32(address, register_value_mfis_mfislckr); + } else { + register_value_mfis_mfislckr = + io_read32(mfis_mfislckr_table[target]); + register_value_mfis_mfislckr &= (~(MFISLCKR_LCK_MASK)); + register_value_mfis_mfislckr |= MFISLCKR_LCK_RELEASE_SET; + /* MFIS Lock Register [j] (MFISLCKR[j]) */ + io_write32(mfis_mfislckr_table[target], + register_value_mfis_mfislckr); + } +} + diff --git a/core/arch/arm/plat-rcar_gen5/drivers/sub.mk b/core/arch/arm/plat-rcar_gen5/drivers/sub.mk new file mode 100644 index 00000000000..cac9adc48d2 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/drivers/sub.mk @@ -0,0 +1,4 @@ +global-incdirs-y += . +srcs-$(CFG_SWDT_DRV) += swdt.c +srcs-$(CFG_RSIPM_FW_SERVICE) += comm.c +srcs-$(CFG_MFIS_DRV) += mfis.c diff --git a/core/arch/arm/plat-rcar_gen5/drivers/swdt.c b/core/arch/arm/plat-rcar_gen5/drivers/swdt.c new file mode 100644 index 00000000000..cd6778d2736 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/drivers/swdt.c @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2025, Renesas Electronics Corporation + */ + +#include +#include +#include +#include +#include +#include +#include "rcar-common.h" + +/******************************************************************************/ +/* Defines */ +/******************************************************************************/ +/* Register */ +#define RST_WDTRSTCR p2v_ioadr(0xC1320420U, MEMORY3_PA_END - 0xC1320420U) +#define SWDT_SWTCNT p2v_ioadr(0x1C050000U, DEVICE0_PA_END - 0x1C050000U) +#define SWDT_SWTCSRA p2v_ioadr(0x1C050004U, DEVICE0_PA_END - 0x1C050004U) +#define SWDT_SWTCSRB p2v_ioadr(0x1C050008U, DEVICE0_PA_END - 0x1C050008U) + +#define SWDT_WDTRSTCR_UPPER_BYTE (0xA55A0000U) +#define SWDT_WDTRSTCR_LOWER_BYTE (0x0000FFFFU) +#define SWDT_SWTCSRA_UPPER_BYTE (0xA5A5A500U) +#define SWDT_SWTCSRA_WRFLG ((uint32_t)1U << 5U) +#define SWDT_SWTCSRA_TME ((uint32_t)1U << 7U) +#define SWDT_SWTCSRA_WOVF ((uint32_t)1U << 4U) +#define SWDT_SWTCSRA_WOVFE ((uint32_t)1U << 3U) +#define SWDT_SWTCSRA_BIT_CKS (0x00000007U) +#define SWDT_SWTCSRB_UPPER_BYTE (0xA5A5A500U) +#define SWDT_SWTCSRB_BIT_CKS (0x0000003FU) +#define SWDT_SWTCNT_UPPER_BYTE (0x5A5A0000U) +#define SWDT_SWTCNT_RESET_VALUE (0x0000F488U) +#define RST_WDTRSTCR_RSTMSK ((uint32_t)1U << 1U) + +#define SPI_SWDT (0x1062U) /* System WDT */ + +#define SWDT_STATE_NOACTIVE (0U) +#define SWDT_STATE_ACTIVE (1U) + +/******************************************************************************/ +/* Prototype */ +/******************************************************************************/ +static void swdt_is_ready(void); +static enum itr_return swdt_handler(struct itr_handler *h); +static TEE_Result swdt_init(void); +static void __maybe_unused swdt_itr_del(void); + +/******************************************************************************/ +/* Global */ +/******************************************************************************/ +static uint32_t thread_global_lock __nex_data = (uint32_t)SPINLOCK_UNLOCK; +static uint16_t swdt_initial_count __nex_bss; +static uint32_t swdt_state __nex_data = SWDT_STATE_NOACTIVE; +static uint16_t swdt_count __nex_bss; +static uint8_t swdt_clk __nex_bss; +static uint8_t swdt_expanded_clk __nex_bss; +static void (*user_cb)(void)__nex_bss; +static uint32_t swdt_init_flag __nex_bss = INIT_FLAG_UNINITIALIZED; + +static void swdt_is_ready(void) +{ + while (0U != (io_read8(SWDT_SWTCSRA) & SWDT_SWTCSRA_WRFLG)) + ; +} + +static enum itr_return swdt_handler(struct itr_handler *h) +{ + uint32_t reg; + (void)h; + + if (user_cb) + user_cb(); + + reg = io_read8(SWDT_SWTCSRA); + reg &= ~SWDT_SWTCSRA_WOVF; + reg |= SWDT_SWTCSRA_UPPER_BYTE; + io_write32(SWDT_SWTCSRA, reg); + + return ITRR_HANDLED; +} + +static struct itr_handler swdt_itr[] = { + /* System Timer */ + { + .it = SPI_SWDT, + .flags = (uint32_t)ITRF_TRIGGER_LEVEL, + .handler = &swdt_handler + } +}; + +int32_t swdt_start(uint16_t count, uint8_t clk, + uint8_t expanded_clk, void (*cb)(void)) +{ + int32_t ret = SWDT_SUCCESS; + uint32_t reg; + uint32_t reg_WTCSRA = 0U; + uint32_t exceptions; + + /* parameter check */ + if (clk > SWDT_FREQ_EXPANDED || count == 0U) + ret = SWDT_ERR_PARAMETER; /* parameter error */ + + exceptions = cpu_spin_lock_xsave(&thread_global_lock); + if (ret == SWDT_SUCCESS && swdt_state != SWDT_STATE_NOACTIVE) + ret = SWDT_ERR_SEQUENCE; + + if (ret == SWDT_SUCCESS) { + swdt_is_ready(); + + swdt_count = count; + swdt_clk = clk; + swdt_expanded_clk = expanded_clk; + user_cb = cb; + + /* counter setting */ + swdt_initial_count = (0xFFFFU - count) + 1U; + io_write32(SWDT_SWTCNT, SWDT_SWTCNT_UPPER_BYTE + | swdt_initial_count); + + /* interrupt or reset setting */ + if (!cb) { /* reset route */ + /* Reset mask register setting */ + reg = io_read32(RST_WDTRSTCR) + & SWDT_WDTRSTCR_LOWER_BYTE; + reg &= ~RST_WDTRSTCR_RSTMSK; + io_write32(RST_WDTRSTCR, + reg | SWDT_WDTRSTCR_UPPER_BYTE); + } else { /* interrupt route */ + /* Reset mask register setting */ + reg = io_read32(RST_WDTRSTCR) + & SWDT_WDTRSTCR_LOWER_BYTE; + reg |= RST_WDTRSTCR_RSTMSK; + io_write32(RST_WDTRSTCR, + reg | SWDT_WDTRSTCR_UPPER_BYTE); + + interrupt_enable(swdt_itr->chip, swdt_itr[0].it); + + /* enable interrupt */ + reg_WTCSRA = SWDT_SWTCSRA_WOVFE; + } + + if (clk == SWDT_FREQ_EXPANDED) { + reg = io_read8(SWDT_SWTCSRB); + reg &= ~(uint32_t)SWDT_SWTCSRB_BIT_CKS; + reg |= SWDT_SWTCSRB_UPPER_BYTE | + ((uint32_t)expanded_clk & SWDT_SWTCSRB_BIT_CKS); + io_write32(SWDT_SWTCSRB, reg); + } + + /* start */ + reg_WTCSRA |= clk; + io_write32(SWDT_SWTCSRA, reg_WTCSRA | SWDT_SWTCSRA_UPPER_BYTE); + + reg = io_read8(SWDT_SWTCSRA); + reg |= SWDT_SWTCSRA_TME; + io_write32(SWDT_SWTCSRA, reg | SWDT_SWTCSRA_UPPER_BYTE); + + swdt_state = SWDT_STATE_ACTIVE; + } + cpu_spin_unlock_xrestore(&thread_global_lock, exceptions); + return ret; +} + +int32_t swdt_stop(void) +{ + uint32_t reg; + int32_t ret = SWDT_SUCCESS; + uint32_t exceptions; + + exceptions = cpu_spin_lock_xsave(&thread_global_lock); + if (swdt_state != SWDT_STATE_ACTIVE) { + ret = SWDT_ERR_SEQUENCE; + } else { + interrupt_disable(swdt_itr->chip, swdt_itr[0].it); + + reg = io_read8(SWDT_SWTCSRA); + reg &= ~SWDT_SWTCSRA_TME; + reg |= SWDT_SWTCSRA_UPPER_BYTE; + io_write32(SWDT_SWTCSRA, reg); + + /* Reset mask register setting */ + reg = io_read32(RST_WDTRSTCR) & SWDT_WDTRSTCR_LOWER_BYTE; + reg |= RST_WDTRSTCR_RSTMSK; + io_write32(RST_WDTRSTCR, reg | SWDT_WDTRSTCR_UPPER_BYTE); + + swdt_state = SWDT_STATE_NOACTIVE; + } + cpu_spin_unlock_xrestore(&thread_global_lock, exceptions); + return ret; +} + +int32_t swdt_kick(void) +{ + int32_t ret = SWDT_SUCCESS; + uint32_t exceptions; + + exceptions = cpu_spin_lock_xsave(&thread_global_lock); + if (swdt_state != SWDT_STATE_ACTIVE) { + ret = SWDT_ERR_SEQUENCE; + } else { + swdt_is_ready(); + io_write32(SWDT_SWTCNT, SWDT_SWTCNT_UPPER_BYTE + | swdt_initial_count); + } + cpu_spin_unlock_xrestore(&thread_global_lock, exceptions); + return ret; +} + +static TEE_Result swdt_init(void) +{ + uint32_t exceptions; + const char *init_msg; + + exceptions = cpu_spin_lock_xsave(&thread_global_lock); + if (swdt_init_flag == INIT_FLAG_UNINITIALIZED) { + interrupt_add_handler_with_chip(interrupt_get_main_chip(), + swdt_itr); + + /* SWDT has been initialized */ + swdt_init_flag = INIT_FLAG_INITIALIZED; + init_msg = "SWDT driver: initialized"; + } else { + init_msg = "SWDT driver: already initialized"; + } + cpu_spin_unlock_xrestore(&thread_global_lock, exceptions); + DMSG("%s\n", init_msg); + + return TEE_SUCCESS; +} + +static void swdt_itr_del(void) +{ + interrupt_remove_handler(swdt_itr); +} + +driver_init(swdt_init); diff --git a/core/arch/arm/plat-rcar_gen5/include/drivers/mfis.h b/core/arch/arm/plat-rcar_gen5/include/drivers/mfis.h new file mode 100644 index 00000000000..42fa5f968ee --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/include/drivers/mfis.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2026, Renesas Electronics Corporation. All rights reserved. + * + */ +#ifndef MFIS_H +#define MFIS_H + +/******************************************************************************/ +/* Definition */ +/******************************************************************************/ +typedef enum { +/* + * MFIS_TARGET_RPC = 0, + * MFIS_TARGET_RESERVED, + * MFIS_TARGET_UFS, + * MFIS_TARGET_OVERLAP_CHECK, + * MFIS_TARGET_MEASUREMENT, + * MFIS_TARGET_MAX, + */ + MFIS_TARGET_HSCIF, +} mfis_target_t; + +#define MFIS_LOCK_TIMEOUT (1000000U) + +/******************************************************************************/ +/* Prototype */ +/******************************************************************************/ +void rcar_mfis_init(void); +void rcar_mfis_lock(mfis_target_t target); +void rcar_mfis_unlock(mfis_target_t target); + +#endif /* MFIS_H */ diff --git a/core/arch/arm/plat-rcar_gen5/include/drivers/mfis_register.h b/core/arch/arm/plat-rcar_gen5/include/drivers/mfis_register.h new file mode 100644 index 00000000000..869fbec4111 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/include/drivers/mfis_register.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2026, Renesas Electronics Corporation. All rights reserved. + * + */ +#include + +#ifndef MFIS_REGISTER_H +#define MFIS_REGISTER_H + +/******************************************************************************/ +/* Definition */ +/******************************************************************************/ +/* MFIS_COMMON_BASE base address */ +#define MFIS_COMMON_BASE (MFIS_BASE) +/* MFIS lock 5 Register Address */ +#define MFIS_MFISLCKR5 (MFIS_COMMON_BASE + (0x000000D4uL)) +/* Write Protection Control Register */ +#define MFIS_MFISWPCNTR (MFIS_COMMON_BASE + (0x00000900uL)) +/* Write Access Control Register Address */ +#define MFIS_MFISWACNTR (MFIS_COMMON_BASE + (0x00000904uL)) + +/* MFISLCKR bit[0] (LCK) Mask */ +#define MFISLCKR_LCK_MASK (0x00000001uL) +/* MFISLCKR bit[0] (LCK) Mutex Control Forbidden Set */ +#define MFISLCKR_LCK_RELEASE_SET (0x00000000uL) +/* MFISLCKR bit[0] (LCK) Mutex acquired Check */ +#define MFISLCKR_LCK_ACQUIRED_CHECK (0x00000001uL) +/* MFISLCKR bit[0] (LCK) Mutex not acquired Check */ +#define MFISLCKR_LCK_NOT_ACQUIRED_CHECK (0x00000000uL) +/* MFISWPCNTR bit[31:16] (Code value) Set */ +#define MFISWPCNTR_CODEVALUE_SET (0xACCE0000uL) +/* MFISWPCNTR bit[0] (WPD): 0 - Enable write protect */ +#define MFISWPCNTR_WPD_UNSET (0x00000000uL) +/* MFISWPCNTR bit[0] (WPD): 1 - Disable write protect */ +#define MFISWPCNTR_WPD_SET (0x00000001uL) +/* MFISWACNTR bit[31:16] (Code value) Set */ +#define MFISWACNTR_CODEVALUE_SET (0xACCE0000uL) +/* MFISWACNTR bit[15:0] (RegisterAddress) Set */ +#define MFISWACNTR_REGISTERADDRESS_MASK (0x0000FFFFuL) + +/******************************************************************************/ +/* Prototype */ +/******************************************************************************/ + +#endif /* MFIS_REGISTER_H */ diff --git a/core/arch/arm/plat-rcar_gen5/include/drivers/swdt.h b/core/arch/arm/plat-rcar_gen5/include/drivers/swdt.h new file mode 100644 index 00000000000..83bc7f95d44 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/include/drivers/swdt.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2025, Renesas Electronics Corporation + */ + +#ifndef SWDT_DRIVER_H_ +#define SWDT_DRIVER_H_ + +#define SWDT_FREQ_OSC_DIV_1_1 (0U) +#define SWDT_FREQ_OSC_DIV_1_4 (1U) +#define SWDT_FREQ_OSC_DIV_1_16 (2U) +#define SWDT_FREQ_OSC_DIV_1_32 (3U) +#define SWDT_FREQ_OSC_DIV_1_64 (4U) +#define SWDT_FREQ_OSC_DIV_1_128 (5U) +#define SWDT_FREQ_OSC_DIV_1_1024 (6U) +#define SWDT_FREQ_EXPANDED (7U) + +#define SWDT_SUCCESS (0) +#define SWDT_ERR_PARAMETER (-1) +#define SWDT_ERR_SEQUENCE (-2) + +int32_t swdt_start(uint16_t count, uint8_t clk, + uint8_t expanded_clk, void (*cb)(void)); +int32_t swdt_stop(void); +int32_t swdt_kick(void); + +#endif /* SWDT_DRIVER_H_ */ diff --git a/core/arch/arm/plat-rcar_gen5/link.mk b/core/arch/arm/plat-rcar_gen5/link.mk new file mode 100644 index 00000000000..51fc371a86e --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/link.mk @@ -0,0 +1,5 @@ +include core/arch/arm/kernel/link.mk + +SRECFLAGS ?= --srec-forceS3 --adjust-vma=$(CFG_TZDRAM_START) + +all: $(link-out-dir)/tee.srec diff --git a/core/arch/arm/plat-rcar_gen5/main.c b/core/arch/arm/plat-rcar_gen5/main.c new file mode 100644 index 00000000000..94be1598c6b --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/main.c @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2025, Renesas Electronics Corporation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "drivers/comm_shared.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rcar_log_func.h" +#include "rcar-common.h" + +#ifdef MEMORY1_BASE +register_phys_mem_pgdir(MEMORY1_TYPE, MEMORY1_BASE, MEMORY1_SIZE); +#endif +#ifdef MEMORY2_BASE +register_phys_mem_pgdir(MEMORY2_TYPE, MEMORY2_BASE, MEMORY2_SIZE); +#endif +#ifdef MEMORY3_BASE +register_phys_mem_pgdir(MEMORY3_TYPE, MEMORY3_BASE, MEMORY3_SIZE); +#endif +#ifdef MEMORY4_BASE +register_phys_mem_pgdir(MEMORY4_TYPE, MEMORY4_BASE, MEMORY4_SIZE); +#endif +#ifdef MEMORY5_BASE +register_phys_mem_pgdir(MEMORY5_TYPE, MEMORY5_BASE, MEMORY5_SIZE); +#endif +#ifdef MEMORY6_BASE +register_phys_mem_pgdir(MEMORY6_TYPE, MEMORY6_BASE, MEMORY6_SIZE); +#endif +#ifdef MEMORY7_BASE +register_phys_mem_pgdir(MEMORY7_TYPE, MEMORY7_BASE, MEMORY7_SIZE); +#endif +#ifdef MEMORY8_BASE +register_phys_mem_pgdir(MEMORY8_TYPE, MEMORY8_BASE, MEMORY8_SIZE); +#endif +#ifdef DEVICE0_PA_BASE +register_phys_mem_pgdir(DEVICE0_TYPE, DEVICE0_PA_BASE, DEVICE0_SIZE); +#endif +#ifdef DEVICE1_PA_BASE +register_phys_mem_pgdir(DEVICE1_TYPE, DEVICE1_PA_BASE, DEVICE1_SIZE); +#endif + +/* + * Register non-secure DDR so core_mmu_nsec_ddr_is_defined() is true and + * OP-TEE advertises dynamic shared memory (required by the Xen OP-TEE + * mediator, otherwise EXCHANGE_CAPABILITIES is rejected and the kernel + * optee driver fails probe with "capabilities mismatch" / -EINVAL). High + * banks only - see platform_config.h. + */ +register_ddr(NSEC_DDR_0_BASE, NSEC_DDR_0_SIZE); +register_ddr(NSEC_DDR_1_BASE, NSEC_DDR_1_SIZE); +register_ddr(NSEC_DDR_2_BASE, NSEC_DDR_2_SIZE); +register_ddr(NSEC_DDR_3_BASE, NSEC_DDR_3_SIZE); +register_ddr(NSEC_DDR_4_BASE, NSEC_DDR_4_SIZE); +register_ddr(NSEC_DDR_5_BASE, NSEC_DDR_5_SIZE); +register_ddr(NSEC_DDR_6_BASE, NSEC_DDR_6_SIZE); +register_ddr(NSEC_DDR_7_BASE, NSEC_DDR_7_SIZE); + +#ifdef CFG_SCIF +static struct hscif_uart_data console_data __nex_bss; +#endif + +#ifdef PRR_BASE +uint32_t rcar_prr_value __nex_bss; +#endif + +uint32_t cpu_on_core_lock __nex_bss = (uint32_t)SPINLOCK_UNLOCK; +uint32_t cpu_on_core_bit __nex_bss; + +#ifdef RCAR_TRNG_BY_RSIPM_HWENGINE +volatile shared_flag_t *p_shared_flag; +volatile r_lsc_comm_payload_t *p_shared_payload; +volatile void *p_shared_data; +#endif + +static void main_secondary_init_gic(void); + +void main_secondary_init_gic(void) +{ + uint32_t exceptions; + uint32_t cpu_mask; + + DMSG("IN cpu_on_core_bit=0x%x, get_core_pos()=%lu", + cpu_on_core_bit, get_core_pos()); + exceptions = cpu_spin_lock_xsave(&cpu_on_core_lock); + + cpu_on_core_bit |= BIT32(get_core_pos()); + cpu_mask = cpu_on_core_bit; + + itr_set_all_cpu_on_mask(cpu_mask); + + cpu_spin_unlock_xrestore(&cpu_on_core_lock, exceptions); + DMSG("OUT cpu_mask=0x%x", cpu_mask); +} + +unsigned long thread_cpu_off_handler(unsigned long a0 __unused, + unsigned long a1 __unused) +{ + uint32_t exceptions; + uint32_t cpu_mask; + + DMSG("IN cpu_on_core_bit=0x%x, get_core_pos()=%lu", + cpu_on_core_bit, get_core_pos()); + exceptions = cpu_spin_lock_xsave(&cpu_on_core_lock); + + cpu_on_core_bit &= ~(BIT32(get_core_pos())); + cpu_mask = cpu_on_core_bit; + + itr_set_all_cpu_off_mask(cpu_mask); + + cpu_spin_unlock_xrestore(&cpu_on_core_lock, exceptions); + DMSG("OUT cpu_mask=0x%x", cpu_mask); + return 0; +} + +void plat_console_init(void) +{ +#ifdef CFG_SCIF + rcar_mfis_init(); + hscif_uart_init(&console_data, CONSOLE_UART_START); + register_serial_console(&console_data.chip); +#endif +} + +#ifdef CFG_RCAR_ROMAPI +/* Should only seed from a hardware random number generator */ +unsigned long plat_get_aslr_seed(void) +{ + unsigned long seed = 0; + + /* On RCAR we can get hw random bytes on early boot stages */ + if (crypto_rng_read(&seed, sizeof(seed))) + panic(); + + return seed; +} +#endif + +void boot_primary_init_intc(void) +{ + gic_init_v3(0, GICD_BASE, GICR_BASE); +#ifndef CFG_SCIF + /* Initialize logging feature */ + log_buf_init(); +#endif +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); + main_secondary_init_gic(); +} + +#ifdef CFG_WITH_SOFTWARE_PRNG /* using the SW RNG supported*/ +void plat_rng_init(void) +{ + TEE_Result res = TEE_SUCCESS; + TEE_Time t = { }; + + res = crypto_rng_init(&t, sizeof(t)); + if (res) { + EMSG("Failed to initialize RNG: %#" PRIx32, res); + panic(); + } +} +#endif /*END CFG_WITH_SOFTWARE_PRNG */ +/* Overriding the default __weak tee_entry_fast() */ +void tee_entry_fast(struct thread_smc_args *args) +{ + DMSG("IN args->a0=0x%lX", args->a0); +#ifdef CFG_NS_VIRTUALIZATION + if (args->a0 == OPTEE_SMC_ENABLE_SHM_CACHE) { +#else + if (args->a0 == OPTEE_SMC_GET_SHM_CONFIG && + args->a1 == SMC_RCAR_CMD && + args->a2 == NORMAL_WORLD_COMPLETE_INIT) { +#endif + is_normal_world_initialized = 1; + DMSG("Normal World was initialized"); + } + __tee_entry_fast(args); + DMSG("OUT Received SMC from Normal World"); +} + diff --git a/core/arch/arm/plat-rcar_gen5/platform_config.h b/core/arch/arm/plat-rcar_gen5/platform_config.h new file mode 100644 index 00000000000..56e30a5b6f5 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/platform_config.h @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2025, Renesas Electronics Corporation. + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#define RCAR_CACHE_LINE_SZ 64 +#define CFG_RCAR_GEN5 1 + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT RCAR_CACHE_LINE_SZ + +#if defined(CFG_RCAR_GEN5) +#define GICD_BASE 0x39000000 +#define GICR_BASE 0x39080000 + +#if CFG_RCAR_UART == 200 /* HSCIF0 */ +#define CONSOLE_UART_START 0xC0710000 +#endif +/* config for MMU mapping */ +#define RCAR_SRAM_BASE 0x8C400000 +#define TZDRAM_BASE RCAR_SRAM_BASE +#define TZDRAM_SIZE (0x02000000U) /* 1024*1024*32 */ + +#define TEE_RAM_START (RCAR_SRAM_BASE) /* TEE RAM address */ +#define TEE_RAM_SIZE (0x00300000U) /* TEE RAM size*/ + +#ifdef CFG_TEE_RAM_VA_SIZE +#ifdef CFG_WITH_PAGER +#define TEE_RAM_PH_SIZE TZSRAM_SIZE +#else +#define TEE_RAM_PH_SIZE TEE_RAM_SIZE +#endif +#endif + +#ifndef TEE_LOAD_ADDR +#define TEE_LOAD_ADDR TEE_RAM_START +#endif + +#define TA_RAM_START (TEE_RAM_START \ + + TEE_RAM_SIZE) /* TA RAM address */ +#define TA_RAM_SIZE (0x01400000U) /* TA RAM size */ +#define OPTEE_LOG_BASE (TA_RAM_START \ + + TA_RAM_SIZE) /* OP-TEE Log Area address */ +#define OPTEE_LOG_SIZE (0x900000U) /* OP-TEE Log Area address size */ +#define NONCACHE_WORK_BASE (OPTEE_LOG_BASE \ + + OPTEE_LOG_SIZE) /* Non Cache Area address */ +#define NONCACHE_WORK_SIZE (0x00100000U) /* Non Cache Area Size */ +#define TEE_SHMEM_START (NONCACHE_WORK_BASE \ + + 0x1D00000U) /* Share Memory address */ +#define TEE_SHMEM_SIZE (0x00100000U) /* Share Memory size */ +#define OPTEE_LOG_NS_BASE (TEE_SHMEM_START \ + + TEE_SHMEM_SIZE) /* OP-TEE Log Area NS addr */ +#define OPTEE_LOG_NS_SIZE (0x00014000U) /* OP-TEE Log Area NS size */ + +#define TA_VERIFICATION_BASE (0x10000000U) /* TA for verification a */ +#define TA_VERIFICATION_SIZE (0x00100000U) /* TA for verification size */ + +#define RSIPM_FW_SHMEM_BASE (0x18500000U) /* RSIPM FW Share Memory address */ +#define RSIPM_FW_SHMEM_SIZE (0x00100000U) /* RSIPM FW Share Memory size */ + +#define SYSSS_MAIN_REGION_0_BASE (0xC1320000) + +/* for Soc Register mapping function */ +#define MAP_DEVICE_REG_RCAR_BASE (0xC0400000) +#define MAP_DEVICE_REG_RCAR_SIZE (0x1FC00000) + +#define LIFEC_BASE (0x1C020000) /* Life Cycle address */ +#define PRR_BASE (0xFFF00000U) /* Product Register address */ +#define MFIS_BASE (0x189E0000U) /* MFIS address */ + +#define MEM_SECTION_SIZE (0x00100000U) +#define MEM_SECTION_MFIS_SIZE (0x00010000U) +#ifdef CFG_WITH_LPAE +#define MAX_XLAT_TABLES CFG_MMAP_REGIONS +#endif + +#define DEVICE0_PA_BASE ROUNDDOWN(LIFEC_BASE, CORE_MMU_PGDIR_SIZE) +#define DEVICE0_SIZE (MEM_SECTION_SIZE) +#define DEVICE0_TYPE MEM_AREA_IO_SEC +#define DEVICE0_PA_END (LIFEC_BASE + DEVICE0_SIZE) + +#define DEVICE1_PA_BASE ROUNDDOWN(GICD_BASE, CORE_MMU_PGDIR_SIZE) +#define DEVICE1_SIZE (MEM_SECTION_SIZE * 9) +#define DEVICE1_TYPE MEM_AREA_IO_SEC + +/* LOG Area for Secure World */ +#define MEMORY1_BASE ROUNDDOWN(OPTEE_LOG_BASE, MEM_SECTION_SIZE) +#define MEMORY1_SIZE (MEM_SECTION_SIZE) +#define MEMORY1_TYPE MEM_AREA_IO_SEC + +/* LOG Area for Normal World */ +#define MEMORY2_BASE ROUNDDOWN(OPTEE_LOG_NS_BASE, MEM_SECTION_SIZE) +#define MEMORY2_SIZE (OPTEE_LOG_NS_SIZE) +#define MEMORY2_TYPE MEM_AREA_RAM_NSEC + +/* HSCIF address map area */ + +/* + * ROUNDDOWN should not be used here, since MAP_DEVICE_REG_RCAR_SIZE is not + * power of 2. With previous implementation of ROUNDDOWN the value of the + * MEMORY3_BASE was unintentionally correctly calculated due to + * MAP_DEVICE_REG_RCAR_BASE and MAP_DEVICE_REG_RCAR_SIZE values. + * However, in new implementation of ROUNDDOWN the value is calculated + * incorrectly (with 28MiB shift from base). + * Moreover all necessary alignments are performed inside + * register_phys_mem_pgdir(). + */ +#define MEMORY3_BASE MAP_DEVICE_REG_RCAR_BASE +#define MEMORY3_SIZE (MAP_DEVICE_REG_RCAR_SIZE) +#define MEMORY3_TYPE MEM_AREA_IO_SEC +#define MEMORY3_PA_END (MAP_DEVICE_REG_RCAR_BASE + MEMORY3_SIZE) + +/* TA area for verification */ +#define MEMORY4_BASE ROUNDDOWN(TA_VERIFICATION_BASE, \ + MEM_SECTION_SIZE) +#define MEMORY4_SIZE (TA_VERIFICATION_SIZE) +#define MEMORY4_TYPE MEM_AREA_IO_SEC + +/* Product Register (PRR) */ +#define MEMORY5_BASE ROUNDDOWN(PRR_BASE, MEM_SECTION_SIZE) +#define MEMORY5_SIZE (MEM_SECTION_SIZE) +#define MEMORY5_TYPE MEM_AREA_IO_SEC + +/* Non Cache Stack Area */ +#define MEMORY6_BASE ROUNDDOWN(NONCACHE_WORK_BASE, \ + MEM_SECTION_SIZE) +#define MEMORY6_SIZE (MEM_SECTION_SIZE) +#define MEMORY6_TYPE MEM_AREA_IO_SEC + +/* ICU FW Share Memory Address Map */ +#define MEMORY7_BASE ROUNDDOWN(RSIPM_FW_SHMEM_BASE, MEM_SECTION_SIZE) +#define MEMORY7_SIZE (RSIPM_FW_SHMEM_SIZE) +#define MEMORY7_TYPE MEM_AREA_IO_SEC + +/* MFIS Address Map */ +#define MEMORY8_BASE ROUNDDOWN(MFIS_BASE, MEM_SECTION_MFIS_SIZE) +#define MEMORY8_SIZE (MEM_SECTION_SIZE) +#define MEMORY8_TYPE MEM_AREA_IO_SEC +#define MEMORY8_PA_END (MFIS_BASE + MEMORY8_SIZE) + +/* + * Non-secure DDR banks (host PA) used to advertise OP-TEE dynamic shared + * memory (OPTEE_SMC_SEC_CAP_DYNAMIC_SHM), required by the Xen OP-TEE + * mediator. + * + * Only the high DRAM banks (>=0x10_80000000) are registered: the low bank + * (0x40000000-0xC0000000) is full of OP-TEE static maps (TZDRAM/TEE RAM + * @0x8C400000, SoC reg block, ...) and firmware-reserved areas, and + * core_mmu_set_discovered_nsec_ddr() panics if non-secure DDR overlaps any + * such map. Guest RAM (DomD is 8 GiB) does not fit in the low bank and is + * placed by Xen in these high banks, so this still covers guest SHM + * buffers. Requires CFG_AUTO_MAX_PA_BITS=y (see conf.mk) so PAs >64GB are + * addressable. Banks follow r8a78000-ironhide-common.dtsi /memory. + */ +#define NSEC_DDR_0_BASE 0x1080000000ULL /* 2 GiB */ +#define NSEC_DDR_0_SIZE 0x80000000U +#define NSEC_DDR_1_BASE 0x1200000000ULL /* 4 GiB each below */ +#define NSEC_DDR_1_SIZE 0x100000000ULL +#define NSEC_DDR_2_BASE 0x1400000000ULL +#define NSEC_DDR_2_SIZE 0x100000000ULL +#define NSEC_DDR_3_BASE 0x1600000000ULL +#define NSEC_DDR_3_SIZE 0x100000000ULL +#define NSEC_DDR_4_BASE 0x1800000000ULL +#define NSEC_DDR_4_SIZE 0x100000000ULL +#define NSEC_DDR_5_BASE 0x1A00000000ULL +#define NSEC_DDR_5_SIZE 0x100000000ULL +#define NSEC_DDR_6_BASE 0x1C00000000ULL +#define NSEC_DDR_6_SIZE 0x100000000ULL +#define NSEC_DDR_7_BASE 0x1E00000000ULL +#define NSEC_DDR_7_SIZE 0x100000000ULL +#endif /* CFG_RCAR_GEN5 */ + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/core/arch/arm/plat-rcar_gen5/rcar-common.h b/core/arch/arm/plat-rcar_gen5/rcar-common.h new file mode 100644 index 00000000000..ccd62a06e11 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/rcar-common.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2025, Renesas Electronics Corporation + */ + +#ifndef RCAR_COMMON_H +#define RCAR_COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Convert a physical address to a virtual address with the + * MEM_AREA_IO_SEC attribute. + */ +#define p2v_ioadr(r, len) ((vaddr_t)(phys_to_virt((r), MEM_AREA_IO_SEC, (len)))) +#define p2v_regadr(r, len) ((phys_to_virt((r), MEM_AREA_IO_SEC, (len)))) + +/* RPC No specific to R-Car */ +#define TEE_RPC_DEBUG_LOG (0x3F000000U) + +/* Product Register */ +#define PRR p2v_ioadr(0xFFF00044U, MEMORY5_SIZE) + +/* Debug log output for test confirmation */ +#ifndef RCAR_TEST_LOG +#define TMSG(...) ((void)0) +#else +#define TMSG(...) trace_printf_helper(TRACE_DEBUG, true, __VA_ARGS__) +#endif /* RCAR_TEST_LOG */ + +/* + * Define the information of debug log that communicates between Normal + * World and Secure World. + */ +#define SMC_RCAR_CMD (12345U) + +#define NORMAL_WORLD_COMPLETE_INIT (1U) + +/* Declaration of global variables */ +extern uint32_t product_type; +extern const int8_t *product_name; +extern uint32_t prr_cut; +extern uint32_t cpu_on_core_lock; +extern uint32_t cpu_on_core_bit; + +/* Define a constant for the initialization flag */ +#define INIT_FLAG_UNINITIALIZED (0U) +#define INIT_FLAG_INITIALIZED (1U) + +#endif /* RCAR_COMMON_H */ diff --git a/core/arch/arm/plat-rcar_gen5/rcar_fw_security_service.c b/core/arch/arm/plat-rcar_gen5/rcar_fw_security_service.c new file mode 100644 index 00000000000..b250947e036 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/rcar_fw_security_service.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Renesas Electronics Corporation + */ + +#include "rcar_fw_security_service.h" +#include "drivers/comm_shared.h" +#include "drivers/comm.h" + +uint32_t fwss_secureboot_get_lcs(uint32_t *lcs_out) +{ + uint32_t ret; + generic_data_t *p_payload = (generic_data_t *)p_shared_data; + + /* Clear flag */ + p_shared_flag->flag = REQ_STATE_NONE; + + /* Set payload */ + p_payload->service_id = (uint8_t)SERVICE_ID_GET_LCS; + /* R_ROM_GetLcs: [OUT] return value */ + p_payload->param[0uL] = BOOTROM_API_RETURN_SB_RET_ERR_INTERNAL_FAIL; + /* R_ROM_GetLcs: [OUT] uint32_t *pLcs */ + p_payload->param[1uL] = 0uL; + p_shared_payload->service_result = SERVICE_RESULT_OK; + p_shared_payload->data_len = LCS_SIZE; + p_shared_payload->p_data = (void *)p_payload; + + /* trigger communication */ + r_comm_trigger_secure(p_payload, p_shared_payload->data_len); + + /* Check the results */ + if (p_shared_payload->service_result != SERVICE_RESULT_OK) { + EMSG("r_comm_trigger_secure() return 0x%x\r\n", + p_shared_payload->service_result); + ret = p_shared_payload->service_result; + } else { + ret = p_payload->param[0uL]; + *lcs_out = p_payload->param[1uL]; + } + + return ret; +} + +uint32_t fwss_secureboot_verify(uint32_t key_cert_addr, uint32_t cnt_cert_addr, + uint32_t extmac_addr, uint32_t *p_des_addr) +{ + uint32_t ret; + generic_data_t *p_payload = (generic_data_t *)p_shared_data; + + /* Clear flag */ + p_shared_flag->flag = REQ_STATE_NONE; + + /* Set payload */ + p_payload->service_id = (uint8_t)SERVICE_ID_SECURE_BOOT_VERIFY; + /* R_ROM_SecureBootVerify: [OUT] return value */ + p_payload->param[0uL] = BOOTROM_API_RETURN_SB_RET_ERR_INTERNAL_FAIL; + /* R_ROM_SecureBootVerify: [IN] uint32_t *pKeyCert */ + p_payload->param[1uL] = key_cert_addr; + /* R_ROM_SecureBootVerify: [IN] uint32_t *pContentCert */ + p_payload->param[2uL] = cnt_cert_addr; + /* R_ROM_SecureBootVerify: [IN] uint32_t *p_rekey */ + p_payload->param[3uL] = extmac_addr; + /* R_ROM_SecureBootVerify: [OUT] uint32_t *dest_addr */ + p_payload->param[4uL] = 0uL; + p_shared_payload->service_result = SERVICE_RESULT_OK; + p_shared_payload->p_data = (void *)p_payload; + + /* trigger communication */ + r_comm_trigger_secure(p_payload, sizeof(generic_data_t)); + + /* Check the results */ + if (p_shared_payload->service_result != SERVICE_RESULT_OK) { + EMSG("r_comm_trigger_secure() return 0x%x\r\n", + p_shared_payload->service_result); + ret = p_shared_payload->service_result; + } else { + ret = p_payload->param[0uL]; + if (p_des_addr != NULL) + p_des_addr = (uint32_t *) + (uintptr_t)p_payload->param[4uL]; + } + + return ret; +} + +uint32_t fwss_secureboot_decrypt(void) +{ + uint32_t ret; + generic_data_t *p_payload = (generic_data_t *)p_shared_data; + + /* Clear flag */ + p_shared_flag->flag = REQ_STATE_NONE; + + /* Set payload */ + p_payload->service_id = (uint8_t)SERVICE_ID_SECURE_BOOT_DECRYPT; + /* R_ROM_SecureBootDecrypt: [OUT] return value */ + p_payload->param[0uL] = BOOTROM_API_RETURN_SB_RET_ERR_INTERNAL_FAIL; + p_shared_payload->service_result = SERVICE_RESULT_OK; + p_shared_payload->p_data = (void *)p_payload; + + /* trigger communication */ + r_comm_trigger_secure(p_payload, sizeof(generic_data_t)); + + /* Check the results */ + if (p_shared_payload->service_result != SERVICE_RESULT_OK) { + EMSG("r_comm_trigger_secure() return 0x%x\r\n", + p_shared_payload->service_result); + ret = p_shared_payload->service_result; + } else { + ret = p_payload->param[0uL]; + } + + return ret; +} + +uint32_t fwss_secureboot_compare(uint32_t *p_hash_cert, uint32_t *p_hash_cal, + uint32_t hash_size) +{ + uint32_t ret; + generic_data_t *p_payload = (generic_data_t *)p_shared_data; + + /* Clear flag */ + p_shared_flag->flag = REQ_STATE_NONE; + + /* Set payload */ + p_payload->service_id = (uint8_t)SERVICE_ID_SECURE_BOOT_COMPARE; + /* R_ROM_SecureBootCompare: [OUT] return value */ + p_payload->param[0uL] = BOOTROM_API_RETURN_SB_RET_ERR_INTERNAL_FAIL; + + /* --------------------- Reserved -------------------- */ + p_payload->param[1uL] = NOT_USE; + p_payload->param[2uL] = NOT_USE; + p_payload->param[3uL] = NOT_USE; + p_payload->param[4uL] = NOT_USE; + p_payload->param[5uL] = NOT_USE; + p_payload->param[6uL] = NOT_USE; + p_payload->param[7uL] = NOT_USE; + /* --------------------------------------------------- */ + + /* R_ROM_SecureBootCompare: [OUT] uint32_t * hash_cert */ + p_payload->param[8uL] = 0uL; + p_payload->param[9uL] = 0uL; + p_payload->param[10uL] = 0uL; + p_payload->param[11uL] = 0uL; + p_payload->param[12uL] = 0uL; + p_payload->param[13uL] = 0uL; + p_payload->param[14uL] = 0uL; + p_payload->param[15uL] = 0uL; + /* --------------------------------------------------- */ + + /* R_ROM_SecureBootCompare: [OUT] uint32_t * hash_calc */ + p_payload->param[16uL] = 0uL; + p_payload->param[17uL] = 0uL; + p_payload->param[18uL] = 0uL; + p_payload->param[19uL] = 0uL; + p_payload->param[20uL] = 0uL; + p_payload->param[21uL] = 0uL; + p_payload->param[22uL] = 0uL; + p_payload->param[23uL] = 0uL; + /* -------------------------------------------------- */ + + /* R_ROM_SecureBootCompare: [IN] uint32_t hash_size */ + p_payload->param[24uL] = hash_size; + + p_shared_payload->service_result = SERVICE_RESULT_OK; + p_shared_payload->p_data = (void *)p_payload; + + /* trigger communication */ + r_comm_trigger_secure(p_payload, sizeof(generic_data_t)); + + /* Check the results */ + if (p_shared_payload->service_result != SERVICE_RESULT_OK) { + EMSG("r_comm_trigger_secure() return 0x%x\r\n", + p_shared_payload->service_result); + ret = p_shared_payload->service_result; + } else { + ret = p_payload->param[0uL]; + *p_hash_cert = p_payload->param[8uL]; + *p_hash_cal = p_payload->param[16uL]; + } + + return ret; +} diff --git a/core/arch/arm/plat-rcar_gen5/rcar_fw_security_service.h b/core/arch/arm/plat-rcar_gen5/rcar_fw_security_service.h new file mode 100644 index 00000000000..9c052fe8c22 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/rcar_fw_security_service.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Renesas Electronics Corporation + */ + +#ifndef RCAR_FW_SECURITY_SERVICE_H +#define RCAR_FW_SECURITY_SERVICE_H + +#include "rcar-common.h" + +#define SYSSS_MAIN_REGION_0_MODE1 p2v_regadr(SYSSS_MAIN_REGION_0_BASE + \ + 0x00001010, DEVICE0_SIZE) +#define MODE1_MD1_MASK (0x00000002uL) + +#define SERVICE_ID_GET_LCS (0x02uL) +#define SERVICE_ID_SECURE_BOOT_VERIFY (0x03uL) +#define SERVICE_ID_SECURE_BOOT_DECRYPT (0x04uL) +#define SERVICE_ID_SECURE_BOOT_COMPARE (0x05uL) + +#define LCS_SIZE (4uL) + +/* Return value of Secure Boot AP */ +#define BOOTROM_API_RETURN_ROM_OK (0x5356F000uL) +#define BOOTROM_API_RETURN_ROM_NO_NEED_DECRYPTION (0x53563C01uL) +#define BOOTROM_API_RETURN_ROM_ERR_PRIVILEGE_ERROR (0xACA96901uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_INTERNAL_FAIL (0xAAAA0000uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_INVALID_ARG (0xAAAA0001uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_UNSUPPORTED_FUNCTION (0xAAAA0002uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_MANI_INVALID_MAGIC (0xAAAA0100uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_MANI_UNSUPPORTED_VERSION (0xAAAA0101uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_MANI_OUT_OF_RANGE_LEN (0xAAAA0102uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_MANI_TLV_FIELD_ERR (0xAAAA0103uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_MANI_TLV_INVALID_LEN (0xAAAA0104uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_MANI_INVALID_IMAGE_LEN (0xAAAA0105uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_MANI_MISMATCH_SIGN_ALGORITHM \ + (0xAAAA0106uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_MANI_UNSUPPORTED_ALGORITHM \ + (0xAAAA0107uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_CRYPTO_FAIL (0xAAAA0200uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_CRYPTO_AUTH_FAIL (0xAAAA0201uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_CRYPTO_UNSUPPORTED_ALGORITHM \ + (0xAAAA0202uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_CRYPTO_PARAM_ERR (0xAAAA0204uL) +#define BOOTROM_API_RETURN_SB_RET_ERR_IMAGE_COMPARE_HASH (0xACA93C03uL) + +#define SERVICE_RESULT_OK (0x0uL) +#define NOT_USE (0x00000000uL) + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ + +uint32_t fwss_secureboot_get_lcs(uint32_t *lcs_out); +uint32_t fwss_secureboot_verify(uint32_t key_cert_addr, uint32_t cnt_cert_addr, + uint32_t extmac_addr, uint32_t *p_des_addr); +uint32_t fwss_secureboot_decrypt(void); +uint32_t fwss_secureboot_compare(uint32_t *p_hash_cert, uint32_t *p_hash_cal, + uint32_t hash_size); + +#endif /* RCAR_FW_SECURITY_SERVICE_H */ diff --git a/core/arch/arm/plat-rcar_gen5/rcar_log_func.c b/core/arch/arm/plat-rcar_gen5/rcar_log_func.c new file mode 100644 index 00000000000..b6b8883bec0 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/rcar_log_func.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2025, Renesas Electronics Corporation + */ + +#include +#include +#include +#include +#include + +#include "rcar_log_func.h" +#include "rcar-common.h" +#include "rcar_version.h" + +struct log_buf_header_t *log_secram_header __nex_data; +static int8_t *log_nonsec_ptr __nex_bss; +uint32_t log_spin_lock __nex_bss; +uint32_t cpu_id_run_log __nex_bss; +int32_t is_normal_world_initialized __nex_bss; +const int8_t version_of_renesas[] __section(".version") = + VERSION_OF_RENESAS; + +void log_buf_init(void) +{ + const int8_t secram_prefix[] = LOG_SEC_PREFIX; + int32_t i; + + /* initialize global variable */ + log_secram_header = (struct log_buf_header_t *) + phys_to_virt(OPTEE_LOG_BASE, MEM_AREA_IO_SEC, MEMORY1_SIZE); + log_nonsec_ptr = (int8_t *)core_mmu_get_va(OPTEE_LOG_NS_BASE, + MEM_AREA_RAM_NSEC, MEMORY2_SIZE); + log_spin_lock = (uint32_t)SPINLOCK_UNLOCK; + cpu_id_run_log = 0; + is_normal_world_initialized = 0; + + /* initialize SDRAM area */ + for (i = 0; i < LOG_SEC_PREFIX_LEN; i++) { + if (secram_prefix[i] != log_secram_header->prefix[i]) + break; + } + if (i < LOG_SEC_PREFIX_LEN || + log_secram_header->index >= LOG_AREA_MAX_SIZE) { + (void)memset((int8_t *)log_secram_header, + 0, sizeof(struct log_buf_header_t)); + (void)memcpy(log_secram_header->prefix, + secram_prefix, sizeof(log_secram_header->prefix)); + } + + IMSG("Logging RAM initialized. (%s)", core_v_str); +} + +void log_buf_write(const struct msg_block_t *msg_block, int32_t msg_block_num) +{ + int8_t *log_area = NULL; + uint32_t end_index; + size_t ram_wsize; + size_t total_wsize = 0U; + size_t index_wsize; + size_t head_wsize; + int32_t i; + + for (i = 0; i < msg_block_num; i++) { + if (!log_secram_header || + total_wsize >= LOG_AREA_MAX_SIZE) { + break; + } + if (!log_area) + log_area = (int8_t *)(&log_secram_header[1]); + ram_wsize = msg_block[i].size; + if ((total_wsize + ram_wsize) > LOG_AREA_MAX_SIZE) + ram_wsize = LOG_AREA_MAX_SIZE - total_wsize; + + end_index = log_secram_header->index + ram_wsize; + head_wsize = 0U; + + if (end_index > LOG_AREA_MAX_SIZE) + head_wsize = end_index - LOG_AREA_MAX_SIZE; + index_wsize = ram_wsize - head_wsize; + + (void)memcpy(&log_area[log_secram_header->index], + &msg_block[i].addr[0], index_wsize); + total_wsize += index_wsize; + + if (head_wsize > 0U) { + (void)memcpy(&log_area[0], + &msg_block[i].addr[index_wsize], head_wsize); + total_wsize += head_wsize; + log_secram_header->index = head_wsize; + } else { + log_secram_header->index += index_wsize; + if (log_secram_header->index == LOG_AREA_MAX_SIZE) + log_secram_header->index = 0U; + } + + if (log_secram_header->size < LOG_AREA_MAX_SIZE) + log_secram_header->size += index_wsize; + } +} + +#ifdef RCAR_DEBUG_LOG +void log_debug_send(const struct msg_block_t *msg_block, int32_t msg_block_num) +{ + static size_t send_log_size[CFG_TEE_CORE_NB_CORE] = {0U}; + struct thread_param params; + uint32_t cpu_id; + int8_t *log_area; + size_t log_offs = 0U; + size_t memcpy_size; + int32_t i; + uint32_t exceptions; + + exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + cpu_id = cpu_id_run_log; + thread_unmask_exceptions(exceptions); + + if (log_nonsec_ptr && cpu_id < CFG_TEE_CORE_NB_CORE) { + log_area = &log_nonsec_ptr[cpu_id * LOG_NS_CPU_AREA_SIZE]; + if ((send_log_size[cpu_id] + LOG_SEND_MAX_SIZE) < + LOG_NS_CPU_AREA_SIZE) { + if (send_log_size[cpu_id] > 0U) { + log_area[send_log_size[cpu_id]] = (int8_t)'\r'; + log_area += send_log_size[cpu_id] + 1U; + } + for (i = 0; i < msg_block_num; i++) { + memcpy_size = msg_block[i].size; + if ((log_offs + memcpy_size) > + LOG_SEND_MAX_SIZE) { + memcpy_size = LOG_SEND_MAX_SIZE - + log_offs; + } + (void)memcpy(&log_area[log_offs], + msg_block[i].addr, memcpy_size); + log_offs += memcpy_size; + } + log_area[log_offs] = (int8_t)'\0'; + (void)cache_operation(TEE_CACHEFLUSH, log_area, + LOG_NS_CPU_AREA_SIZE); + + if (send_log_size[cpu_id] == 0U) { + (void)memset(¶ms, 0, sizeof(params)); + params.attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; + params.u.value.a = cpu_id; + params.u.value.b = 0U; + + send_log_size[cpu_id] = log_offs; + + (void)thread_rpc_cmd(TEE_RPC_DEBUG_LOG, 1, + ¶ms); + + send_log_size[cpu_id] = 0U; + } else { + send_log_size[cpu_id] = log_offs + 1U; + } + } + } +} +#endif diff --git a/core/arch/arm/plat-rcar_gen5/rcar_log_func.h b/core/arch/arm/plat-rcar_gen5/rcar_log_func.h new file mode 100644 index 00000000000..504a2093ed2 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/rcar_log_func.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2025, Renesas Electronics Corporation + */ + +#ifndef RCAR_LOG_FUNC_H +#define RCAR_LOG_FUNC_H + +/* + * Constant definition + */ + +#define LOG_RAM_MAX_SIZE (81920U) +#define LOG_RAM_HEADER_SIZE (16U) +#define LOG_RAM_RESERVE_SIZE (64U) +#define LOG_AREA_MAX_SIZE (LOG_RAM_MAX_SIZE - \ + (LOG_RAM_HEADER_SIZE + LOG_RAM_RESERVE_SIZE)) +#define LOG_TIME_BUF_MAX_SIZE (31) +#define LOG_NS_CPU_AREA_SIZE (1024U) +#define LOG_SEC_PREFIX "SLOG" +#define LOG_SEC_PREFIX_LEN (4) +#define LOG_SEND_MAX_SIZE (256U) + +#define SECRAM_MSG_BLK_NUM (2) +#define SECRAM_IDX_TIME (0) +#define SECRAM_IDX_MESG (1) + +#define TRMLOG_MSG_BLK_NUM (3) +#define TRMLOG_IDX_PRFX (0) +#define TRMLOG_IDX_TIME (1) +#define TRMLOG_IDX_MESG (2) + +#ifdef RCAR_DEBUG_LOG +#define MSG_BLK_MAX_NUM TRMLOG_MSG_BLK_NUM +#else +#define MSG_BLK_MAX_NUM SECRAM_MSG_BLK_NUM +#endif /* RCAR_DEBUG_LOG */ + +/* + * Struct definition + */ + +struct log_buf_header_t { + int8_t prefix[LOG_SEC_PREFIX_LEN]; + uint32_t index; + uint32_t size; + uint32_t reserve; +}; + +struct msg_block_t { + const int8_t *addr; + size_t size; +}; + +/* + * Global variable declaration + */ + +extern struct log_buf_header_t *log_secram_header; +extern uint32_t log_spin_lock; +extern uint32_t cpu_id_run_log; +extern int32_t is_normal_world_initialized; + +/* + * Prototype declaration + */ +void log_buf_init(void); +void log_buf_write(const struct msg_block_t *msg_block, int32_t msg_block_num); +#ifdef RCAR_DEBUG_LOG +void log_debug_send(const struct msg_block_t *msg_block, int32_t msg_block_num); +#endif /* RCAR_DEBUG_LOG */ + +#endif /* RCAR_LOG_FUNC_H */ diff --git a/core/arch/arm/plat-rcar_gen5/rcar_ta_auth.c b/core/arch/arm/plat-rcar_gen5/rcar_ta_auth.c new file mode 100644 index 00000000000..a98d32e7186 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/rcar_ta_auth.c @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015-2024, Renesas Electronics Corporation + */ + +#include +#include +#include + +#include "rcar_ta_auth.h" +#include "platform_config.h" +#include "rcar_fw_security_service.h" +#include "drivers/comm_shared.h" +#include "drivers/comm.h" + +/* Declaration of internal function */ +static uint32_t get_cert_size(const uint32_t *cert_header); +static uint32_t get_object_size(const uint32_t *content_cert); +static uint64_t check_object_addr(const uint32_t *content_cert); +static uint32_t get_auth_mode(void); + +static uint32_t get_cert_size(const uint32_t *cert_header) +{ + sb_cert_t cert; + uint32_t cert_size = 0; + + /* Get TLV Length value */ + cert.base = (const uint32_t *)cert_header; + cert.tlv_length = (const uint32_t *) + (cert.base +(CERT_HEADER_SIZE / 4)); + + /* Calculate certificate size */ + cert_size = *(cert.tlv_length); + cert_size += CERT_HEADER_SIZE; + cert_size += TLV_LENGTH; + + return cert_size; +} + +static uint64_t check_object_addr(const uint32_t *content_cert) +{ + const uint32_t *p_cert_base = NULL; + uint32_t obj_addr = 0U; + + p_cert_base = content_cert; + p_cert_base += (CC_MAGIC_NUMBER / 4); + p_cert_base += (CC_CERT_VERSION / 4); + p_cert_base += (CC_FLAGS / 4); + p_cert_base += (CC_LOAD_ADDR / 4); + + obj_addr = *p_cert_base; + + return obj_addr; +} + +static uint32_t get_object_size(const uint32_t *content_cert) +{ + const uint32_t *p_cert_base; + uint32_t obj_size = 0U; + + p_cert_base = content_cert; + p_cert_base += (CC_MAGIC_NUMBER / 4); + p_cert_base += (CC_CERT_VERSION / 4); + p_cert_base += (CC_FLAGS / 4); + p_cert_base += (CC_LOAD_ADDR / 4); + p_cert_base += (CC_DEST_ADDR / 4); + + obj_size = *p_cert_base; + + return obj_size; +} + +static uint32_t get_auth_mode(void) +{ + uint32_t lcs; + uint32_t md; + uint32_t auth_mode = NORMAL_BOOT_MODE; + uint32_t ret; + + ret = fwss_secureboot_get_lcs(&lcs); + if (ret == BOOTROM_API_RETURN_ROM_OK) { + if (lcs == LCS_SE) { + /* LCS=SE + Secure boot */ + auth_mode = SECURE_BOOT_MODE; + } else { + md = io_read32((vaddr_t)SYSSS_MAIN_REGION_0_MODE1) + & MODE1_MD1_MASK; + if (md == 0U) { + /* MD01=0 => LCS=CM/DM + Secure boot */ + auth_mode = SECURE_BOOT_MODE; + } else { + /* MD01=1 => LCS=CM/DM + Normal boot */ + } + } + } else { + EMSG("fwss_secureboot_get_lcs() error"); + } + + return auth_mode; +} + +TEE_Result rcar_auth_ta_certificate(const struct shdr *key_cert, + struct shdr **secmem_ta, size_t ta_size) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t ret; + uint32_t key_cert_size; + uint32_t content_cert_size = 0U; + uint32_t object_size = 0U; + uint32_t auth_mode; + const uint32_t *content_cert = NULL; + struct shdr *fixed_ta = (struct shdr *)TA_VERIFICATION_BASE; + uint8_t *fixed_base = (uint8_t *)TA_VERIFICATION_BASE; + uint8_t *fixed_key_cert = (uint8_t *)TA_KEY_CERT_ADDR; + uint8_t *fixed_content_cert = (uint8_t *)TA_CONTENT_CERT_ADDR; + uint64_t object_addr; + size_t real_ta_size = 0U; + + uint8_t *p_rekey = NULL; + uint32_t *p_hash_cert = NULL; + uint32_t *p_hash_cal = NULL; + + /* Get SecureBoot KeyCertificate size */ + key_cert_size = get_cert_size((const uint32_t *)key_cert); + if ((key_cert_size == 0U) || (key_cert_size > TA_KEY_CERT_AREA_SIZE)) { + res = TEE_ERROR_SECURITY; + EMSG("key_cert_size error"); + goto out; + } + + /* Get SecureBoot ContentCertificate size */ + content_cert = (const uint32_t *)key_cert + (key_cert_size / 4); + content_cert_size = get_cert_size((const uint32_t *)content_cert); + if ((content_cert_size == 0U) || + (content_cert_size > TA_CONTENT_CERT_AREA_SIZE)) { + res = TEE_ERROR_SECURITY; + EMSG("content_cert_size error"); + goto out; + } + + /* Get object size */ + object_size = get_object_size(content_cert); + real_ta_size = ta_size - key_cert_size - content_cert_size; + if (object_size == 0U || object_size != real_ta_size) { + res = TEE_ERROR_SECURITY; + EMSG("object_size error"); + goto out; + } + + DMSG("Cert size: key_cert=0x%x content_cert=0x%x", + key_cert_size, content_cert_size); + DMSG("TA size: shdr+bin=0x%x real_ta=0x%lx", + object_size, real_ta_size); + + /* check the address of loading TA is the top of verification area */ + object_addr = check_object_addr(content_cert); + if (object_addr != TA_VERIFICATION_BASE) { + res = TEE_ERROR_SECURITY; + EMSG("object_addr error. addrr=0x%x", res); + goto out; + } + + /* + * Fixed memory map | TotalSize=TA_VERIFICATION_SIZE + * --------------------------------------------------------------- + * | TA object data area | TotalSize - [1] - [2] - [3] | + * | (signed header + binary) | | + * --------------------------------------------------------------- + * | Key Certificate area | [1]=TA_KEY_CERT_AREA_SIZE | + * --------------------------------------------------------------- + * | Content Certificate area | [2]=TA_CONTENT_CERT_AREA_SIZE | + * --------------------------------------------------------------- + * | RSIP-M FW shared area | [3]=RSIPM_FW_SHARED_AREA_SIZE | + * --------------------------------------------------------------- + */ + /* copy to fixed memory */ + (void)memcpy(fixed_base, + (const uint8_t *)content_cert + content_cert_size, + object_size); + (void)memcpy(fixed_key_cert, + (const uint8_t *)key_cert, + key_cert_size); + (void)memcpy(fixed_content_cert, + (const uint8_t *)content_cert, + content_cert_size); + + /* Initialize shared buffer */ + IMSG("START: Initialize shared buffer: %lx\r\n", + INTER_CORE_COMM_SHARED_MEM_ADDR); + r_comm_main_init(INTER_CORE_COMM_SHARED_MEM_ADDR); + IMSG("FINISHED: Initialize shared buffer: %lx\r\n", + INTER_CORE_COMM_SHARED_MEM_ADDR); + + auth_mode = get_auth_mode(); + if (auth_mode == SECURE_BOOT_MODE) { + p_rekey = (uint8_t *)calloc(REKEY_SIZE, sizeof(uint8_t)); + if (!p_rekey) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ret = fwss_secureboot_verify((uintptr_t)fixed_key_cert, + (uintptr_t)fixed_content_cert, + (uintptr_t)p_rekey, 0); + if (ret != BOOTROM_API_RETURN_ROM_OK) { + EMSG("Secure boot error: 0x%x", ret); + res = TEE_ERROR_SECURITY; + goto out; + } + + ret = fwss_secureboot_decrypt(); + if (ret != BOOTROM_API_RETURN_ROM_OK && + ret != BOOTROM_API_RETURN_ROM_NO_NEED_DECRYPTION) { + EMSG("Secure boot error: 0x%x", ret); + res = TEE_ERROR_SECURITY; + goto out; + } + + p_hash_cert = (uint32_t *)calloc( + HASH_INTEGRITY_CHECK_HASH_SIZE / 4, sizeof(uint32_t)); + p_hash_cal = (uint32_t *)calloc( + HASH_INTEGRITY_CHECK_HASH_SIZE / 4, sizeof(uint32_t)); + if (!p_hash_cert || !p_hash_cal) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ret = fwss_secureboot_compare((uint32_t *)p_hash_cert, + (uint32_t *)p_hash_cal, + HASH_INTEGRITY_CHECK_HASH_SIZE); + if (ret != BOOTROM_API_RETURN_ROM_OK) { + EMSG("Secure boot error: 0x%x", ret); + res = TEE_ERROR_SECURITY; + goto out; + } + + DMSG("Secure boot success!"); + *secmem_ta = fixed_ta; + } else { + DMSG("Normal boot"); + *secmem_ta = fixed_ta; + } + +out: + if (p_rekey) + free(p_rekey); + if (p_hash_cert) + free(p_hash_cert); + if (p_hash_cal) + free(p_hash_cal); + + return res; +} diff --git a/core/arch/arm/plat-rcar_gen5/rcar_ta_auth.h b/core/arch/arm/plat-rcar_gen5/rcar_ta_auth.h new file mode 100644 index 00000000000..caf5d618554 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/rcar_ta_auth.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2024 Renesas Electronics Corporation + */ + +#ifndef RCAR_TA_AUTH_H +#define RCAR_TA_AUTH_H + +#include +#include "tee_api_types.h" + +#define TA_KEY_CERT_AREA_SIZE (4096U) +#define TA_CONTENT_CERT_AREA_SIZE (4096U) +#define TA_CONTENT_CERT_ADDR (TA_VERIFICATION_BASE + \ + TA_VERIFICATION_SIZE - \ + TA_CONTENT_CERT_AREA_SIZE) +#define TA_KEY_CERT_ADDR (TA_CONTENT_CERT_ADDR - \ + TA_KEY_CERT_AREA_SIZE) + +#define SECURE_BOOT_MODE (0U) +#define NORMAL_BOOT_MODE (1U) + +#define LCS_SE (0xA55AAF50u) + +#define HASH_INTEGRITY_CHECK_HASH_SIZE (0x00000020u) + +#define CERT_HEADER_SIZE (32U) +#define REKEY_SIZE (20U) +#define TLV_LENGTH (4U) + +/* Define header KC */ +#define KC_MAGIC_NUMBER (4U) +#define KC_CERT_VERSION (4U) +#define KC_FLAGS (4U) +#define KC_RESERVED (20U) + +/* Define header CC */ +#define CC_MAGIC_NUMBER (4U) +#define CC_CERT_VERSION (4U) +#define CC_FLAGS (4U) +#define CC_LOAD_ADDR (4U) +#define CC_DEST_ADDR (4U) +#define CC_IMAGE_SIZE (4U) +#define CC_CODE_VERSION (8U) + +#define TYPE_KEYCERT (0U) +#define TYPE_CONTENTCERT (1U) + +/****************************************************************************** + * Typedefs & Enumerations + *****************************************************************************/ +typedef struct { + const uint32_t *base; + const uint32_t *header; /* Header field (32 bytes) */ + const uint32_t *tlv_length; /* TLV Length field */ +} sb_cert_t; + +TEE_Result rcar_auth_ta_certificate(const struct shdr *key_cert, + struct shdr **secmem_ta, size_t ta_size); + +#endif /* RCAR_TA_AUTH_H */ diff --git a/core/arch/arm/plat-rcar_gen5/rcar_trng.c b/core/arch/arm/plat-rcar_gen5/rcar_trng.c new file mode 100644 index 00000000000..9f766ec8545 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/rcar_trng.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2025, Renesas Electronics Corporation + */ +#include +#include +#include "platform_config.h" +#include "drivers/comm.h" +#include "rcar_trng.h" +#include "trace.h" +#include "drivers/comm_shared.h" + +void rsipm_communication(uint8_t *buf, uint32_t buf_len) +{ + generic_data_t *p_payload = (generic_data_t *)p_shared_data; + uint32_t *p_rng_out; + + /* Clear flag */ + p_shared_flag->flag = REQ_STATE_NONE; + + /* Set payload */ + p_payload->service_id = (uint8_t)SERVICE_ID_TRNG; + p_shared_payload->service_result = SERVICE_RESULT_OK; + p_shared_payload->data_len = buf_len; + p_shared_payload->p_data = (void *)p_payload; + + /* trigger communication */ + r_comm_trigger_secure(p_payload, p_shared_payload->data_len); + /* get the trng */ + p_rng_out = (uint32_t *)p_payload->param; + + (void)memcpy((uint8_t *)buf, (uint8_t *)p_rng_out, buf_len); +} + +void rsipm_trng_generate(uint8_t *buf, uint32_t buf_len) +{ + /* Initialize shared buffer */ + IMSG("START: Initialize shared buffer: %lx\r\n", + INTER_CORE_COMM_SHARED_MEM_ADDR); + r_comm_main_init(INTER_CORE_COMM_SHARED_MEM_ADDR); + IMSG("FINISHED: Initialize shared buffer: %lx\r\n", + INTER_CORE_COMM_SHARED_MEM_ADDR); + + /* Wait for Secure CPU initialization to complete */ + /* r_comm_wait_secure_cpu_init(SECURE_CPU_INIT_DONE); */ + + /* Notify the Secure CPU that initialization is complete */ + /* r_comm_set_status_main_to_sec(MAIN_CPU_INIT_DONE, 1); */ + + /* Trigger communication*/ + IMSG("START: Trigger communication with LLD\r\n"); + rsipm_communication(buf, buf_len); + IMSG("FINISHED: Trigger communication with LLD\r\n"); +} diff --git a/core/arch/arm/plat-rcar_gen5/rcar_trng.h b/core/arch/arm/plat-rcar_gen5/rcar_trng.h new file mode 100644 index 00000000000..3394cfd1c6d --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/rcar_trng.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2025, Renesas Electronics Corporation + */ + +#ifndef RCAR_TRNG_FUNC_H +#define RCAR_TRNG_FUNC_H + +#include + +/* + * Constant definition + */ +#define TRNG_MAX_WORD (128u) /* Size in bytes*/ +#define TRNG_BLOCK_SIZE (4u) + +/* Service ID */ +#define SERVICE_ID_TRNG (0x01uL) +#define SERVICE_RESULT_OK (0x0uL) + +/* + * Struct definition + */ + +/* + * Global variable declaration + */ + +/* + * Prototype declaration + */ + +void rsipm_trng_generate(uint8_t *buf, uint32_t buf_len); +void rsipm_communication(uint8_t *buf, uint32_t buf_len); + +#endif /* RCAR_TRNG_FUNC_H */ diff --git a/core/arch/arm/plat-rcar_gen5/rcar_version.c b/core/arch/arm/plat-rcar_gen5/rcar_version.c new file mode 100644 index 00000000000..aad536de521 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/rcar_version.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: BSD-2-Clause + /* + * Copyright (c) 2026, Renesas Electronics Corporation + */ + +#include +#include +#include + +/* + * brief: Parsing the value of RCar renesas version from string to number + * for transferring to the TEE Driver of the Normal World + * param[in] *versionString - pointer to the address where contains + * the revision value as string + * return version_t - return the version that contains the value + * as number(uint) of the revision + */ +static version_t convertVersion(const char *versionString) +{ + char *endptr; + version_t version = {0}; + + if (!versionString) + return version; + + version.major = (int)strtoul(versionString, &endptr, 10); + if (*endptr != '.') + return version; + version.minor = (int)strtoul(endptr + 1, &endptr, 10); + if (*endptr != '.') + return version; + version.patch = (int)strtoul(endptr + 1, &endptr, 10); + return version; +} + +/* + * brief: Getting the RCar BSP revision and start passing + * the value to the Normal World + * param[in/out] *args - pointer to the address where will contain + * the revision value as number for accessing + * from TEE Driver + */ +void tee_entry_get_rcar_bsp_revision(struct thread_smc_args *args) +{ + version_t version = {0}; + + /* Get the RCar revision */ + version = convertVersion(VERSION_OF_RENESAS); + + /* Passed revision value to TEE Drv */ + args->a0 = version.major; + args->a1 = version.minor; + args->a2 = version.patch; +} diff --git a/core/arch/arm/plat-rcar_gen5/rcar_version.h b/core/arch/arm/plat-rcar_gen5/rcar_version.h new file mode 100644 index 00000000000..1ccc54e7267 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/rcar_version.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2025, Renesas Electronics Corporation. + */ + +#ifndef RCAR_VERSION_H +#define RCAR_VERSION_H + +#include +#include + +#define VERSION_OF_RENESAS "1.3.1" + +/* Struct to store version */ +typedef struct { + uint64_t major; + uint64_t minor; + uint64_t patch; +} version_t; + +void tee_entry_get_rcar_bsp_revision(struct thread_smc_args *args); + +#endif /* RCAR_VERSION_H */ diff --git a/core/arch/arm/plat-rcar_gen5/sub.mk b/core/arch/arm/plat-rcar_gen5/sub.mk new file mode 100644 index 00000000000..6ed4fbcb55e --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/sub.mk @@ -0,0 +1,11 @@ +global-incdirs-y += . +global-incdirs-y += include +srcs-y += main.c +srcs-y += rcar_log_func.c +srcs-y += trace_ext.c +srcs-$(RCAR_TRNG_BY_RSIPM_HWENGINE) += rcar_trng.c +srcs-$(CFG_DYNAMIC_TA_AUTH_BY_HWENGINE) += rcar_ta_auth.c +srcs-$(CFG_DYNAMIC_TA_AUTH_BY_HWENGINE) += rcar_fw_security_service.c +srcs-y += rcar_version.c + +subdirs-y += drivers diff --git a/core/arch/arm/plat-rcar_gen5/trace_ext.c b/core/arch/arm/plat-rcar_gen5/trace_ext.c new file mode 100644 index 00000000000..1d1e50e8be1 --- /dev/null +++ b/core/arch/arm/plat-rcar_gen5/trace_ext.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2025, Renesas Electronics Corporation + */ +#include +#include +#include +#include +#include "rcar_log_func.h" +#include "rcar-common.h" + +#ifndef CFG_SCIF +const char trace_ext_prefix[] = "TEE-CORE"; +int trace_level = TRACE_LEVEL; + +void plat_trace_ext_puts(const char *str) +{ + int8_t time_buf[LOG_TIME_BUF_MAX_SIZE] = {0}; + size_t time_len = 0U; + TEE_Time sys_time = {0U, 0U}; + TEE_Result ret; + int32_t res; + struct msg_block_t msg_block[MSG_BLK_MAX_NUM]; + int32_t msg_block_num; + uint32_t exceptions; +#ifdef RCAR_DEBUG_LOG + static const int8_t TERM_LOG_PREFIX[] = "[OP-TEE]"; + const size_t TERM_LOG_PREFIX_LEN = sizeof(TERM_LOG_PREFIX) - 1U; + size_t log_sum_size = 0U; + int32_t i; +#endif + + if (str && log_secram_header) { + exceptions = cpu_spin_lock_xsave(&log_spin_lock); + cpu_id_run_log = (int32_t)get_core_pos(); + + ret = tee_time_get_sys_time(&sys_time); + if (ret == (TEE_Result)TEE_SUCCESS) { + res = snprintf((char *)time_buf, sizeof(time_buf), + "[%u.%06u][%d]", + sys_time.seconds, + sys_time.millis * 1000U, + cpu_id_run_log); + if (res > 0) + time_len = (size_t)res; + } + + msg_block[SECRAM_IDX_TIME].addr = time_buf; + msg_block[SECRAM_IDX_TIME].size = time_len; + msg_block[SECRAM_IDX_MESG].addr = (const int8_t *)str; + msg_block[SECRAM_IDX_MESG].size = strlen(str); + msg_block_num = SECRAM_MSG_BLK_NUM; + + log_buf_write(msg_block, msg_block_num); + + cpu_spin_unlock_xrestore(&log_spin_lock, exceptions); + +#ifdef RCAR_DEBUG_LOG + if (is_normal_world_initialized != 0) { + msg_block[TRMLOG_IDX_PRFX].addr = TERM_LOG_PREFIX; + msg_block[TRMLOG_IDX_PRFX].size = TERM_LOG_PREFIX_LEN; + msg_block[TRMLOG_IDX_TIME].addr = time_buf; + msg_block[TRMLOG_IDX_TIME].size = time_len; + msg_block[TRMLOG_IDX_MESG].addr = (const int8_t *)str; + msg_block[TRMLOG_IDX_MESG].size = strlen(str); + msg_block_num = TRMLOG_MSG_BLK_NUM; + + /* Log size is limited to 256 byte */ + for (i = 0; i < msg_block_num; i++) + log_sum_size += msg_block[i].size; + if (log_sum_size > (size_t)MAX_PRINT_SIZE) { + msg_block[msg_block_num - 1].size -= + log_sum_size - (uint32_t)MAX_PRINT_SIZE; + } + + if ((exceptions & + (uint32_t)THREAD_EXCP_NATIVE_INTR) == 0U) { + /* User context */ + log_debug_send(msg_block, msg_block_num); + } else { + /* Interrupt context */ + } + } +#endif + } +} + +#endif diff --git a/core/arch/arm/tee/entry_fast.c b/core/arch/arm/tee/entry_fast.c index addfc7e436e..5ddf5d5ef7e 100644 --- a/core/arch/arm/tee/entry_fast.c +++ b/core/arch/arm/tee/entry_fast.c @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef CFG_CORE_RESERVED_SHM static void tee_entry_get_shm_config(struct thread_smc_args *args) @@ -279,7 +280,10 @@ void __tee_entry_fast(struct thread_smc_args *args) tee_entry_get_os_uuid(args); break; case OPTEE_SMC_CALL_GET_OS_REVISION: - tee_entry_get_os_revision(args); + if (args->a6 == OPTEE_SMC_GET_RCAR_REVISION) + tee_entry_get_rcar_bsp_revision(args); + else + tee_entry_get_os_revision(args); break; /* OP-TEE specific SMC functions */ diff --git a/core/drivers/gic.c b/core/drivers/gic.c index af7783d326e..1272f1f7cea 100644 --- a/core/drivers/gic.c +++ b/core/drivers/gic.c @@ -48,7 +48,16 @@ #define GICD_ITARGETSR(n) (0x800 + (n) * 4) #define GICD_ICFGR(n) (0xc00 + (n) * 4) #define GICD_IGROUPMODR(n) (0xd00 + (n) * 4) +#define GICD_IROUTER(n) (0x6000 + (n) * 8) #define GICD_SGIR (0xF00) +/* Offsets from gic.gicd_base extend ID*/ +#define GICD_IGROUPR_E(n) (0x1000 + (n) * 4) +#define GICD_ICENABLER_E(n) (0x1400 + (n) * 4) +#define GICD_ICPENDR_E(n) (0x1800 + (n) * 4) +#define GICD_IGROUPMODR_E(n) (0x3400 + (n) * 4) +#define GICD_IPRIORITYR_E(n) (0x2000 + (n) * 4) +#define GICD_ISENABLER_E(n) (0x1200 + (n) * 4) +#define GICD_IROUTER_E(n) (0x8000 + (n) * 8) #ifdef _CFG_ARM_V3_OR_V4 #define GICD_PIDR2 (0xFFE8) @@ -112,11 +121,13 @@ /* Number of targets in one register */ #define NUM_TARGETS_PER_REG 4 -/* Accessors to access ITARGETSRn */ -#define ITARGETSR_FIELD_BITS 8 -#define ITARGETSR_FIELD_MASK 0xff +/* GICv3.1 extended SPIs INTIDs 4096 - 5119 */ +#define MIN_ESPI_ID 4096 +#define MAX_ESPI_ID 5119 #define GICD_TYPER_IT_LINES_NUM_MASK 0x1f +#define GICD_TYPER_ESPI_RANGE 0xf8000000 +#define GICD_TYPER_ESPI 0x100 #define GICC_IAR_IT_ID_MASK 0x3ff #define GICC_IAR_CPU_ID_MASK 0x7 #define GICC_IAR_CPU_ID_SHIFT 10 @@ -202,6 +213,8 @@ static size_t probe_max_it(vaddr_t gicc_base __maybe_unused, vaddr_t gicd_base) size_t ret = 0; size_t max_regs = io_read32(gicd_base + GICD_TYPER) & GICD_TYPER_IT_LINES_NUM_MASK; + size_t is_espi = io_read32(gicd_base + GICD_TYPER) & + GICD_TYPER_ESPI; /* * Probe which interrupt number is the largest. @@ -213,6 +226,28 @@ static size_t probe_max_it(vaddr_t gicc_base __maybe_unused, vaddr_t gicd_base) old_ctlr = io_read32(gicc_base + GICC_CTLR); io_write32(gicc_base + GICC_CTLR, 0); #endif + + if (is_espi) { + size_t max_regs_espi = (io_read32(gicd_base + GICD_TYPER) & + GICD_TYPER_ESPI_RANGE) >> 27; + uint32_t old_reg; + uint32_t reg; + int b; + + for (i = max_regs_espi; i >= 0; i--) { + old_reg = io_read32(gicd_base + GICD_ISENABLER_E(i)); + io_write32(gicd_base + GICD_ISENABLER_E(i), 0xffffffff); + reg = io_read32(gicd_base + GICD_ISENABLER_E(i)); + io_write32(gicd_base + GICD_ICENABLER_E(i), ~old_reg); + for (b = NUM_INTS_PER_REG - 1; b >= 0; b--) { + if (BIT32(b) & reg) { + ret = (i * NUM_INTS_PER_REG + b) + 4096; + goto out; + } + } + } + } + for (i = max_regs; i >= 0; i--) { uint32_t old_reg = 0; uint32_t reg = 0; @@ -269,6 +304,8 @@ static void gicv3_sync_redist_config(struct gic_data *gd) grp0 = io_read32(gicr_base + GICR_IGROUPR0); gmod0 = io_read32(gicr_base + GICR_IGRPMODR0); + gd->per_cpu_group_status = grp0; + gd->per_cpu_group_modifier = gmod0; for (n = GIC_SGI_SEC_BASE; n < GIC_SPI_BASE; n++) { /* Ignore matching bits */ if (!(BIT32(n) & (grp0 ^ gd->per_cpu_group_status)) && @@ -651,20 +688,28 @@ void gic_init_v3(paddr_t gicc_base_pa, paddr_t gicd_base_pa, static void gic_it_configure(struct gic_data *gd, size_t it) { - size_t idx = it / NUM_INTS_PER_REG; - uint32_t mask = 1 << (it % NUM_INTS_PER_REG); + bool is_espi = (it >= MIN_ESPI_ID) && (it <= MAX_ESPI_ID); + size_t idx = !is_espi ? it / NUM_INTS_PER_REG + : (it - MIN_ESPI_ID) / NUM_INTS_PER_REG; + uint32_t mask = 1 << (!is_espi ? it % NUM_INTS_PER_REG + : (it - MIN_ESPI_ID) % NUM_INTS_PER_REG); assert(gd == &gic_data); /* Disable the interrupt */ - io_write32(gd->gicd_base + GICD_ICENABLER(idx), mask); + io_write32(gd->gicd_base + (!is_espi ? GICD_ICENABLER(idx) + : GICD_ICENABLER_E(idx)), mask); /* Make it non-pending */ - io_write32(gd->gicd_base + GICD_ICPENDR(idx), mask); + io_write32(gd->gicd_base + (!is_espi ? GICD_ICPENDR(idx) + : GICD_ICPENDR_E(idx)), mask); /* Assign it to group0 */ - io_clrbits32(gd->gicd_base + GICD_IGROUPR(idx), mask); + io_clrbits32(gd->gicd_base + (!is_espi ? GICD_IGROUPR(idx) + : GICD_IGROUPR_E(idx)), mask); + #ifdef _CFG_ARM_V3_OR_V4 /* Assign it to group1S */ - io_setbits32(gd->gicd_base + GICD_IGROUPMODR(idx), mask); + io_setbits32(gd->gicd_base + (!is_espi ? GICD_IGROUPMODR(idx) + : GICD_IGROUPMODR_E(idx)), mask); #endif } @@ -695,18 +740,24 @@ static void gic_it_set_cpu_mask(struct gic_data *gd, size_t it, static void gic_it_set_prio(struct gic_data *gd, size_t it, uint8_t prio) { - size_t idx __maybe_unused = it / NUM_INTS_PER_REG; - uint32_t mask __maybe_unused = 1 << (it % NUM_INTS_PER_REG); + bool is_espi = (it >= MIN_ESPI_ID) && (it <= MAX_ESPI_ID); + size_t idx __maybe_unused = !is_espi ? it / NUM_INTS_PER_REG + : (it - MIN_ESPI_ID) / NUM_INTS_PER_REG; + uint32_t mask __maybe_unused = 1 << (!is_espi ? it % NUM_INTS_PER_REG + : (it - MIN_ESPI_ID) % NUM_INTS_PER_REG); assert(gd == &gic_data); /* Assigned to group0 */ - assert(!(io_read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask)); + assert(!(io_read32(gd->gicd_base + (!is_espi ? GICD_IGROUPR(idx) + : GICD_IGROUPR_E(idx))) & mask)); /* Set prio it to selected CPUs */ DMSG("prio: writing %#"PRIx8" to %#" PRIxVA, - prio, gd->gicd_base + GICD_IPRIORITYR(0) + it); - io_write8(gd->gicd_base + GICD_IPRIORITYR(0) + it, prio); + prio, gd->gicd_base + (!is_espi ? GICD_IPRIORITYR(0) + + it : GICD_IPRIORITYR_E(0) + (it - MIN_ESPI_ID))); + io_write8(gd->gicd_base + (!is_espi ? GICD_IPRIORITYR(0) + it + : GICD_IPRIORITYR_E(0) + (it - MIN_ESPI_ID)), prio); } static void gic_it_set_type(struct gic_data *gd, size_t it, uint32_t type) @@ -730,31 +781,41 @@ static void gic_it_set_type(struct gic_data *gd, size_t it, uint32_t type) static void gic_it_enable(struct gic_data *gd, size_t it) { - size_t idx = it / NUM_INTS_PER_REG; - uint32_t mask = 1 << (it % NUM_INTS_PER_REG); vaddr_t base = gd->gicd_base; + bool is_espi = (it >= MIN_ESPI_ID) && (it <= MAX_ESPI_ID); + size_t idx = !is_espi ? it / NUM_INTS_PER_REG + : (it - MIN_ESPI_ID) / NUM_INTS_PER_REG; + uint32_t mask = 1 << (!is_espi ? it % NUM_INTS_PER_REG + : (it - MIN_ESPI_ID) % NUM_INTS_PER_REG); assert(gd == &gic_data); /* Assigned to group0 */ - assert(!(io_read32(base + GICD_IGROUPR(idx)) & mask)); + assert(!(io_read32(base + (!is_espi ? GICD_IGROUPR(idx) + : GICD_IGROUPR_E(idx))) & mask)); /* Enable the interrupt */ - io_write32(base + GICD_ISENABLER(idx), mask); + io_write32(base + (!is_espi ? GICD_ISENABLER(idx) + : GICD_ISENABLER_E(idx)), mask); } static void gic_it_disable(struct gic_data *gd, size_t it) { - size_t idx = it / NUM_INTS_PER_REG; - uint32_t mask = 1 << (it % NUM_INTS_PER_REG); + bool is_espi = (it >= MIN_ESPI_ID) && (it <= MAX_ESPI_ID); + size_t idx = !is_espi ? it / NUM_INTS_PER_REG + : (it - MIN_ESPI_ID) / NUM_INTS_PER_REG; + uint32_t mask = 1 << (!is_espi ? it % NUM_INTS_PER_REG + : (it - MIN_ESPI_ID) % NUM_INTS_PER_REG); assert(gd == &gic_data); /* Assigned to group0 */ - assert(!(io_read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask)); + assert(!(io_read32(gd->gicd_base + (!is_espi ? GICD_IGROUPR(idx) + : GICD_IGROUPR_E(idx))) & mask)); /* Disable the interrupt */ - io_write32(gd->gicd_base + GICD_ICENABLER(idx), mask); + io_write32(gd->gicd_base + (!is_espi ? GICD_ICENABLER(idx) + : GICD_ICENABLER_E(idx)), mask); } static void gic_it_set_pending(struct gic_data *gd, size_t it) @@ -954,7 +1015,11 @@ static void __maybe_unused gic_native_itr_handler(void) uint32_t id = 0; iar = gic_read_iar(gd); - id = iar & GICC_IAR_IT_ID_MASK; + + if (affinity_routing_is_enabled(gd)) + id = iar; + else + id = iar & GICC_IAR_IT_ID_MASK; if (id >= 1020 && id <= 1023) { /* diff --git a/core/drivers/hscif.c b/core/drivers/hscif.c new file mode 100644 index 00000000000..e1faa115bbf --- /dev/null +++ b/core/drivers/hscif.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2025, Renesas Electronics Corporation + */ + +#include +#include +#include +#include +#include +#include +#include + +#define SCSCR_TE BIT(5) +#define SCFSR_TDFE BIT(5) +#define SCFSR_TEND BIT(6) + +#define SCFDR_T_SHIFT 8 + +#define SCIF_TX_FIFO_SIZE 16 + +static void hscif_uart_putc(struct serial_chip *chip, uint8_t outchar); +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct hscif_uart_data *pd = + container_of(chip, struct hscif_uart_data, chip); + + return io_pa_or_va(&pd->base, HSCIF_REG_SIZE); +} + +static void hscif_uart_flush(struct serial_chip __maybe_unused *chip) +{ +/* + * do not anything + */ +} + +static void hscif_uart_putc(struct serial_chip *chip, uint8_t outchar) +{ + static uint8_t remain; + bool mmu_enabled = cpu_mmu_enabled(); + + if (mmu_enabled) { + vaddr_t base = chip_to_base(chip); + + while (remain == 0) { + remain = 128 - (io_read16(base + HSCIF_HSFDR_OFFSET) + >> SCFDR_T_SHIFT); + if (remain < 64) + remain = 0; + else + remain -= 64; + } + /* Transfer one character */ + io_write8(base + HSCIF_HSFTDR_OFFSET, outchar); + } else { + /* Wait until there is space in the FIFO */ + while (remain == 0) { + remain = 128 - (io_read16(HSCIF_HSFDR) + >> SCFDR_T_SHIFT); + if (remain < 64) + remain = 0; + else + remain -= 64; + } + /* Transfer one character */ + io_write8(HSCIF_HSFTDR, outchar); + } + remain--; +} + +static const struct serial_ops hscif_uart_ops = { + .flush = hscif_uart_flush, + .putc = hscif_uart_putc, +}; + +DECLARE_KEEP_PAGER(hscif_uart_ops); + +void hscif_uart_init(struct hscif_uart_data *pd, paddr_t pbase) +{ + pd->base.pa = pbase; + pd->chip.ops = &hscif_uart_ops; + hscif_console_init(); + hscif_uart_flush(&pd->chip); +} + +void hscif_console_init(void) +{ + uint16_t reg; + + io_write16(HSCIF_HSSCR, HSCIF_SCSCR_HW_INIT); + reg = io_read16(HSCIF_HSSCR); + reg |= HSCIF_SCSCR_INIT_DATA; + io_write16(HSCIF_HSSCR, reg); + /* enable TE, RE; SC_CLK=no output */ + io_setbits16(HSCIF_HSSCR, SCSCR_TE); +} + diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk index 16166288c20..dc70e72b896 100644 --- a/core/drivers/sub.mk +++ b/core/drivers/sub.mk @@ -21,7 +21,7 @@ srcs-$(CFG_SPRD_UART) += sprd_uart.c srcs-$(CFG_HI16XX_UART) += hi16xx_uart.c srcs-$(CFG_HI16XX_RNG) += hi16xx_rng.c srcs-$(CFG_LPC_UART) += lpc_uart.c -srcs-$(CFG_SCIF) += scif.c +srcs-$(CFG_SCIF) += hscif.c srcs-$(CFG_DRA7_RNG) += dra7_rng.c srcs-$(CFG_STIH_UART) += stih_asc.c srcs-$(CFG_ATMEL_UART) += atmel_uart.c diff --git a/core/include/console.h b/core/include/console.h index c5962839e81..6fb87c102c1 100644 --- a/core/include/console.h +++ b/core/include/console.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited + * Copyright (c) 2025, Renesas Electronics Corporation */ #ifndef __CONSOLE_H @@ -11,7 +12,7 @@ void console_init(void); -void console_putc(int ch); +void console_putc(uint8_t ch); void console_flush(void); void plat_console_init(void); diff --git a/core/include/drivers/gic.h b/core/include/drivers/gic.h index a17dbac0cef..0a9cce866ec 100644 --- a/core/include/drivers/gic.h +++ b/core/include/drivers/gic.h @@ -68,6 +68,10 @@ /* Default IRQ priority for SPIs in Non-Sec EL1 */ #define GIC_SPI_PRI_NS_EL1 0x50 +/* Accessors to access ITARGETSRn */ +#define ITARGETSR_FIELD_BITS 8 +#define ITARGETSR_FIELD_MASK 0xff + /* * The two gic_init() and gic_init_v3() functions initializes the struct * gic_data which is then used by the other functions. These two functions diff --git a/core/include/drivers/hscif.h b/core/include/drivers/hscif.h new file mode 100644 index 00000000000..57a54a10eb7 --- /dev/null +++ b/core/include/drivers/hscif.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2025, Renesas Electronics Corporation + */ + +#ifndef __DRIVERS_HSCIF_H +#define __DRIVERS_HSCIF_H + +#include +#include + +#define HSCIF_REG_SIZE 0x1000 + +struct hscif_uart_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void hscif_uart_init(struct hscif_uart_data *pd, paddr_t base); +void hscif_console_init(void); +#endif /* __DRIVERS_HSCIF_H */ diff --git a/core/include/drivers/hscif_register.h b/core/include/drivers/hscif_register.h new file mode 100644 index 00000000000..75d56136c23 --- /dev/null +++ b/core/include/drivers/hscif_register.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2025, Renesas Electronics Corporation + */ + +#include +#ifndef HSCIF_REGISTER_H_ +#define HSCIF_REGISTER_H_ + +/* define macros */ +#define HSCIF_SCSCR_TE_EN ((uint16_t)((uint16_t)1U << 5U)) +#define HSCIF_SCSCR_RE_EN ((uint16_t)((uint16_t)1U << 4U)) +#define HSCIF_SCSCR_INIT_DATA ((uint16_t)(HSCIF_SCSCR_TE_EN \ + | HSCIF_SCSCR_RE_EN)) +#define HSCIF_SCSCR_HW_INIT ((uint16_t)(0x0000U)) +/* HSCIF0 base address */ +#define HSCIF0_BASE (0xC0710000U) + +#define HSCIF_HSSMR (HSCIF0_BASE + 0x0000U) /* 16 Serial mode register */ +#define HSCIF_HSBRR (HSCIF0_BASE + 0x0004U) /* 8 Bit rate register */ +#define HSCIF_HSSCR (HSCIF0_BASE + 0x0008U) /* 16 Serial control register */ +#define HSCIF_HSFTDR (HSCIF0_BASE + 0x000CU) /* 8 Transmit FIFO data register */ +#define HSCIF_HSFSR (HSCIF0_BASE + 0x0010U) /* 16 Serial status register */ +#define HSCIF_HSFCR (HSCIF0_BASE + 0x0018U) /* 16 FIFO control register */ +#define HSCIF_HSFDR (HSCIF0_BASE + 0x001CU) /* 16 FIFO Data count register */ +#define HSCIF_HSLSR (HSCIF0_BASE + 0x0024U) /* 16 Line status register */ +#define HSCIF_DL (HSCIF0_BASE + 0x0030U) /* 16 Frequency division register */ +#define HSCIF_CKS (HSCIF0_BASE + 0x0034U) /* 16 Clock Select register */ +#define HSCIF_HSSRR (HSCIF0_BASE + 0x0040U) /* 16 Sampling rate register */ + +/*Define some macro after enable mmu*/ +#define HSCIF_HSFDR_OFFSET (0x001CU) /* 16 FIFO Data count register */ +#define HSCIF_HSFTDR_OFFSET (0x000CU) /* 8 Transmit FIFO data register */ +#endif /* HSCIF_REGISTER_H_ */ diff --git a/core/include/drivers/serial.h b/core/include/drivers/serial.h index 2a1e07482b8..67b21fffe09 100644 --- a/core/include/drivers/serial.h +++ b/core/include/drivers/serial.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2025, Renesas Electronics Corporation */ #ifndef __DRIVERS_SERIAL_H #define __DRIVERS_SERIAL_H @@ -17,7 +18,7 @@ struct serial_chip { struct serial_ops { /* Mandatory handler */ - void (*putc)(struct serial_chip *chip, int ch); + void (*putc)(struct serial_chip *chip, uint8_t ch); /* Optional handlers */ void (*flush)(struct serial_chip *chip); bool (*have_rx_data)(struct serial_chip *chip); diff --git a/core/include/kernel/interrupt.h b/core/include/kernel/interrupt.h index 57979c052d2..fb4bc7650cc 100644 --- a/core/include/kernel/interrupt.h +++ b/core/include/kernel/interrupt.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2019, Linaro Limited + * Copyright (c) 2025, Renesas Electronics Corporation */ #ifndef __KERNEL_INTERRUPT_H #define __KERNEL_INTERRUPT_H @@ -570,4 +571,10 @@ static inline TEE_Result interrupt_dt_get(const void *fdt, int node, { return interrupt_dt_get_by_index(fdt, node, 0, chip, itr_num); } + +#ifdef PLATFORM_rcar_gen5 +void itr_set_all_cpu_on_mask(uint32_t cpu_mask); +void itr_set_all_cpu_off_mask(uint32_t cpu_mask); +#endif + #endif /*__KERNEL_INTERRUPT_H*/ diff --git a/core/include/tee/tee_svc_cryp.h b/core/include/tee/tee_svc_cryp.h index 526d6e69842..9fd3d5160b8 100644 --- a/core/include/tee/tee_svc_cryp.h +++ b/core/include/tee/tee_svc_cryp.h @@ -58,6 +58,8 @@ TEE_Result syscall_cryp_derive_key(unsigned long state, TEE_Result syscall_cryp_random_number_generate(void *buf, size_t blen); +TEE_Result syscall_rsipm_trng_generate(uint8_t *buf, uint32_t blen); + TEE_Result syscall_authenc_init(unsigned long state, const void *nonce, size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len); diff --git a/core/kernel/console.c b/core/kernel/console.c index 7558f76a803..871a901d194 100644 --- a/core/kernel/console.c +++ b/core/kernel/console.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited + * Copyright (c) 2025, Renesas Electronics Corporation */ #include @@ -35,7 +36,7 @@ void console_init(void) plat_console_init(); } -void __weak console_putc(int ch) +void __weak console_putc(uint8_t ch) { if (!serial_console) return; diff --git a/core/kernel/interrupt.c b/core/kernel/interrupt.c index 22021273474..f41a5ee583a 100644 --- a/core/kernel/interrupt.c +++ b/core/kernel/interrupt.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2019, Linaro Limited + * Copyright (c) 2025, Renesas Electronics Corporation */ #include @@ -11,6 +12,7 @@ #include #include #include +#include /* * NOTE! @@ -388,3 +390,31 @@ TEE_Result interrupt_dt_get_by_name(const void *fdt, int node, const char *name, return interrupt_dt_get_by_index(fdt, node, idx, chip, itr_num); } #endif /*CFG_DT*/ + +#ifdef PLATFORM_rcar_gen5 +void itr_set_all_cpu_on_mask(uint32_t cpu_mask) +{ + struct itr_handler *h; + + while ((cpu_mask & ITARGETSR_FIELD_MASK) == 0xff) + cpu_mask = cpu_mask >> ITARGETSR_FIELD_BITS; + + SLIST_FOREACH(h, &itr_main_chip->handlers, link) { + itr_main_chip->ops->set_affinity(itr_main_chip, + h->it, cpu_mask); + } +} + +void itr_set_all_cpu_off_mask(uint32_t cpu_mask) +{ + struct itr_handler *h; + + while (((cpu_mask != 0) && (cpu_mask & ITARGETSR_FIELD_MASK) == 0)) + cpu_mask = cpu_mask >> ITARGETSR_FIELD_BITS; + + SLIST_FOREACH(h, &itr_main_chip->handlers, link) { + itr_main_chip->ops->set_affinity(itr_main_chip, + h->it, cpu_mask); + } +} +#endif diff --git a/core/kernel/ree_fs_ta.c b/core/kernel/ree_fs_ta.c index 94f8a5eacbb..5a82a80e6c4 100644 --- a/core/kernel/ree_fs_ta.c +++ b/core/kernel/ree_fs_ta.c @@ -57,6 +57,10 @@ #include #include +#ifdef RCAR_DYNAMIC_TA_AUTH_BY_HWENGINE +#include "rcar_ta_auth.h" +#endif + struct ree_fs_ta_handle { struct shdr *nw_ta; /* Non-secure (shared memory) */ size_t nw_ta_size; @@ -79,6 +83,9 @@ struct ver_db_hdr { uint32_t nb_entries; }; +#if !defined(PLATFORM_rcar_gen5) || \ + (!defined(CFG_RCAR_UNSUPPORT_TA_VER_DB) && \ + !defined(RCAR_DYNAMIC_TA_AUTH_BY_HWENGINE)) static const char ta_ver_db[] = "ta_ver.db"; static const char subkey_ver_db[] = "subkey_ver.db"; static struct mutex ver_db_mutex = MUTEX_INITIALIZER; @@ -188,6 +195,7 @@ static TEE_Result check_update_version(const char *db_name, mutex_unlock(&ver_db_mutex); return res; } +#endif /* * Load a TA via RPC with UUID defined by input param @uuid. The virtual @@ -267,6 +275,12 @@ static TEE_Result ree_fs_ta_open(const TEE_UUID *uuid, if (res != TEE_SUCCESS) goto error; +#ifdef RCAR_DYNAMIC_TA_AUTH_BY_HWENGINE + res = rcar_auth_ta_certificate(ta, &ta, ta_size); + if (res != TEE_SUCCESS) + goto error_free_payload; +#endif + /* Make secure copy of signed header */ shdr = shdr_alloc_and_copy(0, ta, ta_size); if (!shdr) { @@ -310,9 +324,12 @@ static TEE_Result ree_fs_ta_open(const TEE_UUID *uuid, max_depth = pub_key.max_depth; memcpy(next_uuid, pub_key.next_uuid, sizeof(TEE_UUID)); next_uuid_ptr = next_uuid; - +#if !defined(PLATFORM_rcar_gen5) || \ + (!defined(CFG_RCAR_UNSUPPORT_TA_VER_DB) && \ + !defined(RCAR_DYNAMIC_TA_AUTH_BY_HWENGINE)) res = check_update_version(subkey_ver_db, pub_key.uuid, pub_key.version); +#endif if (res) { res = TEE_ERROR_SECURITY; shdr_free_pub_key(&pub_key); @@ -369,6 +386,7 @@ static TEE_Result ree_fs_ta_open(const TEE_UUID *uuid, * Initialize a hash context and run the algorithm over the signed * header (less the final file hash and its signature of course) */ +#ifndef RCAR_DYNAMIC_TA_AUTH_BY_HWENGINE res = crypto_hash_alloc_ctx(&hash_ctx, TEE_DIGEST_HASH_TO_ALGO(shdr->algo)); if (res != TEE_SUCCESS) @@ -379,7 +397,7 @@ static TEE_Result ree_fs_ta_open(const TEE_UUID *uuid, res = crypto_hash_update(hash_ctx, (uint8_t *)shdr, sizeof(*shdr)); if (res != TEE_SUCCESS) goto error_free_hash; - +#endif if (shdr->img_type == SHDR_BOOTSTRAP_TA || shdr->img_type == SHDR_ENCRYPTED_TA) { TEE_UUID bs_uuid = { }; @@ -409,15 +427,16 @@ static TEE_Result ree_fs_ta_open(const TEE_UUID *uuid, res = TEE_ERROR_SECURITY; goto error_free_hash; } - +#ifndef RCAR_DYNAMIC_TA_AUTH_BY_HWENGINE res = crypto_hash_update(hash_ctx, (uint8_t *)bs_hdr, sizeof(*bs_hdr)); if (res != TEE_SUCCESS) goto error_free_hash; +#endif offs += sizeof(*bs_hdr); handle->bs_hdr = bs_hdr; } - +#ifndef RCAR_DYNAMIC_TA_AUTH_BY_HWENGINE if (shdr->img_type == SHDR_ENCRYPTED_TA) { struct shdr_encrypted_ta img_ehdr = { }; size_t sz = shdr_sz; @@ -476,7 +495,7 @@ static TEE_Result ree_fs_ta_open(const TEE_UUID *uuid, res = TEE_ERROR_SECURITY; goto error_free_hash; } - +#endif handle->nw_ta = ta; handle->nw_ta_size = ta_size; handle->offs = offs; @@ -528,6 +547,7 @@ static TEE_Result ree_fs_ta_get_tag(const struct ts_store_handle *h, return TEE_SUCCESS; } +#ifndef RCAR_DYNAMIC_TA_AUTH_BY_HWENGINE static TEE_Result check_digest(struct ree_fs_ta_handle *h) { void *digest = NULL; @@ -548,6 +568,7 @@ static TEE_Result check_digest(struct ree_fs_ta_handle *h) free(digest); return res; } +#endif static TEE_Result ree_fs_ta_read(struct ts_store_handle *h, void *data_core, void *data_user, size_t len) @@ -596,12 +617,15 @@ static TEE_Result ree_fs_ta_read(struct ts_store_handle *h, void *data_core, } else { memcpy(dst, src + num_bytes, n); } - +#ifdef RCAR_DYNAMIC_TA_AUTH_BY_HWENGINE + res = TEE_SUCCESS; +#else res = crypto_hash_update(handle->hash_ctx, dst, n); if (res) { res = TEE_ERROR_SECURITY; goto out; } +#endif if (data_user) { res = copy_to_user((uint8_t *)data_user + num_bytes, dst, n); @@ -614,6 +638,7 @@ static TEE_Result ree_fs_ta_read(struct ts_store_handle *h, void *data_core, } handle->offs = next_offs; +#ifndef RCAR_DYNAMIC_TA_AUTH_BY_HWENGINE if (handle->offs == handle->nw_ta_size) { if (handle->shdr->img_type == SHDR_ENCRYPTED_TA) { /* @@ -634,12 +659,14 @@ static TEE_Result ree_fs_ta_read(struct ts_store_handle *h, void *data_core, res = check_digest(handle); if (res != TEE_SUCCESS) goto out; - +#if !defined(PLATFORM_rcar_gen5) || !defined(CFG_RCAR_UNSUPPORT_TA_VER_DB) if (handle->bs_hdr) res = check_update_version(ta_ver_db, handle->bs_hdr->uuid, handle->bs_hdr->ta_version); +#endif } +#endif out: bb_free(bb, bb_len); return res; diff --git a/core/kernel/scall.c b/core/kernel/scall.c index 4d8869fd768..c94b50636ec 100644 --- a/core/kernel/scall.c +++ b/core/kernel/scall.c @@ -117,6 +117,7 @@ static const struct syscall_entry tee_syscall_table[] = { SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_cache_operation), + SYSCALL_ENTRY(syscall_rsipm_trng_generate), }; /* diff --git a/core/kernel/trace_ext.c b/core/kernel/trace_ext.c index cf61af736f9..553df7f1cc4 100644 --- a/core/kernel/trace_ext.c +++ b/core/kernel/trace_ext.c @@ -11,9 +11,11 @@ #include #include #include +#include +#include -const char trace_ext_prefix[] = "TC"; -int trace_level __nex_data = TRACE_LEVEL; +const char __weak trace_ext_prefix[] = "TC"; +int __weak trace_level __nex_data = TRACE_LEVEL; static unsigned int puts_lock __nex_bss = SPINLOCK_UNLOCK; /* @@ -86,8 +88,18 @@ void trace_ext_puts(const char *str) was_contended = wait_if_trace_contended(&itr_status); +#ifndef CFG_SCIF + release_trace_contention(itr_status); +#else + rcar_mfis_lock(MFIS_TARGET_HSCIF); +#endif + plat_trace_ext_puts(str); +#ifndef CFG_SCIF + return; +#endif + console_flush(); if (was_contended) @@ -98,6 +110,10 @@ void trace_ext_puts(const char *str) console_flush(); +#ifdef CFG_SCIF + rcar_mfis_unlock(MFIS_TARGET_HSCIF); +#endif + release_trace_contention(itr_status); } diff --git a/core/mm/core_mmu.c b/core/mm/core_mmu.c index 8e2f81df3e8..d1b63b489dd 100644 --- a/core/mm/core_mmu.c +++ b/core/mm/core_mmu.c @@ -3,6 +3,7 @@ * Copyright (c) 2016-2025 Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2025, Renesas Electronics Corporation */ #include @@ -21,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -950,6 +952,7 @@ static bool __maybe_unused map_is_pgdir(const struct tee_mmap_region *mm) return mm->region_size == CORE_MMU_PGDIR_SIZE; } +#ifndef RCAR_MMU_DIRECT_MAPPING static int cmp_mmap_by_lower_va(const void *a, const void *b) { const struct tee_mmap_region *mm_a = a; @@ -957,6 +960,7 @@ static int cmp_mmap_by_lower_va(const void *a, const void *b) return CMP_TRILEAN(mm_a->va, mm_b->va); } +#endif static void dump_mmap_table(struct memory_map *mem_map) { @@ -1289,6 +1293,18 @@ static bool assign_mem_va_dir(vaddr_t tee_ram_va, struct memory_map *mem_map, vaddr_t va = 0; size_t n = 0; +#ifdef RCAR_MMU_DIRECT_MAPPING + const paddr_t direct_map_area[][2] = { + { MEMORY4_BASE, MEMORY4_SIZE }, /* TA area for verification */ + { MEMORY7_BASE, MEMORY7_SIZE } /* RSIP-M FW Share Memory */ + }; + const size_t dmnum = sizeof(direct_map_area) / sizeof(paddr_t) / 2; + size_t last; + paddr_t dmaddr; + paddr_t dmsize; + paddr_t rd; + bool va_is_direct = false; +#endif /* * tee_ram_va might equals 0 when CFG_CORE_ASLR=y. * 0 is by design an invalid va, so return false directly. @@ -1323,6 +1339,9 @@ static bool assign_mem_va_dir(vaddr_t tee_ram_va, struct memory_map *mem_map, } if (tee_ram_at_top) { +#ifdef RCAR_MMU_DIRECT_MAPPING + panic(); /*Direct mapping is not supported*/ +#endif /* * Map non-tee ram regions at addresses lower than the tee * ram region. @@ -1386,6 +1405,21 @@ static bool assign_mem_va_dir(vaddr_t tee_ram_va, struct memory_map *mem_map, if (ROUNDUP2_OVERFLOW(va, map->region_size, &va)) return false; +#ifdef RCAR_MMU_DIRECT_MAPPING + for (n = 0; n < dmnum; n++) { + dmaddr = direct_map_area[n][0]; + dmsize = direct_map_area[n][1]; + rd = ROUNDDOWN((dmaddr), CORE_MMU_PGDIR_SIZE); + if (map->pa == rd) { + va_is_direct = true; + } else if ((va <= rd) && + ((va + map->size) >= (rd + dmsize))) { + va = rd + dmsize; + } else { + /* no operation */ + } + } +#endif /* * Make sure that va is aligned with pa for * efficient pgdir mapping. Basically pa & @@ -1398,13 +1432,50 @@ static bool assign_mem_va_dir(vaddr_t tee_ram_va, struct memory_map *mem_map, if (ADD_OVERFLOW(va, offs, &va)) return false; } - +#ifdef RCAR_MMU_DIRECT_MAPPING + if (!va_is_direct) { + map->va = va; + if (ADD_OVERFLOW(va, map->size, &va)) + return false; + } else { + map->va = map->pa; /* pa = va mapping */ + va_is_direct = false; + } +#else map->va = va; if (ADD_OVERFLOW(va, map->size, &va)) return false; +#endif if (!core_mmu_va_is_valid(va)) return false; } +#ifdef RCAR_MMU_DIRECT_MAPPING + last = 0; + for (n = 0; n < mem_map->count; n++) + last++; + /* + * The memory map should be sorted by virtual address + * when this function returns. As we're assigning va in + * the oposite direction we need to reverse the list. + */ + for (n = 0; n < last; n++) { + size_t o; + size_t min; + + min = n; + for (o = n + 1U; o < last; o++) { + if (mem_map->map[min].va > mem_map->map[o].va) + min = o; + } + if (n != min) { + struct tee_mmap_region r; + + r = mem_map->map[n]; + mem_map->map[n] = mem_map->map[min]; + mem_map->map[min] = r; + } + } +#endif } return true; @@ -1557,9 +1628,10 @@ static struct memory_map *init_mem_map(struct memory_map *mem_map, panic(); out: +#ifndef RCAR_MMU_DIRECT_MAPPING qsort(mem_map->map, mem_map->count, sizeof(struct tee_mmap_region), cmp_mmap_by_lower_va); - +#endif dump_mmap_table(mem_map); *ret_offs = offs; diff --git a/core/tee/tee_svc_cryp.c b/core/tee/tee_svc_cryp.c index 09cbdd114f9..cc75a3b2b20 100644 --- a/core/tee/tee_svc_cryp.c +++ b/core/tee/tee_svc_cryp.c @@ -38,6 +38,9 @@ #if defined(CFG_CRYPTO_PBKDF2) #include #endif +#if defined(RCAR_TRNG_BY_RSIPM_HWENGINE) +#include +#endif enum cryp_state { CRYP_STATE_INITIALIZED = 0, @@ -4092,6 +4095,34 @@ TEE_Result syscall_cryp_random_number_generate(void *buf, size_t blen) return res; } +#ifdef RCAR_TRNG_BY_RSIPM_HWENGINE +TEE_Result syscall_rsipm_trng_generate(uint8_t *buf, uint32_t blen) +{ + TEE_Result res = TEE_SUCCESS; + + /* Check input parameter */ + if (!buf) { + res = TEE_ERROR_BAD_PARAMETERS; + return res; + } + if (blen == 0 || blen > (TRNG_MAX_WORD * TRNG_BLOCK_SIZE)) { + res = TEE_ERROR_BAD_PARAMETERS; + return res; + } + rsipm_trng_generate(buf, blen); + return res; +} +#else +TEE_Result syscall_rsipm_trng_generate(uint8_t *buf, uint32_t blen) +{ + (void)buf; + (void)blen; + + /* Always returns success */ + return TEE_SUCCESS; +} +#endif + TEE_Result syscall_authenc_init(unsigned long state, const void *nonce, size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len) diff --git a/lib/libutee/include/tee_internal_api.h b/lib/libutee/include/tee_internal_api.h index 92374e9d7ec..1b2097a670c 100644 --- a/lib/libutee/include/tee_internal_api.h +++ b/lib/libutee/include/tee_internal_api.h @@ -488,6 +488,9 @@ void __GP11_TEE_DeriveKey(TEE_OperationHandle operation, /* Cryptographic Operations API - Random Number Generation Functions */ void TEE_GenerateRandom(void *randomBuffer, size_t randomBufferLen); + +void TEE_RSIPM_TRNG(uint8_t *randomBuffer, uint32_t randomBufferLen); + void __GP11_TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen); /* Date & Time API */ diff --git a/lib/libutee/include/tee_syscall_numbers.h b/lib/libutee/include/tee_syscall_numbers.h index 82d429b3212..989d73f0ae8 100644 --- a/lib/libutee/include/tee_syscall_numbers.h +++ b/lib/libutee/include/tee_syscall_numbers.h @@ -79,8 +79,8 @@ #define TEE_SCN_SE_CHANNEL_CLOSE__DEPRECATED 69 /* End of deprecated Secure Element API syscalls */ #define TEE_SCN_CACHE_OPERATION 70 - -#define TEE_SCN_MAX 70 +#define TEE_RSIPM_TRNG 71 +#define TEE_SCN_MAX 71 /* Maximum number of allowed arguments for a syscall */ #define TEE_SVC_MAX_ARGS 8 diff --git a/lib/libutee/include/utee_syscalls.h b/lib/libutee/include/utee_syscalls.h index e83f80300f1..32e9511fd2b 100644 --- a/lib/libutee/include/utee_syscalls.h +++ b/lib/libutee/include/utee_syscalls.h @@ -132,6 +132,9 @@ TEE_Result _utee_cryp_derive_key(unsigned long state, TEE_Result _utee_cryp_random_number_generate(void *buf, size_t blen); +/* for rsipm function*/ +TEE_Result _utee_rsipm_trng(void *buf, size_t blen); + TEE_Result _utee_authenc_init(unsigned long state, const void *nonce, size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len); diff --git a/lib/libutee/include/utee_syscalls_asm.S b/lib/libutee/include/utee_syscalls_asm.S index 44bc60d2503..7c4acbf4c13 100644 --- a/lib/libutee/include/utee_syscalls_asm.S +++ b/lib/libutee/include/utee_syscalls_asm.S @@ -122,3 +122,4 @@ TEE_SCN_CRYP_OBJ_GENERATE_KEY, 4 UTEE_SYSCALL _utee_cache_operation, TEE_SCN_CACHE_OPERATION, 3 + UTEE_SYSCALL _utee_rsipm_trng, TEE_RSIPM_TRNG, 2 diff --git a/lib/libutee/tee_api_operations.c b/lib/libutee/tee_api_operations.c index 4b7fa63d0da..5d36f49fe4c 100644 --- a/lib/libutee/tee_api_operations.c +++ b/lib/libutee/tee_api_operations.c @@ -2412,6 +2412,17 @@ void TEE_GenerateRandom(void *randomBuffer, size_t randomBufferLen) TEE_Panic(res); } +/* For rsipm algorithms */ +void TEE_RSIPM_TRNG(uint8_t *randomBuffer, uint32_t randomBufferLen) +{ + TEE_Result res; + + res = _utee_rsipm_trng(randomBuffer, randomBufferLen); + if (res != TEE_SUCCESS) { + TEE_Panic(res); + } +} + void __GP11_TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen) { TEE_GenerateRandom(randomBuffer, randomBufferLen); diff --git a/mk/aosp_optee.mk b/mk/aosp_optee.mk index 65cd4a51aa4..0d102966e7c 100644 --- a/mk/aosp_optee.mk +++ b/mk/aosp_optee.mk @@ -44,6 +44,10 @@ else HOST_MAKE := $(MAKE) endif +# The configuration below is generated while the makefiles are parsed, with +# no jobserver to talk to, so keep the -jN out of that invocation. +HOST_MAKE_CONF := $(firstword $(HOST_MAKE)) + # OPTEE_OUT_DIR could be exported explicitly # if PRODUCT_OUT is not the default out directory in aosp workspace @@ -70,6 +74,17 @@ CROSS_COMPILE32 ?= $(TOP_ROOT_ABS)/$($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX CROSS_COMPILE_LINE += CROSS_COMPILE32="$(CROSS_COMPILE32)" endif +# Command line shared by every optee_os invocation below; the TA target +# differs between them, so callers pass it. Deferred assignment, as +# OPTEE_EXTRA_FLAGS may reference variables set while Android.mk is parsed. +OPTEE_MAKE_LINE = -C $(TOP_ROOT_ABS)/$(OPTEE_OS_DIR) \ + O=$(ABS_OPTEE_OS_OUT_DIR) \ + CFG_ARM64_core=$(OPTEE_CFG_ARM64_CORE) \ + PLATFORM=$(OPTEE_PLATFORM) \ + PLATFORM_FLAVOR=$(OPTEE_PLATFORM_FLAVOR) \ + $(CROSS_COMPILE_LINE) \ + $(OPTEE_EXTRA_FLAGS) + OPTEE_BIN := $(OPTEE_OS_OUT_DIR)/core/tee.bin $(OPTEE_BIN) : $(sort $(shell find -L $(OPTEE_OS_DIR))) @@ -78,6 +93,28 @@ OPTEE_TA_DEV_KIT_MK := $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk $(OPTEE_TA_DEV_KIT_MK) : $(sort $(shell find -L $(OPTEE_OS_DIR))) +# Android.mk files test the CFG_ flags of the dev kit to decide what to +# build, so the configuration must exist before they are parsed. A rule +# cannot provide it, as rules only run once parsing is over. Generate it +# here instead, while the makefiles are parsed; building the dev kit itself +# is left to the rule below. The MD5 ties the variable to the configuration, +# so that a change of configuration triggers a new parse. +ifeq ($(filter $(TA_TARGET),$(BUILD_TA_DEV_KIT_CONF_DEFINED)),) +BUILD_TA_DEV_KIT_CONF_DEFINED := $(TA_TARGET) $(BUILD_TA_DEV_KIT_CONF_DEFINED) +TA_DEV_KIT_CONF_$(TA_TARGET) := $(shell \ + mkdir -p $(ABS_OPTEE_OS_OUT_DIR) && \ + env -u MAKEFLAGS -u MAKELEVEL -u MFLAGS \ + $(HOST_MAKE_CONF) -s $(OPTEE_MAKE_LINE) \ + CFG_USER_TA_TARGETS=$(TA_TARGET) \ + ta_dev_kit_conf >/dev/null && \ + md5sum $(TA_DEV_KIT_DIR)/host_include/conf.mk || \ + printf 'ERROR') +ifeq ($(TA_DEV_KIT_CONF_$(TA_TARGET)),ERROR) +$(error Failed to generate the OP-TEE TA dev kit configuration \ + for $(TA_TARGET)) +endif +endif + ########################################################### ## define making rules for $(OPTEE_BIN) target, and add ## ## condition check to make it only be defined once ## @@ -92,14 +129,8 @@ ifneq (true,$(BUILD_OPTEE_OS_DEFINED)) BUILD_OPTEE_OS_DEFINED := true $(OPTEE_BIN): @echo "Start building optee_os..." - +$(HOST_MAKE) -C $(TOP_ROOT_ABS)/$(OPTEE_OS_DIR) \ - O=$(ABS_OPTEE_OS_OUT_DIR) \ - CFG_USER_TA_TARGETS=$(OPTEE_TA_TARGETS) \ - CFG_ARM64_core=$(OPTEE_CFG_ARM64_CORE) \ - PLATFORM=$(OPTEE_PLATFORM) \ - PLATFORM_FLAVOR=$(OPTEE_PLATFORM_FLAVOR) \ - $(CROSS_COMPILE_LINE) \ - $(OPTEE_EXTRA_FLAGS) + +$(HOST_MAKE) $(OPTEE_MAKE_LINE) \ + CFG_USER_TA_TARGETS=$(OPTEE_TA_TARGETS) @echo "Finished building optee_os..." endif @@ -114,15 +145,18 @@ BUILD_TA_DEV_KIT_DEFINED := $(TA_TARGET) $(BUILD_TA_DEV_KIT_DEFINED) $(OPTEE_TA_DEV_KIT_MK): PRIVATE_TA_TARGET := $(TA_TARGET) $(OPTEE_TA_DEV_KIT_MK): @echo "Start building ta_dev_kit ($(PRIVATE_TA_TARGET))..." - +$(HOST_MAKE) -C $(TOP_ROOT_ABS)/$(OPTEE_OS_DIR) \ - O=$(ABS_OPTEE_OS_OUT_DIR) \ - CFG_USER_TA_TARGETS=$(PRIVATE_TA_TARGET) \ - CFG_ARM64_core=$(OPTEE_CFG_ARM64_CORE) \ - PLATFORM=$(OPTEE_PLATFORM) \ - PLATFORM_FLAVOR=$(OPTEE_PLATFORM_FLAVOR) \ - $(CROSS_COMPILE_LINE) \ - $(OPTEE_EXTRA_FLAGS) ta_dev_kit + +$(HOST_MAKE) $(OPTEE_MAKE_LINE) \ + CFG_USER_TA_TARGETS=$(PRIVATE_TA_TARGET) ta_dev_kit @echo "Finished building ta_dev_kit ($(PRIVATE_TA_TARGET))..." + +# Every rule here runs make over the same output directory, each with its own +# CFG_USER_TA_TARGETS, so let them run one at a time: chain every dev kit onto +# the one declared before it, and the core onto them all. The dev kits go +# first, as the TAs are built against them and an early TA setup feeds a built +# TA back into the core build +$(OPTEE_TA_DEV_KIT_MK): $(BUILD_TA_DEV_KIT_PREV) +BUILD_TA_DEV_KIT_PREV := $(OPTEE_TA_DEV_KIT_MK) +$(OPTEE_BIN): $(OPTEE_TA_DEV_KIT_MK) endif ########################################################## @@ -144,6 +178,12 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/optee_armtz LOCAL_MODULE_CLASS := $(call ta_class,$(local_module)) LOCAL_MODULE_TAGS := optional LOCAL_REQUIRED_MODULES := $(local_module_deps) +# A signed TA is an ELF binary wrapped in a signed header, so it does not start +# with the ELF magic. Disable the AOSP prebuilt ELF check for the .ta module to +# avoid a "must have a valid ELF magic word" build failure. +ifeq ($(call ta_class,$(local_module)),EXECUTABLES) +LOCAL_CHECK_ELF_FILES := false +endif TA_TMP_DIR := $(addsuffix _$(TA_TARGET), $(subst /,_,$(LOCAL_PATH))) TA_TMP_FILE := $(OPTEE_TA_OUT_DIR)/$(TA_TMP_DIR)/$(LOCAL_MODULE) diff --git a/mk/config.mk b/mk/config.mk index ce156ed21ab..9f9d8ce8ff7 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -1023,7 +1023,7 @@ ifneq ($(CFG_INSECURE),$(CFG_WARN_INSECURE)) $(error Inconsistent CFG_INSECURE=$(CFG_INSECURE) and CFG_WARN_INSECURE=$(CFG_WARN_INSECURE)) endif endif # CFG_WARN_INSECURE defined -CFG_INSECURE ?= y +CFG_INSECURE ?= n ifneq ($(CFG_INSECURE),y) ifneq ($(CFG_CORE_ASLR_SEED),) diff --git a/ta/ta.mk b/ta/ta.mk index 77af0e34e6e..22b09e615c9 100644 --- a/ta/ta.mk +++ b/ta/ta.mk @@ -191,6 +191,14 @@ $(foreach d, $(incdirs-host), \ $(foreach f, $(incfiles-extra-host), \ $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/host_include))) +# Some dev kit consumers need the configuration before they can build +# anything, typically to pick which sources to compile. Export the +# configuration files alone; they are written by plain shell commands, so +# this builds nothing. +.PHONY: ta_dev_kit_conf +ta_dev_kit_conf: $(foreach f, $(conf-file) $(conf-mk-file) $(conf-cmake-file), \ + $(out-dir)/export-$(sm)/host_include/$(notdir $(f))) + # Copy the src files ta-srcfiles = ta/user_ta_header.c ta/arch/$(ARCH)/ta.ld.S ifeq ($(ta-target),ta_arm32)