[FOSS_TLK]security: tlk_driver: add daemon recovery support
[tegra/ote_partner/tlk_driver.git] / security / tlk_driver / ote_device.c
1 /*
2  * Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
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 as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18
19 #include <linux/atomic.h>
20 #include <linux/uaccess.h>
21 #include <linux/module.h>
22 #include <linux/slab.h>
23 #include <linux/fs.h>
24 #include <linux/printk.h>
25 #include <linux/ioctl.h>
26 #include <linux/miscdevice.h>
27 #include <linux/mm.h>
28 #include <asm/cacheflush.h>
29 #include <asm/outercache.h>
30 #include <linux/list.h>
31 #include <linux/dma-mapping.h>
32 #include <linux/of.h>
33
34 #include "ote_protocol.h"
35
36 #define SET_ANSWER(a, r, ro)    { a.result = r; a.result_origin = ro; }
37
38 struct tlk_device tlk_dev;
39 DEFINE_MUTEX(smc_lock);
40
41 static int te_create_free_cmd_list(struct tlk_device *dev)
42 {
43         int cmd_desc_count, ret = 0;
44         struct te_cmd_req_desc *req_desc;
45         int bitmap_size;
46         bool use_reqbuf;
47
48         /*
49          * Check if new shared req/param register SMC is supported.
50          *
51          * If it is, TLK can map in the shared req/param buffers and do_smc
52          * only needs to send the offsets within each (with cache coherency
53          * being maintained by HW through an NS mapping).
54          *
55          * If the SMC support is not yet present, then fallback to the old
56          * mode of writing to an uncached buffer to maintain coherency (and
57          * phys addresses are passed in do_smc).
58          */
59         dev->req_param_buf = NULL;
60         use_reqbuf = !send_smc(TE_SMC_REGISTER_REQ_BUF, 0, 0);
61
62         if (use_reqbuf) {
63                 dev->req_param_buf = kmalloc((2 * PAGE_SIZE), GFP_KERNEL);
64
65                 /* requests in the first page, params in the second */
66                 dev->req_addr   = (struct te_request *) dev->req_param_buf;
67                 dev->param_addr = (struct te_oper_param *)
68                                         (dev->req_param_buf + PAGE_SIZE);
69
70                 send_smc(TE_SMC_REGISTER_REQ_BUF,
71                                 (uintptr_t)dev->req_addr, (2 * PAGE_SIZE));
72         } else {
73                 dev->req_addr = dma_alloc_coherent(NULL, PAGE_SIZE,
74                                         &dev->req_addr_phys, GFP_KERNEL);
75                 dev->param_addr = dma_alloc_coherent(NULL, PAGE_SIZE,
76                                         &dev->param_addr_phys, GFP_KERNEL);
77         }
78
79         if (!dev->req_addr || !dev->param_addr || !dev->req_param_buf) {
80                 ret = -ENOMEM;
81                 goto error;
82         }
83
84         /* alloc param bitmap allocator */
85         bitmap_size = BITS_TO_LONGS(TE_PARAM_MAX) * sizeof(long);
86         dev->param_bitmap = kzalloc(bitmap_size, GFP_KERNEL);
87
88         for (cmd_desc_count = 0;
89                 cmd_desc_count < TE_CMD_DESC_MAX; cmd_desc_count++) {
90
91                 req_desc = kzalloc(sizeof(struct te_cmd_req_desc), GFP_KERNEL);
92                 if (req_desc == NULL) {
93                         pr_err("Failed to allocate cmd req descriptor\n");
94                         ret = -ENOMEM;
95                         goto error;
96                 }
97                 req_desc->req_addr = dev->req_addr + cmd_desc_count;
98                 INIT_LIST_HEAD(&(req_desc->list));
99
100                 /* Add the cmd param descriptor to free list */
101                 list_add_tail(&req_desc->list, &(dev->free_cmd_list));
102         }
103
104 error:
105         return ret;
106 }
107
108 static struct te_oper_param *te_get_free_params(struct tlk_device *dev,
109         unsigned int nparams)
110 {
111         struct te_oper_param *params = NULL;
112         int idx, nbits;
113
114         if (nparams) {
115                 nbits = get_count_order(nparams);
116                 idx = bitmap_find_free_region(dev->param_bitmap,
117                                 TE_PARAM_MAX, nbits);
118                 if (idx >= 0)
119                         params = dev->param_addr + idx;
120         }
121         return params;
122 }
123
124 static void te_put_free_params(struct tlk_device *dev,
125         struct te_oper_param *params, uint32_t nparams)
126 {
127         int idx, nbits;
128
129         idx = (params - dev->param_addr);
130         nbits = get_count_order(nparams);
131         bitmap_release_region(dev->param_bitmap, idx, nbits);
132 }
133
134 static struct te_cmd_req_desc *te_get_free_cmd_desc(struct tlk_device *dev)
135 {
136         struct te_cmd_req_desc *cmd_desc = NULL;
137
138         if (!(list_empty(&(dev->free_cmd_list)))) {
139                 cmd_desc = list_first_entry(&(dev->free_cmd_list),
140                                 struct te_cmd_req_desc, list);
141                 list_del(&(cmd_desc->list));
142                 list_add_tail(&cmd_desc->list, &(dev->used_cmd_list));
143         }
144         return cmd_desc;
145 }
146
147 static void te_put_used_cmd_desc(struct tlk_device *dev,
148         struct te_cmd_req_desc *cmd_desc)
149 {
150         struct te_cmd_req_desc *param_desc, *tmp_param_desc;
151
152         if (cmd_desc) {
153                 list_for_each_entry_safe(param_desc, tmp_param_desc,
154                                 &(dev->used_cmd_list), list) {
155                         if (cmd_desc->req_addr == param_desc->req_addr) {
156                                 list_del(&param_desc->list);
157                                 list_add_tail(&param_desc->list,
158                                         &(dev->free_cmd_list));
159                         }
160                 }
161         }
162 }
163
164 static void __attribute__((unused)) te_print_cmd_list(
165         struct tlk_device *dev, int used_list)
166 {
167         struct te_cmd_req_desc *param_desc;
168
169         if (!used_list) {
170                 pr_info("Printing free cmd list\n");
171                 if (!(list_empty(&(dev->free_cmd_list)))) {
172                         list_for_each_entry(param_desc, &(dev->free_cmd_list),
173                                         list)
174                                 pr_info("Phys addr for cmd req desc (%p)\n",
175                                         param_desc->req_addr);
176                 }
177         } else {
178                 pr_info("Printing used cmd list\n");
179                 if (!(list_empty(&(dev->used_cmd_list)))) {
180                         list_for_each_entry(param_desc, &(dev->used_cmd_list),
181                                         list)
182                                 pr_info("Phys addr for cmd req desc (%p)\n",
183                                         param_desc->req_addr);
184                 }
185         }
186 }
187
188
189 static void te_close_sessions(struct tlk_context *context)
190 {
191         struct tlk_device *dev = context->dev;
192         union te_cmd cmd;
193         struct te_cmd_req_desc *cmd_desc = NULL;
194         struct te_request *request;
195         struct te_session *session, *tmp_session;
196
197         if (list_empty(&context->session_list))
198                 return;
199
200         cmd_desc = te_get_free_cmd_desc(dev);
201         if (!cmd_desc) {
202                 pr_err("%s: failed to get cmd_desc\n", __func__);
203                 return;
204         }
205
206         request = cmd_desc->req_addr;
207
208         list_for_each_entry_safe(session, tmp_session,
209                 &context->session_list, list) {
210
211                 memset(request, 0, sizeof(struct te_request));
212
213                 cmd.closesession.session_id = session->session_id;
214
215                 te_close_session(&cmd.closesession, request, context);
216         }
217
218         te_put_used_cmd_desc(dev, cmd_desc);
219 }
220
221 static int tlk_device_open(struct inode *inode, struct file *file)
222 {
223         struct tlk_context *context;
224         int ret = 0;
225
226         context = kzalloc(sizeof(struct tlk_context), GFP_KERNEL);
227         if (!context) {
228                 ret = -ENOMEM;
229                 goto error;
230         }
231         context->dev = &tlk_dev;
232         INIT_LIST_HEAD(&context->session_list);
233
234         file->private_data = context;
235         return 0;
236 error:
237         return ret;
238 }
239
240 static int tlk_device_release(struct inode *inode, struct file *file)
241 {
242         struct tlk_context *context = file->private_data;
243
244         /* close any open sessions */
245         mutex_lock(&smc_lock);
246         te_close_sessions(context);
247         mutex_unlock(&smc_lock);
248
249         kfree(file->private_data);
250         file->private_data = NULL;
251         return 0;
252 }
253
254 static int copy_params_from_user(struct te_request *req,
255         struct te_operation *operation)
256 {
257         struct te_oper_param *param_array;
258         struct te_oper_param *user_param;
259         uint32_t i;
260
261         if (operation->list_count == 0)
262                 return 0;
263
264         param_array = (struct te_oper_param *)(uintptr_t)req->params;
265         if (param_array == NULL) {
266                 pr_err("param_array empty\n");
267                 return 1;
268         }
269
270         user_param = (struct te_oper_param *)(uintptr_t)operation->list_head;
271         for (i = 0; i < operation->list_count && user_param != NULL; i++) {
272                 if (copy_from_user(param_array + i, user_param,
273                                         sizeof(struct te_oper_param))) {
274                         pr_err("Failed to copy operation parameter:%d, %p, " \
275                                         "list_count: %d\n",
276                                         i, user_param, operation->list_count);
277                         return 1;
278                 }
279                 user_param = (struct te_oper_param *)(uintptr_t)
280                         param_array[i].next_ptr_user;
281         }
282         return 0;
283 }
284
285 static int copy_params_to_user(struct te_request *req,
286         struct te_operation *operation)
287 {
288         struct te_oper_param *param_array;
289         struct te_oper_param *user_param;
290         uint32_t i;
291
292         if (operation->list_count == 0)
293                 return 0;
294
295         param_array = (struct te_oper_param *)(uintptr_t)req->params;
296         if (param_array == NULL) {
297                 pr_err("param_array empty\n");
298                 return 1;
299         }
300
301         user_param =
302                 (struct te_oper_param *)(uintptr_t)operation->list_head;
303         for (i = 0; i < req->params_size; i++) {
304                 if (copy_to_user(user_param, param_array + i,
305                                         sizeof(struct te_oper_param))) {
306                         pr_err("Failed to copy back parameter:%d %p\n", i,
307                                         user_param);
308                         return 1;
309                 }
310                 user_param = (struct te_oper_param *)(uintptr_t)
311                         param_array[i].next_ptr_user;
312         }
313         return 0;
314 }
315
316 static long te_handle_trustedapp_ioctl(struct file *file,
317         unsigned int ioctl_num, unsigned long ioctl_param)
318 {
319         long err = 0;
320         union te_cmd cmd;
321         struct te_operation *operation = NULL;
322         struct te_oper_param *params = NULL;
323         struct te_request *request;
324         void __user *ptr_user_answer = NULL;
325         struct te_answer answer;
326         struct te_cmd_req_desc *cmd_desc = NULL;
327         struct tlk_context *context = file->private_data;
328         struct tlk_device *dev = context->dev;
329
330         if (copy_from_user(&cmd, (void __user *)ioctl_param,
331                                 sizeof(union te_cmd))) {
332                 pr_err("Failed to copy command request\n");
333                 err = -EFAULT;
334                 goto error;
335         }
336
337         memset(&answer, 0, sizeof(struct te_answer));
338
339         switch (ioctl_num) {
340         case TE_IOCTL_OPEN_CLIENT_SESSION:
341                 operation = &cmd.opensession.operation;
342                 ptr_user_answer = (void *)(uintptr_t)cmd.opensession.answer;
343
344                 cmd_desc = te_get_free_cmd_desc(dev);
345                 params = te_get_free_params(dev, operation->list_count);
346
347                 if (!cmd_desc || (operation->list_count && !params)) {
348                         SET_ANSWER(answer,
349                                    OTE_ERROR_OUT_OF_MEMORY,
350                                    OTE_RESULT_ORIGIN_COMMS);
351                         pr_err("failed to get cmd_desc/params\n");
352                         goto error;
353                 }
354
355                 request = cmd_desc->req_addr;
356                 memset(request, 0, sizeof(struct te_request));
357
358                 request->params = (uintptr_t)params;
359                 request->params_size = operation->list_count;
360
361                 if (copy_params_from_user(request, operation)) {
362                         err = -EFAULT;
363                         pr_info("failed to copy params from user\n");
364                         goto error;
365                 }
366
367                 te_open_session(&cmd.opensession, request, context);
368
369                 SET_ANSWER(answer, request->result, request->result_origin);
370                 answer.session_id = request->session_id;
371                 break;
372
373         case TE_IOCTL_CLOSE_CLIENT_SESSION:
374                 ptr_user_answer = (void *)(uintptr_t)cmd.closesession.answer;
375                 cmd_desc = te_get_free_cmd_desc(dev);
376                 if (!cmd_desc) {
377                         SET_ANSWER(answer,
378                                    OTE_ERROR_OUT_OF_MEMORY,
379                                    OTE_RESULT_ORIGIN_COMMS);
380                         pr_err("failed to get cmd_desc\n");
381                         goto error;
382                 }
383
384                 request = cmd_desc->req_addr;
385                 memset(request, 0, sizeof(struct te_request));
386
387                 /* close session cannot fail */
388                 te_close_session(&cmd.closesession, request, context);
389                 break;
390
391         case TE_IOCTL_LAUNCH_OPERATION:
392                 operation = &cmd.launchop.operation;
393                 ptr_user_answer = (void *)(uintptr_t)cmd.launchop.answer;
394
395                 cmd_desc = te_get_free_cmd_desc(dev);
396                 params = te_get_free_params(dev, operation->list_count);
397
398                 if (!cmd_desc || (operation->list_count && !params)) {
399                         SET_ANSWER(answer,
400                                    OTE_ERROR_OUT_OF_MEMORY,
401                                    OTE_RESULT_ORIGIN_COMMS);
402                         pr_err("failed to get cmd_desc/params\n");
403                         goto error;
404                 }
405
406                 request = cmd_desc->req_addr;
407                 memset(request, 0, sizeof(struct te_request));
408
409                 request->params = (uintptr_t)params;
410                 request->params_size = operation->list_count;
411
412                 if (copy_params_from_user(request, operation)) {
413                         err = -EFAULT;
414                         pr_info("failed to copy params from user\n");
415                         goto error;
416                 }
417
418                 te_launch_operation(&cmd.launchop, request, context);
419
420                 SET_ANSWER(answer, request->result, request->result_origin);
421                 break;
422
423         default:
424                 pr_err("Invalid IOCTL Cmd\n");
425                 err = -EINVAL;
426                 goto error;
427         }
428         if (ptr_user_answer && !err) {
429                 if (copy_to_user(ptr_user_answer, &answer,
430                         sizeof(struct te_answer))) {
431                         pr_err("Failed to copy answer\n");
432                         err = -EFAULT;
433                 }
434         }
435         if (request->params && !err) {
436                 if (copy_params_to_user(request, operation)) {
437                         pr_err("Failed to copy return params\n");
438                         err = -EFAULT;
439                 }
440         }
441
442 error:
443         if (cmd_desc)
444                 te_put_used_cmd_desc(dev, cmd_desc);
445         if (params)
446                 te_put_free_params(dev, params, operation->list_count);
447         return err;
448 }
449
450 static long tlk_device_ioctl(struct file *file, unsigned int ioctl_num,
451         unsigned long ioctl_param)
452 {
453         int err;
454
455         switch (ioctl_num) {
456         case TE_IOCTL_OPEN_CLIENT_SESSION:
457         case TE_IOCTL_CLOSE_CLIENT_SESSION:
458         case TE_IOCTL_LAUNCH_OPERATION:
459                 mutex_lock(&smc_lock);
460                 err = te_handle_trustedapp_ioctl(file, ioctl_num, ioctl_param);
461                 mutex_unlock(&smc_lock);
462                 break;
463
464         case TE_IOCTL_SS_CMD:
465                 err = te_handle_ss_ioctl(file, ioctl_num, ioctl_param);
466                 break;
467
468         default:
469                 pr_err("%s: Invalid IOCTL (0x%x) id 0x%x max 0x%lx\n",
470                         __func__, ioctl_num, _IOC_NR(ioctl_num),
471                         (unsigned long)TE_IOCTL_MAX_NR);
472                 err = -EINVAL;
473                 break;
474         }
475
476         return err;
477 }
478
479 /*
480  * tlk_driver function definitions.
481  */
482 static const struct file_operations tlk_device_fops = {
483         .owner = THIS_MODULE,
484         .open = tlk_device_open,
485         .release = tlk_device_release,
486         .unlocked_ioctl = tlk_device_ioctl,
487 #ifdef CONFIG_COMPAT
488         .compat_ioctl = tlk_device_ioctl,
489 #endif
490 };
491
492 struct miscdevice tlk_misc_device = {
493         .minor = MISC_DYNAMIC_MINOR,
494         .name = "tlk_device",
495         .fops = &tlk_device_fops,
496 };
497
498 static struct device_node *get_tlk_device_node(void)
499 {
500         struct device_node *node;
501
502         node = of_find_compatible_node(NULL, NULL,
503                         "nvidia,trusted-little-kernel");
504         if (!node)
505                 pr_info("TLK node not present in the FDT\n");
506
507         return node;
508 }
509
510 static int __init tlk_init(void)
511 {
512         int ret;
513
514         /* check if the driver node is present in the device tree */
515         if (get_tlk_device_node() == NULL) {
516                 pr_err("%s: fail\n", __func__);
517                 return -ENODEV;
518         }
519
520         INIT_LIST_HEAD(&(tlk_dev.used_cmd_list));
521         INIT_LIST_HEAD(&(tlk_dev.free_cmd_list));
522
523         ret = te_create_free_cmd_list(&tlk_dev);
524         if (ret != 0)
525                 return ret;
526
527         return misc_register(&tlk_misc_device);
528 }
529
530 module_init(tlk_init);
531
532 int ote_property_is_disabled(const char *str)
533 {
534         struct device_node *tlk;
535         const char *prop;
536
537         /* check if the driver node is present in the device tree */
538         tlk = get_tlk_device_node();
539         if (!tlk) {
540                 pr_err("%s: fail\n", __func__);
541                 return -ENODEV;
542         }
543
544         if (of_property_read_string(tlk, str, &prop)) {
545                 pr_warn("missing \"%s\" property\n", str);
546                 return -ENXIO;
547         }
548
549         if (strcmp("enabled", prop))
550                 return -ENOTSUPP;
551
552         return 0;
553 }