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 mobj *mobj; 36 TEE_Result res; 37 void *va; 38 39 va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, 40 THREAD_SHM_TYPE_APPLICATION, 41 TEE_FS_NAME_MAX, &mobj); 42 if (!va) 43 return TEE_ERROR_OUT_OF_MEMORY; 44 45 res = tee_svc_storage_create_filename_dfh(va, TEE_FS_NAME_MAX, dfh); 46 if (res != TEE_SUCCESS) 47 return res; 48 49 struct tee_fs_rpc_operation op = { 50 .id = id, .num_params = 3, .params = { 51 [0] = THREAD_PARAM_VALUE(IN, cmd, 0, 0), 52 [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX), 53 [2] = THREAD_PARAM_VALUE(OUT, 0, 0, 0), 54 } }; 55 56 res = operation_commit(&op); 57 if (res == TEE_SUCCESS) 58 *fd = op.params[2].u.value.a; 59 60 return res; 61 } 62 63 64 65 TEE_Result tee_fs_rpc_open_dfh(uint32_t id, 66 const struct tee_fs_dirfile_fileh *dfh, int *fd) 67 { 68 return operation_open_dfh(id, OPTEE_RPC_FS_OPEN, dfh, fd); 69 } 70 71 TEE_Result tee_fs_rpc_create_dfh(uint32_t id, 72 const struct tee_fs_dirfile_fileh *dfh, 73 int *fd) 74 { 75 return operation_open_dfh(id, OPTEE_RPC_FS_CREATE, dfh, fd); 76 } 77 78 TEE_Result tee_fs_rpc_close(uint32_t id, int fd) 79 { 80 struct tee_fs_rpc_operation op = { 81 .id = id, .num_params = 1, .params = { 82 [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_CLOSE, fd, 0), 83 }, 84 }; 85 86 return operation_commit(&op); 87 } 88 89 TEE_Result tee_fs_rpc_read_init(struct tee_fs_rpc_operation *op, 90 uint32_t id, int fd, tee_fs_off_t offset, 91 size_t data_len, void **out_data) 92 { 93 struct mobj *mobj; 94 uint8_t *va; 95 96 if (offset < 0) 97 return TEE_ERROR_BAD_PARAMETERS; 98 99 va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, 100 THREAD_SHM_TYPE_APPLICATION, 101 data_len, &mobj); 102 if (!va) 103 return TEE_ERROR_OUT_OF_MEMORY; 104 105 *op = (struct tee_fs_rpc_operation){ 106 .id = id, .num_params = 2, .params = { 107 [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_READ, fd, 108 offset), 109 [1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, data_len), 110 }, 111 }; 112 113 *out_data = va; 114 115 return TEE_SUCCESS; 116 } 117 118 TEE_Result tee_fs_rpc_read_final(struct tee_fs_rpc_operation *op, 119 size_t *data_len) 120 { 121 TEE_Result res = operation_commit(op); 122 123 if (res == TEE_SUCCESS) 124 *data_len = op->params[1].u.memref.size; 125 return res; 126 } 127 128 TEE_Result tee_fs_rpc_write_init(struct tee_fs_rpc_operation *op, 129 uint32_t id, int fd, tee_fs_off_t offset, 130 size_t data_len, void **data) 131 { 132 struct mobj *mobj; 133 uint8_t *va; 134 135 if (offset < 0) 136 return TEE_ERROR_BAD_PARAMETERS; 137 138 va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, 139 THREAD_SHM_TYPE_APPLICATION, 140 data_len, &mobj); 141 if (!va) 142 return TEE_ERROR_OUT_OF_MEMORY; 143 144 *op = (struct tee_fs_rpc_operation){ 145 .id = id, .num_params = 2, .params = { 146 [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_WRITE, fd, 147 offset), 148 [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, data_len), 149 }, 150 }; 151 152 *data = va; 153 154 return TEE_SUCCESS; 155 } 156 157 TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op) 158 { 159 return operation_commit(op); 160 } 161 162 TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len) 163 { 164 struct tee_fs_rpc_operation op = { 165 .id = id, .num_params = 1, .params = { 166 [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_TRUNCATE, fd, 167 len), 168 } 169 }; 170 171 return operation_commit(&op); 172 } 173 174 TEE_Result tee_fs_rpc_remove_dfh(uint32_t id, 175 const struct tee_fs_dirfile_fileh *dfh) 176 { 177 TEE_Result res; 178 struct mobj *mobj; 179 void *va; 180 181 va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, 182 THREAD_SHM_TYPE_APPLICATION, 183 TEE_FS_NAME_MAX, &mobj); 184 if (!va) 185 return TEE_ERROR_OUT_OF_MEMORY; 186 187 188 res = tee_svc_storage_create_filename_dfh(va, TEE_FS_NAME_MAX, dfh); 189 if (res != TEE_SUCCESS) 190 return res; 191 192 struct tee_fs_rpc_operation op = { 193 .id = id, .num_params = 2, .params = { 194 [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_REMOVE, 0, 0), 195 [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX), 196 } 197 }; 198 199 return operation_commit(&op); 200 } 201