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_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