11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2b48323a9SJerome Forissier /*
3b48323a9SJerome Forissier * Copyright (c) 2016, Linaro Limited
4b48323a9SJerome Forissier */
5b48323a9SJerome Forissier
6b48323a9SJerome Forissier #include <assert.h>
7b2215adfSJens Wiklander #include <kernel/tee_misc.h>
8b48323a9SJerome Forissier #include <kernel/thread.h>
9b48323a9SJerome Forissier #include <mm/core_memprot.h>
106009538cSJens Wiklander #include <optee_rpc_cmd.h>
11b48323a9SJerome Forissier #include <stdlib.h>
12*45ffd851SJerome Forissier #include <tee/fs_dirfile.h>
13b48323a9SJerome Forissier #include <tee/tee_fs.h>
14b48323a9SJerome Forissier #include <tee/tee_fs_rpc.h>
15b48323a9SJerome Forissier #include <trace.h>
16b48323a9SJerome Forissier #include <util.h>
17b48323a9SJerome Forissier
18b48323a9SJerome Forissier struct tee_fs_dir {
19b48323a9SJerome Forissier int nw_dir;
20b48323a9SJerome Forissier struct tee_fs_dirent d;
21b48323a9SJerome Forissier };
22b48323a9SJerome Forissier
23*45ffd851SJerome Forissier /* "/dirf.db" or "/<file number>" */
create_filename(void * buf,size_t blen,const struct tee_fs_dirfile_fileh * dfh)24*45ffd851SJerome Forissier static TEE_Result create_filename(void *buf, size_t blen,
25*45ffd851SJerome Forissier const struct tee_fs_dirfile_fileh *dfh)
26*45ffd851SJerome Forissier {
27*45ffd851SJerome Forissier char *file = buf;
28*45ffd851SJerome Forissier size_t pos = 0;
29*45ffd851SJerome Forissier size_t l;
30*45ffd851SJerome Forissier
31*45ffd851SJerome Forissier if (pos >= blen)
32*45ffd851SJerome Forissier return TEE_ERROR_SHORT_BUFFER;
33*45ffd851SJerome Forissier
34*45ffd851SJerome Forissier file[pos] = '/';
35*45ffd851SJerome Forissier pos++;
36*45ffd851SJerome Forissier if (pos >= blen)
37*45ffd851SJerome Forissier return TEE_ERROR_SHORT_BUFFER;
38*45ffd851SJerome Forissier
39*45ffd851SJerome Forissier l = blen - pos;
40*45ffd851SJerome Forissier return tee_fs_dirfile_fileh_to_fname(dfh, file + pos, &l);
41*45ffd851SJerome Forissier }
42*45ffd851SJerome Forissier
operation_commit(struct tee_fs_rpc_operation * op)437f4173d8SJens Wiklander static TEE_Result operation_commit(struct tee_fs_rpc_operation *op)
447f4173d8SJens Wiklander {
457f4173d8SJens Wiklander return thread_rpc_cmd(op->id, op->num_params, op->params);
467f4173d8SJens Wiklander }
477f4173d8SJens Wiklander
operation_open_dfh(uint32_t id,unsigned int cmd,const struct tee_fs_dirfile_fileh * dfh,int * fd)4822efbd4aSJens Wiklander static TEE_Result operation_open_dfh(uint32_t id, unsigned int cmd,
4922efbd4aSJens Wiklander const struct tee_fs_dirfile_fileh *dfh,
5022efbd4aSJens Wiklander int *fd)
5122efbd4aSJens Wiklander {
5286eb0536SJens Wiklander struct tee_fs_rpc_operation op = { };
5386eb0536SJens Wiklander struct mobj *mobj = NULL;
5486eb0536SJens Wiklander TEE_Result res = TEE_SUCCESS;
5586eb0536SJens Wiklander void *va = NULL;
5622efbd4aSJens Wiklander
571a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS,
581a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION,
599bee8f2aSJens Wiklander TEE_FS_NAME_MAX, &mobj);
6022efbd4aSJens Wiklander if (!va)
6122efbd4aSJens Wiklander return TEE_ERROR_OUT_OF_MEMORY;
6222efbd4aSJens Wiklander
63*45ffd851SJerome Forissier res = create_filename(va, TEE_FS_NAME_MAX, dfh);
6422efbd4aSJens Wiklander if (res != TEE_SUCCESS)
6522efbd4aSJens Wiklander return res;
6622efbd4aSJens Wiklander
6786eb0536SJens Wiklander op = (struct tee_fs_rpc_operation){
68f4feeeefSJens Wiklander .id = id, .num_params = 3, .params = {
69f4feeeefSJens Wiklander [0] = THREAD_PARAM_VALUE(IN, cmd, 0, 0),
70f4feeeefSJens Wiklander [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX),
71f4feeeefSJens Wiklander [2] = THREAD_PARAM_VALUE(OUT, 0, 0, 0),
72f4feeeefSJens Wiklander } };
7322efbd4aSJens Wiklander
7422efbd4aSJens Wiklander res = operation_commit(&op);
7522efbd4aSJens Wiklander if (res == TEE_SUCCESS)
7622efbd4aSJens Wiklander *fd = op.params[2].u.value.a;
7722efbd4aSJens Wiklander
7822efbd4aSJens Wiklander return res;
7922efbd4aSJens Wiklander }
8022efbd4aSJens Wiklander
8122efbd4aSJens Wiklander
8222efbd4aSJens Wiklander
tee_fs_rpc_open_dfh(uint32_t id,const struct tee_fs_dirfile_fileh * dfh,int * fd)8322efbd4aSJens Wiklander TEE_Result tee_fs_rpc_open_dfh(uint32_t id,
8422efbd4aSJens Wiklander const struct tee_fs_dirfile_fileh *dfh, int *fd)
8522efbd4aSJens Wiklander {
866009538cSJens Wiklander return operation_open_dfh(id, OPTEE_RPC_FS_OPEN, dfh, fd);
8722efbd4aSJens Wiklander }
8822efbd4aSJens Wiklander
tee_fs_rpc_create_dfh(uint32_t id,const struct tee_fs_dirfile_fileh * dfh,int * fd)8922efbd4aSJens Wiklander TEE_Result tee_fs_rpc_create_dfh(uint32_t id,
9022efbd4aSJens Wiklander const struct tee_fs_dirfile_fileh *dfh,
9122efbd4aSJens Wiklander int *fd)
9222efbd4aSJens Wiklander {
936009538cSJens Wiklander return operation_open_dfh(id, OPTEE_RPC_FS_CREATE, dfh, fd);
9422efbd4aSJens Wiklander }
9522efbd4aSJens Wiklander
tee_fs_rpc_close(uint32_t id,int fd)9609a9f39bSJens Wiklander TEE_Result tee_fs_rpc_close(uint32_t id, int fd)
977f4173d8SJens Wiklander {
98f4feeeefSJens Wiklander struct tee_fs_rpc_operation op = {
99f4feeeefSJens Wiklander .id = id, .num_params = 1, .params = {
1006009538cSJens Wiklander [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_CLOSE, fd, 0),
101f4feeeefSJens Wiklander },
102f4feeeefSJens Wiklander };
1037f4173d8SJens Wiklander
1047f4173d8SJens Wiklander return operation_commit(&op);
1057f4173d8SJens Wiklander }
1067f4173d8SJens Wiklander
tee_fs_rpc_read_init(struct tee_fs_rpc_operation * op,uint32_t id,int fd,tee_fs_off_t offset,size_t data_len,void ** out_data)10709a9f39bSJens Wiklander TEE_Result tee_fs_rpc_read_init(struct tee_fs_rpc_operation *op,
1087f4173d8SJens Wiklander uint32_t id, int fd, tee_fs_off_t offset,
1097f4173d8SJens Wiklander size_t data_len, void **out_data)
1107f4173d8SJens Wiklander {
111142d5af2SVolodymyr Babchuk struct mobj *mobj;
1127f4173d8SJens Wiklander uint8_t *va;
1137f4173d8SJens Wiklander
1147f4173d8SJens Wiklander if (offset < 0)
1157f4173d8SJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
1167f4173d8SJens Wiklander
1171a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS,
1181a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION,
1199bee8f2aSJens Wiklander data_len, &mobj);
1207f4173d8SJens Wiklander if (!va)
1217f4173d8SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY;
1227f4173d8SJens Wiklander
123f4feeeefSJens Wiklander *op = (struct tee_fs_rpc_operation){
124f4feeeefSJens Wiklander .id = id, .num_params = 2, .params = {
1256009538cSJens Wiklander [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_READ, fd,
126f4feeeefSJens Wiklander offset),
127f4feeeefSJens Wiklander [1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, data_len),
128f4feeeefSJens Wiklander },
129f4feeeefSJens Wiklander };
1307f4173d8SJens Wiklander
1317f4173d8SJens Wiklander *out_data = va;
1327f4173d8SJens Wiklander
1337f4173d8SJens Wiklander return TEE_SUCCESS;
1347f4173d8SJens Wiklander }
1357f4173d8SJens Wiklander
tee_fs_rpc_read_final(struct tee_fs_rpc_operation * op,size_t * data_len)13609a9f39bSJens Wiklander TEE_Result tee_fs_rpc_read_final(struct tee_fs_rpc_operation *op,
1377f4173d8SJens Wiklander size_t *data_len)
1387f4173d8SJens Wiklander {
1397f4173d8SJens Wiklander TEE_Result res = operation_commit(op);
1407f4173d8SJens Wiklander
1417f4173d8SJens Wiklander if (res == TEE_SUCCESS)
14213eb4e3cSJens Wiklander *data_len = op->params[1].u.memref.size;
1437f4173d8SJens Wiklander return res;
1447f4173d8SJens Wiklander }
1457f4173d8SJens Wiklander
tee_fs_rpc_write_init(struct tee_fs_rpc_operation * op,uint32_t id,int fd,tee_fs_off_t offset,size_t data_len,void ** data)14609a9f39bSJens Wiklander TEE_Result tee_fs_rpc_write_init(struct tee_fs_rpc_operation *op,
1477f4173d8SJens Wiklander uint32_t id, int fd, tee_fs_off_t offset,
1487f4173d8SJens Wiklander size_t data_len, void **data)
1497f4173d8SJens Wiklander {
150142d5af2SVolodymyr Babchuk struct mobj *mobj;
1517f4173d8SJens Wiklander uint8_t *va;
1527f4173d8SJens Wiklander
1537f4173d8SJens Wiklander if (offset < 0)
1547f4173d8SJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
1557f4173d8SJens Wiklander
1561a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS,
1571a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION,
1589bee8f2aSJens Wiklander data_len, &mobj);
1597f4173d8SJens Wiklander if (!va)
1607f4173d8SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY;
1617f4173d8SJens Wiklander
162f4feeeefSJens Wiklander *op = (struct tee_fs_rpc_operation){
163f4feeeefSJens Wiklander .id = id, .num_params = 2, .params = {
1646009538cSJens Wiklander [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_WRITE, fd,
165f4feeeefSJens Wiklander offset),
166f4feeeefSJens Wiklander [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, data_len),
167f4feeeefSJens Wiklander },
168f4feeeefSJens Wiklander };
1697f4173d8SJens Wiklander
1707f4173d8SJens Wiklander *data = va;
1717f4173d8SJens Wiklander
1727f4173d8SJens Wiklander return TEE_SUCCESS;
1737f4173d8SJens Wiklander }
1747f4173d8SJens Wiklander
tee_fs_rpc_write_final(struct tee_fs_rpc_operation * op)17509a9f39bSJens Wiklander TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op)
1767f4173d8SJens Wiklander {
1777f4173d8SJens Wiklander return operation_commit(op);
1787f4173d8SJens Wiklander }
1797f4173d8SJens Wiklander
tee_fs_rpc_truncate(uint32_t id,int fd,size_t len)18009a9f39bSJens Wiklander TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len)
1817f4173d8SJens Wiklander {
182f4feeeefSJens Wiklander struct tee_fs_rpc_operation op = {
183f4feeeefSJens Wiklander .id = id, .num_params = 1, .params = {
1846009538cSJens Wiklander [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_TRUNCATE, fd,
185f4feeeefSJens Wiklander len),
186f4feeeefSJens Wiklander }
187f4feeeefSJens Wiklander };
1887f4173d8SJens Wiklander
1897f4173d8SJens Wiklander return operation_commit(&op);
1907f4173d8SJens Wiklander }
1917f4173d8SJens Wiklander
tee_fs_rpc_remove_dfh(uint32_t id,const struct tee_fs_dirfile_fileh * dfh)19222efbd4aSJens Wiklander TEE_Result tee_fs_rpc_remove_dfh(uint32_t id,
19322efbd4aSJens Wiklander const struct tee_fs_dirfile_fileh *dfh)
19422efbd4aSJens Wiklander {
19586eb0536SJens Wiklander struct tee_fs_rpc_operation op = { };
19686eb0536SJens Wiklander TEE_Result res = TEE_SUCCESS;
19786eb0536SJens Wiklander struct mobj *mobj = NULL;
19886eb0536SJens Wiklander void *va = NULL;
19922efbd4aSJens Wiklander
2001a7d8eaeSJens Wiklander va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS,
2011a7d8eaeSJens Wiklander THREAD_SHM_TYPE_APPLICATION,
2029bee8f2aSJens Wiklander TEE_FS_NAME_MAX, &mobj);
20322efbd4aSJens Wiklander if (!va)
20422efbd4aSJens Wiklander return TEE_ERROR_OUT_OF_MEMORY;
20522efbd4aSJens Wiklander
206142d5af2SVolodymyr Babchuk
207*45ffd851SJerome Forissier res = create_filename(va, TEE_FS_NAME_MAX, dfh);
20822efbd4aSJens Wiklander if (res != TEE_SUCCESS)
20922efbd4aSJens Wiklander return res;
21022efbd4aSJens Wiklander
21186eb0536SJens Wiklander op = (struct tee_fs_rpc_operation){
212f4feeeefSJens Wiklander .id = id, .num_params = 2, .params = {
2136009538cSJens Wiklander [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_REMOVE, 0, 0),
214f4feeeefSJens Wiklander [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX),
215f4feeeefSJens Wiklander }
216f4feeeefSJens Wiklander };
217f4feeeefSJens Wiklander
21822efbd4aSJens Wiklander return operation_commit(&op);
21922efbd4aSJens Wiklander }
220