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(¶ms, 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, ¶ms); 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_end_transaction(int id, bool rollback) 182 { 183 struct tee_fs_rpc head = { 0 }; 184 TEE_Result res; 185 int rc = RPC_FAILED; 186 187 assert(id == OPTEE_MSG_RPC_CMD_SQL_FS); 188 189 DMSG("(id: %d, rollback: %d)...", id, rollback); 190 191 head.op = TEE_FS_END; 192 head.arg = rollback; 193 head.fd = -1; 194 195 res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE); 196 if (res != TEE_SUCCESS) 197 goto exit; 198 199 rc = head.res; 200 exit: 201 DMSG("...%d", rc); 202 return rc; 203 } 204 205 int tee_fs_rpc_link(int id, const char *old, const char *nw) 206 { 207 size_t len_old; 208 size_t len_new; 209 size_t len; 210 struct tee_fs_rpc head = { 0 }; 211 char *tmp = NULL; 212 TEE_Result res; 213 int rc = RPC_FAILED; 214 215 DMSG("(id: %d, old: %s, nw: %s)...", id, old, nw); 216 217 if (!old || !nw) 218 goto exit; 219 220 len_old = strlen(old) + 1; 221 len_new = strlen(nw) + 1; 222 len = len_old + len_new; 223 224 tmp = malloc(len); 225 if (!tmp) 226 goto exit; 227 memcpy(tmp, old, len_old); 228 memcpy(tmp + len_old, nw, len_new); 229 230 head.op = TEE_FS_LINK; 231 232 res = tee_fs_rpc_send_cmd(id, &head, tmp, len, TEE_FS_MODE_IN); 233 if (res != TEE_SUCCESS) 234 goto exit; 235 236 rc = head.res; 237 exit: 238 free(tmp); 239 DMSG("...%d", rc); 240 return rc; 241 } 242 243 int tee_fs_rpc_mkdir(int id, const char *path, tee_fs_mode_t mode) 244 { 245 struct tee_fs_rpc head = { 0 }; 246 TEE_Result res; 247 uint32_t len; 248 int rc = RPC_FAILED; 249 250 DMSG("(id: %d, path: %s, mode: %d)...", id, path, mode); 251 252 if (!path) 253 goto exit; 254 255 len = strlen(path) + 1; 256 if (len <= 1) 257 goto exit; 258 259 head.op = TEE_FS_MKDIR; 260 head.flags = mode; 261 262 res = tee_fs_rpc_send_cmd(id, &head, (void *)path, len, 263 TEE_FS_MODE_IN); 264 if (res != TEE_SUCCESS) 265 goto exit; 266 267 rc = head.res; 268 exit: 269 DMSG("...%d", rc); 270 return rc; 271 } 272 273 struct tee_fs_dir *tee_fs_rpc_opendir(int id, const char *name) 274 { 275 struct tee_fs_rpc head = { 0 }; 276 struct tee_fs_dir *dir = NULL; 277 size_t len; 278 TEE_Result res = TEE_SUCCESS; 279 280 DMSG("(id: %d, name: %s)...", id, name); 281 282 if (!name) 283 goto exit; 284 285 len = strlen(name) + 1; 286 if (len <= 1) 287 goto exit; 288 289 dir = malloc(sizeof(struct tee_fs_dir)); 290 if (!dir) 291 goto exit; 292 293 head.op = TEE_FS_OPENDIR; 294 295 res = tee_fs_rpc_send_cmd(id, &head, (void *)name, len, 296 TEE_FS_MODE_IN); 297 if (res != TEE_SUCCESS) 298 goto free_and_exit; 299 if (head.res < 0) 300 goto free_and_exit; 301 302 dir->nw_dir = head.res; 303 dir->d.d_name = NULL; 304 305 goto exit; 306 307 free_and_exit: 308 free(dir); 309 dir = NULL; 310 exit: 311 DMSG("...%p", (void *)dir); 312 return dir; 313 } 314 315 struct tee_fs_dirent *tee_fs_rpc_readdir(int id, struct tee_fs_dir *d) 316 { 317 struct tee_fs_dirent *rc = NULL; 318 char fname[TEE_FS_NAME_MAX + 1]; 319 struct tee_fs_rpc head = { 0 }; 320 TEE_Result res; 321 322 DMSG("(id: %d, d: %p)...", id, (void *)d); 323 324 if (!d) 325 goto exit; 326 327 head.op = TEE_FS_READDIR; 328 head.arg = (int)d->nw_dir; 329 head.len = sizeof(fname); 330 331 res = tee_fs_rpc_send_cmd(id, &head, fname, sizeof(fname), 332 TEE_FS_MODE_OUT); 333 if (res != TEE_SUCCESS) 334 goto exit; 335 336 if (head.res < 0) 337 goto exit; 338 339 if (!head.len || head.len > sizeof(fname)) 340 goto exit; 341 342 fname[head.len - 1] = '\0'; /* make sure it's zero terminated */ 343 free(d->d.d_name); 344 d->d.d_name = strdup(fname); 345 if (!d->d.d_name) 346 goto exit; 347 348 rc = &d->d; 349 exit: 350 DMSG("...%p", (void *)rc); 351 return rc; 352 } 353 354 int tee_fs_rpc_rename(int id, const char *old, const char *nw) 355 { 356 size_t len_old; 357 size_t len_new; 358 size_t len; 359 struct tee_fs_rpc head = { 0 }; 360 char *tmp = NULL; 361 TEE_Result res; 362 int rc = RPC_FAILED; 363 364 DMSG("(id: %d, old: %s, nw: %s)...", id, old, nw); 365 366 if (!old || !nw) 367 goto exit; 368 369 len_old = strlen(old) + 1; 370 len_new = strlen(nw) + 1; 371 len = len_old + len_new; 372 373 tmp = malloc(len); 374 if (!tmp) 375 goto exit; 376 377 memcpy(tmp, old, len_old); 378 memcpy(tmp + len_old, nw, len_new); 379 380 head.op = TEE_FS_RENAME; 381 382 res = tee_fs_rpc_send_cmd(id, &head, tmp, len, TEE_FS_MODE_IN); 383 if (res != TEE_SUCCESS) 384 goto exit; 385 386 rc = head.res; 387 exit: 388 free(tmp); 389 DMSG("...%d", rc); 390 return rc; 391 } 392 393 int tee_fs_rpc_closedir(int id, struct tee_fs_dir *d) 394 { 395 struct tee_fs_rpc head = { 0 }; 396 TEE_Result res; 397 int rc = RPC_FAILED; 398 399 DMSG("(id: %d, d: %p)...", id, (void *)d); 400 401 if (!d) { 402 rc = 0; 403 goto exit; 404 } 405 406 head.op = TEE_FS_CLOSEDIR; 407 head.arg = (int)d->nw_dir; 408 409 res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE); 410 if (res != TEE_SUCCESS) 411 goto exit; 412 413 rc = head.res; 414 exit: 415 if (d) 416 free(d->d.d_name); 417 free(d); 418 419 DMSG("...%d", rc); 420 return rc; 421 } 422 423 int tee_fs_rpc_rmdir(int id, const char *name) 424 { 425 struct tee_fs_rpc head = { 0 }; 426 TEE_Result res; 427 int rc = RPC_FAILED; 428 size_t len; 429 430 DMSG("(id: %d, name: %s)...", id, name); 431 432 if (!name) 433 goto exit; 434 435 len = strlen(name) + 1; 436 if (len <= 1) 437 goto exit; 438 439 head.op = TEE_FS_RMDIR; 440 441 res = tee_fs_rpc_send_cmd(id, &head, (void *)name, len, 442 TEE_FS_MODE_IN); 443 if (res != TEE_SUCCESS) 444 goto exit; 445 446 rc = head.res; 447 exit: 448 DMSG("...%d", rc); 449 return rc; 450 } 451 452 static TEE_Result operation_commit(struct tee_fs_rpc_operation *op) 453 { 454 return thread_rpc_cmd(op->id, op->num_params, op->params); 455 } 456 457 static TEE_Result operation_open(uint32_t id, unsigned int cmd, 458 const char *fname, int *fd) 459 { 460 struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 }; 461 TEE_Result res; 462 void *va; 463 paddr_t pa; 464 uint64_t cookie; 465 size_t fname_size = strlen(fname) + 1; 466 467 va = tee_fs_rpc_cache_alloc(fname_size, &pa, &cookie); 468 if (!va) 469 return TEE_ERROR_OUT_OF_MEMORY; 470 471 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 472 op.params[0].u.value.a = cmd; 473 474 op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 475 op.params[1].u.tmem.buf_ptr = pa; 476 op.params[1].u.tmem.size = fname_size; 477 op.params[1].u.tmem.shm_ref = cookie; 478 strlcpy(va, fname, fname_size); 479 480 op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT; 481 482 res = operation_commit(&op); 483 if (res == TEE_SUCCESS) 484 *fd = op.params[2].u.value.a; 485 486 return res; 487 } 488 489 TEE_Result tee_fs_rpc_new_open(uint32_t id, const char *fname, int *fd) 490 { 491 return operation_open(id, OPTEE_MRF_OPEN, fname, fd); 492 } 493 494 TEE_Result tee_fs_rpc_new_create(uint32_t id, const char *fname, int *fd) 495 { 496 return operation_open(id, OPTEE_MRF_CREATE, fname, fd); 497 } 498 499 TEE_Result tee_fs_rpc_new_close(uint32_t id, int fd) 500 { 501 struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 }; 502 503 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 504 op.params[0].u.value.a = OPTEE_MRF_CLOSE; 505 op.params[0].u.value.b = fd; 506 507 return operation_commit(&op); 508 } 509 510 TEE_Result tee_fs_rpc_new_read_init(struct tee_fs_rpc_operation *op, 511 uint32_t id, int fd, tee_fs_off_t offset, 512 size_t data_len, void **out_data) 513 { 514 uint8_t *va; 515 paddr_t pa; 516 uint64_t cookie; 517 518 if (offset < 0) 519 return TEE_ERROR_BAD_PARAMETERS; 520 521 va = tee_fs_rpc_cache_alloc(data_len, &pa, &cookie); 522 if (!va) 523 return TEE_ERROR_OUT_OF_MEMORY; 524 525 memset(op, 0, sizeof(*op)); 526 op->id = id; 527 op->num_params = 2; 528 529 op->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 530 op->params[0].u.value.a = OPTEE_MRF_READ; 531 op->params[0].u.value.b = fd; 532 op->params[0].u.value.c = offset; 533 534 op->params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT; 535 op->params[1].u.tmem.buf_ptr = pa; 536 op->params[1].u.tmem.size = data_len; 537 op->params[1].u.tmem.shm_ref = cookie; 538 539 *out_data = va; 540 541 return TEE_SUCCESS; 542 } 543 544 TEE_Result tee_fs_rpc_new_read_final(struct tee_fs_rpc_operation *op, 545 size_t *data_len) 546 { 547 TEE_Result res = operation_commit(op); 548 549 if (res == TEE_SUCCESS) 550 *data_len = op->params[1].u.tmem.size; 551 return res; 552 } 553 554 TEE_Result tee_fs_rpc_new_write_init(struct tee_fs_rpc_operation *op, 555 uint32_t id, int fd, tee_fs_off_t offset, 556 size_t data_len, void **data) 557 { 558 uint8_t *va; 559 paddr_t pa; 560 uint64_t cookie; 561 562 if (offset < 0) 563 return TEE_ERROR_BAD_PARAMETERS; 564 565 va = tee_fs_rpc_cache_alloc(data_len, &pa, &cookie); 566 if (!va) 567 return TEE_ERROR_OUT_OF_MEMORY; 568 569 memset(op, 0, sizeof(*op)); 570 op->id = id; 571 op->num_params = 2; 572 573 574 op->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 575 op->params[0].u.value.a = OPTEE_MRF_WRITE; 576 op->params[0].u.value.b = fd; 577 op->params[0].u.value.c = offset; 578 579 op->params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 580 op->params[1].u.tmem.buf_ptr = pa; 581 op->params[1].u.tmem.size = data_len; 582 op->params[1].u.tmem.shm_ref = cookie; 583 584 *data = va; 585 586 return TEE_SUCCESS; 587 } 588 589 TEE_Result tee_fs_rpc_new_write_final(struct tee_fs_rpc_operation *op) 590 { 591 return operation_commit(op); 592 } 593 594 TEE_Result tee_fs_rpc_new_truncate(uint32_t id, int fd, size_t len) 595 { 596 struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 }; 597 598 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 599 op.params[0].u.value.a = OPTEE_MRF_TRUNCATE; 600 op.params[0].u.value.b = fd; 601 op.params[0].u.value.c = len; 602 603 return operation_commit(&op); 604 } 605 606 TEE_Result tee_fs_rpc_new_remove(uint32_t id, const char *fname) 607 { 608 struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 }; 609 void *va; 610 paddr_t pa; 611 uint64_t cookie; 612 size_t name_len = strlen(fname) + 1; 613 614 va = tee_fs_rpc_cache_alloc(name_len, &pa, &cookie); 615 if (!va) 616 return TEE_ERROR_OUT_OF_MEMORY; 617 618 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 619 op.params[0].u.value.a = OPTEE_MRF_REMOVE; 620 621 op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 622 op.params[1].u.tmem.buf_ptr = pa; 623 op.params[1].u.tmem.size = name_len; 624 op.params[1].u.tmem.shm_ref = cookie; 625 strlcpy(va, fname, name_len); 626 627 return operation_commit(&op); 628 } 629 630 TEE_Result tee_fs_rpc_new_rename(uint32_t id, const char *old_fname, 631 const char *new_fname, bool overwrite) 632 { 633 struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 }; 634 char *va; 635 paddr_t pa; 636 uint64_t cookie; 637 size_t old_fname_size = strlen(old_fname) + 1; 638 size_t new_fname_size = strlen(new_fname) + 1; 639 640 va = tee_fs_rpc_cache_alloc(old_fname_size + new_fname_size, 641 &pa, &cookie); 642 if (!va) 643 return TEE_ERROR_OUT_OF_MEMORY; 644 645 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 646 op.params[0].u.value.a = OPTEE_MRF_RENAME; 647 op.params[0].u.value.b = overwrite; 648 649 op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 650 op.params[1].u.tmem.buf_ptr = pa; 651 op.params[1].u.tmem.size = old_fname_size; 652 op.params[1].u.tmem.shm_ref = cookie; 653 strlcpy(va, old_fname, old_fname_size); 654 655 op.params[2].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 656 op.params[2].u.tmem.buf_ptr = pa + old_fname_size; 657 op.params[2].u.tmem.size = new_fname_size; 658 op.params[2].u.tmem.shm_ref = cookie; 659 strlcpy(va + old_fname_size, new_fname, new_fname_size); 660 661 return operation_commit(&op); 662 } 663 664 TEE_Result tee_fs_rpc_new_opendir(uint32_t id, const char *name, 665 struct tee_fs_dir **d) 666 { 667 TEE_Result res; 668 struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 }; 669 void *va; 670 paddr_t pa; 671 uint64_t cookie; 672 size_t name_len = strlen(name) + 1; 673 struct tee_fs_dir *dir = calloc(1, sizeof(*dir)); 674 675 if (!dir) 676 return TEE_ERROR_OUT_OF_MEMORY; 677 678 va = tee_fs_rpc_cache_alloc(name_len, &pa, &cookie); 679 if (!va) { 680 res = TEE_ERROR_OUT_OF_MEMORY; 681 goto err_exit; 682 } 683 684 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 685 op.params[0].u.value.a = OPTEE_MRF_OPENDIR; 686 687 op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 688 op.params[1].u.tmem.buf_ptr = pa; 689 op.params[1].u.tmem.size = name_len; 690 op.params[1].u.tmem.shm_ref = cookie; 691 strlcpy(va, name, name_len); 692 693 op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT; 694 695 res = operation_commit(&op); 696 697 if (res != TEE_SUCCESS) 698 goto err_exit; 699 700 dir->nw_dir = op.params[2].u.value.a; 701 *d = dir; 702 703 return TEE_SUCCESS; 704 err_exit: 705 free(dir); 706 707 return res; 708 } 709 710 TEE_Result tee_fs_rpc_new_closedir(uint32_t id, struct tee_fs_dir *d) 711 { 712 struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 }; 713 714 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 715 op.params[0].u.value.a = OPTEE_MRF_CLOSEDIR; 716 op.params[0].u.value.b = d->nw_dir; 717 718 if (d) 719 free(d->d.d_name); 720 free(d); 721 return operation_commit(&op); 722 } 723 724 TEE_Result tee_fs_rpc_new_readdir(uint32_t id, struct tee_fs_dir *d, 725 struct tee_fs_dirent **ent) 726 { 727 TEE_Result res; 728 struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 }; 729 void *va; 730 paddr_t pa; 731 uint64_t cookie; 732 const size_t max_name_len = TEE_FS_NAME_MAX + 1; 733 734 if (!d) 735 return TEE_ERROR_ITEM_NOT_FOUND; 736 737 va = tee_fs_rpc_cache_alloc(max_name_len, &pa, &cookie); 738 if (!va) 739 return TEE_ERROR_OUT_OF_MEMORY; 740 741 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 742 op.params[0].u.value.a = OPTEE_MRF_READDIR; 743 op.params[0].u.value.b = d->nw_dir; 744 745 op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT; 746 op.params[1].u.tmem.buf_ptr = pa; 747 op.params[1].u.tmem.size = max_name_len; 748 op.params[1].u.tmem.shm_ref = cookie; 749 750 res = operation_commit(&op); 751 if (res != TEE_SUCCESS) 752 return res; 753 754 free(d->d.d_name); 755 d->d.d_name = strndup(va, max_name_len); 756 if (!d->d.d_name) 757 return TEE_ERROR_OUT_OF_MEMORY; 758 759 *ent = &d->d; 760 return TEE_SUCCESS; 761 } 762 763 TEE_Result tee_fs_rpc_new_begin_transaction(uint32_t id) 764 { 765 struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 }; 766 767 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 768 op.params[0].u.value.a = OPTEE_MRF_BEGIN_TRANSACTION; 769 770 return operation_commit(&op); 771 } 772 773 TEE_Result tee_fs_rpc_new_end_transaction(uint32_t id, bool rollback) 774 { 775 struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 }; 776 777 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 778 op.params[0].u.value.a = OPTEE_MRF_END_TRANSACTION; 779 op.params[0].u.value.b = rollback; 780 781 return operation_commit(&op); 782 } 783