1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2016, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <kernel/tee_misc.h> 8 #include <kernel/thread.h> 9 #include <mm/core_memprot.h> 10 #include <optee_rpc_cmd.h> 11 #include <stdlib.h> 12 #include <string_ext.h> 13 #include <string.h> 14 #include <tee/tee_fs.h> 15 #include <tee/tee_fs_rpc.h> 16 #include <tee/tee_pobj.h> 17 #include <tee/tee_svc_storage.h> 18 #include <trace.h> 19 #include <util.h> 20 21 struct tee_fs_dir { 22 int nw_dir; 23 struct tee_fs_dirent d; 24 }; 25 26 static TEE_Result operation_commit(struct tee_fs_rpc_operation *op) 27 { 28 return thread_rpc_cmd(op->id, op->num_params, op->params); 29 } 30 31 static TEE_Result operation_open_dfh(uint32_t id, unsigned int cmd, 32 const struct tee_fs_dirfile_fileh *dfh, 33 int *fd) 34 { 35 struct tee_fs_rpc_operation op = { }; 36 struct mobj *mobj = NULL; 37 TEE_Result res = TEE_SUCCESS; 38 void *va = NULL; 39 40 va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, 41 THREAD_SHM_TYPE_APPLICATION, 42 TEE_FS_NAME_MAX, &mobj); 43 if (!va) 44 return TEE_ERROR_OUT_OF_MEMORY; 45 46 res = tee_svc_storage_create_filename_dfh(va, TEE_FS_NAME_MAX, dfh); 47 if (res != TEE_SUCCESS) 48 return res; 49 50 op = (struct tee_fs_rpc_operation){ 51 .id = id, .num_params = 3, .params = { 52 [0] = THREAD_PARAM_VALUE(IN, cmd, 0, 0), 53 [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX), 54 [2] = THREAD_PARAM_VALUE(OUT, 0, 0, 0), 55 } }; 56 57 res = operation_commit(&op); 58 if (res == TEE_SUCCESS) 59 *fd = op.params[2].u.value.a; 60 61 return res; 62 } 63 64 65 66 TEE_Result tee_fs_rpc_open_dfh(uint32_t id, 67 const struct tee_fs_dirfile_fileh *dfh, int *fd) 68 { 69 return operation_open_dfh(id, OPTEE_RPC_FS_OPEN, dfh, fd); 70 } 71 72 TEE_Result tee_fs_rpc_create_dfh(uint32_t id, 73 const struct tee_fs_dirfile_fileh *dfh, 74 int *fd) 75 { 76 return operation_open_dfh(id, OPTEE_RPC_FS_CREATE, dfh, fd); 77 } 78 79 TEE_Result tee_fs_rpc_close(uint32_t id, int fd) 80 { 81 struct tee_fs_rpc_operation op = { 82 .id = id, .num_params = 1, .params = { 83 [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_CLOSE, fd, 0), 84 }, 85 }; 86 87 return operation_commit(&op); 88 } 89 90 TEE_Result tee_fs_rpc_read_init(struct tee_fs_rpc_operation *op, 91 uint32_t id, int fd, tee_fs_off_t offset, 92 size_t data_len, void **out_data) 93 { 94 struct mobj *mobj; 95 uint8_t *va; 96 97 if (offset < 0) 98 return TEE_ERROR_BAD_PARAMETERS; 99 100 va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, 101 THREAD_SHM_TYPE_APPLICATION, 102 data_len, &mobj); 103 if (!va) 104 return TEE_ERROR_OUT_OF_MEMORY; 105 106 *op = (struct tee_fs_rpc_operation){ 107 .id = id, .num_params = 2, .params = { 108 [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_READ, fd, 109 offset), 110 [1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, data_len), 111 }, 112 }; 113 114 *out_data = va; 115 116 return TEE_SUCCESS; 117 } 118 119 TEE_Result tee_fs_rpc_read_final(struct tee_fs_rpc_operation *op, 120 size_t *data_len) 121 { 122 TEE_Result res = operation_commit(op); 123 124 if (res == TEE_SUCCESS) 125 *data_len = op->params[1].u.memref.size; 126 return res; 127 } 128 129 TEE_Result tee_fs_rpc_write_init(struct tee_fs_rpc_operation *op, 130 uint32_t id, int fd, tee_fs_off_t offset, 131 size_t data_len, void **data) 132 { 133 struct mobj *mobj; 134 uint8_t *va; 135 136 if (offset < 0) 137 return TEE_ERROR_BAD_PARAMETERS; 138 139 va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, 140 THREAD_SHM_TYPE_APPLICATION, 141 data_len, &mobj); 142 if (!va) 143 return TEE_ERROR_OUT_OF_MEMORY; 144 145 *op = (struct tee_fs_rpc_operation){ 146 .id = id, .num_params = 2, .params = { 147 [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_WRITE, fd, 148 offset), 149 [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, data_len), 150 }, 151 }; 152 153 *data = va; 154 155 return TEE_SUCCESS; 156 } 157 158 TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op) 159 { 160 return operation_commit(op); 161 } 162 163 TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len) 164 { 165 struct tee_fs_rpc_operation op = { 166 .id = id, .num_params = 1, .params = { 167 [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_TRUNCATE, fd, 168 len), 169 } 170 }; 171 172 return operation_commit(&op); 173 } 174 175 TEE_Result tee_fs_rpc_remove_dfh(uint32_t id, 176 const struct tee_fs_dirfile_fileh *dfh) 177 { 178 struct tee_fs_rpc_operation op = { }; 179 TEE_Result res = TEE_SUCCESS; 180 struct mobj *mobj = NULL; 181 void *va = NULL; 182 183 va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, 184 THREAD_SHM_TYPE_APPLICATION, 185 TEE_FS_NAME_MAX, &mobj); 186 if (!va) 187 return TEE_ERROR_OUT_OF_MEMORY; 188 189 190 res = tee_svc_storage_create_filename_dfh(va, TEE_FS_NAME_MAX, dfh); 191 if (res != TEE_SUCCESS) 192 return res; 193 194 op = (struct tee_fs_rpc_operation){ 195 .id = id, .num_params = 2, .params = { 196 [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_REMOVE, 0, 0), 197 [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX), 198 } 199 }; 200 201 return operation_commit(&op); 202 } 203