xref: /optee_os/core/tee/tee_fs_rpc.c (revision 7f4173d82bfb3f631c7d45deef39ee8ce736dcbb)
1 /*
2  * Copyright (c) 2016, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <assert.h>
29 #include <kernel/thread.h>
30 #include <mm/core_memprot.h>
31 #include <optee_msg_fs.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <string_ext.h>
35 #include <tee/tee_fs.h>
36 #include <tee/tee_fs_rpc.h>
37 #include <trace.h>
38 #include <util.h>
39 
40 #define RPC_FAILED -1
41 
42 /* TEE FS operation */
43 #define TEE_FS_OPEN       1
44 #define TEE_FS_CLOSE      2
45 #define TEE_FS_READ       3
46 #define TEE_FS_WRITE      4
47 #define TEE_FS_SEEK       5
48 #define TEE_FS_UNLINK     6
49 #define TEE_FS_RENAME     7
50 #define TEE_FS_TRUNC      8
51 #define TEE_FS_MKDIR      9
52 #define TEE_FS_OPENDIR   10
53 #define TEE_FS_CLOSEDIR  11
54 #define TEE_FS_READDIR   12
55 #define TEE_FS_RMDIR     13
56 #define TEE_FS_ACCESS    14
57 #define TEE_FS_LINK      15
58 #define TEE_FS_BEGIN     16 /* SQL FS: begin transaction */
59 #define TEE_FS_END       17 /* SQL FS: end transaction */
60 
61 #define TEE_FS_MODE_NONE 0
62 #define TEE_FS_MODE_IN   1
63 #define TEE_FS_MODE_OUT  2
64 
65 struct tee_fs_rpc {
66 	int op;
67 	int flags;
68 	int arg;
69 	int fd;
70 	uint32_t len;
71 	int res;
72 };
73 
74 struct tee_fs_dir {
75 	int nw_dir;
76 	struct tee_fs_dirent d;
77 };
78 
79 static TEE_Result tee_fs_rpc_send_cmd(int cmd_id, struct tee_fs_rpc *bf_cmd,
80 				      void *data, uint32_t len, uint32_t mode)
81 {
82 	TEE_Result ret;
83 	struct optee_msg_param params;
84 	paddr_t phpayload = 0;
85 	uint64_t cpayload = 0;
86 	struct tee_fs_rpc *bf;
87 	int res = TEE_ERROR_GENERIC;
88 
89 	assert(cmd_id == OPTEE_MSG_RPC_CMD_FS ||
90 	       cmd_id == OPTEE_MSG_RPC_CMD_SQL_FS);
91 
92 	bf = tee_fs_rpc_cache_alloc(sizeof(struct tee_fs_rpc) + len,
93 				    &phpayload, &cpayload);
94 	if (!bf)
95 		goto exit;
96 
97 	memset(&params, 0, sizeof(params));
98 	params.attr = OPTEE_MSG_ATTR_TYPE_TMEM_INOUT;
99 	params.u.tmem.buf_ptr = phpayload;
100 	params.u.tmem.size = sizeof(struct tee_fs_rpc) + len;
101 	params.u.tmem.shm_ref = cpayload;
102 
103 	/* fill in parameters */
104 	*bf = *bf_cmd;
105 
106 	if (mode & TEE_FS_MODE_IN)
107 		memcpy((void *)(bf + 1), data, len);
108 
109 	ret = thread_rpc_cmd(cmd_id, 1, &params);
110 	/* update result */
111 	*bf_cmd = *bf;
112 	if (ret != TEE_SUCCESS)
113 		goto exit;
114 
115 	if (mode & TEE_FS_MODE_OUT) {
116 		uint32_t olen = MIN(len, bf->len);
117 
118 		memcpy(data, (void *)(bf + 1), olen);
119 	}
120 
121 	res = TEE_SUCCESS;
122 
123 exit:
124 	return res;
125 }
126 
127 int tee_fs_rpc_access(int id, const char *name, int mode)
128 {
129 	struct tee_fs_rpc head = { 0 };
130 	TEE_Result res;
131 	int rc = RPC_FAILED;
132 	size_t len;
133 
134 	DMSG("(id: %d, name: %s, mode: %d)...", id, name, mode);
135 
136 	if (!name)
137 		goto exit;
138 
139 	len = strlen(name) + 1;
140 	if (len <= 1)
141 		goto exit;
142 
143 	head.op = TEE_FS_ACCESS;
144 	head.flags = mode;
145 
146 	res = tee_fs_rpc_send_cmd(id, &head, (void *)name, len, TEE_FS_MODE_IN);
147 	if (res != TEE_SUCCESS)
148 		goto exit;
149 
150 	rc = head.res;
151 exit:
152 	DMSG("...%d", rc);
153 	return rc;
154 }
155 
156 int tee_fs_rpc_begin_transaction(int id)
157 {
158 	struct tee_fs_rpc head = { 0 };
159 	TEE_Result res;
160 	int rc = RPC_FAILED;
161 
162 	assert(id == OPTEE_MSG_RPC_CMD_SQL_FS);
163 
164 	DMSG("(id: %d)...", id);
165 
166 	/* fill in parameters */
167 	head.op = TEE_FS_BEGIN;
168 	head.fd = -1;
169 
170 	res = tee_fs_rpc_send_cmd(id, &head, NULL, 0,
171 				  TEE_FS_MODE_NONE);
172 	if (res != TEE_SUCCESS)
173 		goto exit;
174 
175 	rc = head.res;
176 exit:
177 	DMSG("...%d", rc);
178 	return rc;
179 }
180 
181 int tee_fs_rpc_close(int id, int fd)
182 {
183 	struct tee_fs_rpc head = { 0 };
184 	TEE_Result res;
185 	int rc = RPC_FAILED;
186 
187 	DMSG("(id: %d, fd: %d)...", id, fd);
188 
189 	head.op = TEE_FS_CLOSE;
190 	head.fd = fd;
191 
192 	res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE);
193 	if (res != TEE_SUCCESS)
194 		goto exit;
195 
196 	rc = head.res;
197 exit:
198 	DMSG("...%d", rc);
199 	return rc;
200 }
201 
202 int tee_fs_rpc_end_transaction(int id, bool rollback)
203 {
204 	struct tee_fs_rpc head = { 0 };
205 	TEE_Result res;
206 	int rc = RPC_FAILED;
207 
208 	assert(id == OPTEE_MSG_RPC_CMD_SQL_FS);
209 
210 	DMSG("(id: %d, rollback: %d)...", id, rollback);
211 
212 	head.op = TEE_FS_END;
213 	head.arg = rollback;
214 	head.fd = -1;
215 
216 	res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE);
217 	if (res != TEE_SUCCESS)
218 		goto exit;
219 
220 	rc = head.res;
221 exit:
222 	DMSG("...%d", rc);
223 	return rc;
224 }
225 
226 int tee_fs_rpc_ftruncate(int id, int fd, tee_fs_off_t length)
227 {
228 	struct tee_fs_rpc head = { 0 };
229 	TEE_Result res;
230 	int rc = RPC_FAILED;
231 
232 	DMSG("(id: %d, fd: %d, length: %" PRId64 ")...", id, fd, length);
233 
234 	head.op = TEE_FS_TRUNC;
235 	head.fd = fd;
236 	head.arg = length;
237 
238 	res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE);
239 	if (res != TEE_SUCCESS)
240 		goto exit;
241 
242 	rc = head.res;
243 exit:
244 	DMSG("...%d", rc);
245 	return rc;
246 }
247 
248 int tee_fs_rpc_link(int id, const char *old, const char *nw)
249 {
250 	size_t len_old;
251 	size_t len_new;
252 	size_t len;
253 	struct tee_fs_rpc head = { 0 };
254 	char *tmp = NULL;
255 	TEE_Result res;
256 	int rc = RPC_FAILED;
257 
258 	DMSG("(id: %d, old: %s, nw: %s)...", id, old, nw);
259 
260 	if (!old || !nw)
261 		goto exit;
262 
263 	len_old = strlen(old) + 1;
264 	len_new = strlen(nw) + 1;
265 	len = len_old + len_new;
266 
267 	tmp = malloc(len);
268 	if (!tmp)
269 		goto exit;
270 	memcpy(tmp, old, len_old);
271 	memcpy(tmp + len_old, nw, len_new);
272 
273 	head.op = TEE_FS_LINK;
274 
275 	res = tee_fs_rpc_send_cmd(id, &head, tmp, len, TEE_FS_MODE_IN);
276 	if (res != TEE_SUCCESS)
277 		goto exit;
278 
279 	rc = head.res;
280 exit:
281 	free(tmp);
282 	DMSG("...%d", rc);
283 	return rc;
284 }
285 
286 tee_fs_off_t tee_fs_rpc_lseek(int id, int fd, tee_fs_off_t offset,
287 				  int whence)
288 {
289 	struct tee_fs_rpc head = { 0 };
290 	tee_fs_off_t rc = RPC_FAILED;
291 	TEE_Result res;
292 
293 	DMSG("(id: %d, fd: %d, offset: %" PRId64 ", whence: %d)...", id, fd,
294 	     offset, whence);
295 
296 	head.op = TEE_FS_SEEK;
297 	head.fd = fd;
298 	head.arg = offset;
299 	head.flags = whence;
300 
301 	res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE);
302 	if (res != TEE_SUCCESS)
303 		goto exit;
304 
305 	rc = head.res;
306 exit:
307 	DMSG("...%" PRId64, rc);
308 	return rc;
309 }
310 
311 int tee_fs_rpc_mkdir(int id, const char *path, tee_fs_mode_t mode)
312 {
313 	struct tee_fs_rpc head = { 0 };
314 	TEE_Result res;
315 	uint32_t len;
316 	int rc = RPC_FAILED;
317 
318 	DMSG("(id: %d, path: %s, mode: %d)...", id, path, mode);
319 
320 	if (!path)
321 		goto exit;
322 
323 	len = strlen(path) + 1;
324 	if (len <= 1)
325 		goto exit;
326 
327 	head.op = TEE_FS_MKDIR;
328 	head.flags = mode;
329 
330 	res = tee_fs_rpc_send_cmd(id, &head, (void *)path, len,
331 				  TEE_FS_MODE_IN);
332 	if (res != TEE_SUCCESS)
333 		goto exit;
334 
335 	rc = head.res;
336 exit:
337 	DMSG("...%d", rc);
338 	return rc;
339 }
340 
341 int tee_fs_rpc_open(int id, const char *file, int flags)
342 {
343 	struct tee_fs_rpc head = { 0 };
344 	TEE_Result res;
345 	int rc = RPC_FAILED;
346 	size_t len;
347 
348 	DMSG("(id: %d, file: %s, flags: %d)...", id, file, flags);
349 
350 	if (!file)
351 		goto exit;
352 
353 	len = strlen(file) + 1;
354 	if (len <= 1)
355 		goto exit;
356 
357 	head.op = TEE_FS_OPEN;
358 	head.flags = flags;
359 
360 	res = tee_fs_rpc_send_cmd(id, &head, (void *)file, len,
361 				  TEE_FS_MODE_IN);
362 	if (res != TEE_SUCCESS)
363 		goto exit;
364 
365 	rc = head.res;
366 exit:
367 	DMSG("...%d", rc);
368 	return rc;
369 }
370 
371 struct tee_fs_dir *tee_fs_rpc_opendir(int id, const char *name)
372 {
373 	struct tee_fs_rpc head = { 0 };
374 	struct tee_fs_dir *dir = NULL;
375 	size_t len;
376 	TEE_Result res = TEE_SUCCESS;
377 
378 	DMSG("(id: %d, name: %s)...", id, name);
379 
380 	if (!name)
381 		goto exit;
382 
383 	len = strlen(name) + 1;
384 	if (len <= 1)
385 		goto exit;
386 
387 	dir = malloc(sizeof(struct tee_fs_dir));
388 	if (!dir)
389 		goto exit;
390 
391 	head.op = TEE_FS_OPENDIR;
392 
393 	res = tee_fs_rpc_send_cmd(id, &head, (void *)name, len,
394 				  TEE_FS_MODE_IN);
395 	if (res != TEE_SUCCESS)
396 		goto free_and_exit;
397 	if (head.res < 0)
398 		goto free_and_exit;
399 
400 	dir->nw_dir = head.res;
401 	dir->d.d_name = NULL;
402 
403 	goto exit;
404 
405 free_and_exit:
406 	free(dir);
407 	dir = NULL;
408 exit:
409 	DMSG("...%p", (void *)dir);
410 	return dir;
411 }
412 
413 int tee_fs_rpc_read(int id, int fd, void *buf, size_t len)
414 {
415 	struct tee_fs_rpc head = { 0 };
416 	TEE_Result res;
417 	int rc = RPC_FAILED;
418 
419 	DMSG("(id: %d, fd: %d, buf: %p, len: %zu)...", id, fd, (void *)buf,
420 	     len);
421 
422 	if (!len) {
423 		res = 0;
424 		goto exit;
425 	}
426 
427 	if (!buf)
428 		goto exit;
429 
430 	head.op = TEE_FS_READ;
431 	head.fd = fd;
432 	head.len = (uint32_t)len;
433 
434 	res = tee_fs_rpc_send_cmd(id, &head, (void *)buf, len,
435 				  TEE_FS_MODE_OUT);
436 	if (res != TEE_SUCCESS)
437 		goto exit;
438 
439 	rc = head.res;
440 exit:
441 	DMSG("...%d", rc);
442 	return rc;
443 }
444 
445 struct tee_fs_dirent *tee_fs_rpc_readdir(int id, struct tee_fs_dir *d)
446 {
447 	struct tee_fs_dirent *rc = NULL;
448 	char fname[TEE_FS_NAME_MAX + 1];
449 	struct tee_fs_rpc head = { 0 };
450 	TEE_Result res;
451 
452 	DMSG("(id: %d, d: %p)...", id, (void *)d);
453 
454 	if (!d)
455 		goto exit;
456 
457 	head.op = TEE_FS_READDIR;
458 	head.arg = (int)d->nw_dir;
459 	head.len = sizeof(fname);
460 
461 	res = tee_fs_rpc_send_cmd(id, &head, fname, sizeof(fname),
462 				  TEE_FS_MODE_OUT);
463 	if (res != TEE_SUCCESS)
464 		goto exit;
465 
466 	if (head.res < 0)
467 		goto exit;
468 
469 	if (!head.len || head.len > sizeof(fname))
470 		goto exit;
471 
472 	fname[head.len - 1] = '\0'; /* make sure it's zero terminated */
473 	free(d->d.d_name);
474 	d->d.d_name = strdup(fname);
475 	if (!d->d.d_name)
476 		goto exit;
477 
478 	rc = &d->d;
479 exit:
480 	DMSG("...%p", (void *)rc);
481 	return rc;
482 }
483 
484 int tee_fs_rpc_rename(int id, const char *old, const char *nw)
485 {
486 	size_t len_old;
487 	size_t len_new;
488 	size_t len;
489 	struct tee_fs_rpc head = { 0 };
490 	char *tmp = NULL;
491 	TEE_Result res;
492 	int rc = RPC_FAILED;
493 
494 	DMSG("(id: %d, old: %s, nw: %s)...", id, old, nw);
495 
496 	if (!old || !nw)
497 		goto exit;
498 
499 	len_old = strlen(old) + 1;
500 	len_new = strlen(nw) + 1;
501 	len = len_old + len_new;
502 
503 	tmp = malloc(len);
504 	if (!tmp)
505 		goto exit;
506 
507 	memcpy(tmp, old, len_old);
508 	memcpy(tmp + len_old, nw, len_new);
509 
510 	head.op = TEE_FS_RENAME;
511 
512 	res = tee_fs_rpc_send_cmd(id, &head, tmp, len, TEE_FS_MODE_IN);
513 	if (res != TEE_SUCCESS)
514 		goto exit;
515 
516 	rc = head.res;
517 exit:
518 	free(tmp);
519 	DMSG("...%d", rc);
520 	return rc;
521 }
522 
523 int tee_fs_rpc_write(int id, int fd, const void *buf, size_t len)
524 {
525 	struct tee_fs_rpc head = { 0 };
526 	TEE_Result res;
527 	int rc = RPC_FAILED;
528 
529 	DMSG("(id: %d, fd: %d, buf: %p, len: %zu)...", id, fd, buf, len);
530 
531 	if (!len) {
532 		res = 0;
533 		goto exit;
534 	}
535 
536 	if (!buf)
537 		goto exit;
538 
539 	head.op = TEE_FS_WRITE;
540 	head.fd = fd;
541 	head.len = (uint32_t)len;
542 
543 	res = tee_fs_rpc_send_cmd(id, &head, (void *)buf, len, TEE_FS_MODE_IN);
544 	if (res != TEE_SUCCESS)
545 		goto exit;
546 
547 	rc = head.res;
548 exit:
549 	DMSG("...%d", rc);
550 	return rc;
551 }
552 
553 int tee_fs_rpc_closedir(int id, struct tee_fs_dir *d)
554 {
555 	struct tee_fs_rpc head = { 0 };
556 	TEE_Result res;
557 	int rc = RPC_FAILED;
558 
559 	DMSG("(id: %d, d: %p)...", id, (void *)d);
560 
561 	if (!d) {
562 		rc = 0;
563 		goto exit;
564 	}
565 
566 	head.op = TEE_FS_CLOSEDIR;
567 	head.arg = (int)d->nw_dir;
568 
569 	res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE);
570 	if (res != TEE_SUCCESS)
571 		goto exit;
572 
573 	rc = head.res;
574 exit:
575 	if (d)
576 		free(d->d.d_name);
577 	free(d);
578 
579 	DMSG("...%d", rc);
580 	return rc;
581 }
582 
583 int tee_fs_rpc_rmdir(int id, const char *name)
584 {
585 	struct tee_fs_rpc head = { 0 };
586 	TEE_Result res;
587 	int rc = RPC_FAILED;
588 	size_t len;
589 
590 	DMSG("(id: %d, name: %s)...", id, name);
591 
592 	if (!name)
593 		goto exit;
594 
595 	len = strlen(name) + 1;
596 	if (len <= 1)
597 		goto exit;
598 
599 	head.op = TEE_FS_RMDIR;
600 
601 	res = tee_fs_rpc_send_cmd(id, &head, (void *)name, len,
602 				  TEE_FS_MODE_IN);
603 	if (res != TEE_SUCCESS)
604 		goto exit;
605 
606 	rc = head.res;
607 exit:
608 	DMSG("...%d", rc);
609 	return rc;
610 }
611 
612 int tee_fs_rpc_unlink(int id, const char *file)
613 {
614 	struct tee_fs_rpc head = { 0 };
615 	size_t len;
616 	TEE_Result res;
617 	int rc = RPC_FAILED;
618 
619 	DMSG("(id: %d, file: %s)...", id, file);
620 
621 	if (!file)
622 		goto exit;
623 
624 	len = strlen(file) + 1;
625 	if (len <= 1)
626 		goto exit;
627 
628 	head.op = TEE_FS_UNLINK;
629 
630 	res = tee_fs_rpc_send_cmd(id, &head, (void *)file, len,
631 				  TEE_FS_MODE_IN);
632 	if (res != TEE_SUCCESS)
633 		goto exit;
634 
635 	rc = head.res;
636 exit:
637 	DMSG("...%d", rc);
638 	return rc;
639 }
640 
641 static TEE_Result operation_commit(struct tee_fs_rpc_operation *op)
642 {
643 	return thread_rpc_cmd(op->id, op->num_params, op->params);
644 }
645 
646 static TEE_Result operation_open(uint32_t id, unsigned int cmd,
647 				 const char *fname, int *fd)
648 {
649 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
650 	TEE_Result res;
651 	void *va;
652 	paddr_t pa;
653 	uint64_t cookie;
654 	size_t fname_size = strlen(fname) + 1;
655 
656 	va = tee_fs_rpc_cache_alloc(fname_size, &pa, &cookie);
657 	if (!va)
658 		return TEE_ERROR_OUT_OF_MEMORY;
659 
660 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
661 	op.params[0].u.value.a = cmd;
662 
663 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
664 	op.params[1].u.tmem.buf_ptr = pa;
665 	op.params[1].u.tmem.size = fname_size;
666 	op.params[1].u.tmem.shm_ref = cookie;
667 	strlcpy(va, fname, fname_size);
668 
669 	op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
670 
671 	res = operation_commit(&op);
672 	if (res == TEE_SUCCESS)
673 		*fd = op.params[2].u.value.a;
674 
675 	return res;
676 }
677 
678 TEE_Result tee_fs_rpc_new_open(uint32_t id, const char *fname, int *fd)
679 {
680 	return operation_open(id, OPTEE_MRF_OPEN, fname, fd);
681 }
682 
683 TEE_Result tee_fs_rpc_new_create(uint32_t id, const char *fname, int *fd)
684 {
685 	return operation_open(id, OPTEE_MRF_CREATE, fname, fd);
686 }
687 
688 TEE_Result tee_fs_rpc_new_close(uint32_t id, int fd)
689 {
690 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
691 
692 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
693 	op.params[0].u.value.a = OPTEE_MRF_CLOSE;
694 	op.params[0].u.value.b = fd;
695 
696 	return operation_commit(&op);
697 }
698 
699 TEE_Result tee_fs_rpc_new_read_init(struct tee_fs_rpc_operation *op,
700 				    uint32_t id, int fd, tee_fs_off_t offset,
701 				    size_t data_len, void **out_data)
702 {
703 	uint8_t *va;
704 	paddr_t pa;
705 	uint64_t cookie;
706 
707 	if (offset < 0)
708 		return TEE_ERROR_BAD_PARAMETERS;
709 
710 	va = tee_fs_rpc_cache_alloc(data_len, &pa, &cookie);
711 	if (!va)
712 		return TEE_ERROR_OUT_OF_MEMORY;
713 
714 	memset(op, 0, sizeof(*op));
715 	op->id = id;
716 	op->num_params = 2;
717 
718 	op->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
719 	op->params[0].u.value.a = OPTEE_MRF_READ;
720 	op->params[0].u.value.b = fd;
721 	op->params[0].u.value.c = offset;
722 
723 	op->params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
724 	op->params[1].u.tmem.buf_ptr = pa;
725 	op->params[1].u.tmem.size = data_len;
726 	op->params[1].u.tmem.shm_ref = cookie;
727 
728 	*out_data = va;
729 
730 	return TEE_SUCCESS;
731 }
732 
733 TEE_Result tee_fs_rpc_new_read_final(struct tee_fs_rpc_operation *op,
734 				     size_t *data_len)
735 {
736 	TEE_Result res = operation_commit(op);
737 
738 	if (res == TEE_SUCCESS)
739 		*data_len = op->params[1].u.tmem.size;
740 	return res;
741 }
742 
743 TEE_Result tee_fs_rpc_new_write_init(struct tee_fs_rpc_operation *op,
744 				     uint32_t id, int fd, tee_fs_off_t offset,
745 				     size_t data_len, void **data)
746 {
747 	uint8_t *va;
748 	paddr_t pa;
749 	uint64_t cookie;
750 
751 	if (offset < 0)
752 		return TEE_ERROR_BAD_PARAMETERS;
753 
754 	va = tee_fs_rpc_cache_alloc(data_len, &pa, &cookie);
755 	if (!va)
756 		return TEE_ERROR_OUT_OF_MEMORY;
757 
758 	memset(op, 0, sizeof(*op));
759 	op->id = id;
760 	op->num_params = 2;
761 
762 
763 	op->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
764 	op->params[0].u.value.a = OPTEE_MRF_WRITE;
765 	op->params[0].u.value.b = fd;
766 	op->params[0].u.value.c = offset;
767 
768 	op->params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
769 	op->params[1].u.tmem.buf_ptr = pa;
770 	op->params[1].u.tmem.size = data_len;
771 	op->params[1].u.tmem.shm_ref = cookie;
772 
773 	*data = va;
774 
775 	return TEE_SUCCESS;
776 }
777 
778 TEE_Result tee_fs_rpc_new_write_final(struct tee_fs_rpc_operation *op)
779 {
780 	return operation_commit(op);
781 }
782 
783 TEE_Result tee_fs_rpc_new_truncate(uint32_t id, int fd, size_t len)
784 {
785 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
786 
787 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
788 	op.params[0].u.value.a = OPTEE_MRF_TRUNCATE;
789 	op.params[0].u.value.b = fd;
790 	op.params[0].u.value.c = len;
791 
792 	return operation_commit(&op);
793 }
794 
795 TEE_Result tee_fs_rpc_new_remove(uint32_t id, const char *fname)
796 {
797 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 };
798 	void *va;
799 	paddr_t pa;
800 	uint64_t cookie;
801 	size_t name_len = strlen(fname) + 1;
802 
803 	va = tee_fs_rpc_cache_alloc(name_len, &pa, &cookie);
804 	if (!va)
805 		return TEE_ERROR_OUT_OF_MEMORY;
806 
807 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
808 	op.params[0].u.value.a = OPTEE_MRF_REMOVE;
809 
810 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
811 	op.params[1].u.tmem.buf_ptr = pa;
812 	op.params[1].u.tmem.size = name_len;
813 	op.params[1].u.tmem.shm_ref = cookie;
814 	strlcpy(va, fname, name_len);
815 
816 	return operation_commit(&op);
817 }
818 
819 TEE_Result tee_fs_rpc_new_rename(uint32_t id, const char *old_fname,
820 				 const char *new_fname, bool overwrite)
821 {
822 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
823 	char *va;
824 	paddr_t pa;
825 	uint64_t cookie;
826 	size_t old_fname_size = strlen(old_fname) + 1;
827 	size_t new_fname_size = strlen(new_fname) + 1;
828 
829 	va = tee_fs_rpc_cache_alloc(old_fname_size + new_fname_size,
830 				    &pa, &cookie);
831 	if (!va)
832 		return TEE_ERROR_OUT_OF_MEMORY;
833 
834 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
835 	op.params[0].u.value.a = OPTEE_MRF_RENAME;
836 	op.params[0].u.value.b = overwrite;
837 
838 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
839 	op.params[1].u.tmem.buf_ptr = pa;
840 	op.params[1].u.tmem.size = old_fname_size;
841 	op.params[1].u.tmem.shm_ref = cookie;
842 	strlcpy(va, old_fname, old_fname_size);
843 
844 	op.params[2].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
845 	op.params[2].u.tmem.buf_ptr = pa + old_fname_size;
846 	op.params[2].u.tmem.size = new_fname_size;
847 	op.params[2].u.tmem.shm_ref = cookie;
848 	strlcpy(va + old_fname_size, new_fname, new_fname_size);
849 
850 	return operation_commit(&op);
851 }
852 
853 TEE_Result tee_fs_rpc_new_opendir(uint32_t id, const char *name,
854 				  struct tee_fs_dir **d)
855 {
856 	TEE_Result res;
857 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
858 	void *va;
859 	paddr_t pa;
860 	uint64_t cookie;
861 	size_t name_len = strlen(name) + 1;
862 	struct tee_fs_dir *dir = calloc(1, sizeof(*dir));
863 
864 	if (!dir)
865 		return TEE_ERROR_OUT_OF_MEMORY;
866 
867 	va = tee_fs_rpc_cache_alloc(name_len, &pa, &cookie);
868 	if (!va) {
869 		res = TEE_ERROR_OUT_OF_MEMORY;
870 		goto err_exit;
871 	}
872 
873 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
874 	op.params[0].u.value.a = OPTEE_MRF_OPENDIR;
875 
876 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
877 	op.params[1].u.tmem.buf_ptr = pa;
878 	op.params[1].u.tmem.size = name_len;
879 	op.params[1].u.tmem.shm_ref = cookie;
880 	strlcpy(va, name, name_len);
881 
882 	op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
883 
884 	res = operation_commit(&op);
885 
886 	if (res != TEE_SUCCESS)
887 		goto err_exit;
888 
889 	dir->nw_dir = op.params[2].u.value.a;
890 	*d = dir;
891 
892 	return TEE_SUCCESS;
893 err_exit:
894 	free(dir);
895 
896 	return res;
897 }
898 
899 TEE_Result tee_fs_rpc_new_closedir(uint32_t id, struct tee_fs_dir *d)
900 {
901 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
902 
903 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
904 	op.params[0].u.value.a = OPTEE_MRF_CLOSEDIR;
905 	op.params[0].u.value.b = d->nw_dir;
906 
907 	free(d);
908 	return operation_commit(&op);
909 }
910 
911 TEE_Result tee_fs_rpc_new_readdir(uint32_t id, struct tee_fs_dir *d,
912 				  struct tee_fs_dirent **ent)
913 {
914 	TEE_Result res;
915 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 };
916 	void *va;
917 	paddr_t pa;
918 	uint64_t cookie;
919 	const size_t max_name_len = TEE_FS_NAME_MAX + 1;
920 
921 	if (!d)
922 		return TEE_ERROR_ITEM_NOT_FOUND;
923 
924 	va = tee_fs_rpc_cache_alloc(max_name_len, &pa, &cookie);
925 	if (!va)
926 		return TEE_ERROR_OUT_OF_MEMORY;
927 
928 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
929 	op.params[0].u.value.a = OPTEE_MRF_READDIR;
930 	op.params[0].u.value.b = d->nw_dir;
931 
932 	op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
933 	op.params[1].u.tmem.buf_ptr = pa;
934 	op.params[1].u.tmem.size = max_name_len;
935 	op.params[1].u.tmem.shm_ref = cookie;
936 
937 	res = operation_commit(&op);
938 	if (res != TEE_SUCCESS)
939 		return res;
940 
941 	free(d->d.d_name);
942 	d->d.d_name = strndup(va, max_name_len);
943 	if (!d->d.d_name)
944 		return TEE_ERROR_OUT_OF_MEMORY;
945 
946 	*ent = &d->d;
947 	return TEE_SUCCESS;
948 }
949 
950 TEE_Result tee_fs_rpc_new_begin_transaction(uint32_t id)
951 {
952 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
953 
954 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
955 	op.params[0].u.value.a = OPTEE_MRF_BEGIN_TRANSACTION;
956 
957 	return operation_commit(&op);
958 }
959 
960 TEE_Result tee_fs_rpc_new_end_transaction(uint32_t id, bool rollback)
961 {
962 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
963 
964 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
965 	op.params[0].u.value.a = OPTEE_MRF_END_TRANSACTION;
966 	op.params[0].u.value.b = rollback;
967 
968 	return operation_commit(&op);
969 }
970