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