Merge tag 'v3.10.92'
[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                         mutex_lock(&rpc->outsync);
82
83                         memcpy(&rpc->commToUser, data, datalen);
84
85                         mutex_unlock(&rpc->outsync);
86
87                         dev_dbg(tee->dev,
88                                 "Supplicant Cmd: %x. Give hand to supplicant\n",
89                                 rpc->commToUser.cmd);
90
91                         up(&rpc->datatouser);
92
93                         down(&rpc->datafromuser);
94
95                         dev_dbg(tee->dev,
96                                 "Supplicant Cmd: %x. Give hand to fw\n",
97                                 rpc->commToUser.cmd);
98
99                         mutex_lock(&rpc->insync);
100
101                         memcpy(data, &rpc->commFromUser, datalen);
102
103                         mutex_unlock(&rpc->insync);
104
105                         res = TEEC_RPC_OK;
106
107                         break;
108                 }
109         default:
110                 /* not supported */
111                 break;
112         }
113
114 out:
115         dev_dbg(tee->dev, "< res: [%d]\n", res);
116
117         return res;
118 }
119 EXPORT_SYMBOL(tee_supp_cmd);
120
121 ssize_t tee_supp_read(struct file *filp, char __user *buffer,
122                   size_t length, loff_t *offset)
123 {
124         struct tee_context *ctx = (struct tee_context *)(filp->private_data);
125         struct tee *tee;
126         struct tee_rpc *rpc;
127         struct task_struct *task = current;
128         int ret;
129
130         BUG_ON(!ctx);
131         tee = ctx->tee;
132         BUG_ON(!tee);
133         BUG_ON(!tee->dev);
134         BUG_ON(!tee->rpc);
135
136         dev_dbg(tee->dev, "> ctx %p\n", ctx);
137
138         rpc = tee->rpc;
139
140         if (atomic_read(&rpc->used) == 0) {
141                 dev_err(tee->dev, "%s: ERROR Supplicant application NOT ready\n"
142                                 , __func__);
143                 ret = -EPERM;
144                 goto out;
145         }
146
147         if (down_interruptible(&rpc->datatouser))
148                 return -ERESTARTSYS;
149
150         dev_dbg(tee->dev, "> tgid:[%d]\n", task->tgid);
151
152         mutex_lock(&rpc->outsync);
153
154         ret =
155             sizeof(rpc->commToUser) - sizeof(rpc->commToUser.cmds) +
156             sizeof(rpc->commToUser.cmds[0]) * rpc->commToUser.nbr_bf;
157         if (length < ret) {
158                 ret = -EINVAL;
159         } else {
160                 if (copy_to_user(buffer, &rpc->commToUser, ret)) {
161                         dev_err(tee->dev,
162                                 "[%s] error, copy_to_user failed!\n", __func__);
163                         ret = -EINVAL;
164                 }
165         }
166
167         mutex_unlock(&rpc->outsync);
168
169 out:
170         dev_dbg(tee->dev, "< [%d]\n", ret);
171         return ret;
172 }
173
174 ssize_t tee_supp_write(struct file *filp, const char __user *buffer,
175                    size_t length, loff_t *offset)
176 {
177         struct tee_context *ctx = (struct tee_context *)(filp->private_data);
178         struct tee *tee;
179         struct tee_rpc *rpc;
180         struct task_struct *task = current;
181         int ret = 0;
182
183         BUG_ON(!ctx);
184         BUG_ON(!ctx->tee);
185         BUG_ON(!ctx->tee->rpc);
186         tee = ctx->tee;
187         rpc = tee->rpc;
188         dev_dbg(tee->dev, "> tgid:[%d]\n", task->tgid);
189
190         if (atomic_read(&rpc->used) == 0) {
191                 dev_err(tee->dev, "%s: ERROR Supplicant application NOT ready\n"
192                                 , __func__);
193                 goto out;
194         }
195
196         if (length > 0 && length < sizeof(rpc->commFromUser)) {
197                 uint32_t i;
198
199                 mutex_lock(&rpc->insync);
200
201                 if (copy_from_user(&rpc->commFromUser, buffer, length)) {
202                         dev_err(tee->dev,
203                                 "%s: ERROR, tee_session copy_from_user failed\n",
204                                 __func__);
205                         mutex_unlock(&rpc->insync);
206                         ret = -EINVAL;
207                         goto out;
208                 }
209
210                 /* Translate virtual address of caller into physical address */
211                 for (i = 0; i < rpc->commFromUser.nbr_bf; i++) {
212                         if (rpc->commFromUser.cmds[i].type == TEE_RPC_BUFFER
213                             && rpc->commFromUser.cmds[i].buffer) {
214                                 struct vm_area_struct *vma =
215                                     find_vma(current->mm,
216                                              (unsigned long)rpc->
217                                              commFromUser.cmds[i].buffer);
218                                 if (vma != NULL) {
219                                         struct tee_shm *shm =
220                                             vma->vm_private_data;
221                                         BUG_ON(!shm);
222                                         dev_dbg(tee->dev,
223                                                 "%d gid2pa(0x%p => %x)\n", i,
224                                                 rpc->commFromUser.cmds[i].
225                                                 buffer,
226                                                 (unsigned int)shm->paddr);
227                                         rpc->commFromUser.cmds[i].buffer =
228                                             (void *)shm->paddr;
229                                 } else
230                                         dev_dbg(tee->dev,
231                                                 " gid2pa(0x%p => NULL\n)",
232                                                 rpc->commFromUser.cmds[i].
233                                                 buffer);
234                         }
235                 }
236
237                 mutex_unlock(&rpc->insync);
238                 up(&rpc->datafromuser);
239                 ret = length;
240         }
241
242 out:
243         dev_dbg(tee->dev, "< [%d]\n", ret);
244         return ret;
245 }
246
247 int tee_supp_init(struct tee *tee)
248 {
249         struct tee_rpc *rpc =
250             devm_kzalloc(tee->dev, sizeof(struct tee_rpc), GFP_KERNEL);
251         if (!rpc) {
252                 dev_err(tee->dev, "%s: can't allocate tee_rpc structure\n",
253                                 __func__);
254                 return -ENOMEM;
255         }
256
257         rpc->datafromuser = (struct semaphore)
258             __SEMAPHORE_INITIALIZER(rpc->datafromuser, 0);
259         rpc->datatouser = (struct semaphore)
260             __SEMAPHORE_INITIALIZER(rpc->datatouser, 0);
261         mutex_init(&rpc->outsync);
262         mutex_init(&rpc->insync);
263         atomic_set(&rpc->used, 0);
264         tee->rpc = rpc;
265         return 0;
266 }
267
268 void tee_supp_deinit(struct tee *tee)
269 {
270         devm_kfree(tee->dev, tee->rpc);
271         tee->rpc = NULL;
272 }