xref: /optee_os/core/tee/tee_fs_rpc.c (revision c020046d88419100dd7d1188dce7f4a9a2e54e36)
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