OP-TEE: update optee_linuxdriver to match updated optee_os & optee_client
[firefly-linux-kernel-4.4.55.git] / security / optee_linuxdriver / core / tee_supp_com.c
1 /*
2  * Copyright (c) 2014, STMicroelectronics International N.V.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License Version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  */
13 #include <linux/kernel.h>
14 #include <linux/fs.h>
15 #include <linux/mutex.h>
16 #include <linux/miscdevice.h>
17 #include <linux/uaccess.h>
18 #include <linux/anon_inodes.h>
19 #include <linux/semaphore.h>
20 #include <linux/mm.h>
21 #include <linux/sched.h>
22 #include <linux/device.h>
23
24 #include "tee_shm.h"
25 #include "tee_core.h"
26 #include "tee_supp_com.h"
27
28 #define TEE_RPC_BUFFER  0x00000001
29 #define TEE_RPC_VALUE   0x00000002
30
31 enum teec_rpc_result tee_supp_cmd(struct tee *tee,
32                                   uint32_t id, void *data, size_t datalen)
33 {
34         struct tee_rpc *rpc = tee->rpc;
35         enum teec_rpc_result res = TEEC_RPC_FAIL;
36         size_t size;
37         struct task_struct *task = current;
38
39         dev_dbg(tee->dev, "> tgid:[%d] id:[0x%08x]\n", task->tgid, id);
40
41         if (atomic_read(&rpc->used) == 0) {
42                 dev_err(tee->dev, "%s: ERROR Supplicant application NOT ready\n"
43                                 , __func__);
44                 goto out;
45         }
46
47         switch (id) {
48         case TEE_RPC_ICMD_ALLOCATE:
49                 {
50                         struct tee_rpc_alloc *alloc;
51                         struct tee_shm *shmint;
52
53                         alloc = (struct tee_rpc_alloc *)data;
54                         size = alloc->size;
55                         memset(alloc, 0, sizeof(struct tee_rpc_alloc));
56                         shmint = tee_shm_alloc_from_rpc(tee, size);
57                         if (IS_ERR_OR_NULL(shmint))
58                                 break;
59
60                         alloc->size = size;
61                         alloc->data = (void *)shmint->paddr;
62                         alloc->shm = shmint;
63                         res = TEEC_RPC_OK;
64
65                         break;
66                 }
67         case TEE_RPC_ICMD_FREE:
68                 {
69                         struct tee_rpc_free *free;
70
71                         free = (struct tee_rpc_free *)data;
72                         tee_shm_free_from_rpc(free->shm);
73                         res = TEEC_RPC_OK;
74                         break;
75                 }
76         case TEE_RPC_ICMD_INVOKE:
77                 {
78                         if (sizeof(rpc->commToUser) < datalen)
79                                 break;
80
81                         /*
82                          * Other threads blocks here until we've copied our
83                          * answer from the supplicant
84                          */
85                         mutex_lock(&rpc->thrd_mutex);
86
87                         mutex_lock(&rpc->outsync);
88                         memcpy(&rpc->commToUser, data, datalen);
89                         mutex_unlock(&rpc->outsync);
90
91                         dev_dbg(tee->dev,
92                                 "Supplicant Cmd: %x. Give hand to supplicant\n",
93                                 rpc->commToUser.cmd);
94
95                         up(&rpc->datatouser);
96
97                         down(&rpc->datafromuser);
98
99                         dev_dbg(tee->dev,
100                                 "Supplicant Cmd: %x. Give hand to fw\n",
101                                 rpc->commToUser.cmd);
102
103                         mutex_lock(&rpc->insync);
104                         memcpy(data, &rpc->commFromUser, datalen);
105                         mutex_unlock(&rpc->insync);
106
107                         mutex_unlock(&rpc->thrd_mutex);
108
109                         res = TEEC_RPC_OK;
110
111                         break;
112                 }
113         default:
114                 /* not supported */
115                 break;
116         }
117
118 out:
119         dev_dbg(tee->dev, "< res: [%d]\n", res);
120
121         return res;
122 }
123 EXPORT_SYMBOL(tee_supp_cmd);
124
125 ssize_t tee_supp_read(struct file *filp, char __user *buffer,
126                   size_t length, loff_t *offset)
127 {
128         struct tee_context *ctx = (struct tee_context *)(filp->private_data);
129         struct tee *tee;
130         struct tee_rpc *rpc;
131         struct task_struct *task = current;
132         int ret;
133
134         BUG_ON(!ctx);
135         tee = ctx->tee;
136         BUG_ON(!tee);
137         BUG_ON(!tee->dev);
138         BUG_ON(!tee->rpc);
139
140         dev_dbg(tee->dev, "> ctx %p\n", ctx);
141
142         rpc = tee->rpc;
143
144         if (atomic_read(&rpc->used) == 0) {
145                 dev_err(tee->dev, "%s: ERROR Supplicant application NOT ready\n"
146                                 , __func__);
147                 ret = -EPERM;
148                 goto out;
149         }
150
151         if (down_interruptible(&rpc->datatouser))
152                 return -ERESTARTSYS;
153
154         dev_dbg(tee->dev, "> tgid:[%d]\n", task->tgid);
155
156         mutex_lock(&rpc->outsync);
157
158         ret =
159             sizeof(rpc->commToUser) - sizeof(rpc->commToUser.cmds) +
160             sizeof(rpc->commToUser.cmds[0]) * rpc->commToUser.nbr_bf;
161         if (length < ret) {
162                 ret = -EINVAL;
163         } else {
164                 if (copy_to_user(buffer, &rpc->commToUser, ret)) {
165                         dev_err(tee->dev,
166                                 "[%s] error, copy_to_user failed!\n", __func__);
167                         ret = -EINVAL;
168                 }
169         }
170
171         mutex_unlock(&rpc->outsync);
172
173 out:
174         dev_dbg(tee->dev, "< [%d]\n", ret);
175         return ret;
176 }
177
178 ssize_t tee_supp_write(struct file *filp, const char __user *buffer,
179                    size_t length, loff_t *offset)
180 {
181         struct tee_context *ctx = (struct tee_context *)(filp->private_data);
182         struct tee *tee;
183         struct tee_rpc *rpc;
184         struct task_struct *task = current;
185         int ret = 0;
186
187         BUG_ON(!ctx);
188         BUG_ON(!ctx->tee);
189         BUG_ON(!ctx->tee->rpc);
190         tee = ctx->tee;
191         rpc = tee->rpc;
192         dev_dbg(tee->dev, "> tgid:[%d]\n", task->tgid);
193
194         if (atomic_read(&rpc->used) == 0) {
195                 dev_err(tee->dev, "%s: ERROR Supplicant application NOT ready\n"
196                                 , __func__);
197                 goto out;
198         }
199
200         if (length > 0 && length < sizeof(rpc->commFromUser)) {
201                 uint32_t i;
202
203                 mutex_lock(&rpc->insync);
204
205                 if (copy_from_user(&rpc->commFromUser, buffer, length)) {
206                         dev_err(tee->dev,
207                                 "%s: ERROR, tee_session copy_from_user failed\n",
208                                 __func__);
209                         mutex_unlock(&rpc->insync);
210                         ret = -EINVAL;
211                         goto out;
212                 }
213
214                 /* Translate virtual address of caller into physical address */
215                 for (i = 0; i < rpc->commFromUser.nbr_bf; i++) {
216                         if (rpc->commFromUser.cmds[i].type == TEE_RPC_BUFFER
217                             && rpc->commFromUser.cmds[i].buffer) {
218                                 struct vm_area_struct *vma =
219                                     find_vma(current->mm,
220                                              (unsigned long)rpc->
221                                              commFromUser.cmds[i].buffer);
222                                 if (vma != NULL) {
223                                         struct tee_shm *shm =
224                                             vma->vm_private_data;
225                                         BUG_ON(!shm);
226                                         dev_dbg(tee->dev,
227                                                 "%d gid2pa(0x%p => %x)\n", i,
228                                                 rpc->commFromUser.cmds[i].
229                                                 buffer,
230                                                 (unsigned int)shm->paddr);
231                                         rpc->commFromUser.cmds[i].buffer =
232                                             (void *)shm->paddr;
233                                 } else
234                                         dev_dbg(tee->dev,
235                                                 " gid2pa(0x%p => NULL\n)",
236                                                 rpc->commFromUser.cmds[i].
237                                                 buffer);
238                         }
239                 }
240
241                 mutex_unlock(&rpc->insync);
242                 up(&rpc->datafromuser);
243                 ret = length;
244         }
245
246 out:
247         dev_dbg(tee->dev, "< [%d]\n", ret);
248         return ret;
249 }
250
251 int tee_supp_init(struct tee *tee)
252 {
253         struct tee_rpc *rpc =
254             devm_kzalloc(tee->dev, sizeof(struct tee_rpc), GFP_KERNEL);
255         if (!rpc) {
256                 dev_err(tee->dev, "%s: can't allocate tee_rpc structure\n",
257                                 __func__);
258                 return -ENOMEM;
259         }
260
261         rpc->datafromuser = (struct semaphore)
262             __SEMAPHORE_INITIALIZER(rpc->datafromuser, 0);
263         rpc->datatouser = (struct semaphore)
264             __SEMAPHORE_INITIALIZER(rpc->datatouser, 0);
265         mutex_init(&rpc->thrd_mutex);
266         mutex_init(&rpc->outsync);
267         mutex_init(&rpc->insync);
268         atomic_set(&rpc->used, 0);
269         tee->rpc = rpc;
270         return 0;
271 }
272
273 void tee_supp_deinit(struct tee *tee)
274 {
275         devm_kfree(tee->dev, tee->rpc);
276         tee->rpc = NULL;
277 }