1 /*
2 * Copyright (c) 2014, STMicroelectronics International N.V.
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 #include <assert.h>
28 #include <dirent.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <handle.h>
32 #include <libgen.h>
33 #include <optee_msg_supplicant.h>
34 #include <stdbool.h>
35 #include <stdint.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/stat.h>
40 #include <teec_trace.h>
41 #include <tee_supp_fs.h>
42 #include <tee_supplicant.h>
43 #include <unistd.h>
44
45 #ifndef __aligned
46 #define __aligned(x) __attribute__((__aligned__(x)))
47 #endif
48 #include <linux/tee.h>
49
50 #ifndef PATH_MAX
51 #define PATH_MAX 255
52 #endif
53
54 /* Path to all secure storage files. */
55 static char tee_fs_root[PATH_MAX];
56
57 #define TEE_FS_FILENAME_MAX_LENGTH 150
58
59 static pthread_mutex_t dir_handle_db_mutex = PTHREAD_MUTEX_INITIALIZER;
60 static struct handle_db dir_handle_db =
61 HANDLE_DB_INITIALIZER_WITH_MUTEX(&dir_handle_db_mutex);
62
tee_fs_get_absolute_filename(char * file,char * out,size_t out_size)63 static size_t tee_fs_get_absolute_filename(char *file, char *out,
64 size_t out_size)
65 {
66 int s = 0;
67
68 if (!file || !out || (out_size <= strlen(tee_fs_root) + 1))
69 return 0;
70
71 s = snprintf(out, out_size, "%s%s", tee_fs_root, file);
72 if (s < 0 || (size_t)s >= out_size)
73 return 0;
74
75 /* Safe to cast since we have checked that sizes are OK */
76 return (size_t)s;
77 }
78
do_mkdir(const char * path,mode_t mode)79 static int do_mkdir(const char *path, mode_t mode)
80 {
81 struct stat st;
82
83 memset(&st, 0, sizeof(st));
84
85 if (mkdir(path, mode) != 0 && errno != EEXIST)
86 return -1;
87
88 if (stat(path, &st) != 0 && !S_ISDIR(st.st_mode))
89 return -1;
90
91 return 0;
92 }
93
mkpath(const char * path,mode_t mode)94 static int mkpath(const char *path, mode_t mode)
95 {
96 int status = 0;
97 char *subpath = strdup(path);
98 char *prev = subpath;
99 char *curr = NULL;
100
101 while (status == 0 && (curr = strchr(prev, '/')) != 0) {
102 /*
103 * Check for root or double slash
104 */
105 if (curr != prev) {
106 *curr = '\0';
107 status = do_mkdir(subpath, mode);
108 *curr = '/';
109 }
110 prev = curr + 1;
111 }
112 if (status == 0)
113 status = do_mkdir(path, mode);
114
115 free(subpath);
116 return status;
117 }
118
tee_supp_fs_init(void)119 static int tee_supp_fs_init(void)
120 {
121 size_t n = 0;
122 mode_t mode = 0700;
123
124 n = snprintf(tee_fs_root, sizeof(tee_fs_root), "%s/", TEE_FS_PARENT_PATH);
125 if (n >= sizeof(tee_fs_root))
126 return -1;
127
128 if (mkpath(tee_fs_root, mode) != 0)
129 return -1;
130
131 return 0;
132 }
133
open_wrapper(const char * fname,int flags)134 static int open_wrapper(const char *fname, int flags)
135 {
136 int fd = 0;
137
138 while (true) {
139 fd = open(fname, flags | O_SYNC, 0600);
140 if (fd >= 0 || errno != EINTR)
141 return fd;
142 }
143 }
144
ree_fs_new_open(size_t num_params,struct tee_ioctl_param * params)145 static TEEC_Result ree_fs_new_open(size_t num_params,
146 struct tee_ioctl_param *params)
147 {
148 char abs_filename[PATH_MAX] = { 0 };
149 char *fname = NULL;
150 int fd = 0;
151
152 if (num_params != 3 ||
153 (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
154 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
155 (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
156 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
157 (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
158 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)
159 return TEEC_ERROR_BAD_PARAMETERS;
160
161 fname = tee_supp_param_to_va(params + 1);
162 if (!fname)
163 return TEEC_ERROR_BAD_PARAMETERS;
164
165 if (!tee_fs_get_absolute_filename(fname, abs_filename,
166 sizeof(abs_filename)))
167 return TEEC_ERROR_BAD_PARAMETERS;
168
169 fd = open_wrapper(abs_filename, O_RDWR);
170 if (fd < 0) {
171 /*
172 * In case the problem is the filesystem is RO, retry with the
173 * open flags restricted to RO.
174 */
175 fd = open_wrapper(abs_filename, O_RDONLY);
176 if (fd < 0)
177 return TEEC_ERROR_ITEM_NOT_FOUND;
178 }
179
180 params[2].a = fd;
181 return TEEC_SUCCESS;
182 }
183
ree_fs_new_create(size_t num_params,struct tee_ioctl_param * params)184 static TEEC_Result ree_fs_new_create(size_t num_params,
185 struct tee_ioctl_param *params)
186 {
187 char abs_filename[PATH_MAX] = { 0 };
188 char abs_dir[PATH_MAX] = { 0 };
189 char *fname = NULL;
190 char *d = NULL;
191 int fd = 0;
192 const int flags = O_RDWR | O_CREAT | O_TRUNC;
193
194 if (num_params != 3 ||
195 (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
196 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
197 (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
198 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
199 (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
200 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)
201 return TEEC_ERROR_BAD_PARAMETERS;
202
203 fname = tee_supp_param_to_va(params + 1);
204 if (!fname)
205 return TEEC_ERROR_BAD_PARAMETERS;
206
207 if (!tee_fs_get_absolute_filename(fname, abs_filename,
208 sizeof(abs_filename)))
209 return TEEC_ERROR_BAD_PARAMETERS;
210
211 fd = open_wrapper(abs_filename, flags);
212 if (fd >= 0)
213 goto out;
214 if (errno != ENOENT)
215 return TEEC_ERROR_GENERIC;
216
217 /* Directory for file missing, try make to it */
218 strncpy(abs_dir, abs_filename, sizeof(abs_dir));
219 abs_dir[sizeof(abs_dir) - 1] = '\0';
220 d = dirname(abs_dir);
221 if (!mkdir(d, 0700)) {
222 fd = open_wrapper(abs_filename, flags);
223 if (fd >= 0)
224 goto out;
225 /*
226 * The directory was made but the file could still not be
227 * created.
228 */
229 rmdir(d);
230 return TEEC_ERROR_GENERIC;
231 }
232 if (errno != ENOENT)
233 return TEEC_ERROR_GENERIC;
234
235 /* Parent directory for file missing, try to make it */
236 d = dirname(d);
237 if (mkdir(d, 0700))
238 return TEEC_ERROR_GENERIC;
239
240 /* Try to make directory for file again */
241 strncpy(abs_dir, abs_filename, sizeof(abs_dir));
242 abs_dir[sizeof(abs_dir) - 1] = '\0';
243 d = dirname(abs_dir);
244 if (mkdir(d, 0700)) {
245 d = dirname(d);
246 rmdir(d);
247 return TEEC_ERROR_GENERIC;
248 }
249
250 fd = open_wrapper(abs_filename, flags);
251 if (fd < 0) {
252 rmdir(d);
253 d = dirname(d);
254 rmdir(d);
255 return TEEC_ERROR_GENERIC;
256 }
257
258 out:
259 params[2].a = fd;
260 return TEEC_SUCCESS;
261 }
262
ree_fs_new_close(size_t num_params,struct tee_ioctl_param * params)263 static TEEC_Result ree_fs_new_close(size_t num_params,
264 struct tee_ioctl_param *params)
265 {
266 int fd = 0;
267
268 if (num_params != 1 ||
269 (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
270 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
271 return TEEC_ERROR_BAD_PARAMETERS;
272
273 fd = params[0].b;
274 while (close(fd)) {
275 if (errno != EINTR)
276 return TEEC_ERROR_GENERIC;
277 }
278 return TEEC_SUCCESS;
279 }
280
ree_fs_new_read(size_t num_params,struct tee_ioctl_param * params)281 static TEEC_Result ree_fs_new_read(size_t num_params,
282 struct tee_ioctl_param *params)
283 {
284 uint8_t *buf = NULL;
285 size_t len = 0;
286 off_t offs = 0;
287 int fd = 0;
288 ssize_t r = 0;
289 size_t s = 0;
290
291 if (num_params != 2 ||
292 (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
293 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
294 (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
295 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT)
296 return TEEC_ERROR_BAD_PARAMETERS;
297
298 fd = params[0].b;
299 offs = params[0].c;
300
301 buf = tee_supp_param_to_va(params + 1);
302 if (!buf)
303 return TEEC_ERROR_BAD_PARAMETERS;
304 len = MEMREF_SIZE(params + 1);
305
306 s = 0;
307 r = -1;
308 while (r && len) {
309 r = pread(fd, buf, len, offs);
310 if (r < 0) {
311 if (errno == EINTR)
312 continue;
313 return TEEC_ERROR_GENERIC;
314 }
315 assert((size_t)r <= len);
316 buf += r;
317 len -= r;
318 offs += r;
319 s += r;
320 }
321
322 MEMREF_SIZE(params + 1) = s;
323 return TEEC_SUCCESS;
324 }
325
ree_fs_new_write(size_t num_params,struct tee_ioctl_param * params)326 static TEEC_Result ree_fs_new_write(size_t num_params,
327 struct tee_ioctl_param *params)
328 {
329 uint8_t *buf = NULL;
330 size_t len = 0;
331 off_t offs = 0;
332 int fd = 0;
333 ssize_t r = 0;
334
335 if (num_params != 2 ||
336 (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
337 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
338 (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
339 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
340 return TEEC_ERROR_BAD_PARAMETERS;
341
342 fd = params[0].b;
343 offs = params[0].c;
344
345 buf = tee_supp_param_to_va(params + 1);
346 if (!buf)
347 return TEEC_ERROR_BAD_PARAMETERS;
348 len = MEMREF_SIZE(params + 1);
349
350 while (len) {
351 r = pwrite(fd, buf, len, offs);
352 if (r < 0) {
353 if (errno == EINTR)
354 continue;
355 return TEEC_ERROR_GENERIC;
356 }
357 assert((size_t)r <= len);
358 buf += r;
359 len -= r;
360 offs += r;
361 }
362
363 return TEEC_SUCCESS;
364 }
365
ree_fs_new_truncate(size_t num_params,struct tee_ioctl_param * params)366 static TEEC_Result ree_fs_new_truncate(size_t num_params,
367 struct tee_ioctl_param *params)
368 {
369 size_t len = 0;
370 int fd = 0;
371
372 if (num_params != 1 ||
373 (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
374 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
375 return TEEC_ERROR_BAD_PARAMETERS;
376
377 fd = params[0].b;
378 len = params[0].c;
379
380 while (ftruncate(fd, len)) {
381 if (errno != EINTR)
382 return TEEC_ERROR_GENERIC;
383 }
384
385 return TEEC_SUCCESS;
386 }
387
ree_fs_new_remove(size_t num_params,struct tee_ioctl_param * params)388 static TEEC_Result ree_fs_new_remove(size_t num_params,
389 struct tee_ioctl_param *params)
390 {
391 char abs_filename[PATH_MAX] = { 0 };
392 char *fname = NULL;
393 char *d = NULL;
394
395 if (num_params != 2 ||
396 (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
397 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
398 (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
399 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
400 return TEEC_ERROR_BAD_PARAMETERS;
401
402 fname = tee_supp_param_to_va(params + 1);
403 if (!fname)
404 return TEEC_ERROR_BAD_PARAMETERS;
405
406 if (!tee_fs_get_absolute_filename(fname, abs_filename,
407 sizeof(abs_filename)))
408 return TEEC_ERROR_BAD_PARAMETERS;
409
410 if (unlink(abs_filename)) {
411 if (errno == ENOENT)
412 return TEEC_ERROR_ITEM_NOT_FOUND;
413 return TEEC_ERROR_GENERIC;
414 }
415
416 /* If a file is removed, maybe the directory can be removed to? */
417 d = dirname(abs_filename);
418 if (!rmdir(d)) {
419 /*
420 * If the directory was removed, maybe the parent directory
421 * can be removed too?
422 */
423 d = dirname(d);
424 rmdir(d);
425 }
426
427 return TEEC_SUCCESS;
428 }
429
ree_fs_new_rename(size_t num_params,struct tee_ioctl_param * params)430 static TEEC_Result ree_fs_new_rename(size_t num_params,
431 struct tee_ioctl_param *params)
432 {
433 char old_abs_filename[PATH_MAX] = { 0 };
434 char new_abs_filename[PATH_MAX] = { 0 };
435 char *old_fname = NULL;
436 char *new_fname = NULL;
437 bool overwrite = false;
438
439 if (num_params != 3 ||
440 (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
441 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
442 (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
443 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
444 (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
445 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
446 return TEEC_ERROR_BAD_PARAMETERS;
447
448 overwrite = !!params[0].b;
449
450 old_fname = tee_supp_param_to_va(params + 1);
451 if (!old_fname)
452 return TEEC_ERROR_BAD_PARAMETERS;
453
454 new_fname = tee_supp_param_to_va(params + 2);
455 if (!new_fname)
456 return TEEC_ERROR_BAD_PARAMETERS;
457
458 if (!tee_fs_get_absolute_filename(old_fname, old_abs_filename,
459 sizeof(old_abs_filename)))
460 return TEEC_ERROR_BAD_PARAMETERS;
461
462 if (!tee_fs_get_absolute_filename(new_fname, new_abs_filename,
463 sizeof(new_abs_filename)))
464 return TEEC_ERROR_BAD_PARAMETERS;
465
466 if (!overwrite) {
467 struct stat st;
468
469 if (!stat(new_abs_filename, &st))
470 return TEEC_ERROR_ACCESS_CONFLICT;
471 }
472 if (rename(old_abs_filename, new_abs_filename)) {
473 if (errno == ENOENT)
474 return TEEC_ERROR_ITEM_NOT_FOUND;
475 }
476 return TEEC_SUCCESS;
477 }
478
ree_fs_new_opendir(size_t num_params,struct tee_ioctl_param * params)479 static TEEC_Result ree_fs_new_opendir(size_t num_params,
480 struct tee_ioctl_param *params)
481 {
482 char abs_filename[PATH_MAX] = { 0 };
483 char *fname = NULL;
484 DIR *dir = NULL;
485 int handle = 0;
486 struct dirent *dent = NULL;
487 bool empty = true;
488
489 if (num_params != 3 ||
490 (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
491 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
492 (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
493 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
494 (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
495 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)
496 return TEEC_ERROR_BAD_PARAMETERS;
497
498 fname = tee_supp_param_to_va(params + 1);
499 if (!fname)
500 return TEEC_ERROR_BAD_PARAMETERS;
501
502 if (!tee_fs_get_absolute_filename(fname, abs_filename,
503 sizeof(abs_filename)))
504 return TEEC_ERROR_BAD_PARAMETERS;
505
506 dir = opendir(abs_filename);
507 if (!dir)
508 return TEEC_ERROR_ITEM_NOT_FOUND;
509
510 /*
511 * Ignore empty directories. Works around an issue when the
512 * data path is mounted over NFS. Due to the way OP-TEE implements
513 * TEE_CloseAndDeletePersistentObject1() currently, tee-supplicant
514 * still has a file descriptor open to the file when it's removed in
515 * ree_fs_new_remove(). In this case the NFS server may create a
516 * temporary reference called .nfs????, and the rmdir() call fails
517 * so that the TA directory is left over. Checking this special case
518 * here avoids that TEE_StartPersistentObjectEnumerator() returns
519 * TEE_SUCCESS when it should return TEEC_ERROR_ITEM_NOT_FOUND.
520 * Test case: "xtest 6009 6010".
521 */
522 while ((dent = readdir(dir))) {
523 if (dent->d_name[0] == '.')
524 continue;
525 empty = false;
526 break;
527 }
528 if (empty) {
529 closedir(dir);
530 return TEEC_ERROR_ITEM_NOT_FOUND;
531 }
532 rewinddir(dir);
533
534 handle = handle_get(&dir_handle_db, dir);
535 if (handle < 0) {
536 closedir(dir);
537 return TEEC_ERROR_OUT_OF_MEMORY;
538 }
539
540 params[2].a = handle;
541 return TEEC_SUCCESS;
542 }
543
ree_fs_new_closedir(size_t num_params,struct tee_ioctl_param * params)544 static TEEC_Result ree_fs_new_closedir(size_t num_params,
545 struct tee_ioctl_param *params)
546 {
547 DIR *dir = NULL;
548
549 if (num_params != 1 ||
550 (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
551 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
552 return TEEC_ERROR_BAD_PARAMETERS;
553
554 dir = handle_put(&dir_handle_db, params[0].b);
555 if (!dir)
556 return TEEC_ERROR_BAD_PARAMETERS;
557
558 closedir(dir);
559
560 return TEEC_SUCCESS;
561 }
562
ree_fs_new_readdir(size_t num_params,struct tee_ioctl_param * params)563 static TEEC_Result ree_fs_new_readdir(size_t num_params,
564 struct tee_ioctl_param *params)
565 {
566 DIR *dir = NULL;
567 struct dirent *dirent = NULL;
568 char *buf = NULL;
569 size_t len = 0;
570 size_t fname_len = 0;
571
572 if (num_params != 2 ||
573 (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
574 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT ||
575 (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
576 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT)
577 return TEEC_ERROR_BAD_PARAMETERS;
578
579
580 buf = tee_supp_param_to_va(params + 1);
581 if (!buf)
582 return TEEC_ERROR_BAD_PARAMETERS;
583 len = MEMREF_SIZE(params + 1);
584
585 dir = handle_lookup(&dir_handle_db, params[0].b);
586 if (!dir)
587 return TEEC_ERROR_BAD_PARAMETERS;
588
589 while (true) {
590 dirent = readdir(dir);
591 if (!dirent)
592 return TEEC_ERROR_ITEM_NOT_FOUND;
593 if (dirent->d_name[0] != '.')
594 break;
595 }
596
597 fname_len = strlen(dirent->d_name) + 1;
598 MEMREF_SIZE(params + 1) = fname_len;
599 if (fname_len > len)
600 return TEEC_ERROR_SHORT_BUFFER;
601
602 memcpy(buf, dirent->d_name, fname_len);
603
604 return TEEC_SUCCESS;
605 }
606
tee_supp_fs_process(size_t num_params,struct tee_ioctl_param * params)607 TEEC_Result tee_supp_fs_process(size_t num_params,
608 struct tee_ioctl_param *params)
609 {
610 if (!num_params || !tee_supp_param_is_value(params))
611 return TEEC_ERROR_BAD_PARAMETERS;
612
613 if (strlen(tee_fs_root) == 0) {
614 if (tee_supp_fs_init() != 0) {
615 EMSG("error tee_supp_fs_init: failed to create %s/",
616 TEE_FS_PARENT_PATH);
617 memset(tee_fs_root, 0, sizeof(tee_fs_root));
618 return TEEC_ERROR_STORAGE_NOT_AVAILABLE;
619 }
620 }
621
622 switch (params->a) {
623 case OPTEE_MRF_OPEN:
624 return ree_fs_new_open(num_params, params);
625 case OPTEE_MRF_CREATE:
626 return ree_fs_new_create(num_params, params);
627 case OPTEE_MRF_CLOSE:
628 return ree_fs_new_close(num_params, params);
629 case OPTEE_MRF_READ:
630 return ree_fs_new_read(num_params, params);
631 case OPTEE_MRF_WRITE:
632 return ree_fs_new_write(num_params, params);
633 case OPTEE_MRF_TRUNCATE:
634 return ree_fs_new_truncate(num_params, params);
635 case OPTEE_MRF_REMOVE:
636 return ree_fs_new_remove(num_params, params);
637 case OPTEE_MRF_RENAME:
638 return ree_fs_new_rename(num_params, params);
639 case OPTEE_MRF_OPENDIR:
640 return ree_fs_new_opendir(num_params, params);
641 case OPTEE_MRF_CLOSEDIR:
642 return ree_fs_new_closedir(num_params, params);
643 case OPTEE_MRF_READDIR:
644 return ree_fs_new_readdir(num_params, params);
645 default:
646 return TEEC_ERROR_BAD_PARAMETERS;
647 }
648 }
649