diff --git a/arch/arm/cpu/armv7/qca/common/scm.c b/arch/arm/cpu/armv7/qca/common/scm.c index d2685f12b1..de2472dfd2 100644 --- a/arch/arm/cpu/armv7/qca/common/scm.c +++ b/arch/arm/cpu/armv7/qca/common/scm.c @@ -262,6 +262,41 @@ int __qca_scm_call_armv8_32(u32 x0, u32 x1, u32 x2, u32 x3, u32 x4, u32 x5, return r0; } +/** + * __scm_call_64() - Invoke a syscall in the secure world + * svc_id: service identifier + * cmd_id: command identifier + * ownr_id: owner identifier + * fn_id: The function ID for this syscall + * desc: Descriptor structure containing arguments and return values + * + * Sends a command to the SCM and waits for the command to finish processing. + * + */ +static int __scm_call_64(u32 svc_id, u32 cmd_id, u32 ownr_id, struct qca_scm_desc *desc) +{ + int arglen = desc->arginfo & 0xf; + int ret; + u32 fn_id = QCA_SCM_FNID(svc_id, cmd_id, ownr_id); + + + if (arglen > QCA_MAX_ARG_LEN) { + printf("Error Extra args not supported\n"); + hang(); + } + + desc->ret[0] = desc->ret[1] = desc->ret[2] = 0; + + flush_dcache_all(); + + ret = __qca_scm_call_armv8_32(fn_id, desc->arginfo, + desc->args[0], desc->args[1], + desc->args[2], desc->x5, + &desc->ret[0], &desc->ret[1], + &desc->ret[2]); + + return ret; +} /** * scm_call_64() - Invoke a syscall in the secure world @@ -275,26 +310,7 @@ int __qca_scm_call_armv8_32(u32 x0, u32 x1, u32 x2, u32 x3, u32 x4, u32 x5, */ static int scm_call_64(u32 svc_id, u32 cmd_id, struct qca_scm_desc *desc) { - int arglen = desc->arginfo & 0xf; - int ret; - u32 fn_id = QCA_SCM_SIP_FNID(svc_id, cmd_id); - - - if (arglen > QCA_MAX_ARG_LEN) { - printf("Error Extra args not supported\n"); - hang(); - } - - desc->ret[0] = desc->ret[1] = desc->ret[2] = 0; - - flush_dcache_all(); - ret = __qca_scm_call_armv8_32(fn_id, desc->arginfo, - desc->args[0], desc->args[1], - desc->args[2], desc->x5, - &desc->ret[0], &desc->ret[1], - &desc->ret[2]); - - return ret; + return __scm_call_64(svc_id, cmd_id, SCM_OWNR_SIP, desc); } static enum scm_interface_version { @@ -663,3 +679,12 @@ int qca_scm_usb_mode_write(u32 arg1, u32 arg2) return ret; } +#ifdef CONFIG_IPQ_TZT +int qca_scm(u32 svc_id, u32 cmd_id, u32 ownr_id, u32 *addr, u32 val) +{ + struct qca_scm_desc desc = {0}; + + memcpy(&desc, addr, sizeof(u32)*val); + return __scm_call_64(svc_id, cmd_id, ownr_id, &desc); +} +#endif diff --git a/arch/arm/include/asm/arch-qca-common/scm.h b/arch/arm/include/asm/arch-qca-common/scm.h index c82d0fed0b..4bbe13f48a 100644 --- a/arch/arm/include/asm/arch-qca-common/scm.h +++ b/arch/arm/include/asm/arch-qca-common/scm.h @@ -48,6 +48,19 @@ #define SCM_ERROR -1 #define SCM_INTERRUPTED 1 +/* OWNER IDs */ +#define SCM_OWNR_SIP 2 +#define SCM_OWNR_QSEE_OS 50 +#define SCM_OWNR_TEE_HLOS 51 + +/* SVC IDs */ +#define SCM_SVC_APP_MGR 1 /* Application service manager */ +#define SCM_SVC_LISTENER 2 /* Listener service manager */ +#define SCM_SVC_EXTERNAL 3 /* External Image loading */ +#define SCM_SVC_MON_SAT 252 /* Monitor SAT test calls */ +#define SCM_SVC_TEST_1 253 /* TZ test calls (continued). */ +#define SCM_SVC_TEST_0 254 /* TZ test calls */ + /* to align the pointer to the (next) page boundary */ #define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE) @@ -112,6 +125,9 @@ int qca_scm_secure_authenticate(void *cmd_buf, size_t cmd_len); s32 qca_scm_call_atomic_ver2_32(u32 svc, u32 cmd, u32 arg1, u32 arg2); int qca_scm_auth_kernel(void *cmd_buf, size_t cmd_len); int is_scm_sec_auth_available(u32 svc_id, u32 cmd_id); +#ifdef CONFIG_IPQ_TZT +int qca_scm(u32 svc_id, u32 cmd_id, u32 ownr_id, u32 *addr, u32 len); +#endif #define MAX_QCA_SCM_RETS 3 #define MAX_QCA_SCM_ARGS 10 #define SCM_READ_OP 1 @@ -155,6 +171,9 @@ struct qca_scm_desc { #define QCA_SCM_SIP_FNID(s, c) (((((s) & 0xFF) << 8) | \ ((c) & 0xFF)) | 0x02000000) +#define QCA_SCM_FNID(s, c, o) (((((s) & 0xFF) << 8) | \ + ((c) & 0xFF)) | (((o) & 0xFF) << 24)) + #define QCA_SMC_ATOMIC_MASK 0x80000000 #define QCA_MAX_ARG_LEN 5 diff --git a/board/qca/arm/common/Makefile b/board/qca/arm/common/Makefile index 415f0d3c24..aeb5dc0e72 100644 --- a/board/qca/arm/common/Makefile +++ b/board/qca/arm/common/Makefile @@ -2,6 +2,7 @@ obj-y := cmd_bootqca.o obj-y += cmd_blowsecfuse.o obj-y += cmd_sec_auth.o obj-y += cmd_exectzt.o +obj-$(CONFIG_IPQ_TZT) += cmd_tzt.o obj-$(CONFIG_SMP_CMD_SUPPORT) += cmd_runmulticore.o obj-y += fdt_info.o obj-y += board_init.o diff --git a/board/qca/arm/common/cmd_tzt.c b/board/qca/arm/common/cmd_tzt.c new file mode 100644 index 0000000000..4dc8d8460d --- /dev/null +++ b/board/qca/arm/common/cmd_tzt.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +#define PRINT_BUF_LEN 0x400 +#define MDT_SIZE 0x1B88 +/* Region for loading test application */ +#define TZT_LOAD_ADDR 0x49B00000 +/* Reserved size for application */ +#define TZT_LOAD_SIZE 0x00200000 + +#define LOAD_TZTESTEXEC_IMG_ID 0x0 +#define REGION_NOTIFICATION_ID 0x5 +#define REGISTER_LOG_BUFFER_ID 0x6 +#define SEC_TEST_ID 0x2C +#define XPU_TEST_ID 0x80100004 + +static int tzt_loaded; + +struct xpu_tzt { + u64 test_id; + u64 num_param; + u64 param1; + u64 param2; + u64 param3; + u64 param4; + u64 param5; + u64 param6; + u64 param7; + u64 param8; + u64 param9; + u64 param10; +}; + +struct resp { + u64 status; + u64 index; + u64 total_tests; +}; + +struct log_buff { + u16 wrap; + u16 log_pos; + char buffer[PRINT_BUF_LEN]; +}; + +static int run_xpu_config_tst(void) +{ + int i = 0; + struct xpu_tzt xputzt = {0}; + struct resp resp_buf __aligned(CONFIG_SYS_CACHELINE_SIZE); + u32 passed = 0, failed = 0; + u32 args_log[MAX_QCA_SCM_ARGS + 1]; + u32 args[MAX_QCA_SCM_ARGS + 1]; + struct log_buff logbuff; + + xputzt.test_id = XPU_TEST_ID; + xputzt.num_param = 0x3; + xputzt.param1 = 0; + xputzt.param2 = 0; + xputzt.param3 = (u64)((u32)&resp_buf); + + args_log[0] = QCA_SCM_ARGS(2, SCM_IO_WRITE); + args_log[1] = (u32)&logbuff; + args_log[2] = PRINT_BUF_LEN; + + args[0] = QCA_SCM_ARGS(2, SCM_IO_WRITE); + args[1] = (u32)&xputzt; + args[2] = sizeof(struct xpu_tzt); + + printf("****** xPU Configuration Validation Test Begin ******\n"); + + do { + qca_scm(SCM_SVC_APP_MGR, REGISTER_LOG_BUFFER_ID, + SCM_OWNR_QSEE_OS, args_log, 3); + + xputzt.param2 = i++; + qca_scm(SCM_SVC_TEST_1, SEC_TEST_ID, SCM_OWNR_SIP, args, 3); + + invalidate_dcache_range((unsigned long)&resp_buf, + (unsigned long)&resp_buf + + CONFIG_SYS_CACHELINE_SIZE); + + if (resp_buf.status == 0) + passed++; + else if (resp_buf.status == 1) + failed++; + + logbuff.buffer[logbuff.log_pos] = '\0'; + printf("%s", logbuff.buffer); + + } while (i < resp_buf.total_tests); + + printf("******************************************************\n"); + printf("Test Result: Passed %u Failed %u (total %u)\n", + passed, failed, (u32)resp_buf.total_tests); + printf("****** xPU Configuration Validation Test End ******\n"); + return 0; +} + +static int do_tzt(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + char *cmd; + u32 img_addr; + u32 img_size; + u32 args[MAX_QCA_SCM_ARGS + 1]; + + /* at least two arguments should be there */ + if (argc < 2) + return -1; + + cmd = argv[1]; + if (strcmp(cmd, "load") == 0) { + if (argc < 4) + return -1; + + img_addr = simple_strtoul(argv[2], NULL, 16); + img_size = simple_strtoul(argv[3], NULL, 16); + + args[0] = QCA_SCM_ARGS(2, SCM_IO_WRITE); + args[1] = TZT_LOAD_ADDR; + args[2] = TZT_LOAD_SIZE; + qca_scm(SCM_SVC_APP_MGR, REGION_NOTIFICATION_ID, + SCM_OWNR_QSEE_OS, args, 3); + + args[0] = QCA_SCM_ARGS(3); + args[1] = MDT_SIZE; + args[2] = img_size - MDT_SIZE; + args[3] = img_addr; + qca_scm(SCM_SVC_EXTERNAL, LOAD_TZTESTEXEC_IMG_ID, + SCM_OWNR_QSEE_OS, args, 4); + tzt_loaded = 1; + return 0; + } + + if (!tzt_loaded) { + printf("load tzt image before running test cases\n"); + return -1; + } + + if (strcmp(cmd, "xpu") == 0) + return run_xpu_config_tst(); + + return -1; +} + +U_BOOT_CMD(tzt, 4, 0, do_tzt, + "load and run tzt\n", + "tzt load address size - To load tzt image\n" + "tzt xpu - To run xpu config test\n"); diff --git a/include/configs/ipq6018.h b/include/configs/ipq6018.h index 23a473422d..75e230d072 100644 --- a/include/configs/ipq6018.h +++ b/include/configs/ipq6018.h @@ -361,5 +361,6 @@ extern loff_t board_env_size; #define CONFIG_ARMV7_PSCI #define CONFIG_IPQ_ELF_AUTH #define IPQ_UBI_VOL_WRITE_SUPPORT +#define CONFIG_IPQ_TZT #endif /* _IPQ6018_H */