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; +}