diff options
Diffstat (limited to 'security/tlk_driver/ote_fs.c')
-rw-r--r-- | security/tlk_driver/ote_fs.c | 87 |
1 files changed, 78 insertions, 9 deletions
diff --git a/security/tlk_driver/ote_fs.c b/security/tlk_driver/ote_fs.c index e3d427ae9a2f..f58bdd64aecb 100644 --- a/security/tlk_driver/ote_fs.c +++ b/security/tlk_driver/ote_fs.c @@ -30,6 +30,7 @@ static DECLARE_COMPLETION(req_ready); static DECLARE_COMPLETION(req_complete); +static struct te_ss_op_legacy *ss_op_shmem_legacy; static struct te_ss_op *ss_op_shmem; static uint32_t ss_op_size; @@ -38,26 +39,26 @@ static void indicate_ss_op_complete(void) tlk_generic_smc(TE_SMC_SS_REQ_COMPLETE, 0, 0); } -int te_handle_ss_ioctl(struct file *file, unsigned int ioctl_num, +int te_handle_ss_ioctl_legacy(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { switch (ioctl_num) { - case TE_IOCTL_SS_NEW_REQ: + case TE_IOCTL_SS_NEW_REQ_LEGACY: /* wait for a new request */ if (wait_for_completion_interruptible(&req_ready)) return -ENODATA; /* transfer pending request to daemon's buffer */ - if (copy_to_user((void __user *)ioctl_param, ss_op_shmem, + if (copy_to_user((void __user *)ioctl_param, ss_op_shmem_legacy, ss_op_size)) { pr_err("copy_to_user failed for new request\n"); return -EFAULT; } break; - case TE_IOCTL_SS_REQ_COMPLETE: /* request complete */ - if (copy_from_user(ss_op_shmem, (void __user *)ioctl_param, - ss_op_size)) { + case TE_IOCTL_SS_REQ_COMPLETE_LEGACY: /* request complete */ + if (copy_from_user(ss_op_shmem_legacy, + (void __user *)ioctl_param, ss_op_size)) { pr_err("copy_from_user failed for request\n"); return -EFAULT; } @@ -70,7 +71,7 @@ int te_handle_ss_ioctl(struct file *file, unsigned int ioctl_num, return 0; } -void tlk_ss_op(uint32_t size) +void tlk_ss_op_legacy(uint32_t size) { /* store size of request */ ss_op_size = size; @@ -85,9 +86,71 @@ void tlk_ss_op(uint32_t size) indicate_ss_op_complete(); } +static int __init tlk_ss_init_legacy(void) +{ + dma_addr_t ss_op_shmem_dma; + + /* allocate shared memory buffer */ + ss_op_shmem_legacy = dma_alloc_coherent(NULL, + sizeof(struct te_ss_op_legacy), &ss_op_shmem_dma, GFP_KERNEL); + if (!ss_op_shmem_legacy) { + pr_err("%s: no memory available for fs operations\n", __func__); + return -ENOMEM; + } + + tlk_generic_smc(TE_SMC_SS_REGISTER_HANDLER_LEGACY, + (uintptr_t)tlk_ss_op_legacy, (uintptr_t)ss_op_shmem_legacy); + + return 0; +} + +arch_initcall(tlk_ss_init_legacy); + +int te_handle_ss_ioctl(struct file *file, unsigned int ioctl_num, + unsigned long ioctl_param) +{ + switch (ioctl_num) { + case TE_IOCTL_SS_NEW_REQ: + /* wait for a new request */ + if (wait_for_completion_interruptible(&req_ready)) + return -ENODATA; + + /* transfer pending request to daemon's buffer */ + if (copy_to_user((void __user *)ioctl_param, ss_op_shmem->data, + ss_op_shmem->req_size)) { + pr_err("copy_to_user failed for new request\n"); + return -EFAULT; + } + break; + + case TE_IOCTL_SS_REQ_COMPLETE: /* request complete */ + if (copy_from_user(ss_op_shmem->data, + (void __user *)ioctl_param, ss_op_shmem->req_size)) { + pr_err("copy_from_user failed for request\n"); + return -EFAULT; + } + + /* signal the producer */ + complete(&req_complete); + break; + } + + return 0; +} + +void tlk_ss_op(void) +{ + /* signal consumer */ + complete(&req_ready); + + /* wait for the consumer's signal */ + wait_for_completion(&req_complete); +} + static int __init tlk_ss_init(void) { dma_addr_t ss_op_shmem_dma; + int32_t ret; /* allocate shared memory buffer */ ss_op_shmem = dma_alloc_coherent(NULL, sizeof(struct te_ss_op), @@ -97,8 +160,14 @@ static int __init tlk_ss_init(void) return -ENOMEM; } - tlk_generic_smc(TE_SMC_SS_REGISTER_HANDLER, - (uintptr_t)tlk_ss_op, (uintptr_t)ss_op_shmem); + ret = tlk_generic_smc(TE_SMC_SS_REGISTER_HANDLER, + (uintptr_t)ss_op_shmem, 0); + if (ret != 0) { + dma_free_coherent(NULL, sizeof(struct te_ss_op), + (void *)ss_op_shmem, ss_op_shmem_dma); + ss_op_shmem = NULL; + return -ENOTSUPP; + } return 0; } |