blob: 70d6a70a6244ed98dd3d8d585b1426e91d1cf6a9 [file] [log] [blame]
Chris Johnson9c975ae2011-11-18 16:14:07 -08001/**
2 * Copyright (c) 2011 Trusted Logic S.A.
3 * All Rights Reserved.
4 *
Hyung Taek Ryoofd6034d2013-02-19 13:45:53 -08005 * Copyright (C) 2011-2013 NVIDIA Corporation.
Charles Tanc7faf7f2012-10-25 23:09:37 -07006 *
Chris Johnson9c975ae2011-11-18 16:14:07 -08007 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19 * MA 02111-1307 USA
20 */
21
22#include <linux/atomic.h>
23#include <linux/uaccess.h>
24#include <linux/module.h>
25#include <linux/errno.h>
26#include <linux/mm.h>
27#include <linux/page-flags.h>
28#include <linux/pm.h>
Dan Willemsenbc31c952011-12-19 11:33:07 -080029#include <linux/syscore_ops.h>
Chris Johnson9c975ae2011-11-18 16:14:07 -080030#include <linux/vmalloc.h>
31#include <linux/signal.h>
32#ifdef CONFIG_ANDROID
33#include <linux/device.h>
34#endif
35
36#include "tf_protocol.h"
37#include "tf_defs.h"
38#include "tf_util.h"
39#include "tf_conn.h"
40#include "tf_comm.h"
41#ifdef CONFIG_TF_ZEBRA
42#include <plat/cpu.h>
43#include "tf_zebra.h"
44#endif
45#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
46#include "tf_crypto.h"
47#endif
48
49#include "s_version.h"
50
Charles Tanc7faf7f2012-10-25 23:09:37 -070051#define CREATE_TRACE_POINTS
52#include <trace/events/nvsecurity.h>
53
Chris Johnson9c975ae2011-11-18 16:14:07 -080054/*----------------------------------------------------------------------------
55 * Forward Declarations
56 *----------------------------------------------------------------------------*/
57
58/*
59 * Creates and registers the device to be managed by the specified driver.
60 *
61 * Returns zero upon successful completion, or an appropriate error code upon
62 * failure.
63 */
64static int tf_device_register(void);
65
66
67/*
68 * Implements the device Open callback.
69 */
70static int tf_device_open(
71 struct inode *inode,
72 struct file *file);
73
74
75/*
76 * Implements the device Release callback.
77 */
78static int tf_device_release(
79 struct inode *inode,
80 struct file *file);
81
82
83/*
84 * Implements the device ioctl callback.
85 */
86static long tf_device_ioctl(
87 struct file *file,
88 unsigned int ioctl_num,
89 unsigned long ioctl_param);
90
91
92/*
93 * Implements the device shutdown callback.
94 */
Sanjay Singh Rawatf9389682012-03-26 15:45:23 +053095static void tf_device_shutdown(void);
Chris Johnson9c975ae2011-11-18 16:14:07 -080096
97
98/*
99 * Implements the device suspend callback.
100 */
Dan Willemsenbc31c952011-12-19 11:33:07 -0800101static int tf_device_suspend(void);
Chris Johnson9c975ae2011-11-18 16:14:07 -0800102
103
104/*
105 * Implements the device resume callback.
106 */
Sanjay Singh Rawatf9389682012-03-26 15:45:23 +0530107static void tf_device_resume(void);
Chris Johnson9c975ae2011-11-18 16:14:07 -0800108
109
110/*---------------------------------------------------------------------------
111 * Module Parameters
112 *---------------------------------------------------------------------------*/
113
114/*
115 * The device major number used to register a unique character device driver.
116 * Let the default value be 122
117 */
118static int device_major_number = 122;
119
120module_param(device_major_number, int, 0000);
121MODULE_PARM_DESC(device_major_number,
122 "The device major number used to register a unique character "
123 "device driver");
124
125#ifdef CONFIG_TF_TRUSTZONE
Hyung Taek Ryoofd6034d2013-02-19 13:45:53 -0800126/*
127 * This software interrupt line is used by the S-World interrupt system
128 * to inform N-World that it must schedule S-World as soon as it is possible.
Chris Johnson9c975ae2011-11-18 16:14:07 -0800129 */
Hyung Taek Ryoofd6034d2013-02-19 13:45:53 -0800130static int soft_interrupt = 191; /*-1;*/
131/*
132 * Interrupt line #191 is not used by the hardware of Tegra3 and Tegra4.
133 * The same signaling interrupt must be specified in S-World (GIC driver)
134 */
Chris Johnson9c975ae2011-11-18 16:14:07 -0800135
136module_param(soft_interrupt, int, 0000);
137MODULE_PARM_DESC(soft_interrupt,
138 "The softint interrupt line used by the Secure world");
139#endif
140
141#ifdef CONFIG_TF_DRIVER_DEBUG_SUPPORT
142unsigned tf_debug_level = UINT_MAX;
143module_param_named(debug, tf_debug_level, uint, 0644);
144#endif
145
146#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
147char *tf_integrity_hmac_sha256_expected_value;
148module_param_named(hmac_sha256, tf_integrity_hmac_sha256_expected_value,
149 charp, 0444);
150
151#ifdef CONFIG_TF_DRIVER_FAULT_INJECTION
152unsigned tf_fault_injection_mask;
153module_param_named(fault, tf_fault_injection_mask, uint, 0644);
154#endif
155
156int tf_self_test_blkcipher_align;
157module_param_named(post_align, tf_self_test_blkcipher_align, int, 0644);
158int tf_self_test_blkcipher_use_vmalloc;
159module_param_named(post_vmalloc, tf_self_test_blkcipher_use_vmalloc, int, 0644);
160#endif
161
162#ifdef CONFIG_ANDROID
163static struct class *tf_class;
164#endif
165
Chris Johnson9c975ae2011-11-18 16:14:07 -0800166/*----------------------------------------------------------------------------
167 * Global Variables
168 *----------------------------------------------------------------------------*/
169
170/*
171 * tf_driver character device definitions.
172 * read and write methods are not defined
173 * and will return an error if used by user space
174 */
175static const struct file_operations g_tf_device_file_ops = {
176 .owner = THIS_MODULE,
177 .open = tf_device_open,
178 .release = tf_device_release,
179 .unlocked_ioctl = tf_device_ioctl,
180 .llseek = no_llseek,
181};
182
183
Dan Willemsenbc31c952011-12-19 11:33:07 -0800184static struct syscore_ops g_tf_device_syscore_ops = {
Chris Johnson9c975ae2011-11-18 16:14:07 -0800185 .shutdown = tf_device_shutdown,
186 .suspend = tf_device_suspend,
187 .resume = tf_device_resume,
188};
189
190/* The single device supported by this driver */
191static struct tf_device g_tf_dev;
192
193/*----------------------------------------------------------------------------
194 * Implementations
195 *----------------------------------------------------------------------------*/
196
197struct tf_device *tf_get_device(void)
198{
199 return &g_tf_dev;
200}
201
202/*
203 * sysfs entries
204 */
205struct tf_sysfs_entry {
206 struct attribute attr;
207 ssize_t (*show)(struct tf_device *, char *);
208 ssize_t (*store)(struct tf_device *, const char *, size_t);
209};
210
211/*
212 * sysfs entry showing allocation stats
213 */
214static ssize_t info_show(struct tf_device *dev, char *buf)
215{
216 struct tf_device_stats *dev_stats = &dev->stats;
217
218 return snprintf(buf, PAGE_SIZE,
219 "stat.memories.allocated: %d\n"
220 "stat.pages.allocated: %d\n"
221 "stat.pages.locked: %d\n",
222 atomic_read(&dev_stats->stat_memories_allocated),
223 atomic_read(&dev_stats->stat_pages_allocated),
224 atomic_read(&dev_stats->stat_pages_locked));
225}
226static struct tf_sysfs_entry tf_info_entry = __ATTR_RO(info);
227
228#ifdef CONFIG_TF_ZEBRA
229/*
230 * sysfs entry showing whether secure world is up and running
231 */
232static ssize_t tf_started_show(struct tf_device *dev, char *buf)
233{
234 int tf_started = test_bit(TF_COMM_FLAG_PA_AVAILABLE,
235 &dev->sm.flags);
236
237 return snprintf(buf, PAGE_SIZE, "%s\n", tf_started ? "yes" : "no");
238}
239static struct tf_sysfs_entry tf_started_entry =
240 __ATTR_RO(tf_started);
241
242static ssize_t workspace_addr_show(struct tf_device *dev, char *buf)
243{
244 return snprintf(buf, PAGE_SIZE, "0x%08x\n", dev->workspace_addr);
245}
246static struct tf_sysfs_entry tf_workspace_addr_entry =
247 __ATTR_RO(workspace_addr);
248
249static ssize_t workspace_size_show(struct tf_device *dev, char *buf)
250{
251 return snprintf(buf, PAGE_SIZE, "0x%08x\n", dev->workspace_size);
252}
253static struct tf_sysfs_entry tf_workspace_size_entry =
254 __ATTR_RO(workspace_size);
255#endif
256
257static ssize_t tf_attr_show(struct kobject *kobj, struct attribute *attr,
258 char *page)
259{
260 struct tf_sysfs_entry *entry = container_of(attr, struct tf_sysfs_entry,
261 attr);
262 struct tf_device *dev = container_of(kobj, struct tf_device, kobj);
263
264 if (!entry->show)
265 return -EIO;
266
267 return entry->show(dev, page);
268}
269
270static ssize_t tf_attr_store(struct kobject *kobj, struct attribute *attr,
271 const char *page, size_t length)
272{
273 struct tf_sysfs_entry *entry = container_of(attr, struct tf_sysfs_entry,
274 attr);
275 struct tf_device *dev = container_of(kobj, struct tf_device, kobj);
276
277 if (!entry->store)
278 return -EIO;
279
280 return entry->store(dev, page, length);
281}
282
283static void tf_kobj_release(struct kobject *kobj) {}
284
285static struct attribute *tf_default_attrs[] = {
286 &tf_info_entry.attr,
287#ifdef CONFIG_TF_ZEBRA
288 &tf_started_entry.attr,
289 &tf_workspace_addr_entry.attr,
290 &tf_workspace_size_entry.attr,
291#endif
292 NULL,
293};
294static const struct sysfs_ops tf_sysfs_ops = {
295 .show = tf_attr_show,
296 .store = tf_attr_store,
297};
298static struct kobj_type tf_ktype = {
299 .release = tf_kobj_release,
300 .sysfs_ops = &tf_sysfs_ops,
301 .default_attrs = tf_default_attrs
302};
303
304/*----------------------------------------------------------------------------*/
305
306#if defined(MODULE) && defined(CONFIG_TF_ZEBRA)
307static char *smc_mem;
308module_param(smc_mem, charp, S_IRUGO);
309#endif
310
311/*
312 * First routine called when the kernel module is loaded
313 */
314static int __init tf_device_register(void)
315{
316 int error;
317 struct tf_device *dev = &g_tf_dev;
318
319 dprintk(KERN_INFO "tf_device_register()\n");
320
321 /*
322 * Initialize the device
323 */
324 dev->dev_number = MKDEV(device_major_number,
325 TF_DEVICE_MINOR_NUMBER);
326 cdev_init(&dev->cdev, &g_tf_device_file_ops);
327 dev->cdev.owner = THIS_MODULE;
328
Chris Johnson9c975ae2011-11-18 16:14:07 -0800329 INIT_LIST_HEAD(&dev->connection_list);
330 spin_lock_init(&dev->connection_list_lock);
331
332#if defined(MODULE) && defined(CONFIG_TF_ZEBRA)
333 error = (*tf_comm_early_init)();
334 if (error)
335 goto module_early_init_failed;
336
337 error = tf_device_mshield_init(smc_mem);
338 if (error)
339 goto mshield_init_failed;
340
341#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
342 error = tf_crypto_hmac_module_init();
343 if (error)
344 goto hmac_init_failed;
345
346 error = tf_self_test_register_device();
347 if (error)
348 goto self_test_register_device_failed;
349#endif
350#endif
351
352 /* register the sysfs object driver stats */
353 error = kobject_init_and_add(&dev->kobj, &tf_ktype, NULL, "%s",
354 TF_DEVICE_BASE_NAME);
355 if (error) {
356 printk(KERN_ERR "tf_device_register(): "
357 "kobject_init_and_add failed (error %d)!\n", error);
358 kobject_put(&dev->kobj);
359 goto kobject_init_and_add_failed;
360 }
361
362 /*
363 * Register the system device.
364 */
Dan Willemsenbc31c952011-12-19 11:33:07 -0800365 register_syscore_ops(&g_tf_device_syscore_ops);
Chris Johnson9c975ae2011-11-18 16:14:07 -0800366
367 /*
368 * Register the char device.
369 */
370 printk(KERN_INFO "Registering char device %s (%u:%u)\n",
371 TF_DEVICE_BASE_NAME,
372 MAJOR(dev->dev_number),
373 MINOR(dev->dev_number));
374 error = register_chrdev_region(dev->dev_number, 1,
375 TF_DEVICE_BASE_NAME);
376 if (error != 0) {
377 printk(KERN_ERR "tf_device_register():"
378 " register_chrdev_region failed (error %d)!\n",
379 error);
380 goto register_chrdev_region_failed;
381 }
382
383 error = cdev_add(&dev->cdev, dev->dev_number, 1);
384 if (error != 0) {
385 printk(KERN_ERR "tf_device_register(): "
386 "cdev_add failed (error %d)!\n",
387 error);
388 goto cdev_add_failed;
389 }
390
391 /*
392 * Initialize the communication with the Secure World.
393 */
394#ifdef CONFIG_TF_TRUSTZONE
395 dev->sm.soft_int_irq = soft_interrupt;
396#endif
397 error = tf_init(&g_tf_dev.sm);
398 if (error != S_SUCCESS) {
399 dprintk(KERN_ERR "tf_device_register(): "
400 "tf_init failed (error %d)!\n",
401 error);
402 goto init_failed;
403 }
404
405#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
Hyung Taek Ryoo4a143162012-10-24 00:22:49 -0700406 error = tf_self_test_post_init(&(g_tf_dev.kobj));
Chris Johnson9c975ae2011-11-18 16:14:07 -0800407 /* N.B. error > 0 indicates a POST failure, which will not
408 prevent the module from loading. */
409 if (error < 0) {
410 dprintk(KERN_ERR "tf_device_register(): "
411 "tf_self_test_post_vectors failed (error %d)!\n",
412 error);
413 goto post_failed;
414 }
415#endif
416
417#ifdef CONFIG_ANDROID
418 tf_class = class_create(THIS_MODULE, TF_DEVICE_BASE_NAME);
419 device_create(tf_class, NULL,
420 dev->dev_number,
421 NULL, TF_DEVICE_BASE_NAME);
422#endif
423
424#ifdef CONFIG_TF_ZEBRA
425 /*
426 * Initializes the /dev/tf_ctrl device node.
427 */
428 error = tf_ctrl_device_register();
429 if (error)
430 goto ctrl_failed;
431#endif
432
433#ifdef CONFIG_TF_DRIVER_DEBUG_SUPPORT
434 address_cache_property((unsigned long) &tf_device_register);
435#endif
436 /*
437 * Successful completion.
438 */
439
440 dprintk(KERN_INFO "tf_device_register(): Success\n");
441 return 0;
442
443 /*
444 * Error: undo all operations in the reverse order
445 */
446#ifdef CONFIG_TF_ZEBRA
447ctrl_failed:
448#endif
449#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
450 tf_self_test_post_exit();
451post_failed:
452#endif
453init_failed:
454 cdev_del(&dev->cdev);
455cdev_add_failed:
456 unregister_chrdev_region(dev->dev_number, 1);
457register_chrdev_region_failed:
Dan Willemsenbc31c952011-12-19 11:33:07 -0800458 unregister_syscore_ops(&g_tf_device_syscore_ops);
Chris Johnson9c975ae2011-11-18 16:14:07 -0800459kobject_init_and_add_failed:
460 kobject_del(&g_tf_dev.kobj);
461
462#if defined(MODULE) && defined(CONFIG_TF_ZEBRA)
463#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
464 tf_self_test_unregister_device();
465self_test_register_device_failed:
466 tf_crypto_hmac_module_exit();
467hmac_init_failed:
468#endif
469 tf_device_mshield_exit();
470mshield_init_failed:
471module_early_init_failed:
472#endif
473 dprintk(KERN_INFO "tf_device_register(): Failure (error %d)\n",
474 error);
475 return error;
476}
477
478/*----------------------------------------------------------------------------*/
479
480static int tf_device_open(struct inode *inode, struct file *file)
481{
482 int error;
483 struct tf_device *dev = &g_tf_dev;
484 struct tf_connection *connection = NULL;
485
486 dprintk(KERN_INFO "tf_device_open(%u:%u, %p)\n",
487 imajor(inode), iminor(inode), file);
488
489 /* Dummy lseek for non-seekable driver */
490 error = nonseekable_open(inode, file);
491 if (error != 0) {
492 dprintk(KERN_ERR "tf_device_open(%p): "
493 "nonseekable_open failed (error %d)!\n",
494 file, error);
495 goto error;
496 }
497
498#ifndef CONFIG_ANDROID
499 /*
500 * Check file flags. We only autthorize the O_RDWR access
501 */
502 if (file->f_flags != O_RDWR) {
503 dprintk(KERN_ERR "tf_device_open(%p): "
504 "Invalid access mode %u\n",
505 file, file->f_flags);
506 error = -EACCES;
507 goto error;
508 }
509#endif
510
511 /*
512 * Open a new connection.
513 */
514
515 error = tf_open(dev, file, &connection);
516 if (error != 0) {
517 dprintk(KERN_ERR "tf_device_open(%p): "
518 "tf_open failed (error %d)!\n",
519 file, error);
520 goto error;
521 }
522
523 file->private_data = connection;
524
525 /*
526 * Send the CreateDeviceContext command to the secure
527 */
528 error = tf_create_device_context(connection);
529 if (error != 0) {
530 dprintk(KERN_ERR "tf_device_open(%p): "
531 "tf_create_device_context failed (error %d)!\n",
532 file, error);
533 goto error1;
534 }
535
536 /*
537 * Successful completion.
538 */
539
540 dprintk(KERN_INFO "tf_device_open(%p): Success (connection=%p)\n",
541 file, connection);
542 return 0;
543
544 /*
545 * Error handling.
546 */
547
548error1:
549 tf_close(connection);
550error:
551 dprintk(KERN_INFO "tf_device_open(%p): Failure (error %d)\n",
552 file, error);
553 return error;
554}
555
556/*----------------------------------------------------------------------------*/
557
558static int tf_device_release(struct inode *inode, struct file *file)
559{
560 struct tf_connection *connection;
561
562 dprintk(KERN_INFO "tf_device_release(%u:%u, %p)\n",
563 imajor(inode), iminor(inode), file);
564
565 connection = tf_conn_from_file(file);
566 tf_close(connection);
567
568 dprintk(KERN_INFO "tf_device_release(%p): Success\n", file);
569 return 0;
570}
571
572/*----------------------------------------------------------------------------*/
573
574static long tf_device_ioctl(struct file *file, unsigned int ioctl_num,
575 unsigned long ioctl_param)
576{
577 int result = S_SUCCESS;
578 struct tf_connection *connection;
579 union tf_command command;
580 struct tf_command_header header;
581 union tf_answer answer;
582 u32 command_size;
583 u32 answer_size;
584 void *user_answer;
585
586 dprintk(KERN_INFO "tf_device_ioctl(%p, %u, %p)\n",
587 file, ioctl_num, (void *) ioctl_param);
588
589 switch (ioctl_num) {
590 case IOCTL_TF_GET_VERSION:
591 /* ioctl is asking for the driver interface version */
592 result = TF_DRIVER_INTERFACE_VERSION;
593 goto exit;
594
Hyung Taek Ryoo4a143162012-10-24 00:22:49 -0700595#ifdef CONFIG_TF_ION
596 case IOCTL_TF_ION_REGISTER: {
597 int ion_register;
598 /* ioctl is asking to register an ion handle */
599 if (copy_from_user(&ion_register,
600 (int *) ioctl_param,
601 sizeof(int))) {
602 dprintk(KERN_ERR "tf_device_ioctl(%p): "
603 "copy_from_user failed\n",
604 file);
605 result = -EFAULT;
606 goto exit;
607 }
608
609 connection = tf_conn_from_file(file);
610 BUG_ON(connection == NULL);
611
612 /* Initialize ION connection */
613 if (connection->ion_client == NULL) {
614 connection->ion_client = ion_client_create(
615 zebra_ion_device,
616 (1 << ION_HEAP_TYPE_CARVEOUT),
617 "tf");
618 }
619
620 if (connection->ion_client == NULL) {
621 dprintk(KERN_ERR "tf_device_ioctl(%p): "
622 "unable to create ion client\n",
623 file);
624 result = -EFAULT;
625 goto exit;
626 }
627
628 /*
629 * TODO: We should use a reference count on this handle in order
630 * to not unregistered it while using it.
631 */
632 return (long)ion_import_fd(connection->ion_client, ion_register);
633 }
634
635 case IOCTL_TF_ION_UNREGISTER: {
636 int ion_register;
637 /* ioctl is asking to unregister an ion handle */
638
639 if (copy_from_user(&ion_register,
640 (int *) ioctl_param,
641 sizeof(int))) {
642 dprintk(KERN_ERR "tf_device_ioctl(%p): "
643 "copy_from_user failed\n",
644 file);
645 result = -EFAULT;
646 goto exit;
647 }
648
649 connection = tf_conn_from_file(file);
650 BUG_ON(connection == NULL);
651
652 if (connection->ion_client == NULL) {
653 dprintk(KERN_ERR "tf_device_ioctl(%p): "
654 "ion client does not exist\n",
655 file);
656 result = -EFAULT;
657 goto exit;
658 }
659
660 ion_free(connection->ion_client,
661 (struct ion_handle *) ion_register);
662
663 return S_SUCCESS;
664 }
665#endif
666
Chris Johnson9c975ae2011-11-18 16:14:07 -0800667 case IOCTL_TF_EXCHANGE:
668 /*
669 * ioctl is asking to perform a message exchange with the Secure
670 * Module
671 */
672
673 /*
674 * Make a local copy of the data from the user application
675 * This routine checks the data is readable
676 *
677 * Get the header first.
678 */
679 if (copy_from_user(&header,
680 (struct tf_command_header *)ioctl_param,
681 sizeof(struct tf_command_header))) {
682 dprintk(KERN_ERR "tf_device_ioctl(%p): "
683 "Cannot access ioctl parameter %p\n",
684 file, (void *) ioctl_param);
685 result = -EFAULT;
686 goto exit;
687 }
688
689 /* size in words of u32 */
690 command_size = header.message_size +
691 sizeof(struct tf_command_header)/sizeof(u32);
692 if (command_size > sizeof(command)/sizeof(u32)) {
693 dprintk(KERN_ERR "tf_device_ioctl(%p): "
694 "Buffer overflow: too many bytes to copy %d\n",
695 file, command_size);
696 result = -EFAULT;
697 goto exit;
698 }
699
700 if (copy_from_user(&command,
701 (union tf_command *)ioctl_param,
702 command_size * sizeof(u32))) {
703 dprintk(KERN_ERR "tf_device_ioctl(%p): "
704 "Cannot access ioctl parameter %p\n",
705 file, (void *) ioctl_param);
706 result = -EFAULT;
707 goto exit;
708 }
709
710 connection = tf_conn_from_file(file);
711 BUG_ON(connection == NULL);
712
713 /*
714 * The answer memory space address is in the operation_id field
715 */
716 user_answer = (void *) command.header.operation_id;
717
718 atomic_inc(&(connection->pending_op_count));
719
720 dprintk(KERN_WARNING "tf_device_ioctl(%p): "
721 "Sending message type 0x%08x\n",
722 file, command.header.message_type);
723
724 switch (command.header.message_type) {
725 case TF_MESSAGE_TYPE_OPEN_CLIENT_SESSION:
726 result = tf_open_client_session(connection,
727 &command, &answer);
728 break;
729
730 case TF_MESSAGE_TYPE_CLOSE_CLIENT_SESSION:
731 result = tf_close_client_session(connection,
732 &command, &answer);
733 break;
734
735 case TF_MESSAGE_TYPE_REGISTER_SHARED_MEMORY:
736 result = tf_register_shared_memory(connection,
737 &command, &answer);
738 break;
739
740 case TF_MESSAGE_TYPE_RELEASE_SHARED_MEMORY:
741 result = tf_release_shared_memory(connection,
742 &command, &answer);
743 break;
744
745 case TF_MESSAGE_TYPE_INVOKE_CLIENT_COMMAND:
Charles Tanc7faf7f2012-10-25 23:09:37 -0700746 trace_invoke_client_command(NVSEC_INVOKE_CMD_START);
Chris Johnson9c975ae2011-11-18 16:14:07 -0800747 result = tf_invoke_client_command(connection,
748 &command, &answer);
Charles Tanc7faf7f2012-10-25 23:09:37 -0700749 trace_invoke_client_command(NVSEC_INVOKE_CMD_DONE);
Chris Johnson9c975ae2011-11-18 16:14:07 -0800750 break;
751
752 case TF_MESSAGE_TYPE_CANCEL_CLIENT_COMMAND:
753 result = tf_cancel_client_command(connection,
754 &command, &answer);
755 break;
756
757 default:
758 dprintk(KERN_ERR "tf_device_ioctl(%p): "
759 "Incorrect message type (0x%08x)!\n",
760 connection, command.header.message_type);
761 result = -EOPNOTSUPP;
762 break;
763 }
764
765 atomic_dec(&(connection->pending_op_count));
766
767 if (result != 0) {
768 dprintk(KERN_WARNING "tf_device_ioctl(%p): "
769 "Operation returning error code 0x%08x)!\n",
770 file, result);
771 goto exit;
772 }
773
774 /*
775 * Copy the answer back to the user space application.
776 * The driver does not check this field, only copy back to user
777 * space the data handed over by Secure World
778 */
779 answer_size = answer.header.message_size +
780 sizeof(struct tf_answer_header)/sizeof(u32);
781 if (copy_to_user(user_answer,
782 &answer, answer_size * sizeof(u32))) {
783 dprintk(KERN_WARNING "tf_device_ioctl(%p): "
784 "Failed to copy back the full command "
785 "answer to %p\n", file, user_answer);
786 result = -EFAULT;
787 goto exit;
788 }
789
790 /* successful completion */
791 dprintk(KERN_INFO "tf_device_ioctl(%p): Success\n", file);
792 break;
793
794 case IOCTL_TF_GET_DESCRIPTION: {
795 /* ioctl asking for the version information buffer */
796 struct tf_version_information_buffer *pInfoBuffer;
797
798 dprintk(KERN_INFO "IOCTL_TF_GET_DESCRIPTION:(%p, %u, %p)\n",
799 file, ioctl_num, (void *) ioctl_param);
800
801 pInfoBuffer =
802 ((struct tf_version_information_buffer *) ioctl_param);
803
804 dprintk(KERN_INFO "IOCTL_TF_GET_DESCRIPTION1: "
805 "driver_description=\"%64s\"\n", S_VERSION_STRING);
806
807 if (copy_to_user(pInfoBuffer->driver_description,
808 S_VERSION_STRING,
809 strlen(S_VERSION_STRING) + 1)) {
810 dprintk(KERN_ERR "tf_device_ioctl(%p): "
811 "Fail to copy back the driver description "
812 "to %p\n",
813 file, pInfoBuffer->driver_description);
814 result = -EFAULT;
815 goto exit;
816 }
817
818 dprintk(KERN_INFO "IOCTL_TF_GET_DESCRIPTION2: "
819 "secure_world_description=\"%64s\"\n",
820 tf_get_description(&g_tf_dev.sm));
821
822 if (copy_to_user(pInfoBuffer->secure_world_description,
823 tf_get_description(&g_tf_dev.sm),
824 TF_DESCRIPTION_BUFFER_LENGTH)) {
825 dprintk(KERN_WARNING "tf_device_ioctl(%p): "
826 "Failed to copy back the secure world "
827 "description to %p\n",
828 file, pInfoBuffer->secure_world_description);
829 result = -EFAULT;
830 goto exit;
831 }
832 break;
833 }
834
835 default:
836 dprintk(KERN_ERR "tf_device_ioctl(%p): "
837 "Unknown IOCTL code 0x%08x!\n",
838 file, ioctl_num);
839 result = -EOPNOTSUPP;
840 goto exit;
841 }
842
843exit:
844 return result;
845}
846
847/*----------------------------------------------------------------------------*/
848
Sanjay Singh Rawatf9389682012-03-26 15:45:23 +0530849static void tf_device_shutdown(void)
Chris Johnson9c975ae2011-11-18 16:14:07 -0800850{
Sanjay Singh Rawatf9389682012-03-26 15:45:23 +0530851 if (0 > tf_power_management(&g_tf_dev.sm, TF_POWER_OPERATION_SHUTDOWN))
852 dprintk(KERN_ERR "tf_device_shutdown failing\n");
Chris Johnson9c975ae2011-11-18 16:14:07 -0800853}
854
855/*----------------------------------------------------------------------------*/
856
Dan Willemsenbc31c952011-12-19 11:33:07 -0800857static int tf_device_suspend(void)
Chris Johnson9c975ae2011-11-18 16:14:07 -0800858{
859 dprintk(KERN_INFO "tf_device_suspend: Enter\n");
860 return tf_power_management(&g_tf_dev.sm,
861 TF_POWER_OPERATION_HIBERNATE);
862}
863
864
865/*----------------------------------------------------------------------------*/
866
Sanjay Singh Rawatf9389682012-03-26 15:45:23 +0530867static void tf_device_resume(void)
Chris Johnson9c975ae2011-11-18 16:14:07 -0800868{
Sanjay Singh Rawatf9389682012-03-26 15:45:23 +0530869 if (0 > tf_power_management(&g_tf_dev.sm, TF_POWER_OPERATION_RESUME))
870 dprintk(KERN_ERR "tf_device_resume failing\n");
Chris Johnson9c975ae2011-11-18 16:14:07 -0800871}
872
873
874/*----------------------------------------------------------------------------*/
875
876module_init(tf_device_register);
877
878MODULE_LICENSE("GPL");
879MODULE_AUTHOR("Trusted Logic S.A.");