1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 2018-2020 Linaro Limited 4 */ 5 6#include <cpu_func.h> 7#include <dm.h> 8#include <dm/device_compat.h> 9#include <dm/lists.h> 10#include <log.h> 11#include <malloc.h> 12#include <tee.h> 13#include <linux/arm-smccc.h> 14#include <linux/err.h> 15#include <linux/io.h> 16#include <tee/optee_service.h> 17 18#include "optee_smc.h" 19#include "optee_msg.h" 20#include "optee_private.h" 21 22#define PAGELIST_ENTRIES_PER_PAGE \ 23 ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(u64)) - 1) 24 25/* 26 * PTA_DEVICE_ENUM interface exposed by OP-TEE to discover enumerated services 27 */ 28#define PTA_DEVICE_ENUM { 0x7011a688, 0xddde, 0x4053, \ 29 { 0xa5, 0xa9, 0x7b, 0x3c, 0x4d, 0xdf, 0x13, 0xb8 } } 30/* 31 * PTA_CMD_GET_DEVICES - List services without supplicant dependencies 32 * 33 * [out] memref[0]: List of the UUIDs of service enumerated by OP-TEE 34 */ 35#define PTA_CMD_GET_DEVICES 0x0 36 37/* 38 * PTA_CMD_GET_DEVICES_SUPP - List services depending on tee supplicant 39 * 40 * [out] memref[0]: List of the UUIDs of service enumerated by OP-TEE 41 */ 42#define PTA_CMD_GET_DEVICES_SUPP 0x1 43 44typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long, 45 unsigned long, unsigned long, unsigned long, 46 unsigned long, unsigned long, 47 struct arm_smccc_res *); 48 49struct optee_pdata { 50 optee_invoke_fn *invoke_fn; 51}; 52 53struct rpc_param { 54 u32 a0; 55 u32 a1; 56 u32 a2; 57 u32 a3; 58 u32 a4; 59 u32 a5; 60 u32 a6; 61 u32 a7; 62}; 63 64static struct optee_service *find_service_driver(const struct tee_optee_ta_uuid *uuid) 65{ 66 struct optee_service *service; 67 u8 loc_uuid[TEE_UUID_LEN]; 68 size_t service_cnt, idx; 69 70 service_cnt = ll_entry_count(struct optee_service, optee_service); 71 service = ll_entry_start(struct optee_service, optee_service); 72 73 for (idx = 0; idx < service_cnt; idx++, service++) { 74 tee_optee_ta_uuid_to_octets(loc_uuid, &service->uuid); 75 if (!memcmp(uuid, loc_uuid, sizeof(*uuid))) 76 return service; 77 } 78 79 return NULL; 80} 81 82static int bind_service_list(struct udevice *dev, struct tee_shm *service_list, size_t count) 83{ 84 const struct tee_optee_ta_uuid *service_uuid = (const void *)service_list->addr; 85 struct optee_service *service; 86 size_t idx; 87 int ret; 88 89 for (idx = 0; idx < count; idx++) { 90 service = find_service_driver(service_uuid + idx); 91 if (!service) 92 continue; 93 94 ret = device_bind_driver_to_node(dev, service->driver_name, service->driver_name, 95 dev_ofnode(dev), NULL); 96 if (ret) { 97 dev_warn(dev, "%s was not bound: %d, ignored\n", service->driver_name, ret); 98 continue; 99 } 100 } 101 102 return 0; 103} 104 105static int __enum_services(struct udevice *dev, struct tee_shm *shm, size_t *shm_size, u32 tee_sess, 106 unsigned int pta_cmd) 107{ 108 struct tee_invoke_arg arg = { }; 109 struct tee_param param = { }; 110 int ret = 0; 111 112 arg.func = pta_cmd; 113 arg.session = tee_sess; 114 115 /* Fill invoke cmd params */ 116 param.attr = TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT; 117 param.u.memref.shm = shm; 118 param.u.memref.size = *shm_size; 119 120 ret = tee_invoke_func(dev, &arg, 1, ¶m); 121 if (ret || (arg.ret && arg.ret != TEE_ERROR_SHORT_BUFFER)) { 122 dev_err(dev, "Enumeration command 0x%x failed: 0x%x\n", pta_cmd, arg.ret); 123 return -EINVAL; 124 } 125 126 *shm_size = param.u.memref.size; 127 128 return 0; 129} 130 131static int enum_services(struct udevice *dev, struct tee_shm **shm, size_t *count, u32 tee_sess, 132 unsigned int pta_cmd) 133{ 134 size_t shm_size = 0; 135 int ret; 136 137 ret = __enum_services(dev, NULL, &shm_size, tee_sess, pta_cmd); 138 if (ret) 139 return ret; 140 141 if (!shm_size) { 142 *count = 0; 143 return 0; 144 } 145 146 ret = tee_shm_alloc(dev, shm_size, 0, shm); 147 if (ret) { 148 dev_err(dev, "Failed to allocated shared memory: %d\n", ret); 149 return ret; 150 } 151 152 ret = __enum_services(dev, *shm, &shm_size, tee_sess, pta_cmd); 153 if (!ret) 154 *count = shm_size / sizeof(struct tee_optee_ta_uuid); 155 156 return ret; 157} 158 159static int open_enum_session(struct udevice *dev, u32 *tee_sess) 160{ 161 const struct tee_optee_ta_uuid pta_uuid = PTA_DEVICE_ENUM; 162 struct tee_open_session_arg arg = { }; 163 int ret; 164 165 tee_optee_ta_uuid_to_octets(arg.uuid, &pta_uuid); 166 167 ret = tee_open_session(dev, &arg, 0, NULL); 168 if (ret || arg.ret) { 169 if (!ret) 170 ret = -EIO; 171 return ret; 172 } 173 174 *tee_sess = arg.session; 175 176 return 0; 177} 178 179static int bind_service_drivers(struct udevice *dev) 180{ 181 struct tee_shm *service_list = NULL; 182 size_t service_count; 183 u32 tee_sess; 184 int ret, ret2; 185 186 ret = open_enum_session(dev, &tee_sess); 187 if (ret) 188 return ret; 189 190 ret = enum_services(dev, &service_list, &service_count, tee_sess, 191 PTA_CMD_GET_DEVICES); 192 if (!ret && service_count) 193 ret = bind_service_list(dev, service_list, service_count); 194 195 tee_shm_free(service_list); 196 service_list = NULL; 197 198 ret2 = enum_services(dev, &service_list, &service_count, tee_sess, 199 PTA_CMD_GET_DEVICES_SUPP); 200 if (!ret2 && service_count) 201 ret2 = bind_service_list(dev, service_list, service_count); 202 203 tee_shm_free(service_list); 204 205 tee_close_session(dev, tee_sess); 206 207 if (ret) 208 return ret; 209 210 return ret2; 211} 212 213/** 214 * reg_pair_to_ptr() - Make a pointer of 2 32-bit values 215 * @reg0: High bits of the pointer 216 * @reg1: Low bits of the pointer 217 * 218 * Returns the combined result, note that if a pointer is 32-bit wide @reg0 219 * will be discarded. 220 */ 221static void *reg_pair_to_ptr(u32 reg0, u32 reg1) 222{ 223 return (void *)(ulong)(((u64)reg0 << 32) | reg1); 224} 225 226/** 227 * reg_pair_from_64() - Split a 64-bit value into two 32-bit values 228 * @reg0: High bits of @val 229 * @reg1: Low bits of @val 230 * @val: The value to split 231 */ 232static void reg_pair_from_64(u32 *reg0, u32 *reg1, u64 val) 233{ 234 *reg0 = val >> 32; 235 *reg1 = val; 236} 237 238/** 239 * optee_alloc_and_init_page_list() - Provide page list of memory buffer 240 * @buf: Start of buffer 241 * @len: Length of buffer 242 * @phys_buf_ptr Physical pointer with coded offset to page list 243 * 244 * Secure world doesn't share mapping with Normal world (U-Boot in this case) 245 * so physical pointers are needed when sharing pointers. 246 * 247 * Returns a pointer page list on success or NULL on failure 248 */ 249void *optee_alloc_and_init_page_list(void *buf, ulong len, u64 *phys_buf_ptr) 250{ 251 const unsigned int page_size = OPTEE_MSG_NONCONTIG_PAGE_SIZE; 252 const phys_addr_t page_mask = page_size - 1; 253 u8 *buf_base; 254 unsigned int page_offset; 255 unsigned int num_pages; 256 unsigned int list_size; 257 unsigned int n; 258 void *page_list; 259 struct { 260 u64 pages_list[PAGELIST_ENTRIES_PER_PAGE]; 261 u64 next_page_data; 262 } *pages_data; 263 264 /* 265 * A Memory buffer is described in chunks of 4k. The list of 266 * physical addresses has to be represented by a physical pointer 267 * too and a single list has to start at a 4k page and fit into 268 * that page. In order to be able to describe large memory buffers 269 * these 4k pages carrying physical addresses are linked together 270 * in a list. See OPTEE_MSG_ATTR_NONCONTIG in 271 * drivers/tee/optee/optee_msg.h for more information. 272 */ 273 274 page_offset = (ulong)buf & page_mask; 275 num_pages = roundup(page_offset + len, page_size) / page_size; 276 list_size = DIV_ROUND_UP(num_pages, PAGELIST_ENTRIES_PER_PAGE) * 277 page_size; 278 page_list = memalign(page_size, list_size); 279 if (!page_list) 280 return NULL; 281 282 pages_data = page_list; 283 buf_base = (u8 *)rounddown((ulong)buf, page_size); 284 n = 0; 285 while (num_pages) { 286 pages_data->pages_list[n] = virt_to_phys(buf_base); 287 n++; 288 buf_base += page_size; 289 num_pages--; 290 291 if (n == PAGELIST_ENTRIES_PER_PAGE) { 292 pages_data->next_page_data = 293 virt_to_phys(pages_data + 1); 294 pages_data++; 295 n = 0; 296 } 297 } 298 299 *phys_buf_ptr = virt_to_phys(page_list) | page_offset; 300 return page_list; 301} 302 303static void optee_get_version(struct udevice *dev, 304 struct tee_version_data *vers) 305{ 306 struct tee_version_data v = { 307 .gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM, 308 }; 309 310 *vers = v; 311} 312 313static int get_msg_arg(struct udevice *dev, uint num_params, 314 struct tee_shm **shmp, struct optee_msg_arg **msg_arg) 315{ 316 int rc; 317 struct optee_msg_arg *ma; 318 319 rc = __tee_shm_add(dev, OPTEE_MSG_NONCONTIG_PAGE_SIZE, NULL, 320 OPTEE_MSG_GET_ARG_SIZE(num_params), TEE_SHM_ALLOC, 321 shmp); 322 if (rc) 323 return rc; 324 325 ma = (*shmp)->addr; 326 memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params)); 327 ma->num_params = num_params; 328 *msg_arg = ma; 329 330 return 0; 331} 332 333static int to_msg_param(struct optee_msg_param *msg_params, uint num_params, 334 const struct tee_param *params) 335{ 336 uint n; 337 338 for (n = 0; n < num_params; n++) { 339 const struct tee_param *p = params + n; 340 struct optee_msg_param *mp = msg_params + n; 341 342 switch (p->attr) { 343 case TEE_PARAM_ATTR_TYPE_NONE: 344 mp->attr = OPTEE_MSG_ATTR_TYPE_NONE; 345 memset(&mp->u, 0, sizeof(mp->u)); 346 break; 347 case TEE_PARAM_ATTR_TYPE_VALUE_INPUT: 348 case TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT: 349 case TEE_PARAM_ATTR_TYPE_VALUE_INOUT: 350 mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr - 351 TEE_PARAM_ATTR_TYPE_VALUE_INPUT; 352 mp->u.value.a = p->u.value.a; 353 mp->u.value.b = p->u.value.b; 354 mp->u.value.c = p->u.value.c; 355 break; 356 case TEE_PARAM_ATTR_TYPE_MEMREF_INPUT: 357 case TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT: 358 case TEE_PARAM_ATTR_TYPE_MEMREF_INOUT: 359 mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr - 360 TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; 361 mp->u.rmem.shm_ref = (ulong)p->u.memref.shm; 362 mp->u.rmem.size = p->u.memref.size; 363 mp->u.rmem.offs = p->u.memref.shm_offs; 364 break; 365 default: 366 return -EINVAL; 367 } 368 } 369 return 0; 370} 371 372static int from_msg_param(struct tee_param *params, uint num_params, 373 const struct optee_msg_param *msg_params) 374{ 375 uint n; 376 struct tee_shm *shm; 377 378 for (n = 0; n < num_params; n++) { 379 struct tee_param *p = params + n; 380 const struct optee_msg_param *mp = msg_params + n; 381 u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK; 382 383 switch (attr) { 384 case OPTEE_MSG_ATTR_TYPE_NONE: 385 p->attr = TEE_PARAM_ATTR_TYPE_NONE; 386 memset(&p->u, 0, sizeof(p->u)); 387 break; 388 case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT: 389 case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT: 390 case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT: 391 p->attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT + attr - 392 OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 393 p->u.value.a = mp->u.value.a; 394 p->u.value.b = mp->u.value.b; 395 p->u.value.c = mp->u.value.c; 396 break; 397 case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT: 398 case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: 399 case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: 400 p->attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT + attr - 401 OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; 402 p->u.memref.size = mp->u.rmem.size; 403 shm = (struct tee_shm *)(ulong)mp->u.rmem.shm_ref; 404 405 if (!shm) { 406 p->u.memref.shm_offs = 0; 407 p->u.memref.shm = NULL; 408 break; 409 } 410 p->u.memref.shm_offs = mp->u.rmem.offs; 411 p->u.memref.shm = shm; 412 break; 413 default: 414 return -EINVAL; 415 } 416 } 417 return 0; 418} 419 420static void handle_rpc(struct udevice *dev, struct rpc_param *param, 421 void *page_list) 422{ 423 struct tee_shm *shm; 424 425 switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) { 426 case OPTEE_SMC_RPC_FUNC_ALLOC: 427 if (!__tee_shm_add(dev, OPTEE_MSG_NONCONTIG_PAGE_SIZE, NULL, 428 param->a1, TEE_SHM_ALLOC | TEE_SHM_REGISTER, 429 &shm)) { 430 reg_pair_from_64(¶m->a1, ¶m->a2, 431 virt_to_phys(shm->addr)); 432 /* "cookie" */ 433 reg_pair_from_64(¶m->a4, ¶m->a5, (ulong)shm); 434 } else { 435 param->a1 = 0; 436 param->a2 = 0; 437 param->a4 = 0; 438 param->a5 = 0; 439 } 440 break; 441 case OPTEE_SMC_RPC_FUNC_FREE: 442 shm = reg_pair_to_ptr(param->a1, param->a2); 443 tee_shm_free(shm); 444 break; 445 case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR: 446 break; 447 case OPTEE_SMC_RPC_FUNC_CMD: 448 shm = reg_pair_to_ptr(param->a1, param->a2); 449 optee_suppl_cmd(dev, shm, page_list); 450 break; 451 default: 452 break; 453 } 454 455 param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC; 456} 457 458static u32 call_err_to_res(u32 call_err) 459{ 460 switch (call_err) { 461 case OPTEE_SMC_RETURN_OK: 462 return TEE_SUCCESS; 463 default: 464 return TEE_ERROR_BAD_PARAMETERS; 465 } 466} 467 468static void flush_shm_dcache(struct udevice *dev, struct optee_msg_arg *arg) 469{ 470 size_t sz = OPTEE_MSG_GET_ARG_SIZE(arg->num_params); 471 472 flush_dcache_range(rounddown((ulong)arg, CONFIG_SYS_CACHELINE_SIZE), 473 roundup((ulong)arg + sz, CONFIG_SYS_CACHELINE_SIZE)); 474 475 tee_flush_all_shm_dcache(dev); 476} 477 478static u32 do_call_with_arg(struct udevice *dev, struct optee_msg_arg *arg) 479{ 480 struct optee_pdata *pdata = dev_get_plat(dev); 481 struct rpc_param param = { .a0 = OPTEE_SMC_CALL_WITH_ARG }; 482 void *page_list = NULL; 483 484 reg_pair_from_64(¶m.a1, ¶m.a2, virt_to_phys(arg)); 485 while (true) { 486 struct arm_smccc_res res; 487 488 /* If cache are off from U-Boot, sync the cache shared with OP-TEE */ 489 if (!dcache_status()) 490 flush_shm_dcache(dev, arg); 491 492 pdata->invoke_fn(param.a0, param.a1, param.a2, param.a3, 493 param.a4, param.a5, param.a6, param.a7, &res); 494 495 /* If cache are off from U-Boot, sync the cache shared with OP-TEE */ 496 if (!dcache_status()) 497 flush_shm_dcache(dev, arg); 498 499 free(page_list); 500 page_list = NULL; 501 502 if (OPTEE_SMC_RETURN_IS_RPC(res.a0)) { 503 param.a0 = res.a0; 504 param.a1 = res.a1; 505 param.a2 = res.a2; 506 param.a3 = res.a3; 507 handle_rpc(dev, ¶m, &page_list); 508 } else { 509 /* 510 * In case we've accessed RPMB to serve an RPC 511 * request we need to restore the previously 512 * selected partition as the caller may expect it 513 * to remain unchanged. 514 */ 515 optee_suppl_rpmb_release(dev); 516 return call_err_to_res(res.a0); 517 } 518 } 519} 520 521static int optee_close_session(struct udevice *dev, u32 session) 522{ 523 int rc; 524 struct tee_shm *shm; 525 struct optee_msg_arg *msg_arg; 526 527 rc = get_msg_arg(dev, 0, &shm, &msg_arg); 528 if (rc) 529 return rc; 530 531 msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION; 532 msg_arg->session = session; 533 do_call_with_arg(dev, msg_arg); 534 535 tee_shm_free(shm); 536 537 return 0; 538} 539 540static int optee_open_session(struct udevice *dev, 541 struct tee_open_session_arg *arg, 542 uint num_params, struct tee_param *params) 543{ 544 int rc; 545 struct tee_shm *shm; 546 struct optee_msg_arg *msg_arg; 547 548 rc = get_msg_arg(dev, num_params + 2, &shm, &msg_arg); 549 if (rc) 550 return rc; 551 552 msg_arg->cmd = OPTEE_MSG_CMD_OPEN_SESSION; 553 /* 554 * Initialize and add the meta parameters needed when opening a 555 * session. 556 */ 557 msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT | 558 OPTEE_MSG_ATTR_META; 559 msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT | 560 OPTEE_MSG_ATTR_META; 561 memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid)); 562 memcpy(&msg_arg->params[1].u.value, arg->uuid, sizeof(arg->clnt_uuid)); 563 msg_arg->params[1].u.value.c = arg->clnt_login; 564 565 rc = to_msg_param(msg_arg->params + 2, num_params, params); 566 if (rc) 567 goto out; 568 569 arg->ret = do_call_with_arg(dev, msg_arg); 570 if (arg->ret) { 571 arg->ret_origin = TEE_ORIGIN_COMMS; 572 goto out; 573 } 574 575 if (from_msg_param(params, num_params, msg_arg->params + 2)) { 576 arg->ret = TEE_ERROR_COMMUNICATION; 577 arg->ret_origin = TEE_ORIGIN_COMMS; 578 /* Close session again to avoid leakage */ 579 optee_close_session(dev, msg_arg->session); 580 goto out; 581 } 582 583 arg->session = msg_arg->session; 584 arg->ret = msg_arg->ret; 585 arg->ret_origin = msg_arg->ret_origin; 586out: 587 tee_shm_free(shm); 588 589 return rc; 590} 591 592static int optee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg, 593 uint num_params, struct tee_param *params) 594{ 595 struct tee_shm *shm; 596 struct optee_msg_arg *msg_arg; 597 int rc; 598 599 rc = get_msg_arg(dev, num_params, &shm, &msg_arg); 600 if (rc) 601 return rc; 602 msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND; 603 msg_arg->func = arg->func; 604 msg_arg->session = arg->session; 605 606 rc = to_msg_param(msg_arg->params, num_params, params); 607 if (rc) 608 goto out; 609 610 arg->ret = do_call_with_arg(dev, msg_arg); 611 if (arg->ret) { 612 arg->ret_origin = TEE_ORIGIN_COMMS; 613 goto out; 614 } 615 616 if (from_msg_param(params, num_params, msg_arg->params)) { 617 arg->ret = TEE_ERROR_COMMUNICATION; 618 arg->ret_origin = TEE_ORIGIN_COMMS; 619 goto out; 620 } 621 622 arg->ret = msg_arg->ret; 623 arg->ret_origin = msg_arg->ret_origin; 624out: 625 tee_shm_free(shm); 626 return rc; 627} 628 629static int optee_shm_register(struct udevice *dev, struct tee_shm *shm) 630{ 631 struct tee_shm *shm_arg; 632 struct optee_msg_arg *msg_arg; 633 void *pl; 634 u64 ph_ptr; 635 int rc; 636 637 rc = get_msg_arg(dev, 1, &shm_arg, &msg_arg); 638 if (rc) 639 return rc; 640 641 pl = optee_alloc_and_init_page_list(shm->addr, shm->size, &ph_ptr); 642 if (!pl) { 643 rc = -ENOMEM; 644 goto out; 645 } 646 647 msg_arg->cmd = OPTEE_MSG_CMD_REGISTER_SHM; 648 msg_arg->params->attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | 649 OPTEE_MSG_ATTR_NONCONTIG; 650 msg_arg->params->u.tmem.buf_ptr = ph_ptr; 651 msg_arg->params->u.tmem.shm_ref = (ulong)shm; 652 msg_arg->params->u.tmem.size = shm->size; 653 654 if (do_call_with_arg(dev, msg_arg) || msg_arg->ret) 655 rc = -EINVAL; 656 657 free(pl); 658out: 659 tee_shm_free(shm_arg); 660 661 return rc; 662} 663 664static int optee_shm_unregister(struct udevice *dev, struct tee_shm *shm) 665{ 666 struct tee_shm *shm_arg; 667 struct optee_msg_arg *msg_arg; 668 int rc; 669 670 rc = get_msg_arg(dev, 1, &shm_arg, &msg_arg); 671 if (rc) 672 return rc; 673 674 msg_arg->cmd = OPTEE_MSG_CMD_UNREGISTER_SHM; 675 msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; 676 msg_arg->params[0].u.rmem.shm_ref = (ulong)shm; 677 678 if (do_call_with_arg(dev, msg_arg) || msg_arg->ret) 679 rc = -EINVAL; 680 tee_shm_free(shm_arg); 681 682 return rc; 683} 684 685static const struct tee_driver_ops optee_ops = { 686 .get_version = optee_get_version, 687 .open_session = optee_open_session, 688 .close_session = optee_close_session, 689 .invoke_func = optee_invoke_func, 690 .shm_register = optee_shm_register, 691 .shm_unregister = optee_shm_unregister, 692}; 693 694static bool is_optee_api(optee_invoke_fn *invoke_fn) 695{ 696 struct arm_smccc_res res; 697 698 invoke_fn(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res); 699 700 return res.a0 == OPTEE_MSG_UID_0 && res.a1 == OPTEE_MSG_UID_1 && 701 res.a2 == OPTEE_MSG_UID_2 && res.a3 == OPTEE_MSG_UID_3; 702} 703 704static void print_os_revision(struct udevice *dev, optee_invoke_fn *invoke_fn) 705{ 706 union { 707 struct arm_smccc_res smccc; 708 struct optee_smc_call_get_os_revision_result result; 709 } res = { 710 .result = { 711 .build_id = 0 712 } 713 }; 714 715 invoke_fn(OPTEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0, 0, 716 &res.smccc); 717 718 if (res.result.build_id) 719 dev_info(dev, "OP-TEE: revision %lu.%lu (%08lx)\n", 720 res.result.major, res.result.minor, 721 res.result.build_id); 722 else 723 dev_info(dev, "OP-TEE: revision %lu.%lu\n", 724 res.result.major, res.result.minor); 725} 726 727static bool api_revision_is_compatible(optee_invoke_fn *invoke_fn) 728{ 729 union { 730 struct arm_smccc_res smccc; 731 struct optee_smc_calls_revision_result result; 732 } res; 733 734 invoke_fn(OPTEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc); 735 736 return res.result.major == OPTEE_MSG_REVISION_MAJOR && 737 (int)res.result.minor >= OPTEE_MSG_REVISION_MINOR; 738} 739 740static bool exchange_capabilities(optee_invoke_fn *invoke_fn, u32 *sec_caps) 741{ 742 union { 743 struct arm_smccc_res smccc; 744 struct optee_smc_exchange_capabilities_result result; 745 } res; 746 747 invoke_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES, 748 OPTEE_SMC_NSEC_CAP_UNIPROCESSOR, 0, 0, 0, 0, 0, 0, 749 &res.smccc); 750 751 if (res.result.status != OPTEE_SMC_RETURN_OK) 752 return false; 753 754 *sec_caps = res.result.capabilities; 755 756 return true; 757} 758 759/* Simple wrapper functions to be able to use a function pointer */ 760static void optee_smccc_smc(unsigned long a0, unsigned long a1, 761 unsigned long a2, unsigned long a3, 762 unsigned long a4, unsigned long a5, 763 unsigned long a6, unsigned long a7, 764 struct arm_smccc_res *res) 765{ 766 arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, res); 767} 768 769static void optee_smccc_hvc(unsigned long a0, unsigned long a1, 770 unsigned long a2, unsigned long a3, 771 unsigned long a4, unsigned long a5, 772 unsigned long a6, unsigned long a7, 773 struct arm_smccc_res *res) 774{ 775 arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res); 776} 777 778static optee_invoke_fn *get_invoke_func(struct udevice *dev) 779{ 780 const char *method; 781 782 debug("optee: looking for conduit method in DT.\n"); 783 method = ofnode_get_property(dev_ofnode(dev), "method", NULL); 784 if (!method) { 785 debug("optee: missing \"method\" property\n"); 786 return ERR_PTR(-ENXIO); 787 } 788 789 if (!strcmp("hvc", method)) 790 return optee_smccc_hvc; 791 else if (!strcmp("smc", method)) 792 return optee_smccc_smc; 793 794 debug("optee: invalid \"method\" property: %s\n", method); 795 return ERR_PTR(-EINVAL); 796} 797 798static int optee_of_to_plat(struct udevice *dev) 799{ 800 struct optee_pdata *pdata = dev_get_plat(dev); 801 802 pdata->invoke_fn = get_invoke_func(dev); 803 if (IS_ERR(pdata->invoke_fn)) 804 return PTR_ERR(pdata->invoke_fn); 805 806 return 0; 807} 808 809static int optee_bind(struct udevice *dev) 810{ 811 if (IS_ENABLED(CONFIG_OPTEE_SERVICE_DISCOVERY)) 812 dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND); 813 814 return 0; 815} 816 817static int optee_probe(struct udevice *dev) 818{ 819 struct optee_pdata *pdata = dev_get_plat(dev); 820 u32 sec_caps; 821 int ret; 822 823 if (!is_optee_api(pdata->invoke_fn)) { 824 dev_err(dev, "OP-TEE api uid mismatch\n"); 825 return -ENOENT; 826 } 827 828 print_os_revision(dev, pdata->invoke_fn); 829 830 if (!api_revision_is_compatible(pdata->invoke_fn)) { 831 dev_err(dev, "OP-TEE api revision mismatch\n"); 832 return -ENOENT; 833 } 834 835 /* 836 * OP-TEE can use both shared memory via predefined pool or as 837 * dynamic shared memory provided by normal world. To keep things 838 * simple we're only using dynamic shared memory in this driver. 839 */ 840 if (!exchange_capabilities(pdata->invoke_fn, &sec_caps) || 841 !(sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)) { 842 dev_err(dev, "OP-TEE capabilities mismatch\n"); 843 return -ENOENT; 844 } 845 846 if (IS_ENABLED(CONFIG_OPTEE_SERVICE_DISCOVERY)) { 847 ret = bind_service_drivers(dev); 848 if (ret) 849 dev_warn(dev, "optee service enumeration failed: %d\n", ret); 850 } else if (IS_ENABLED(CONFIG_RNG_OPTEE)) { 851 /* 852 * Discovery of TAs on the TEE bus is not supported in U-Boot: 853 * only bind the drivers associated to the supported OP-TEE TA 854 */ 855 ret = device_bind_driver_to_node(dev, "optee-rng", "optee-rng", 856 dev_ofnode(dev), NULL); 857 if (ret) 858 dev_warn(dev, "optee-rng failed to bind: %d\n", ret); 859 } 860 861 return 0; 862} 863 864static const struct udevice_id optee_match[] = { 865 { .compatible = "linaro,optee-tz" }, 866 {}, 867}; 868 869U_BOOT_DRIVER(optee) = { 870 .name = "optee", 871 .id = UCLASS_TEE, 872 .of_match = optee_match, 873 .of_to_plat = optee_of_to_plat, 874 .probe = optee_probe, 875 .bind = optee_bind, 876 .ops = &optee_ops, 877 .plat_auto = sizeof(struct optee_pdata), 878 .priv_auto = sizeof(struct optee_private), 879}; 880