diff options
author | Olof Johansson <olof@lixom.net> | 2018-08-26 19:27:32 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2018-08-26 19:27:32 -0400 |
commit | 63c65b872562a2faf8a3a289c117d0c0e3bceb5a (patch) | |
tree | e455b65cfbf1ea60ffbd792ac644d742aea23961 | |
parent | 5b394b2ddf0347bef56e50c69a58773c94343ff3 (diff) | |
parent | 25559c22cef879c5cf7119540bfe21fb379d29f3 (diff) |
Merge tag 'tee-drv-for-4.20' of git://git.linaro.org/people/jens.wiklander/linux-tee into next/drivers
Misc enhancement for tee driver subsystem
* Adds a kernel internal tee client interface allowing other drivers
etc to access a TEE
* OP-TEE driver takes DT status property into account
* tag 'tee-drv-for-4.20' of git://git.linaro.org/people/jens.wiklander/linux-tee:
tee: add kernel internal client interface
tee: optee: take DT status property into account
Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r-- | drivers/tee/optee/core.c | 2 | ||||
-rw-r--r-- | drivers/tee/tee_core.c | 113 | ||||
-rw-r--r-- | include/linux/tee_drv.h | 73 |
3 files changed, 180 insertions, 8 deletions
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index e1aafe842d66..34dce850067b 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c | |||
@@ -696,7 +696,7 @@ static int __init optee_driver_init(void) | |||
696 | return -ENODEV; | 696 | return -ENODEV; |
697 | 697 | ||
698 | np = of_find_matching_node(fw_np, optee_match); | 698 | np = of_find_matching_node(fw_np, optee_match); |
699 | if (!np) | 699 | if (!np || !of_device_is_available(np)) |
700 | return -ENODEV; | 700 | return -ENODEV; |
701 | 701 | ||
702 | optee = optee_probe(np); | 702 | optee = optee_probe(np); |
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index dd46b758852a..7b2bb4c50058 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c | |||
@@ -38,15 +38,13 @@ static DEFINE_SPINLOCK(driver_lock); | |||
38 | static struct class *tee_class; | 38 | static struct class *tee_class; |
39 | static dev_t tee_devt; | 39 | static dev_t tee_devt; |
40 | 40 | ||
41 | static int tee_open(struct inode *inode, struct file *filp) | 41 | static struct tee_context *teedev_open(struct tee_device *teedev) |
42 | { | 42 | { |
43 | int rc; | 43 | int rc; |
44 | struct tee_device *teedev; | ||
45 | struct tee_context *ctx; | 44 | struct tee_context *ctx; |
46 | 45 | ||
47 | teedev = container_of(inode->i_cdev, struct tee_device, cdev); | ||
48 | if (!tee_device_get(teedev)) | 46 | if (!tee_device_get(teedev)) |
49 | return -EINVAL; | 47 | return ERR_PTR(-EINVAL); |
50 | 48 | ||
51 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | 49 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
52 | if (!ctx) { | 50 | if (!ctx) { |
@@ -57,16 +55,16 @@ static int tee_open(struct inode *inode, struct file *filp) | |||
57 | kref_init(&ctx->refcount); | 55 | kref_init(&ctx->refcount); |
58 | ctx->teedev = teedev; | 56 | ctx->teedev = teedev; |
59 | INIT_LIST_HEAD(&ctx->list_shm); | 57 | INIT_LIST_HEAD(&ctx->list_shm); |
60 | filp->private_data = ctx; | ||
61 | rc = teedev->desc->ops->open(ctx); | 58 | rc = teedev->desc->ops->open(ctx); |
62 | if (rc) | 59 | if (rc) |
63 | goto err; | 60 | goto err; |
64 | 61 | ||
65 | return 0; | 62 | return ctx; |
66 | err: | 63 | err: |
67 | kfree(ctx); | 64 | kfree(ctx); |
68 | tee_device_put(teedev); | 65 | tee_device_put(teedev); |
69 | return rc; | 66 | return ERR_PTR(rc); |
67 | |||
70 | } | 68 | } |
71 | 69 | ||
72 | void teedev_ctx_get(struct tee_context *ctx) | 70 | void teedev_ctx_get(struct tee_context *ctx) |
@@ -100,6 +98,18 @@ static void teedev_close_context(struct tee_context *ctx) | |||
100 | teedev_ctx_put(ctx); | 98 | teedev_ctx_put(ctx); |
101 | } | 99 | } |
102 | 100 | ||
101 | static int tee_open(struct inode *inode, struct file *filp) | ||
102 | { | ||
103 | struct tee_context *ctx; | ||
104 | |||
105 | ctx = teedev_open(container_of(inode->i_cdev, struct tee_device, cdev)); | ||
106 | if (IS_ERR(ctx)) | ||
107 | return PTR_ERR(ctx); | ||
108 | |||
109 | filp->private_data = ctx; | ||
110 | return 0; | ||
111 | } | ||
112 | |||
103 | static int tee_release(struct inode *inode, struct file *filp) | 113 | static int tee_release(struct inode *inode, struct file *filp) |
104 | { | 114 | { |
105 | teedev_close_context(filp->private_data); | 115 | teedev_close_context(filp->private_data); |
@@ -928,6 +938,95 @@ void *tee_get_drvdata(struct tee_device *teedev) | |||
928 | } | 938 | } |
929 | EXPORT_SYMBOL_GPL(tee_get_drvdata); | 939 | EXPORT_SYMBOL_GPL(tee_get_drvdata); |
930 | 940 | ||
941 | struct match_dev_data { | ||
942 | struct tee_ioctl_version_data *vers; | ||
943 | const void *data; | ||
944 | int (*match)(struct tee_ioctl_version_data *, const void *); | ||
945 | }; | ||
946 | |||
947 | static int match_dev(struct device *dev, const void *data) | ||
948 | { | ||
949 | const struct match_dev_data *match_data = data; | ||
950 | struct tee_device *teedev = container_of(dev, struct tee_device, dev); | ||
951 | |||
952 | teedev->desc->ops->get_version(teedev, match_data->vers); | ||
953 | return match_data->match(match_data->vers, match_data->data); | ||
954 | } | ||
955 | |||
956 | struct tee_context * | ||
957 | tee_client_open_context(struct tee_context *start, | ||
958 | int (*match)(struct tee_ioctl_version_data *, | ||
959 | const void *), | ||
960 | const void *data, struct tee_ioctl_version_data *vers) | ||
961 | { | ||
962 | struct device *dev = NULL; | ||
963 | struct device *put_dev = NULL; | ||
964 | struct tee_context *ctx = NULL; | ||
965 | struct tee_ioctl_version_data v; | ||
966 | struct match_dev_data match_data = { vers ? vers : &v, data, match }; | ||
967 | |||
968 | if (start) | ||
969 | dev = &start->teedev->dev; | ||
970 | |||
971 | do { | ||
972 | dev = class_find_device(tee_class, dev, &match_data, match_dev); | ||
973 | if (!dev) { | ||
974 | ctx = ERR_PTR(-ENOENT); | ||
975 | break; | ||
976 | } | ||
977 | |||
978 | put_device(put_dev); | ||
979 | put_dev = dev; | ||
980 | |||
981 | ctx = teedev_open(container_of(dev, struct tee_device, dev)); | ||
982 | } while (IS_ERR(ctx) && PTR_ERR(ctx) != -ENOMEM); | ||
983 | |||
984 | put_device(put_dev); | ||
985 | return ctx; | ||
986 | } | ||
987 | EXPORT_SYMBOL_GPL(tee_client_open_context); | ||
988 | |||
989 | void tee_client_close_context(struct tee_context *ctx) | ||
990 | { | ||
991 | teedev_close_context(ctx); | ||
992 | } | ||
993 | EXPORT_SYMBOL_GPL(tee_client_close_context); | ||
994 | |||
995 | void tee_client_get_version(struct tee_context *ctx, | ||
996 | struct tee_ioctl_version_data *vers) | ||
997 | { | ||
998 | ctx->teedev->desc->ops->get_version(ctx->teedev, vers); | ||
999 | } | ||
1000 | EXPORT_SYMBOL_GPL(tee_client_get_version); | ||
1001 | |||
1002 | int tee_client_open_session(struct tee_context *ctx, | ||
1003 | struct tee_ioctl_open_session_arg *arg, | ||
1004 | struct tee_param *param) | ||
1005 | { | ||
1006 | if (!ctx->teedev->desc->ops->open_session) | ||
1007 | return -EINVAL; | ||
1008 | return ctx->teedev->desc->ops->open_session(ctx, arg, param); | ||
1009 | } | ||
1010 | EXPORT_SYMBOL_GPL(tee_client_open_session); | ||
1011 | |||
1012 | int tee_client_close_session(struct tee_context *ctx, u32 session) | ||
1013 | { | ||
1014 | if (!ctx->teedev->desc->ops->close_session) | ||
1015 | return -EINVAL; | ||
1016 | return ctx->teedev->desc->ops->close_session(ctx, session); | ||
1017 | } | ||
1018 | EXPORT_SYMBOL_GPL(tee_client_close_session); | ||
1019 | |||
1020 | int tee_client_invoke_func(struct tee_context *ctx, | ||
1021 | struct tee_ioctl_invoke_arg *arg, | ||
1022 | struct tee_param *param) | ||
1023 | { | ||
1024 | if (!ctx->teedev->desc->ops->invoke_func) | ||
1025 | return -EINVAL; | ||
1026 | return ctx->teedev->desc->ops->invoke_func(ctx, arg, param); | ||
1027 | } | ||
1028 | EXPORT_SYMBOL_GPL(tee_client_invoke_func); | ||
1029 | |||
931 | static int __init tee_init(void) | 1030 | static int __init tee_init(void) |
932 | { | 1031 | { |
933 | int rc; | 1032 | int rc; |
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index a2b3dfcee0b5..6cfe05893a76 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h | |||
@@ -453,6 +453,79 @@ static inline int tee_shm_get_id(struct tee_shm *shm) | |||
453 | */ | 453 | */ |
454 | struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id); | 454 | struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id); |
455 | 455 | ||
456 | /** | ||
457 | * tee_client_open_context() - Open a TEE context | ||
458 | * @start: if not NULL, continue search after this context | ||
459 | * @match: function to check TEE device | ||
460 | * @data: data for match function | ||
461 | * @vers: if not NULL, version data of TEE device of the context returned | ||
462 | * | ||
463 | * This function does an operation similar to open("/dev/teeX") in user space. | ||
464 | * A returned context must be released with tee_client_close_context(). | ||
465 | * | ||
466 | * Returns a TEE context of the first TEE device matched by the match() | ||
467 | * callback or an ERR_PTR. | ||
468 | */ | ||
469 | struct tee_context * | ||
470 | tee_client_open_context(struct tee_context *start, | ||
471 | int (*match)(struct tee_ioctl_version_data *, | ||
472 | const void *), | ||
473 | const void *data, struct tee_ioctl_version_data *vers); | ||
474 | |||
475 | /** | ||
476 | * tee_client_close_context() - Close a TEE context | ||
477 | * @ctx: TEE context to close | ||
478 | * | ||
479 | * Note that all sessions previously opened with this context will be | ||
480 | * closed when this function is called. | ||
481 | */ | ||
482 | void tee_client_close_context(struct tee_context *ctx); | ||
483 | |||
484 | /** | ||
485 | * tee_client_get_version() - Query version of TEE | ||
486 | * @ctx: TEE context to TEE to query | ||
487 | * @vers: Pointer to version data | ||
488 | */ | ||
489 | void tee_client_get_version(struct tee_context *ctx, | ||
490 | struct tee_ioctl_version_data *vers); | ||
491 | |||
492 | /** | ||
493 | * tee_client_open_session() - Open a session to a Trusted Application | ||
494 | * @ctx: TEE context | ||
495 | * @arg: Open session arguments, see description of | ||
496 | * struct tee_ioctl_open_session_arg | ||
497 | * @param: Parameters passed to the Trusted Application | ||
498 | * | ||
499 | * Returns < 0 on error else see @arg->ret for result. If @arg->ret | ||
500 | * is TEEC_SUCCESS the session identifier is available in @arg->session. | ||
501 | */ | ||
502 | int tee_client_open_session(struct tee_context *ctx, | ||
503 | struct tee_ioctl_open_session_arg *arg, | ||
504 | struct tee_param *param); | ||
505 | |||
506 | /** | ||
507 | * tee_client_close_session() - Close a session to a Trusted Application | ||
508 | * @ctx: TEE Context | ||
509 | * @session: Session id | ||
510 | * | ||
511 | * Return < 0 on error else 0, regardless the session will not be | ||
512 | * valid after this function has returned. | ||
513 | */ | ||
514 | int tee_client_close_session(struct tee_context *ctx, u32 session); | ||
515 | |||
516 | /** | ||
517 | * tee_client_invoke_func() - Invoke a function in a Trusted Application | ||
518 | * @ctx: TEE Context | ||
519 | * @arg: Invoke arguments, see description of | ||
520 | * struct tee_ioctl_invoke_arg | ||
521 | * @param: Parameters passed to the Trusted Application | ||
522 | * | ||
523 | * Returns < 0 on error else see @arg->ret for result. | ||
524 | */ | ||
525 | int tee_client_invoke_func(struct tee_context *ctx, | ||
526 | struct tee_ioctl_invoke_arg *arg, | ||
527 | struct tee_param *param); | ||
528 | |||
456 | static inline bool tee_param_is_memref(struct tee_param *param) | 529 | static inline bool tee_param_is_memref(struct tee_param *param) |
457 | { | 530 | { |
458 | switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { | 531 | switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { |