From df538e29bdfa27e8607f1bf29d6d641bd85ef124 Mon Sep 17 00:00:00 2001 From: Hisping Lin Date: Tue, 9 Jun 2020 10:34:46 +0800 Subject: [PATCH] lib: optee_client v2: support RKFS version 2 1.use get_rkss_version function to get rkss version, if security partition have data with rkss version 1, then we choice rkss version 1, if security partition is empty, then we choice rkss version 2 2.rkss version 2 support dual backup mechanism, security partition total use 1M 3.rkss version 2 R&W 256k data one time Change-Id: I2f17b22d6a442df84be0d94a808b03465dc6fefe Signed-off-by: Hisping Lin --- ...eeClientRkFs-v2.h => OpteeClientRkNewFs.h} | 78 +- lib/optee_clientApi/Makefile | 5 +- lib/optee_clientApi/OpteeClientRPC.c | 4 +- lib/optee_clientApi/OpteeClientRkFs_common.c | 24 + ...lientRkFs-v2.c => OpteeClientRkNewFs_v1.c} | 237 +-- lib/optee_clientApi/OpteeClientRkNewFs_v2.c | 1428 +++++++++++++++++ 6 files changed, 1602 insertions(+), 174 deletions(-) rename include/optee_include/{OpteeClientRkFs-v2.h => OpteeClientRkNewFs.h} (58%) rename lib/optee_clientApi/{OpteeClientRkFs-v2.c => OpteeClientRkNewFs_v1.c} (85%) create mode 100644 lib/optee_clientApi/OpteeClientRkNewFs_v2.c diff --git a/include/optee_include/OpteeClientRkFs-v2.h b/include/optee_include/OpteeClientRkNewFs.h similarity index 58% rename from include/optee_include/OpteeClientRkFs-v2.h rename to include/optee_include/OpteeClientRkNewFs.h index 57138a07dd..889039b9dc 100644 --- a/include/optee_include/OpteeClientRkFs-v2.h +++ b/include/optee_include/OpteeClientRkNewFs.h @@ -27,6 +27,55 @@ #ifndef TEE_SUPP_RK_FS_H #define TEE_SUPP_RK_FS_H +/* + * Operations and defines shared with TEE. + */ +#define OPTEE_MRF_OPEN 0 +#define OPTEE_MRF_CREATE 1 +#define OPTEE_MRF_CLOSE 2 +#define OPTEE_MRF_READ 3 +#define OPTEE_MRF_WRITE 4 +#define OPTEE_MRF_TRUNCATE 5 +#define OPTEE_MRF_REMOVE 6 +#define OPTEE_MRF_RENAME 7 +#define OPTEE_MRF_OPENDIR 8 +#define OPTEE_MRF_CLOSEDIR 9 +#define OPTEE_MRF_READDIR 10 + +/* + * Open flags, defines shared with TEE. + */ +#define TEE_FS_O_RDONLY 0x1 +#define TEE_FS_O_WRONLY 0x2 +#define TEE_FS_O_RDWR 0x4 +#define TEE_FS_O_CREAT 0x8 +#define TEE_FS_O_EXCL 0x10 +#define TEE_FS_O_APPEND 0x20 + +/* + * Seek flags, defines shared with TEE. + */ +#define TEE_FS_SEEK_SET 0x1 +#define TEE_FS_SEEK_END 0x2 +#define TEE_FS_SEEK_CUR 0x4 + +/* + * Mkdir flags, defines shared with TEE. + */ +#define TEE_FS_S_IWUSR 0x1 +#define TEE_FS_S_IRUSR 0x2 + +/* + * Access flags, X_OK not supported, defines shared with TEE. + */ +#define TEE_FS_R_OK 0x1 +#define TEE_FS_W_OK 0x2 +#define TEE_FS_F_OK 0x4 + +#define RK_FS_R 0x1 +#define RK_FS_W 0x2 +#define RK_FS_D 0x8 + #define TEE_IOCTL_PARAM_ATTR_TYPE_MASK 0xff #define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT 1 #define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT 2 @@ -56,21 +105,28 @@ struct tee_ioctl_param { } u; }; -struct tee_ioctl_param; +/* Function Defines */ +#define UNREFERENCED_PARAMETER(P) (P = P) +#define CHECKFLAG(flags, flag) (flags & flag) +#define ADDFLAG(flags, flag) (flags | flag) -struct blk_desc *rockchip_get_bootdev(void); -int part_get_info_by_name(struct blk_desc *dev_desc, const char *name, - disk_partition_t *info); -unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start, - lbaint_t blkcnt, void *buffer); -unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, - lbaint_t blkcnt, const void *buffer); +#define RKSS_VERSION_V1 1 +#define RKSS_VERSION_V2 2 +#define RKSS_VERSION_ERR 100 -int tee_supp_rk_fs_init(void); +int tee_supp_rk_fs_init_v1(void); -int tee_supp_rk_fs_process(size_t num_params, +int tee_supp_rk_fs_process_v1(size_t num_params, struct tee_ioctl_param *params); + +int tee_supp_rk_fs_init_v2(void); + +int tee_supp_rk_fs_process_v2(size_t num_params, + struct tee_ioctl_param *params); + int OpteeClientRkFsInit(void); -int check_security_exist(int print_flag); + +int OpteeClientRkFsProcess(size_t num_params, + struct tee_ioctl_param *params); #endif diff --git a/lib/optee_clientApi/Makefile b/lib/optee_clientApi/Makefile index 2ecb905e4e..4ee69ec055 100644 --- a/lib/optee_clientApi/Makefile +++ b/lib/optee_clientApi/Makefile @@ -9,14 +9,15 @@ obj-y += OpteeClientInterface.o obj-y += OpteeClientSMC.o obj-y += OpteeClientRPC.o obj-y += tee_smc-arm64.o +obj-y += OpteeClientRkFs_common.o ifdef CONFIG_OPTEE_V1 -obj-y += OpteeClientRkFs_common.o obj-y += OpteeClientRkFs_v1.o obj-y += OpteeClientRkFs_v2.o endif ifdef CONFIG_OPTEE_V2 -obj-y += OpteeClientRkFs-v2.o +obj-y += OpteeClientRkNewFs_v1.o +obj-y += OpteeClientRkNewFs_v2.o endif diff --git a/lib/optee_clientApi/OpteeClientRPC.c b/lib/optee_clientApi/OpteeClientRPC.c index 3938f63a5c..1a78308acb 100644 --- a/lib/optee_clientApi/OpteeClientRPC.c +++ b/lib/optee_clientApi/OpteeClientRPC.c @@ -19,7 +19,7 @@ #include #endif #ifdef CONFIG_OPTEE_V2 -#include +#include #endif /* @@ -524,7 +524,7 @@ TEEC_Result OpteeRpcCmdFs(t_teesmc32_arg *TeeSmc32Arg) TeeSmc32Param[0].u.memref.size); #endif #ifdef CONFIG_OPTEE_V2 - TeecResult = tee_supp_rk_fs_process((size_t)TeeSmc32Arg->num_params, + TeecResult = OpteeClientRkFsProcess((size_t)TeeSmc32Arg->num_params, (struct tee_ioctl_param *)TeeSmc32Param); #endif diff --git a/lib/optee_clientApi/OpteeClientRkFs_common.c b/lib/optee_clientApi/OpteeClientRkFs_common.c index f3d95f8fba..7dcd1eb2f1 100644 --- a/lib/optee_clientApi/OpteeClientRkFs_common.c +++ b/lib/optee_clientApi/OpteeClientRkFs_common.c @@ -10,7 +10,12 @@ #include #include #include +#ifdef CONFIG_OPTEE_V1 #include +#endif +#ifdef CONFIG_OPTEE_V2 +#include +#endif static int rkss_version; static int get_rkss_version(void) @@ -79,6 +84,7 @@ int OpteeClientRkFsInit(void) return -1; } +#ifdef CONFIG_OPTEE_V1 int OpteeClientRkFsProcess(void *cmd, size_t cmd_size) { int version; @@ -92,3 +98,21 @@ int OpteeClientRkFsProcess(void *cmd, size_t cmd_size) else return -1; } +#endif + +#ifdef CONFIG_OPTEE_V2 +int OpteeClientRkFsProcess(size_t num_params, + struct tee_ioctl_param *params) +{ + int version; + + version = get_rkss_version(); + debug("TEEC: OpteeClientRkFsProcess version=%d\n", version); + if (version == RKSS_VERSION_V1) + return tee_supp_rk_fs_process_v1(num_params, params); + else if (version == RKSS_VERSION_V2) + return tee_supp_rk_fs_process_v2(num_params, params); + else + return -1; +} +#endif diff --git a/lib/optee_clientApi/OpteeClientRkFs-v2.c b/lib/optee_clientApi/OpteeClientRkNewFs_v1.c similarity index 85% rename from lib/optee_clientApi/OpteeClientRkFs-v2.c rename to lib/optee_clientApi/OpteeClientRkNewFs_v1.c index 2ebc238256..c258262cb9 100644 --- a/lib/optee_clientApi/OpteeClientRkFs-v2.c +++ b/lib/optee_clientApi/OpteeClientRkNewFs_v1.c @@ -1,33 +1,16 @@ /* - * Copyright (c) 2016, Fuzhou Rockchip Electronics Co.,Ltd. - * All rights reserved. + * Copyright 2020, Rockchip Electronics Co., Ltd + * hisping lin, * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: GPL-2.0+ */ + #include #include #include -#include +#include +#include +#include #include /* @@ -35,51 +18,6 @@ *#define DEBUG_CLEAN_RKSS */ -/* - * Operations and defines shared with TEE. - */ -#define OPTEE_MRF_OPEN 0 -#define OPTEE_MRF_CREATE 1 -#define OPTEE_MRF_CLOSE 2 -#define OPTEE_MRF_READ 3 -#define OPTEE_MRF_WRITE 4 -#define OPTEE_MRF_TRUNCATE 5 -#define OPTEE_MRF_REMOVE 6 -#define OPTEE_MRF_RENAME 7 -#define OPTEE_MRF_OPENDIR 8 -#define OPTEE_MRF_CLOSEDIR 9 -#define OPTEE_MRF_READDIR 10 - -/* - * Open flags, defines shared with TEE. - */ -#define TEE_FS_O_RDONLY 0x1 -#define TEE_FS_O_WRONLY 0x2 -#define TEE_FS_O_RDWR 0x4 -#define TEE_FS_O_CREAT 0x8 -#define TEE_FS_O_EXCL 0x10 -#define TEE_FS_O_APPEND 0x20 - -/* - * Seek flags, defines shared with TEE. - */ -#define TEE_FS_SEEK_SET 0x1 -#define TEE_FS_SEEK_END 0x2 -#define TEE_FS_SEEK_CUR 0x4 - -/* - * Mkdir flags, defines shared with TEE. - */ -#define TEE_FS_S_IWUSR 0x1 -#define TEE_FS_S_IRUSR 0x2 - -/* - * Access flags, X_OK not supported, defines shared with TEE. - */ -#define TEE_FS_R_OK 0x1 -#define TEE_FS_W_OK 0x2 -#define TEE_FS_F_OK 0x4 - /* * RK Secure Storage Ctrl * Storage Size : 512 kb @@ -105,11 +43,11 @@ * */ #define RKSS_DATA_SECTION_COUNT 1024 -#define RKSS_DATA_LEN 512 +#define RKSS_DATA_SECTION_LEN 512 #define RKSS_PARTITION_TABLE_COUNT 128 /* total size 512 * 128*/ -#define RKSS_EACH_FILEFOLDER_COUNT 4 /* 504 / 126 = 4*/ -#define RKSS_NAME_MAX_LENGTH 117 /* 116 char + "\0"*/ -#define RKSS_USEDFLAGS_INDEX RKSS_PARTITION_TABLE_COUNT +#define RKSS_EACH_SECTION_FILECOUNT 4 /* 504 / 126 = 4*/ +#define RKSS_MAX_NAME_LENGTH 117 /* 116 char + "\0"*/ +#define RKSS_USED_FLAGS_INDEX RKSS_PARTITION_TABLE_COUNT #define RKSS_BACKUP_INDEX RKSS_DATA_SECTION_COUNT #define RKSS_BACKUP_COUNT 256 @@ -131,13 +69,9 @@ struct rkss_backup_info { unsigned int backup_usedflag; }; -#define RK_FS_R 0x1 -#define RK_FS_W 0x2 -#define RK_FS_D 0x8 - typedef struct rkss_file_info { uint8_t used; - char name[RKSS_NAME_MAX_LENGTH]; + char name[RKSS_MAX_NAME_LENGTH]; uint16_t index; /* from 129 to 1023*/ uint16_t size; /* size of data*/ uint16_t father; @@ -145,7 +79,6 @@ typedef struct rkss_file_info { uint8_t flags; } rkss_file_info; /* 126 byte for each*/ -#define RKSS_VERSION ((uint32_t)0x1) #define RKSS_CHECK_STR ((uint32_t)0x12345678) #define RKSS_CHECK_PT ((uint8_t)0xFC) typedef struct rkss_file_verification { @@ -155,27 +88,18 @@ typedef struct rkss_file_verification { typedef struct rk_secure_storage { unsigned long index; - unsigned char data[RKSS_DATA_LEN]; + unsigned char data[RKSS_DATA_SECTION_LEN]; } rk_secure_storage; -/* Path to all secure storage dev. */ -#define RKSS_DEV_NAND "/dev/block/rknand_security" -#define RKSS_DEV_EMMC "/dev/block/by-name/security" - -/* Function Defines */ -#define UNREFERENCED_PARAMETER(P) (P = P) -#define CHECKFLAG(flags, flag) (flags & flag) -#define ADDFLAG(flags, flag) (flags | flag) - /* RK Secure Storage Calls */ -static char dir_cache[RKSS_NAME_MAX_LENGTH][12]; +static char dir_cache[RKSS_MAX_NAME_LENGTH][12]; static int dir_num; static int dir_seek; -static struct blk_desc *dev_desc = NULL; +static struct blk_desc *dev_desc; static disk_partition_t part_info; -int check_security_exist(int print_flag) +static int check_security_exist(int print_flag) { if (!dev_desc) { dev_desc = rockchip_get_bootdev(); @@ -214,7 +138,7 @@ int check_security_exist(int print_flag) */ static int rkss_begin_commit(void) { - unsigned char data[RKSS_DATA_LEN]; + unsigned char data[RKSS_DATA_SECTION_LEN]; struct rkss_backup_verification p; unsigned long ret; @@ -239,7 +163,7 @@ static int rkss_begin_commit(void) static int rkss_finish_commit(void) { - unsigned char data[RKSS_DATA_LEN]; + unsigned char data[RKSS_DATA_SECTION_LEN]; unsigned long ret; if (check_security_exist(1) < 0) @@ -258,7 +182,7 @@ static int rkss_finish_commit(void) static int rkss_backup_sections(unsigned long index, unsigned int num) { - unsigned char data[RKSS_DATA_LEN]; + unsigned char data[RKSS_DATA_SECTION_LEN]; unsigned char *backup_data = NULL; struct rkss_backup_verification p; struct rkss_backup_info info_last, info_current; @@ -300,7 +224,7 @@ static int rkss_backup_sections(unsigned long index, unsigned int num) debug("TEEC: %s index=0x%lx num=0x%x backup_data_index=0x%x\n", __func__, index, num, info_current.backup_data_index); - backup_data = malloc(num * RKSS_DATA_LEN); + backup_data = malloc(num * RKSS_DATA_SECTION_LEN); if (!backup_data) { printf("TEEC: malloc backup_data fail\n"); goto error; @@ -344,7 +268,7 @@ error: static int rkss_resume(void) { - unsigned char data[RKSS_DATA_LEN]; + unsigned char data[RKSS_DATA_SECTION_LEN]; unsigned char *backup_data = NULL; struct rkss_backup_verification p; struct rkss_backup_info info_current; @@ -388,7 +312,7 @@ static int rkss_resume(void) goto error; } backup_data = malloc(info_current.backup_num * - RKSS_DATA_LEN); + RKSS_DATA_SECTION_LEN); if (!backup_data) { printf("TEEC: malloc backup_data fail\n"); goto error; @@ -502,7 +426,7 @@ static void rkss_dump_ptable(void) struct rkss_file_info *p; unsigned char *table_data; - table_data = malloc(RKSS_PARTITION_TABLE_COUNT * RKSS_DATA_LEN); + table_data = malloc(RKSS_PARTITION_TABLE_COUNT * RKSS_DATA_SECTION_LEN); if (table_data == NULL) { printf("TEEC: malloc table_data fail\n"); return; @@ -516,14 +440,14 @@ static void rkss_dump_ptable(void) printf("-------------- DUMP ptable --------------\n"); for (i = 0; i < RKSS_PARTITION_TABLE_COUNT; i++) { rkss.index = i; - memcpy(rkss.data, table_data + rkss.index * RKSS_DATA_LEN, RKSS_DATA_LEN); + memcpy(rkss.data, table_data + rkss.index * RKSS_DATA_SECTION_LEN, RKSS_DATA_SECTION_LEN); - for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) { + for (n = 0; n < RKSS_EACH_SECTION_FILECOUNT; n++) { pdata = rkss.data; p = (struct rkss_file_info *)pdata; p += n; printf("[%02d][%c] %s , inx:%d, size:%d", - i*RKSS_EACH_FILEFOLDER_COUNT+n, p->used == 0 ? 'F':'T', p->name, + i*RKSS_EACH_SECTION_FILECOUNT+n, p->used == 0 ? 'F':'T', p->name, p->index, p->size); } } @@ -536,13 +460,13 @@ static void rkss_dump_usedflags(void) struct rk_secure_storage rkss = {0}; int ret; - rkss.index = RKSS_USEDFLAGS_INDEX; + rkss.index = RKSS_USED_FLAGS_INDEX; ret = rkss_read_multi_sections(rkss.data, rkss.index, 1); if (ret < 0) { printf("TEEC: rkss_read_multi_sections fail ! ret: %d.\n", ret); return; } - rkss_dump(rkss.data, RKSS_DATA_LEN); + rkss_dump(rkss.data, RKSS_DATA_SECTION_LEN); } #endif @@ -553,16 +477,16 @@ static int rkss_verify_ptable(unsigned char *table_data) int ret, i; for (i = 0; i < RKSS_PARTITION_TABLE_COUNT; i++) { - cp = table_data + (i * RKSS_DATA_LEN); - vp = cp + RKSS_DATA_LEN - sizeof(struct rkss_file_verification); + cp = table_data + (i * RKSS_DATA_SECTION_LEN); + vp = cp + RKSS_DATA_SECTION_LEN - sizeof(struct rkss_file_verification); verify = (struct rkss_file_verification *)(void *)vp; - if (verify->version != RKSS_VERSION + if (verify->version != RKSS_VERSION_V1 || verify->checkstr != RKSS_CHECK_STR) { printf("TEEC: verify [%d] fail, cleanning ....", i); - memset(cp, 0, RKSS_DATA_LEN); + memset(cp, 0, RKSS_DATA_SECTION_LEN); verify->checkstr = RKSS_CHECK_STR; - verify->version = RKSS_VERSION; + verify->version = RKSS_VERSION_V1; } } ret = rkss_write_multi_sections(table_data, 0, RKSS_PARTITION_TABLE_COUNT); @@ -585,7 +509,7 @@ static int rkss_verify_usedflags(struct rk_secure_storage *rkss) flag = i & 0x1 ? duel & 0x0F : (duel & 0xF0) >> 4; if (flag != 0x1) { debug("TEEC: init usedflags section ...\n"); - memset(rkss->data, 0x00, RKSS_DATA_LEN); + memset(rkss->data, 0x00, RKSS_DATA_SECTION_LEN); for (n = 0; n < RKSS_PARTITION_TABLE_COUNT + 1; n++) { flagw = (uint8_t *)rkss->data + (int)n/2; value = 0x1; @@ -607,8 +531,8 @@ static int rkss_verify_usedflags(struct rk_secure_storage *rkss) static int rkss_get_fileinfo_by_index(int fd, struct rkss_file_info *pfileinfo) { - int i = fd / RKSS_EACH_FILEFOLDER_COUNT; - int n = fd - (RKSS_EACH_FILEFOLDER_COUNT * i); + int i = fd / RKSS_EACH_SECTION_FILECOUNT; + int n = fd - (RKSS_EACH_SECTION_FILECOUNT * i); struct rk_secure_storage rkss = {0}; int ret; void *pdata; @@ -654,12 +578,12 @@ static int rkss_get_fileinfo_by_name( int size_in, size_sv; len = strlen(filename); - if (len > RKSS_NAME_MAX_LENGTH - 1) { + if (len > RKSS_MAX_NAME_LENGTH - 1) { printf("TEEC: filename is too long. length:%u\n", len); return TEEC_ERROR_GENERIC; } - table_data = malloc(RKSS_DATA_LEN * RKSS_PARTITION_TABLE_COUNT); + table_data = malloc(RKSS_DATA_SECTION_LEN * RKSS_PARTITION_TABLE_COUNT); if (table_data == NULL) { printf("TEEC: malloc table_data fail\n"); return TEEC_ERROR_GENERIC; @@ -672,9 +596,9 @@ static int rkss_get_fileinfo_by_name( for (i = 0; i < RKSS_PARTITION_TABLE_COUNT; i++) { rkss.index = i; - memcpy(rkss.data, table_data + rkss.index * RKSS_DATA_LEN, RKSS_DATA_LEN); + memcpy(rkss.data, table_data + rkss.index * RKSS_DATA_SECTION_LEN, RKSS_DATA_SECTION_LEN); - for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) { + for (n = 0; n < RKSS_EACH_SECTION_FILECOUNT; n++) { pdata = rkss.data; p = (struct rkss_file_info *)pdata; p += n; @@ -685,10 +609,10 @@ static int rkss_get_fileinfo_by_name( /* Full Matching*/ if (!strcmp(p->name, filename)) { debug("TEEC: rkss_get_fileinfo_by_name: hit table[%d/%d], index[%d/%d]\n", - i, RKSS_PARTITION_TABLE_COUNT, n, RKSS_EACH_FILEFOLDER_COUNT); + i, RKSS_PARTITION_TABLE_COUNT, n, RKSS_EACH_SECTION_FILECOUNT); memcpy(pfileinfo, p, sizeof(struct rkss_file_info)); free(table_data); - return i * RKSS_EACH_FILEFOLDER_COUNT + n; + return i * RKSS_EACH_SECTION_FILECOUNT + n; } /* Folder Matching*/ @@ -737,12 +661,12 @@ static int rkss_get_dirs_by_name(char *filename) char *chk, *file, *subdir; len = strlen(filename); - if (len > RKSS_NAME_MAX_LENGTH - 1) { + if (len > RKSS_MAX_NAME_LENGTH - 1) { printf("TEEC: filename is too long. length:%u\n", len); return TEEC_ERROR_GENERIC; } - table_data = malloc(RKSS_DATA_LEN * RKSS_PARTITION_TABLE_COUNT); + table_data = malloc(RKSS_DATA_SECTION_LEN * RKSS_PARTITION_TABLE_COUNT); if (table_data == NULL) { printf("TEEC: malloc table_data fail\n"); return TEEC_ERROR_GENERIC; @@ -756,9 +680,9 @@ static int rkss_get_dirs_by_name(char *filename) dir_num = 0; for (i = 0; i < RKSS_PARTITION_TABLE_COUNT; i++) { rkss.index = i; - memcpy(rkss.data, table_data + rkss.index * RKSS_DATA_LEN, RKSS_DATA_LEN); + memcpy(rkss.data, table_data + rkss.index * RKSS_DATA_SECTION_LEN, RKSS_DATA_SECTION_LEN); - for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) { + for (n = 0; n < RKSS_EACH_SECTION_FILECOUNT; n++) { pdata = rkss.data; p = (struct rkss_file_info *)pdata; p += n; @@ -769,7 +693,7 @@ static int rkss_get_dirs_by_name(char *filename) /* Full Matching*/ ret = memcmp(p->name, filename, strlen(filename)); debug("TEEC: comparing [fd:%d] : %s ?= %s , ret:%d\n", - i*RKSS_EACH_FILEFOLDER_COUNT+n, p->name, filename, ret); + i*RKSS_EACH_SECTION_FILECOUNT+n, p->name, filename, ret); if (!ret && strlen(p->name) > strlen(filename)) { chk = p->name + strlen(filename); if (*chk == '/') { @@ -794,7 +718,7 @@ static int rkss_get_empty_section_from_usedflags(int section_size) uint8_t *flag; uint8_t value; - rkss.index = RKSS_USEDFLAGS_INDEX; + rkss.index = RKSS_USED_FLAGS_INDEX; ret = rkss_read_multi_sections(rkss.data, rkss.index, 1); if (ret < 0) { printf("TEEC: rkss_read_multi_sections fail ! ret: %d.\n", ret); @@ -829,7 +753,7 @@ static int rkss_incref_multi_usedflags_sections(unsigned int index, unsigned int return TEEC_ERROR_GENERIC; } - rkss.index = RKSS_USEDFLAGS_INDEX; + rkss.index = RKSS_USED_FLAGS_INDEX; ret = rkss_read_multi_sections(rkss.data, rkss.index, 1); if (ret < 0) { printf("TEEC: rkss_read_multi_sections fail ! ret: %d.\n", ret); @@ -865,7 +789,7 @@ static int rkss_decref_multi_usedflags_sections(unsigned int index, unsigned int return TEEC_ERROR_GENERIC; } - rkss.index = RKSS_USEDFLAGS_INDEX; + rkss.index = RKSS_USED_FLAGS_INDEX; ret = rkss_read_multi_sections(rkss.data, rkss.index, 1); if (ret < 0) { printf("TEEC: rkss_read_multi_sections fail ! ret: %d.\n", ret); @@ -897,7 +821,7 @@ static int rkss_write_empty_ptable(struct rkss_file_info *pfileinfo) void *pdata; struct rkss_file_info *p; - table_data = malloc(RKSS_DATA_LEN * RKSS_PARTITION_TABLE_COUNT); + table_data = malloc(RKSS_DATA_SECTION_LEN * RKSS_PARTITION_TABLE_COUNT); if (table_data == NULL) { printf("TEEC: malloc table_data fail\n"); return TEEC_ERROR_GENERIC; @@ -911,8 +835,8 @@ static int rkss_write_empty_ptable(struct rkss_file_info *pfileinfo) for (i = 0; i < RKSS_PARTITION_TABLE_COUNT; i++) { rkss.index = i; - memcpy(rkss.data, table_data + rkss.index * RKSS_DATA_LEN, RKSS_DATA_LEN); - for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) { + memcpy(rkss.data, table_data + rkss.index * RKSS_DATA_SECTION_LEN, RKSS_DATA_SECTION_LEN); + for (n = 0; n < RKSS_EACH_SECTION_FILECOUNT; n++) { pdata = rkss.data; p = (struct rkss_file_info *)pdata; p += n; @@ -932,7 +856,7 @@ static int rkss_write_empty_ptable(struct rkss_file_info *pfileinfo) } free(table_data); - return i * RKSS_EACH_FILEFOLDER_COUNT + n; + return i * RKSS_EACH_SECTION_FILECOUNT + n; } } } @@ -943,8 +867,8 @@ static int rkss_write_empty_ptable(struct rkss_file_info *pfileinfo) static int rkss_write_back_ptable(int fd, struct rkss_file_info *pfileinfo) { - int i = fd / RKSS_EACH_FILEFOLDER_COUNT; - int n = fd - (RKSS_EACH_FILEFOLDER_COUNT * i); + int i = fd / RKSS_EACH_SECTION_FILECOUNT; + int n = fd - (RKSS_EACH_SECTION_FILECOUNT * i); struct rk_secure_storage rkss = {0}; int ret; void *pdata; @@ -991,7 +915,7 @@ static uint32_t ree_fs_new_open(size_t num_params, if (!filename) return TEEC_ERROR_BAD_PARAMETERS; - if (strlen(filename) > RKSS_NAME_MAX_LENGTH) { + if (strlen(filename) > RKSS_MAX_NAME_LENGTH) { printf("TEEC: ree_fs_new_open: file name too long. %s\n", filename); return TEEC_ERROR_BAD_PARAMETERS; } @@ -1031,7 +955,7 @@ static TEEC_Result ree_fs_new_create(size_t num_params, if (!filename) return TEEC_ERROR_BAD_PARAMETERS; - if (strlen(filename) > RKSS_NAME_MAX_LENGTH) { + if (strlen(filename) > RKSS_MAX_NAME_LENGTH) { printf("TEEC: ree_fs_new_create: file name too long. %s\n", filename); return TEEC_ERROR_BAD_PARAMETERS; } @@ -1041,7 +965,7 @@ static TEEC_Result ree_fs_new_create(size_t num_params, if (fd >= 0) { debug("TEEC: ree_fs_new_create : file exist, clear it. %s\n", filename); /* decrease ref from usedflags */ - num = p.size / RKSS_DATA_LEN + 1; + num = p.size / RKSS_DATA_SECTION_LEN + 1; ret = rkss_decref_multi_usedflags_sections(p.index, num); if (ret < 0) { printf("TEEC: rkss_decref_multi_usedflags_sections error !\n"); @@ -1124,8 +1048,8 @@ static TEEC_Result ree_fs_new_read(size_t num_params, if (offs >= p.size) return TEEC_ERROR_BAD_PARAMETERS; - section_num = p.size / RKSS_DATA_LEN + 1; - temp_file_data = malloc(section_num * RKSS_DATA_LEN); + section_num = p.size / RKSS_DATA_SECTION_LEN + 1; + temp_file_data = malloc(section_num * RKSS_DATA_SECTION_LEN); ret = rkss_read_multi_sections(temp_file_data, p.index, section_num); if (ret < 0) { printf("TEEC: unavailable file index!\n"); @@ -1150,7 +1074,7 @@ static TEEC_Result ree_fs_new_write(size_t num_params, struct rkss_file_info p = {0}; int ret, fd, new_size; int section_num; - uint8_t *file_data=0, *temp_file_data=0; + uint8_t *file_data = 0, *temp_file_data = 0; ret = rkss_begin_commit(); if (ret < 0) { @@ -1183,8 +1107,8 @@ static TEEC_Result ree_fs_new_write(size_t num_params, if (p.size != 0) { /* Read old file data out */ - section_num = p.size / RKSS_DATA_LEN + 1; - temp_file_data = malloc(section_num * RKSS_DATA_LEN); + section_num = p.size / RKSS_DATA_SECTION_LEN + 1; + temp_file_data = malloc(section_num * RKSS_DATA_SECTION_LEN); ret = rkss_read_multi_sections(temp_file_data, p.index, section_num); if (ret < 0) { printf("TEEC: unavailable file index %d section_num %d\n", p.index, section_num); @@ -1205,7 +1129,7 @@ static TEEC_Result ree_fs_new_write(size_t num_params, /* update new file info */ memcpy(file_data + offs, data, len); p.size = new_size; - section_num = new_size / RKSS_DATA_LEN + 1; + section_num = new_size / RKSS_DATA_SECTION_LEN + 1; p.index = rkss_get_empty_section_from_usedflags(section_num); debug("TEEC: Get Empty section in %d\n", p.index); p.used = 1; @@ -1224,8 +1148,8 @@ static TEEC_Result ree_fs_new_write(size_t num_params, } /* write new file data */ - temp_file_data = malloc(section_num * RKSS_DATA_LEN); - memset(temp_file_data, 0, section_num * RKSS_DATA_LEN); + temp_file_data = malloc(section_num * RKSS_DATA_SECTION_LEN); + memset(temp_file_data, 0, section_num * RKSS_DATA_SECTION_LEN); memcpy(temp_file_data, file_data, p.size); rkss_write_multi_sections(temp_file_data, p.index, section_num); free(temp_file_data); @@ -1280,8 +1204,8 @@ static TEEC_Result ree_fs_new_truncate(size_t num_params, printf("TEEC: truncate error!\n"); return TEEC_ERROR_GENERIC; } - section_num_old = p.size / RKSS_DATA_LEN + 1; - section_num_new = len / RKSS_DATA_LEN + 1; + section_num_old = p.size / RKSS_DATA_SECTION_LEN + 1; + section_num_new = len / RKSS_DATA_SECTION_LEN + 1; ret = rkss_decref_multi_usedflags_sections(p.index + section_num_new, section_num_old - section_num_new); if (ret < 0) { printf("TEEC: rkss_decref_multi_usedflags_sections error !\n"); @@ -1332,7 +1256,7 @@ static TEEC_Result ree_fs_new_remove(size_t num_params, debug("TEEC: ree_fs_new_remove! %s fd:%d index:%d size:%d\n", filename, fd, p.index, p.size); /* decrease ref from usedflags */ - num = p.size / RKSS_DATA_LEN + 1; + num = p.size / RKSS_DATA_SECTION_LEN + 1; ret = rkss_decref_multi_usedflags_sections(p.index, num); if (ret < 0) { printf("TEEC: rkss_decref_multi_usedflags_sections error !\n"); @@ -1386,7 +1310,7 @@ static TEEC_Result ree_fs_new_rename(size_t num_params, if (!new_fname) return TEEC_ERROR_BAD_PARAMETERS; - if (strlen(new_fname) > RKSS_NAME_MAX_LENGTH) { + if (strlen(new_fname) > RKSS_MAX_NAME_LENGTH) { printf("TEEC: new file name too long. %s\n", new_fname); return TEEC_ERROR_BAD_PARAMETERS; } @@ -1487,10 +1411,10 @@ static TEEC_Result ree_fs_new_readdir(size_t num_params, return TEEC_SUCCESS; } -int tee_supp_rk_fs_init(void) +int tee_supp_rk_fs_init_v1(void) { assert(sizeof(struct rkss_file_info) == 126); - assert(512 / sizeof(struct rkss_file_info) == RKSS_EACH_FILEFOLDER_COUNT); + assert(512 / sizeof(struct rkss_file_info) == RKSS_EACH_SECTION_FILECOUNT); int ret; struct rk_secure_storage rkss = {0}; @@ -1509,7 +1433,7 @@ int tee_supp_rk_fs_init(void) #ifdef DEBUG_CLEAN_RKSS int i = 0; for (i = 0; i < RKSS_DATA_SECTION_COUNT; i++) { - memset(rkss.data, 0, RKSS_DATA_LEN); + memset(rkss.data, 0, RKSS_DATA_SECTION_LEN); rkss.index = i; rkss_write_multi_sections(rkss.data, rkss.index, 1); printf("TEEC: cleaned [%d]", i); @@ -1521,7 +1445,7 @@ int tee_supp_rk_fs_init(void) return TEEC_ERROR_GENERIC; } - table_data = malloc(RKSS_DATA_LEN * RKSS_PARTITION_TABLE_COUNT); + table_data = malloc(RKSS_DATA_SECTION_LEN * RKSS_PARTITION_TABLE_COUNT); if (table_data == NULL) { printf("TEEC: malloc table_data fail\n"); return TEEC_ERROR_GENERIC; @@ -1538,7 +1462,7 @@ int tee_supp_rk_fs_init(void) table_data = NULL; /* Verify Usedflags Section*/ - rkss.index = RKSS_USEDFLAGS_INDEX; + rkss.index = RKSS_USED_FLAGS_INDEX; ret = rkss_read_multi_sections(rkss.data, rkss.index, 1); if (ret < 0) { printf("TEEC: rkss_read_multi_sections fail ! ret: %d.\n", ret); @@ -1564,12 +1488,7 @@ int tee_supp_rk_fs_init(void) return TEEC_SUCCESS; } -int OpteeClientRkFsInit(void) -{ - debug("TEEC: OpteeClientRkFsInit\n"); - return tee_supp_rk_fs_init(); -} -bool tee_supp_param_is_value(struct tee_ioctl_param *param) +static bool tee_supp_param_is_value(struct tee_ioctl_param *param) { switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: @@ -1582,7 +1501,7 @@ bool tee_supp_param_is_value(struct tee_ioctl_param *param) } static int rkss_step; -int tee_supp_rk_fs_process(size_t num_params, +int tee_supp_rk_fs_process_v1(size_t num_params, struct tee_ioctl_param *params) { if (!num_params || !tee_supp_param_is_value(params)) diff --git a/lib/optee_clientApi/OpteeClientRkNewFs_v2.c b/lib/optee_clientApi/OpteeClientRkNewFs_v2.c new file mode 100644 index 0000000000..7bb950454d --- /dev/null +++ b/lib/optee_clientApi/OpteeClientRkNewFs_v2.c @@ -0,0 +1,1428 @@ +/* + * Copyright 2020, Rockchip Electronics Co., Ltd + * hisping lin, + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + *#define DEBUG_RKSS + *#define DEBUG_CLEAN_RKSS + */ + +/* + * RK Secure Storage Version 2 + * Area0 Backup 0 Size : 256 kb <----> Area0 Backup 1 Size : 256 kb + * Area1 Backup 0 Size : 256 kb <----> Area1 Backup 1 Size : 256 kb + * + * ------ 1 section is 512 bytes ----- + * ------ Area0 Backup0 section from 0 to 511 -------- + * 1 section for file header [0] + * 1 section for used flags [1] + * - 1 byte = 2 flag + * 62 section for file tables [2-63] + * - size of table 128 bytes + * 447 section for data [64-510] + * 1 section for file footer [511] + * + * ------ Area0 Backup1 section from 512 to 1023 -------- + * 1 section for file header [512] + * 1 section for used flags [513] + * - 1 byte = 2 flag + * 62 section for file tables [514-575] + * - size of table 128 bytes + * 447 section for data [576-1022] + * 1 section for file footer [1023] + * + * ------ Area1 Backup0 section from 1024 to 1535 -------- + * 1 section for file header [1024] + * 1 section for used flags [1025] + * - 1 byte = 2 flag + * 62 section for file tables [1026-1087] + * - size of table 128 bytes + * 447 section for data [1088-1534] + * 1 section for file footer [1535] + * + * ------ Area1 Backup1 section from 1536 to 2047 -------- + * 1 section for file header [1536] + * 1 section for used flags [1537] + * - 1 byte = 2 flag + * 62 section for file tables [1538-1599] + * - size of table 128 bytes + * 447 section for data [1600-2046] + * 1 section for file footer [2047] + */ + +/* define for backup */ +#define RKSS_HEADER_INDEX 0 +#define RKSS_HEADER_COUNT 1 +#define RKSS_USEDFLAGS_INDEX 1 +#define RKSS_USEDFLAGS_COUNT 1 +#define RKSS_TABLE_INDEX 2 +#define RKSS_TABLE_COUNT 62 +#define RKSS_DATA_INDEX 64 +#define RKSS_DATA_COUNT 447 +#define RKSS_FOOTER_INDEX 511 +#define RKSS_FOOTER_COUNT 1 +#define RKSS_SECTION_COUNT 512 + +#define RKSS_MAX_AREA_NUM 8 +#define RKSS_ACTIVE_AREA_NUM 2 +#define RKSS_DATA_LEN 512 +#define RKSS_EACH_FILEFOLDER_COUNT 4 +#define RKSS_TABLE_SIZE 128 +#define RKSS_NAME_MAX_LENGTH 112 +#define RKSS_BACKUP_NUM 2 +#define RKSS_TAG 0x524B5353 + +struct rkss_file_header { + uint32_t tag; + uint32_t version; + uint32_t backup_count; + uint16_t backup_index; + uint16_t backup_dirty; + uint8_t reserve[496]; +}; +struct rkss_file_table { + uint32_t size; + uint16_t index; + uint8_t flags; + uint8_t used; + char name[RKSS_NAME_MAX_LENGTH]; + uint8_t reserve[8]; +}; +struct rkss_file_footer { + uint8_t reserve[508]; + uint32_t backup_count; +}; +struct rkss_file { + struct rkss_file_header *header; + uint8_t *flags; + struct rkss_file_table *table; + uint8_t *data; + struct rkss_file_footer *footer; +}; + +/* RK Secure Storage Calls */ +static char dir_cache[RKSS_NAME_MAX_LENGTH][12]; +static int dir_num; +static int dir_seek; +static uint8_t *rkss_buffer[RKSS_MAX_AREA_NUM]; +static struct rkss_file rkss_info[RKSS_MAX_AREA_NUM]; + +static struct blk_desc *dev_desc; +static disk_partition_t part_info; + +static int check_security_exist(int print_flag) +{ + if (!dev_desc) { + dev_desc = rockchip_get_bootdev(); + if (!dev_desc) { + printf("TEEC: %s: Could not find device\n", __func__); + return -1; + } + + if (part_get_info_by_name(dev_desc, + "security", &part_info) < 0) { + dev_desc = NULL; + if (print_flag != 0) + printf("TEEC: Could not find security partition\n"); + return -1; + } + } + return 0; +} + +static int rkss_verify_usedflags(unsigned int area_index) +{ + uint8_t *flags; + int i, duel, flag, n, value; + uint8_t *flagw; + int used_count; + + if (area_index >= RKSS_MAX_AREA_NUM) { + printf("TEEC: Not support area_index 0x%x\n", area_index); + return -1; + } + + flags = rkss_info[area_index].flags; + if (flags == NULL) { + printf("TEEC: %s flags is null\n", __func__); + return -1; + } + + used_count = RKSS_HEADER_COUNT + + RKSS_USEDFLAGS_COUNT + + RKSS_TABLE_COUNT; + + for (i = 0; i < used_count; i++) { + duel = *(flags + (int)i/2); + flag = i & 0x1 ? duel & 0x0F : (duel & 0xF0) >> 4; + if (flag != 0x1) + goto init; + } + + for (i = RKSS_FOOTER_INDEX; i < RKSS_USEDFLAGS_COUNT * RKSS_DATA_LEN * 2; i++) { + duel = *(flags + (int)i/2); + flag = i & 0x1 ? duel & 0x0F : (duel & 0xF0) >> 4; + if (flag != 0x1) + goto init; + } + + debug("TEEC: %s: success.\n", __func__); + return 0; + +init: + debug("TEEC: init usedflags section ...\n"); + memset(flags, 0, RKSS_USEDFLAGS_COUNT * RKSS_DATA_LEN); + for (n = 0; n < used_count; n++) { + flagw = flags + (int)n/2; + value = 0x1; + *flagw = n & 0x1 ? (*flagw & 0xF0) | (value & 0x0F) : + (*flagw & 0x0F) | (value << 4); + } + + for (n = RKSS_FOOTER_INDEX; n < RKSS_USEDFLAGS_COUNT * RKSS_DATA_LEN * 2; n++) { + flagw = flags + (int)n/2; + value = 0x1; + *flagw = n & 0x1 ? (*flagw & 0xF0) | (value & 0x0F) : + (*flagw & 0x0F) | (value << 4); + } + return 0; +} + +#ifdef DEBUG_CLEAN_RKSS +static int rkss_storage_delete(uint32_t area_index) +{ + int ret; + uint32_t size; + uint8_t *delete_buff; + + if (area_index >= RKSS_MAX_AREA_NUM) { + printf("TEEC: Not support area_index 0x%x\n", area_index); + return -1; + } + + printf("TEEC: delete area index 0x%x!\n", area_index); + size = RKSS_SECTION_COUNT * RKSS_BACKUP_NUM * RKSS_DATA_LEN; + delete_buff = (uint8_t *)malloc(size); + if (!delete_buff) { + printf("TEEC: Malloc failed!\n"); + return -1; + } + memset(delete_buff, 0, size); + ret = blk_dwrite(dev_desc, + part_info.start + area_index * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM, + RKSS_SECTION_COUNT * RKSS_BACKUP_NUM, delete_buff); + if (ret != RKSS_SECTION_COUNT * RKSS_BACKUP_NUM) { + free(delete_buff); + printf("TEEC: blk_dwrite fail\n"); + return -1; + } + + if (delete_buff) + free(delete_buff); + printf("TEEC: delete area success!\n"); + return 0; +} + +static int rkss_storage_reset(void) +{ + if (rkss_storage_delete(0) < 0) + return -1; + if (rkss_storage_delete(1) < 0) + return -1; + return 0; +} +#endif + +#ifdef DEBUG_RKSS +static void rkss_dump(void *data, unsigned int len) +{ + char *p = (char *)data; + unsigned int i = 0; + + printf("-------------- DUMP %d --------------\n", len); + for (i = 0; i < len; i++) { + if (i % 32 == 0) + printf("\n"); + printf("%02x ", *(p + i)); + } + printf("\n"); + printf("------------- DUMP END -------------\n"); +} + +static void rkss_dump_ptable(void) +{ + int i, j, n; + struct rkss_file_table *ptable; + + printf("-------------- DUMP ptable --------------\n"); + + for (i = 0; i < RKSS_MAX_AREA_NUM; i++) { + ptable = rkss_info[i].table; + if (rkss_info[i].table == NULL) + continue; + printf("--------------- area[%d] tables ------------\n", i); + for (j = 0; j < RKSS_TABLE_COUNT; j++) { + for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) { + printf("[%02d][%c] %s , inx:%d, size:%d\n", + j * RKSS_EACH_FILEFOLDER_COUNT + n, + ptable->used == 0 ? 'F':'T', ptable->name, + ptable->index, ptable->size); + + ptable++; + } + } + } + printf("-------------- DUMP END --------------\n"); +} + +static void rkss_dump_usedflags(void) +{ + int i; + + for (i = 0; i < RKSS_MAX_AREA_NUM; i++) { + if (rkss_info[i].flags == NULL) + continue; + printf("--------------- area[%d] flags ------------\n", i); + rkss_dump(rkss_info[i].flags, RKSS_USEDFLAGS_COUNT * RKSS_DATA_LEN); + } +} +#endif + +static int rkss_read_multi_sections(unsigned int area_index, + unsigned char *data, unsigned long index, unsigned int num) +{ + if (area_index >= RKSS_MAX_AREA_NUM) { + printf("TEEC: %s area_index invalid\n", __func__); + return -1; + } + if (index >= RKSS_SECTION_COUNT || num > RKSS_SECTION_COUNT || + (index + num) > RKSS_SECTION_COUNT) { + printf("TEEC: %s index num invalid\n", __func__); + return -1; + } + if (rkss_buffer[area_index] == NULL) { + printf("TEEC: %s rkss_buffer is null\n", __func__); + return -1; + } + memcpy(data, rkss_buffer[area_index] + index * RKSS_DATA_LEN, num * RKSS_DATA_LEN); + return 0; +} + +static int rkss_write_multi_sections(unsigned int area_index, + unsigned char *data, unsigned long index, unsigned int num) +{ + if (num == 0) + return 0; + + if (area_index >= RKSS_MAX_AREA_NUM) { + printf("TEEC: %s area_index invalid\n", __func__); + return -1; + } + + if (index >= RKSS_SECTION_COUNT || num > RKSS_SECTION_COUNT || + (index + num) > RKSS_SECTION_COUNT) { + printf("TEEC: %s index num invalid\n", __func__); + return -1; + } + + if (rkss_buffer[area_index] == NULL) { + printf("TEEC: %s rkss_buffer is null\n", __func__); + return -1; + } + + memcpy(rkss_buffer[area_index] + index * RKSS_DATA_LEN, data, num * RKSS_DATA_LEN); + rkss_info[area_index].header->backup_dirty = 1; + return 0; +} + +static int rkss_get_fileinfo_by_index(int fd, + struct rkss_file_table *ptable, unsigned int *out_area_index) +{ + struct rkss_file_table *p; + unsigned int area_index; + + area_index = fd / (RKSS_TABLE_COUNT * RKSS_EACH_FILEFOLDER_COUNT); + if (area_index >= RKSS_MAX_AREA_NUM) { + printf("TEEC: %s area_index invalid\n", __func__); + return -1; + } + + p = rkss_info[area_index].table; + if (p == NULL) { + printf("TEEC: %s table is null\n", __func__); + return -1; + } + + p += fd % (RKSS_TABLE_COUNT * RKSS_EACH_FILEFOLDER_COUNT); + if (p->used != 1) { + debug("TEEC: %s unused table!\n", __func__); + return -1; + } + debug("TEEC: %s p->used = %d p->name=%s p->index=%d p->size=%d\n", + __func__, p->used, p->name, p->index, p->size); + memcpy(ptable, p, sizeof(struct rkss_file_table)); + *out_area_index = area_index; + return 0; +} + +static int rkss_get_fileinfo_by_name(char *filename, + struct rkss_file_table *ptable, unsigned int *out_area_index) +{ + int ret; + unsigned int i, j, n, len; + struct rkss_file_table *p; + + len = strlen(filename); + if (len > RKSS_NAME_MAX_LENGTH - 1) { + printf("TEEC: filename is too long. length:%u\n", len); + return -1; + } + + for (i = 0; i < RKSS_MAX_AREA_NUM; i++) { + if (rkss_info[i].table == NULL) + continue; + for (j = 0; j < RKSS_TABLE_COUNT; j++) { + for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) { + p = rkss_info[i].table + j * RKSS_EACH_FILEFOLDER_COUNT + n; + + if (p->used == 0) + continue; + + if (!strcmp(p->name, filename)) { + debug("TEEC: %s: area%d hit table[%d/%d], index[%d/%d]\n", + __func__, i, j, RKSS_TABLE_COUNT, n, RKSS_EACH_FILEFOLDER_COUNT); + memcpy(ptable, p, sizeof(struct rkss_file_table)); + *out_area_index = i; + ret = i * RKSS_TABLE_COUNT * RKSS_EACH_FILEFOLDER_COUNT + + j * RKSS_EACH_FILEFOLDER_COUNT + n; + return ret; + } + + // Folder Matching + const char *split = "/"; + char *last_inpos = filename; + char *last_svpos = p->name; + char *cur_inpos = NULL; + char *cur_svpos = NULL; + + do { + cur_inpos = strstr(last_inpos, split); + cur_svpos = strstr(last_svpos, split); + int size_in = cur_inpos == NULL ? + (int)strlen(last_inpos) : cur_inpos - last_inpos; + int size_sv = cur_svpos == NULL ? + (int)strlen(last_svpos) : cur_svpos - last_svpos; + + ret = memcmp(last_inpos, last_svpos, size_in); + + last_inpos = cur_inpos + 1; + last_svpos = cur_svpos + 1; + + if (size_in != size_sv || ret) + goto UNMATCHFOLDER; + + } while (cur_inpos && cur_svpos); + + debug("TEEC: Matched folder: %s\n", p->name); + return -100; +UNMATCHFOLDER: + debug("TEEC: Unmatched ..."); + } + } + } + debug("TEEC: %s: file or dir no found!\n", __func__); + return -1; +} + +static int rkss_get_dirs_by_name(char *filename) +{ + int ret; + unsigned int i, j, n, len; + struct rkss_file_table *p; + + len = strlen(filename); + if (len > RKSS_NAME_MAX_LENGTH - 1) { + printf("TEEC: filename is too long. length:%u\n", len); + return -1; + } + + dir_num = 0; + for (i = 0; i < RKSS_MAX_AREA_NUM; i++) { + if (rkss_info[i].table == NULL) + continue; + for (j = 0; j < RKSS_TABLE_COUNT; j++) { + for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) { + p = rkss_info[i].table + j * RKSS_EACH_FILEFOLDER_COUNT + n; + + if (p->used == 0) + continue; + + // Full Matching + ret = memcmp(p->name, filename, strlen(filename)); + debug("TEEC: comparing [fd:%d] : %s ?= %s, ret: %d\n", + (i * RKSS_TABLE_COUNT + j) * RKSS_EACH_FILEFOLDER_COUNT + n, + p->name, filename, ret); + if (!ret && strlen(p->name) > strlen(filename)) { + char *chk = p->name + strlen(filename); + if (*chk == '/') { + char *file = p->name + strlen(filename) + 1; + char *subdir = strtok(file, "/"); + debug("TEEC: found: %s\n", subdir); + strcpy(dir_cache[dir_num], subdir); + ++dir_num; + } + } + } + } + } + return dir_num; +} + +static int rkss_get_empty_section_from_usedflags( + unsigned int area_index, int section_size) +{ + int i = 0; + int count0 = 0; + + if (area_index >= RKSS_MAX_AREA_NUM) { + printf("TEEC: %s area_index invalid\n", __func__); + return -1; + } + if (rkss_info[area_index].flags == NULL) { + printf("TEEC: %s flags is null\n", __func__); + return -1; + } + for (i = 0; i < RKSS_SECTION_COUNT; i++) { + uint8_t *flag = rkss_info[area_index].flags + (int)i/2; + uint8_t value = i & 0x1 ? *flag & 0x0F : (*flag & 0xF0) >> 4; + + if (value == 0x0) { + if (++count0 == section_size) + return (i + 1 - section_size); + } else { + count0 = 0; + } + } + + printf("TEEC: Not enough space available in secure storage !\n"); + return -10; +} + +static int rkss_incref_multi_usedflags_sections( + unsigned int area_index, unsigned int index, unsigned int num) +{ + int value, i; + uint8_t *flag; + + if (area_index >= RKSS_MAX_AREA_NUM) { + printf("TEEC: %s area_index invalid\n", __func__); + return -1; + } + + if (index >= RKSS_SECTION_COUNT || num > RKSS_SECTION_COUNT || + (index + num) > RKSS_SECTION_COUNT) { + printf("TEEC: index[%d] out of range.\n", index); + return -1; + } + if (rkss_info[area_index].flags == NULL) { + printf("TEEC: %s flags is null\n", __func__); + return -1; + } + + for (i = 0; i < num; i++, index++) { + flag = rkss_info[area_index].flags + (int)index / 2; + value = index & 0x1 ? *flag & 0x0F : (*flag & 0xF0) >> 4; + if (++value > 0xF) { + printf("TEEC: reference out of data: %d\n", value); + value = 0xF; + } + *flag = index & 0x1 ? (*flag & 0xF0) | (value & 0x0F) : + (*flag & 0x0F) | (value << 4); + } + rkss_info[area_index].header->backup_dirty = 1; + return 0; +} + +static int rkss_decref_multi_usedflags_sections( + unsigned int area_index, unsigned int index, unsigned int num) +{ + int value, i; + uint8_t *flag; + + if (area_index >= RKSS_MAX_AREA_NUM) { + printf("TEEC: %s area_index invalid\n", __func__); + return -1; + } + + if (index >= RKSS_SECTION_COUNT || num > RKSS_SECTION_COUNT || + (index + num) > RKSS_SECTION_COUNT) { + printf("TEEC: index[%d] out of range.\n", index); + return -1; + } + if (rkss_info[area_index].flags == NULL) { + printf("TEEC: %s flags is null\n", __func__); + return -1; + } + + for (i = 0; i < num; i++, index++) { + flag = rkss_info[area_index].flags + (int)index / 2; + value = index & 0x1 ? *flag & 0x0F : (*flag & 0xF0) >> 4; + if (--value < 0) { + printf("TEEC: reference out of data: %d\n", value); + value = 0x0; + } + *flag = index & 0x1 ? (*flag & 0xF0) | (value & 0x0F) : + (*flag & 0x0F) | (value << 4); + } + rkss_info[area_index].header->backup_dirty = 1; + return 0; +} + +static int rkss_get_remain_tables(struct rkss_file_table *p) +{ + unsigned int i, n; + int count = 0; + + if (p == NULL) + return -1; + + for (i = 0; i < RKSS_TABLE_COUNT; i++) { + for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) { + if (p->used == 0) + count++; + p++; + } + } + return count; +} + +static int rkss_get_remain_flags(uint8_t *flags) +{ + unsigned int i, value; + uint8_t *flag; + int count = 0; + + if (flags == NULL) + return -1; + + for (i = 0; i < RKSS_SECTION_COUNT; i++) { + flag = flags + (int)i / 2; + value = i & 0x1 ? *flag & 0x0F : (*flag & 0xF0) >> 4; + if (value == 0) + count++; + } + return count; +} + +static int rkss_get_larger_area(void) +{ + int i, tables, flags, max_flags = 0; + int area_index = -1; + + for (i = 0; i < RKSS_MAX_AREA_NUM; i++) { + if (rkss_info[i].table == NULL || + rkss_info[i].flags == NULL) + continue; + tables = rkss_get_remain_tables(rkss_info[i].table); + flags = rkss_get_remain_flags(rkss_info[i].flags); + if (tables > 0 && flags > 0 && flags > max_flags) { + max_flags = flags; + area_index = i; + } + } + return area_index; +} + +static int rkss_write_area_empty_ptable( + unsigned int area_index, struct rkss_file_table *pfile_table) +{ + int i, n, ret; + struct rkss_file_table *p; + + if (rkss_info[area_index].table == NULL) { + printf("TEEC: %s table is null\n", __func__); + return -1; + } + for (i = 0; i < RKSS_TABLE_COUNT; i++) { + for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) { + p = rkss_info[area_index].table + i * RKSS_EACH_FILEFOLDER_COUNT + n; + if (p->used == 0) { + memcpy(p, pfile_table, sizeof(struct rkss_file_table)); + p->used = 1; + debug("TEEC: write emt ptable : [%d,%d] name:%s, index:%d, size:%d, used:%d\n", + i, n, p->name, p->index, p->size, p->used); + rkss_info[area_index].header->backup_dirty = 1; + ret = area_index * RKSS_TABLE_COUNT * RKSS_EACH_FILEFOLDER_COUNT + + i * RKSS_EACH_FILEFOLDER_COUNT + n; + return ret; + } + } + } + printf("TEEC: No enough ptable space available in secure storage.\n"); + return -1; +} + +static int rkss_write_empty_ptable(struct rkss_file_table *pfile_table) +{ + int area_index; + + area_index = rkss_get_larger_area(); + if (area_index < 0) { + printf("TEEC: get area index fail\n"); + return -1; + } + + return rkss_write_area_empty_ptable(area_index, pfile_table); +} + +static int rkss_write_back_ptable( + int fd, struct rkss_file_table *pfile_table) +{ + struct rkss_file_table *p; + unsigned int area_index; + + area_index = fd / (RKSS_TABLE_COUNT * RKSS_EACH_FILEFOLDER_COUNT); + if (area_index >= RKSS_MAX_AREA_NUM) { + printf("TEEC: %s area_index invalid\n", __func__); + return -1; + } + + p = rkss_info[area_index].table; + if (p == NULL) { + printf("TEEC: %s table is null\n", __func__); + return -1; + } + + p += fd % (RKSS_TABLE_COUNT * RKSS_EACH_FILEFOLDER_COUNT); + + memcpy(p, pfile_table, sizeof(struct rkss_file_table)); + debug("TEEC: write ptable : name:%s, index:%d, size:%d, used:%d\n", + p->name, p->index, p->size, p->used); + + rkss_info[area_index].header->backup_dirty = 1; + return 0; +} + +static int rkss_storage_write(void) +{ + int ret, i; + + for (i = 0; i < RKSS_MAX_AREA_NUM; i++) { + if (rkss_info[i].header != NULL && rkss_info[i].header->backup_dirty == 1) { + rkss_info[i].header->backup_count++; + rkss_info[i].footer->backup_count = rkss_info[i].header->backup_count; + rkss_info[i].header->backup_index++; + if (rkss_info[i].header->backup_index >= RKSS_BACKUP_NUM) + rkss_info[i].header->backup_index = 0; + rkss_info[i].header->backup_dirty = 0; + + if (rkss_info[i].header->backup_count == 0xffffffff) { + rkss_info[i].header->backup_count = 1; + rkss_info[i].footer->backup_count = 1; + ret = blk_dwrite(dev_desc, + part_info.start + i * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM + + rkss_info[i].header->backup_index * RKSS_SECTION_COUNT, + RKSS_SECTION_COUNT, rkss_buffer[i]); + if (ret != RKSS_SECTION_COUNT) { + printf("TEEC: blk_dwrite fail\n"); + return -1; + } + + rkss_info[i].header->backup_count = 2; + rkss_info[i].footer->backup_count = 2; + rkss_info[i].header->backup_index++; + if (rkss_info[i].header->backup_index >= RKSS_BACKUP_NUM) + rkss_info[i].header->backup_index = 0; + ret = blk_dwrite(dev_desc, + part_info.start + i * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM + + rkss_info[i].header->backup_index * RKSS_SECTION_COUNT, + RKSS_SECTION_COUNT, rkss_buffer[i]); + if (ret != RKSS_SECTION_COUNT) { + printf("TEEC: blk_dwrite fail\n"); + return -1; + } + } else { + ret = blk_dwrite(dev_desc, + part_info.start + i * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM + + rkss_info[i].header->backup_index * RKSS_SECTION_COUNT, + RKSS_SECTION_COUNT, rkss_buffer[i]); + if (ret != RKSS_SECTION_COUNT) { + printf("TEEC: blk_dwrite fail\n"); + return -1; + } + } + } + } + return 0; +} + +static int rkss_storage_init(uint32_t area_index) +{ + unsigned long ret = 0; + uint32_t size, i; + uint32_t max_ver = 0; + uint32_t max_index = 0; + uint32_t flags_offset, table_offset, data_offset, footer_offset; + + if (area_index >= RKSS_MAX_AREA_NUM) { + printf("TEEC: Not support index=0x%x\n", area_index); + return -1; + } + + size = RKSS_SECTION_COUNT * RKSS_DATA_LEN; + flags_offset = RKSS_USEDFLAGS_INDEX * RKSS_DATA_LEN; + table_offset = RKSS_TABLE_INDEX * RKSS_DATA_LEN; + data_offset = RKSS_DATA_INDEX * RKSS_DATA_LEN; + footer_offset = RKSS_FOOTER_INDEX * RKSS_DATA_LEN; + + if (rkss_buffer[area_index] == NULL) { + /* Always use, no need to release */ + rkss_buffer[area_index] = (uint8_t *)malloc(size); + if (!(rkss_buffer[area_index])) { + printf("TEEC: Malloc failed!\n"); + return -1; + } + + /* Pointer initialization */ + rkss_info[area_index].header = (struct rkss_file_header *)(rkss_buffer[area_index]); + rkss_info[area_index].flags = (uint8_t *)(rkss_buffer[area_index] + flags_offset); + rkss_info[area_index].table = (struct rkss_file_table *)(rkss_buffer[area_index] + table_offset); + rkss_info[area_index].data = (uint8_t *)(rkss_buffer[area_index] + data_offset); + rkss_info[area_index].footer = (struct rkss_file_footer *)(rkss_buffer[area_index] + footer_offset); + + /* Find valid from (backup0 - backup1) */ + for (i = 0; i < RKSS_BACKUP_NUM; i++) { + ret = blk_dread(dev_desc, + part_info.start + + area_index * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM + + i * RKSS_SECTION_COUNT, + RKSS_SECTION_COUNT, rkss_buffer[area_index]); + if (ret != RKSS_SECTION_COUNT) { + printf("TEEC: blk_dread fail\n"); + return -1; + } + + if ((rkss_info[area_index].header->tag == RKSS_TAG) && + (rkss_info[area_index].footer->backup_count == rkss_info[area_index].header->backup_count)) { + if (max_ver < rkss_info[area_index].header->backup_count) { + max_index = i; + max_ver = rkss_info[area_index].header->backup_count; + } + } + } + + if (max_ver) { + debug("TEEC: max_ver=%d, max_index=%d.\n", + max_ver, max_index); + + if (max_index != (RKSS_BACKUP_NUM - 1)) { + ret = blk_dread(dev_desc, + part_info.start + + area_index * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM + + max_index * RKSS_SECTION_COUNT, + RKSS_SECTION_COUNT, rkss_buffer[area_index]); + if (ret != RKSS_SECTION_COUNT) { + printf("TEEC: blk_dread fail\n"); + return -1; + } + } + + if (rkss_info[area_index].header->version == RKSS_VERSION_V2) { + debug("TEEC: data version equal to image version, do nothing!\n"); + } else if (rkss_info[area_index].header->version < RKSS_VERSION_V2) { + printf("TEEC: data version lower than image version!\n"); + /* convert rkss version 2 to higher rkss version */ + free(rkss_buffer[area_index]); + rkss_buffer[area_index] = NULL; + return -1; + } else { + printf("TEEC: data version higher than image version!\n"); + printf("TEEC: please update image!\n"); + free(rkss_buffer[area_index]); + rkss_buffer[area_index] = NULL; + return -1; + } + } else { + printf("TEEC: Reset area[%d] info...\n", area_index); + memset(rkss_buffer[area_index], 0, size); + rkss_info[area_index].header->tag = RKSS_TAG; + rkss_info[area_index].header->version = RKSS_VERSION_V2; + rkss_info[area_index].header->backup_count = 1; + rkss_info[area_index].footer->backup_count = 1; + /* Verify Usedflags Section */ + if (rkss_verify_usedflags(area_index) < 0) { + printf("TEEC: rkss_verify_usedflags fail !\n"); + return -1; + } + } + } + return 0; +} + +static uint32_t ree_fs_new_open(size_t num_params, + struct tee_ioctl_param *params) +{ + char *filename; + int fd; + struct rkss_file_table p = {0}; + unsigned int area_index; + + debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n", + params[1].u.memref.shm_id, params[1].u.memref.shm_offs); + + filename = (char *)(size_t)params[1].u.memref.shm_id; + if (!filename) + return TEEC_ERROR_BAD_PARAMETERS; + + if (strlen(filename) > RKSS_NAME_MAX_LENGTH) { + printf("TEEC: %s: file name too long. %s\n", __func__, filename); + return TEEC_ERROR_BAD_PARAMETERS; + } + + debug("TEEC: %s open file: %s, len: %zu\n", + __func__, filename, strlen(filename)); + fd = rkss_get_fileinfo_by_name(filename, &p, &area_index); + if (fd < 0) { + printf("TEEC: %s : no such file. %s\n", __func__, filename); + return TEEC_ERROR_ITEM_NOT_FOUND; + } + + params[2].u.value.a = fd; + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_create(size_t num_params, + struct tee_ioctl_param *params) +{ + char *filename; + int fd; + int ret, num; + struct rkss_file_table p = {0}; + unsigned int area_index; + /* file open flags: O_RDWR | O_CREAT | O_TRUNC + * if file exists, we must remove it first. + */ + filename = (char *)(size_t)params[1].u.memref.shm_id; + debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n", + params[1].u.memref.shm_id, params[1].u.memref.shm_offs); + if (!filename) + return TEEC_ERROR_BAD_PARAMETERS; + + if (strlen(filename) > RKSS_NAME_MAX_LENGTH) { + printf("TEEC: %s: file name too long. %s\n", __func__, filename); + return TEEC_ERROR_BAD_PARAMETERS; + } + + debug("TEEC: %s create file: %s, len: %zu\n", + __func__, filename, strlen(filename)); + fd = rkss_get_fileinfo_by_name(filename, &p, &area_index); + if (fd >= 0) { + printf("TEEC: %s : file exist, clear it. %s\n", __func__, filename); + /* decrease ref from usedflags */ + num = p.size / RKSS_DATA_LEN + 1; + ret = rkss_decref_multi_usedflags_sections(area_index, p.index, num); + if (ret < 0) { + printf("TEEC: rkss_decref_multi_usedflags_sections error !\n"); + return TEEC_ERROR_GENERIC; + } + + /* rm from ptable */ + memset(&p, 0, sizeof(struct rkss_file_table)); + ret = rkss_write_back_ptable(fd, &p); + if (ret < 0) { + printf("TEEC: %s : write back error %d\n", __func__, ret); + return TEEC_ERROR_GENERIC; + } + } + + strcpy(p.name, filename); + p.index = 0; + p.size = 0; + p.used = 1; + p.flags = RK_FS_R | RK_FS_W; + fd = rkss_write_empty_ptable(&p); + if (fd < 0) { + printf("TEEC: %s : write empty ptable error. %s\n", __func__, filename); + return TEEC_ERROR_GENERIC; + } + + params[2].u.value.a = fd; + + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_close(size_t num_params, + struct tee_ioctl_param *params) +{ + debug("TEEC: %s !\n", __func__); + UNREFERENCED_PARAMETER(params); + UNREFERENCED_PARAMETER(num_params); + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_read(size_t num_params, + struct tee_ioctl_param *params) +{ + uint8_t *data; + size_t len; + off_t offs; + int fd; + int ret; + struct rkss_file_table p = {0}; + int di, section_num; + uint8_t *temp_file_data; + unsigned int area_index; + + fd = params[0].u.value.b; + offs = params[0].u.value.c; + + data = (uint8_t *)(size_t)params[1].u.memref.shm_id; + debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n", + params[1].u.memref.shm_id, params[1].u.memref.shm_offs); + + if (!data) + return TEEC_ERROR_BAD_PARAMETERS; + len = params[1].u.memref.size; + + debug("TEEC: %s! fd:%d, len:%zu, offs:%ld\n", + __func__, fd, len, offs); + + ret = rkss_get_fileinfo_by_index(fd, &p, &area_index); + if (ret < 0) { + printf("TEEC: unavailable fd: %d!\n", fd); + return TEEC_ERROR_GENERIC; + } + + if (offs >= p.size) + return TEEC_ERROR_BAD_PARAMETERS; + + section_num = p.size / RKSS_DATA_LEN + 1; + temp_file_data = malloc(section_num * RKSS_DATA_LEN); + ret = rkss_read_multi_sections(area_index, temp_file_data, p.index, section_num); + if (ret < 0) { + printf("TEEC: unavailable file index!\n"); + free(temp_file_data); + return TEEC_ERROR_GENERIC; + } + di = (offs + len) > p.size ? (p.size - offs) : len; + memcpy(data, temp_file_data + offs, di); + free(temp_file_data); + temp_file_data = 0; + params[1].u.memref.size = di; + + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_write(size_t num_params, + struct tee_ioctl_param *params) +{ + uint8_t *data; + size_t len; + off_t offs; + struct rkss_file_table p = {0}; + int ret, fd, new_size; + int section_num; + uint8_t *file_data = 0, *temp_file_data = 0; + unsigned int area_index; + + fd = params[0].u.value.b; + offs = params[0].u.value.c; + + data = (uint8_t *)(size_t)params[1].u.memref.shm_id; + debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n", + params[1].u.memref.shm_id, params[1].u.memref.shm_offs); + if (!data) + return TEEC_ERROR_BAD_PARAMETERS; + len = params[1].u.memref.size; + + debug("TEEC: %s ! fd:%d, len:%zu, offs:%ld\n", + __func__, fd, len, offs); + + ret = rkss_get_fileinfo_by_index(fd, &p, &area_index); + if (ret < 0) { + printf("TEEC: %s: fd:%d unvailable!\n", __func__, fd); + return TEEC_ERROR_BAD_PARAMETERS; + } + + new_size = offs + len > p.size ? offs + len : p.size; + file_data = malloc(new_size); + if (!file_data) + return TEEC_ERROR_OUT_OF_MEMORY; + + if (p.size != 0) { + /* Read old file data out */ + section_num = p.size / RKSS_DATA_LEN + 1; + temp_file_data = malloc(section_num * RKSS_DATA_LEN); + ret = rkss_read_multi_sections(area_index, temp_file_data, p.index, section_num); + if (ret < 0) { + printf("TEEC: unavailable file index %d section_num %d\n", p.index, section_num); + ret = TEEC_ERROR_GENERIC; + goto out; + } + memcpy(file_data, temp_file_data, p.size); + free(temp_file_data); + temp_file_data = 0; + ret = rkss_decref_multi_usedflags_sections(area_index, p.index, section_num); + if (ret < 0) { + printf("TEEC: rkss_decref_multi_usedflags_sections error !\n"); + ret = TEEC_ERROR_GENERIC; + goto out; + } + } + + /* update new file info */ + memcpy(file_data + offs, data, len); + p.size = new_size; + section_num = new_size / RKSS_DATA_LEN + 1; + p.index = rkss_get_empty_section_from_usedflags(area_index, section_num); + debug("TEEC: Get Empty section in %d\n", p.index); + p.used = 1; + ret = rkss_incref_multi_usedflags_sections(area_index, p.index, section_num); + if (ret < 0) { + printf("TEEC: rkss_incref_multi_usedflags_sections error !\n"); + ret = TEEC_ERROR_GENERIC; + goto out; + } + + ret = rkss_write_back_ptable(fd, &p); + if (ret < 0) { + printf("TEEC: %s: write ptable error!\n", __func__); + ret = TEEC_ERROR_GENERIC; + goto out; + } + + /* write new file data */ + temp_file_data = malloc(section_num * RKSS_DATA_LEN); + memset(temp_file_data, 0, section_num * RKSS_DATA_LEN); + memcpy(temp_file_data, file_data, p.size); + rkss_write_multi_sections(area_index, temp_file_data, p.index, section_num); + free(temp_file_data); + temp_file_data = 0; + +out: + if (file_data) + free(file_data); + if (temp_file_data) { + free(temp_file_data); + temp_file_data = 0; + } + + return TEEC_SUCCESS; +} + +/* TODO: update file data space */ +static TEEC_Result ree_fs_new_truncate(size_t num_params, + struct tee_ioctl_param *params) +{ + size_t len; + int fd, ret; + struct rkss_file_table p = {0}; + unsigned int section_num_old, section_num_new; + unsigned int area_index; + + fd = params[0].u.value.b; + len = params[0].u.value.c; + + debug("TEEC: %s: fd:%d, lenth:%zu\n", __func__, fd, len); + + ret = rkss_get_fileinfo_by_index(fd, &p, &area_index); + if (ret < 0) { + printf("TEEC: fd:%d unvailable!\n", fd); + return TEEC_ERROR_GENERIC; + } + if (len > p.size) { + printf("TEEC: truncate error!\n"); + return TEEC_ERROR_GENERIC; + } + section_num_old = p.size / RKSS_DATA_LEN + 1; + section_num_new = len / RKSS_DATA_LEN + 1; + ret = rkss_decref_multi_usedflags_sections(area_index, p.index + section_num_new, section_num_old - section_num_new); + if (ret < 0) { + printf("TEEC: rkss_decref_multi_usedflags_sections error !\n"); + ret = TEEC_ERROR_GENERIC; + } + p.size = len; + ret = rkss_write_back_ptable(fd, &p); + if (ret < 0) { + printf("TEEC: %s: write ptable error!\n", __func__); + return TEEC_ERROR_GENERIC; + } + + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_remove(size_t num_params, + struct tee_ioctl_param *params) +{ + char *filename; + struct rkss_file_table p = {0}; + int ret, fd, num; + unsigned int area_index; + + debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n", + params[1].u.memref.shm_id, params[1].u.memref.shm_offs); + + filename = (char *)(size_t)params[1].u.memref.shm_id; + if (!filename) + return TEEC_ERROR_BAD_PARAMETERS; + + ret = rkss_get_fileinfo_by_name(filename, &p, &area_index); + if (ret < 0) { + printf("TEEC: %s: no such file. %s\n", __func__, filename); + return 0; + } + fd = ret; + + debug("TEEC: %s! %s fd:%d index:%d size:%d\n", + __func__, filename, fd, p.index, p.size); + + /* decrease ref from usedflags */ + num = p.size / RKSS_DATA_LEN + 1; + ret = rkss_decref_multi_usedflags_sections(area_index, p.index, num); + if (ret < 0) { + printf("TEEC: rkss_decref_multi_usedflags_sections error !\n"); + return TEEC_ERROR_GENERIC; + } + + /* rm from ptable */ + memset(&p, 0, sizeof(struct rkss_file_table)); + ret = rkss_write_back_ptable(fd, &p); + if (ret < 0) { + printf("TEEC: %s: write back error %d\n", __func__, ret); + return TEEC_ERROR_GENERIC; + } + + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_rename(size_t num_params, + struct tee_ioctl_param *params) +{ + char *old_fname; + char *new_fname; + struct rkss_file_table p = {0}; + int ret; + unsigned int area_index; + + old_fname = (char *)(size_t)params[1].u.memref.shm_id; + debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n", + params[1].u.memref.shm_id, params[1].u.memref.shm_offs); + if (!old_fname) + return TEEC_ERROR_BAD_PARAMETERS; + + new_fname = (char *)(size_t)params[2].u.memref.shm_id; + debug("TEEC: params[2].u.memref.shm_id = 0x%llx params[2].u.memref.shm_offs = 0x%llx\n", + params[2].u.memref.shm_id, params[2].u.memref.shm_offs); + if (!new_fname) + return TEEC_ERROR_BAD_PARAMETERS; + + if (strlen(new_fname) > RKSS_NAME_MAX_LENGTH) { + printf("TEEC: new file name too long. %s\n", new_fname); + return TEEC_ERROR_BAD_PARAMETERS; + } + + debug("TEEC: rename: %s -> %s\n", old_fname, new_fname); + + ret = rkss_get_fileinfo_by_name(old_fname, &p, &area_index); + if (ret < 0) { + printf("TEEC: filename: %s no found.\n", old_fname); + return TEEC_ERROR_ITEM_NOT_FOUND; + } + + strcpy(p.name, new_fname); + + ret = rkss_write_back_ptable(ret, &p); + if (ret < 0) { + printf("TEEC: write ptable error!\n"); + return TEEC_ERROR_GENERIC; + } + + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_opendir(size_t num_params, + struct tee_ioctl_param *params) +{ + char *dirname; + int ret; + + debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n", + params[1].u.memref.shm_id, params[1].u.memref.shm_offs); + + dirname = (char *)(size_t)params[1].u.memref.shm_id; + if (!dirname) + return TEEC_ERROR_BAD_PARAMETERS; + + dir_seek = 0; + ret = rkss_get_dirs_by_name(dirname); + if (ret < 0) { + printf("TEEC: %s: error\n", __func__); + return TEEC_ERROR_GENERIC; + } + + debug("TEEC: %s: %s, seek/num:%d/%d\n", + __func__, dirname, dir_seek, dir_num); + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_closedir(size_t num_params, + struct tee_ioctl_param *params) +{ + if (num_params != 1 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) + return TEEC_ERROR_BAD_PARAMETERS; + + dir_seek = 0; + dir_num = 0; + + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_readdir(size_t num_params, + struct tee_ioctl_param *params) +{ + char *dirname; + size_t len; + size_t dirname_len; + + dirname = (char *)(size_t)params[1].u.memref.shm_id; + debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n", + params[1].u.memref.shm_id, params[1].u.memref.shm_offs); + if (!dirname) + return TEEC_ERROR_BAD_PARAMETERS; + len = params[1].u.memref.size; + + debug("TEEC: seek/num:%d/%d\n", dir_seek, dir_num); + if (dir_seek == dir_num) { + params[1].u.memref.size = 0; + debug("TEEC: %s: END\n", __func__); + return TEEC_ERROR_BAD_STATE; + } + + dirname_len = strlen(dir_cache[dir_seek]) + 1; + params[1].u.memref.size = dirname_len; + if (dirname_len > len) + return TEEC_ERROR_SHORT_BUFFER; + + strcpy(dirname, dir_cache[dir_seek]); + ++dir_seek; + + debug("TEEC: %s: %s\n", __func__, dirname); + + return TEEC_SUCCESS; +} + +int tee_supp_rk_fs_init_v2(void) +{ + assert(sizeof(struct rkss_file_table) == RKSS_TABLE_SIZE); + assert(RKSS_DATA_LEN / sizeof(struct rkss_file_table) == RKSS_EACH_FILEFOLDER_COUNT); + + if (check_security_exist(0) < 0) + return 0; + + /* clean secure storage */ +#ifdef DEBUG_CLEAN_RKSS + if (rkss_storage_reset() < 0) + return -1; +#endif + + for (uint32_t i = 0; i < RKSS_ACTIVE_AREA_NUM; i++) { + if (rkss_storage_init(i) < 0) + return -1; + } + +#ifdef DEBUG_RKSS + rkss_dump_ptable(); + rkss_dump_usedflags(); +#endif + + return 0; +} + +static bool tee_supp_param_is_value(struct tee_ioctl_param *param) +{ + switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: + return true; + default: + return false; + } +} + +static int rkss_step; +int tee_supp_rk_fs_process_v2(size_t num_params, + struct tee_ioctl_param *params) +{ + uint32_t ret; + + if (!num_params || !tee_supp_param_is_value(params)) + return TEEC_ERROR_BAD_PARAMETERS; + + switch (params->u.value.a) { + case OPTEE_MRF_OPEN: + debug(">>>>>>> [%d] OPTEE_MRF_OPEN!\n", rkss_step++); + ret = ree_fs_new_open(num_params, params); + break; + case OPTEE_MRF_CREATE: + debug(">>>>>>> [%d] OPTEE_MRF_CREATE!\n", rkss_step++); + ret = ree_fs_new_create(num_params, params); + break; + case OPTEE_MRF_CLOSE: + debug(">>>>>>> [%d] OPTEE_MRF_CLOSE!\n", rkss_step++); + ret = ree_fs_new_close(num_params, params); + rkss_storage_write(); + break; + case OPTEE_MRF_READ: + debug(">>>>>>> [%d] OPTEE_MRF_READ!\n", rkss_step++); + ret = ree_fs_new_read(num_params, params); + break; + case OPTEE_MRF_WRITE: + debug(">>>>>>> [%d] OPTEE_MRF_WRITE!\n", rkss_step++); + ret = ree_fs_new_write(num_params, params); + break; + case OPTEE_MRF_TRUNCATE: + debug(">>>>>>> [%d] OPTEE_MRF_TRUNCATE!\n", rkss_step++); + ret = ree_fs_new_truncate(num_params, params); + break; + case OPTEE_MRF_REMOVE: + debug(">>>>>>> [%d] OPTEE_MRF_REMOVE!\n", rkss_step++); + ret = ree_fs_new_remove(num_params, params); + rkss_storage_write(); + break; + case OPTEE_MRF_RENAME: + debug(">>>>>>> [%d] OPTEE_MRF_RENAME!\n", rkss_step++); + ret = ree_fs_new_rename(num_params, params); + rkss_storage_write(); + break; + case OPTEE_MRF_OPENDIR: + debug(">>>>>>> [%d] OPTEE_MRF_OPENDIR!\n", rkss_step++); + ret = ree_fs_new_opendir(num_params, params); + break; + case OPTEE_MRF_CLOSEDIR: + debug(">>>>>>> [%d] OPTEE_MRF_CLOSEDIR!\n", rkss_step++); + ret = ree_fs_new_closedir(num_params, params); + break; + case OPTEE_MRF_READDIR: + debug(">>>>>>> [%d] OPTEE_MRF_READDIR!\n", rkss_step++); + ret = ree_fs_new_readdir(num_params, params); + break; + default: + ret = TEEC_ERROR_BAD_PARAMETERS; + break; + } + return ret; +}