blob: 47ff39e6561d47990979e70a0e7c6d233d3eb12b [file] [log] [blame]
Chris Johnson9c975ae2011-11-18 16:14:07 -08001/**
2 * Copyright (c) 2011 Trusted Logic S.A.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
17 * MA 02111-1307 USA
18 */
19
20#include <linux/atomic.h>
21#include <linux/uaccess.h>
22#include <linux/module.h>
23#include <linux/errno.h>
24#include <linux/mm.h>
25#include <linux/page-flags.h>
26#include <linux/pm.h>
27#include <linux/sysdev.h>
28#include <linux/vmalloc.h>
29#include <linux/signal.h>
30#ifdef CONFIG_ANDROID
31#include <linux/device.h>
32#endif
33
34#include "tf_protocol.h"
35#include "tf_defs.h"
36#include "tf_util.h"
37#include "tf_conn.h"
38#include "tf_comm.h"
39#ifdef CONFIG_TF_ZEBRA
40#include <plat/cpu.h>
41#include "tf_zebra.h"
42#endif
43#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
44#include "tf_crypto.h"
45#endif
46
47#include "s_version.h"
48
49/*----------------------------------------------------------------------------
50 * Forward Declarations
51 *----------------------------------------------------------------------------*/
52
53/*
54 * Creates and registers the device to be managed by the specified driver.
55 *
56 * Returns zero upon successful completion, or an appropriate error code upon
57 * failure.
58 */
59static int tf_device_register(void);
60
61
62/*
63 * Implements the device Open callback.
64 */
65static int tf_device_open(
66 struct inode *inode,
67 struct file *file);
68
69
70/*
71 * Implements the device Release callback.
72 */
73static int tf_device_release(
74 struct inode *inode,
75 struct file *file);
76
77
78/*
79 * Implements the device ioctl callback.
80 */
81static long tf_device_ioctl(
82 struct file *file,
83 unsigned int ioctl_num,
84 unsigned long ioctl_param);
85
86
87/*
88 * Implements the device shutdown callback.
89 */
90static int tf_device_shutdown(
91 struct sys_device *sysdev);
92
93
94/*
95 * Implements the device suspend callback.
96 */
97static int tf_device_suspend(
98 struct sys_device *sysdev,
99 pm_message_t state);
100
101
102/*
103 * Implements the device resume callback.
104 */
105static int tf_device_resume(
106 struct sys_device *sysdev);
107
108
109/*---------------------------------------------------------------------------
110 * Module Parameters
111 *---------------------------------------------------------------------------*/
112
113/*
114 * The device major number used to register a unique character device driver.
115 * Let the default value be 122
116 */
117static int device_major_number = 122;
118
119module_param(device_major_number, int, 0000);
120MODULE_PARM_DESC(device_major_number,
121 "The device major number used to register a unique character "
122 "device driver");
123
124#ifdef CONFIG_TF_TRUSTZONE
125/**
126 * The softint interrupt line used by the Secure World.
127 */
128static int soft_interrupt = -1;
129
130module_param(soft_interrupt, int, 0000);
131MODULE_PARM_DESC(soft_interrupt,
132 "The softint interrupt line used by the Secure world");
133#endif
134
135#ifdef CONFIG_TF_DRIVER_DEBUG_SUPPORT
136unsigned tf_debug_level = UINT_MAX;
137module_param_named(debug, tf_debug_level, uint, 0644);
138#endif
139
140#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
141char *tf_integrity_hmac_sha256_expected_value;
142module_param_named(hmac_sha256, tf_integrity_hmac_sha256_expected_value,
143 charp, 0444);
144
145#ifdef CONFIG_TF_DRIVER_FAULT_INJECTION
146unsigned tf_fault_injection_mask;
147module_param_named(fault, tf_fault_injection_mask, uint, 0644);
148#endif
149
150int tf_self_test_blkcipher_align;
151module_param_named(post_align, tf_self_test_blkcipher_align, int, 0644);
152int tf_self_test_blkcipher_use_vmalloc;
153module_param_named(post_vmalloc, tf_self_test_blkcipher_use_vmalloc, int, 0644);
154#endif
155
156#ifdef CONFIG_ANDROID
157static struct class *tf_class;
158#endif
159
160/*
161 * Interfaces the system device with the kernel.
162 */
163struct sys_device g_tf_sysdev;
164
165/*----------------------------------------------------------------------------
166 * Global Variables
167 *----------------------------------------------------------------------------*/
168
169/*
170 * tf_driver character device definitions.
171 * read and write methods are not defined
172 * and will return an error if used by user space
173 */
174static const struct file_operations g_tf_device_file_ops = {
175 .owner = THIS_MODULE,
176 .open = tf_device_open,
177 .release = tf_device_release,
178 .unlocked_ioctl = tf_device_ioctl,
179 .llseek = no_llseek,
180};
181
182
183static struct sysdev_class g_tf_device_sys_class = {
184 .name = TF_DEVICE_BASE_NAME,
185 .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
329 g_tf_sysdev.id = 0;
330 g_tf_sysdev.cls = &g_tf_device_sys_class;
331
332 INIT_LIST_HEAD(&dev->connection_list);
333 spin_lock_init(&dev->connection_list_lock);
334
335#if defined(MODULE) && defined(CONFIG_TF_ZEBRA)
336 error = (*tf_comm_early_init)();
337 if (error)
338 goto module_early_init_failed;
339
340 error = tf_device_mshield_init(smc_mem);
341 if (error)
342 goto mshield_init_failed;
343
344#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
345 error = tf_crypto_hmac_module_init();
346 if (error)
347 goto hmac_init_failed;
348
349 error = tf_self_test_register_device();
350 if (error)
351 goto self_test_register_device_failed;
352#endif
353#endif
354
355 /* register the sysfs object driver stats */
356 error = kobject_init_and_add(&dev->kobj, &tf_ktype, NULL, "%s",
357 TF_DEVICE_BASE_NAME);
358 if (error) {
359 printk(KERN_ERR "tf_device_register(): "
360 "kobject_init_and_add failed (error %d)!\n", error);
361 kobject_put(&dev->kobj);
362 goto kobject_init_and_add_failed;
363 }
364
365 /*
366 * Register the system device.
367 */
368
369 error = sysdev_class_register(&g_tf_device_sys_class);
370 if (error != 0) {
371 printk(KERN_ERR "tf_device_register():"
372 " sysdev_class_register failed (error %d)!\n",
373 error);
374 goto sysdev_class_register_failed;
375 }
376
377 error = sysdev_register(&g_tf_sysdev);
378 if (error != 0) {
379 dprintk(KERN_ERR "tf_device_register(): "
380 "sysdev_register failed (error %d)!\n",
381 error);
382 goto sysdev_register_failed;
383 }
384
385 /*
386 * Register the char device.
387 */
388 printk(KERN_INFO "Registering char device %s (%u:%u)\n",
389 TF_DEVICE_BASE_NAME,
390 MAJOR(dev->dev_number),
391 MINOR(dev->dev_number));
392 error = register_chrdev_region(dev->dev_number, 1,
393 TF_DEVICE_BASE_NAME);
394 if (error != 0) {
395 printk(KERN_ERR "tf_device_register():"
396 " register_chrdev_region failed (error %d)!\n",
397 error);
398 goto register_chrdev_region_failed;
399 }
400
401 error = cdev_add(&dev->cdev, dev->dev_number, 1);
402 if (error != 0) {
403 printk(KERN_ERR "tf_device_register(): "
404 "cdev_add failed (error %d)!\n",
405 error);
406 goto cdev_add_failed;
407 }
408
409 /*
410 * Initialize the communication with the Secure World.
411 */
412#ifdef CONFIG_TF_TRUSTZONE
413 dev->sm.soft_int_irq = soft_interrupt;
414#endif
415 error = tf_init(&g_tf_dev.sm);
416 if (error != S_SUCCESS) {
417 dprintk(KERN_ERR "tf_device_register(): "
418 "tf_init failed (error %d)!\n",
419 error);
420 goto init_failed;
421 }
422
423#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
424 error = tf_self_test_post_init(&(dev_stats->kobj));
425 /* N.B. error > 0 indicates a POST failure, which will not
426 prevent the module from loading. */
427 if (error < 0) {
428 dprintk(KERN_ERR "tf_device_register(): "
429 "tf_self_test_post_vectors failed (error %d)!\n",
430 error);
431 goto post_failed;
432 }
433#endif
434
435#ifdef CONFIG_ANDROID
436 tf_class = class_create(THIS_MODULE, TF_DEVICE_BASE_NAME);
437 device_create(tf_class, NULL,
438 dev->dev_number,
439 NULL, TF_DEVICE_BASE_NAME);
440#endif
441
442#ifdef CONFIG_TF_ZEBRA
443 /*
444 * Initializes the /dev/tf_ctrl device node.
445 */
446 error = tf_ctrl_device_register();
447 if (error)
448 goto ctrl_failed;
449#endif
450
451#ifdef CONFIG_TF_DRIVER_DEBUG_SUPPORT
452 address_cache_property((unsigned long) &tf_device_register);
453#endif
454 /*
455 * Successful completion.
456 */
457
458 dprintk(KERN_INFO "tf_device_register(): Success\n");
459 return 0;
460
461 /*
462 * Error: undo all operations in the reverse order
463 */
464#ifdef CONFIG_TF_ZEBRA
465ctrl_failed:
466#endif
467#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
468 tf_self_test_post_exit();
469post_failed:
470#endif
471init_failed:
472 cdev_del(&dev->cdev);
473cdev_add_failed:
474 unregister_chrdev_region(dev->dev_number, 1);
475register_chrdev_region_failed:
476 sysdev_unregister(&g_tf_sysdev);
477sysdev_register_failed:
478 sysdev_class_unregister(&g_tf_device_sys_class);
479sysdev_class_register_failed:
480kobject_init_and_add_failed:
481 kobject_del(&g_tf_dev.kobj);
482
483#if defined(MODULE) && defined(CONFIG_TF_ZEBRA)
484#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
485 tf_self_test_unregister_device();
486self_test_register_device_failed:
487 tf_crypto_hmac_module_exit();
488hmac_init_failed:
489#endif
490 tf_device_mshield_exit();
491mshield_init_failed:
492module_early_init_failed:
493#endif
494 dprintk(KERN_INFO "tf_device_register(): Failure (error %d)\n",
495 error);
496 return error;
497}
498
499/*----------------------------------------------------------------------------*/
500
501static int tf_device_open(struct inode *inode, struct file *file)
502{
503 int error;
504 struct tf_device *dev = &g_tf_dev;
505 struct tf_connection *connection = NULL;
506
507 dprintk(KERN_INFO "tf_device_open(%u:%u, %p)\n",
508 imajor(inode), iminor(inode), file);
509
510 /* Dummy lseek for non-seekable driver */
511 error = nonseekable_open(inode, file);
512 if (error != 0) {
513 dprintk(KERN_ERR "tf_device_open(%p): "
514 "nonseekable_open failed (error %d)!\n",
515 file, error);
516 goto error;
517 }
518
519#ifndef CONFIG_ANDROID
520 /*
521 * Check file flags. We only autthorize the O_RDWR access
522 */
523 if (file->f_flags != O_RDWR) {
524 dprintk(KERN_ERR "tf_device_open(%p): "
525 "Invalid access mode %u\n",
526 file, file->f_flags);
527 error = -EACCES;
528 goto error;
529 }
530#endif
531
532 /*
533 * Open a new connection.
534 */
535
536 error = tf_open(dev, file, &connection);
537 if (error != 0) {
538 dprintk(KERN_ERR "tf_device_open(%p): "
539 "tf_open failed (error %d)!\n",
540 file, error);
541 goto error;
542 }
543
544 file->private_data = connection;
545
546 /*
547 * Send the CreateDeviceContext command to the secure
548 */
549 error = tf_create_device_context(connection);
550 if (error != 0) {
551 dprintk(KERN_ERR "tf_device_open(%p): "
552 "tf_create_device_context failed (error %d)!\n",
553 file, error);
554 goto error1;
555 }
556
557 /*
558 * Successful completion.
559 */
560
561 dprintk(KERN_INFO "tf_device_open(%p): Success (connection=%p)\n",
562 file, connection);
563 return 0;
564
565 /*
566 * Error handling.
567 */
568
569error1:
570 tf_close(connection);
571error:
572 dprintk(KERN_INFO "tf_device_open(%p): Failure (error %d)\n",
573 file, error);
574 return error;
575}
576
577/*----------------------------------------------------------------------------*/
578
579static int tf_device_release(struct inode *inode, struct file *file)
580{
581 struct tf_connection *connection;
582
583 dprintk(KERN_INFO "tf_device_release(%u:%u, %p)\n",
584 imajor(inode), iminor(inode), file);
585
586 connection = tf_conn_from_file(file);
587 tf_close(connection);
588
589 dprintk(KERN_INFO "tf_device_release(%p): Success\n", file);
590 return 0;
591}
592
593/*----------------------------------------------------------------------------*/
594
595static long tf_device_ioctl(struct file *file, unsigned int ioctl_num,
596 unsigned long ioctl_param)
597{
598 int result = S_SUCCESS;
599 struct tf_connection *connection;
600 union tf_command command;
601 struct tf_command_header header;
602 union tf_answer answer;
603 u32 command_size;
604 u32 answer_size;
605 void *user_answer;
606
607 dprintk(KERN_INFO "tf_device_ioctl(%p, %u, %p)\n",
608 file, ioctl_num, (void *) ioctl_param);
609
610 switch (ioctl_num) {
611 case IOCTL_TF_GET_VERSION:
612 /* ioctl is asking for the driver interface version */
613 result = TF_DRIVER_INTERFACE_VERSION;
614 goto exit;
615
616 case IOCTL_TF_EXCHANGE:
617 /*
618 * ioctl is asking to perform a message exchange with the Secure
619 * Module
620 */
621
622 /*
623 * Make a local copy of the data from the user application
624 * This routine checks the data is readable
625 *
626 * Get the header first.
627 */
628 if (copy_from_user(&header,
629 (struct tf_command_header *)ioctl_param,
630 sizeof(struct tf_command_header))) {
631 dprintk(KERN_ERR "tf_device_ioctl(%p): "
632 "Cannot access ioctl parameter %p\n",
633 file, (void *) ioctl_param);
634 result = -EFAULT;
635 goto exit;
636 }
637
638 /* size in words of u32 */
639 command_size = header.message_size +
640 sizeof(struct tf_command_header)/sizeof(u32);
641 if (command_size > sizeof(command)/sizeof(u32)) {
642 dprintk(KERN_ERR "tf_device_ioctl(%p): "
643 "Buffer overflow: too many bytes to copy %d\n",
644 file, command_size);
645 result = -EFAULT;
646 goto exit;
647 }
648
649 if (copy_from_user(&command,
650 (union tf_command *)ioctl_param,
651 command_size * sizeof(u32))) {
652 dprintk(KERN_ERR "tf_device_ioctl(%p): "
653 "Cannot access ioctl parameter %p\n",
654 file, (void *) ioctl_param);
655 result = -EFAULT;
656 goto exit;
657 }
658
659 connection = tf_conn_from_file(file);
660 BUG_ON(connection == NULL);
661
662 /*
663 * The answer memory space address is in the operation_id field
664 */
665 user_answer = (void *) command.header.operation_id;
666
667 atomic_inc(&(connection->pending_op_count));
668
669 dprintk(KERN_WARNING "tf_device_ioctl(%p): "
670 "Sending message type 0x%08x\n",
671 file, command.header.message_type);
672
673 switch (command.header.message_type) {
674 case TF_MESSAGE_TYPE_OPEN_CLIENT_SESSION:
675 result = tf_open_client_session(connection,
676 &command, &answer);
677 break;
678
679 case TF_MESSAGE_TYPE_CLOSE_CLIENT_SESSION:
680 result = tf_close_client_session(connection,
681 &command, &answer);
682 break;
683
684 case TF_MESSAGE_TYPE_REGISTER_SHARED_MEMORY:
685 result = tf_register_shared_memory(connection,
686 &command, &answer);
687 break;
688
689 case TF_MESSAGE_TYPE_RELEASE_SHARED_MEMORY:
690 result = tf_release_shared_memory(connection,
691 &command, &answer);
692 break;
693
694 case TF_MESSAGE_TYPE_INVOKE_CLIENT_COMMAND:
695 result = tf_invoke_client_command(connection,
696 &command, &answer);
697 break;
698
699 case TF_MESSAGE_TYPE_CANCEL_CLIENT_COMMAND:
700 result = tf_cancel_client_command(connection,
701 &command, &answer);
702 break;
703
704 default:
705 dprintk(KERN_ERR "tf_device_ioctl(%p): "
706 "Incorrect message type (0x%08x)!\n",
707 connection, command.header.message_type);
708 result = -EOPNOTSUPP;
709 break;
710 }
711
712 atomic_dec(&(connection->pending_op_count));
713
714 if (result != 0) {
715 dprintk(KERN_WARNING "tf_device_ioctl(%p): "
716 "Operation returning error code 0x%08x)!\n",
717 file, result);
718 goto exit;
719 }
720
721 /*
722 * Copy the answer back to the user space application.
723 * The driver does not check this field, only copy back to user
724 * space the data handed over by Secure World
725 */
726 answer_size = answer.header.message_size +
727 sizeof(struct tf_answer_header)/sizeof(u32);
728 if (copy_to_user(user_answer,
729 &answer, answer_size * sizeof(u32))) {
730 dprintk(KERN_WARNING "tf_device_ioctl(%p): "
731 "Failed to copy back the full command "
732 "answer to %p\n", file, user_answer);
733 result = -EFAULT;
734 goto exit;
735 }
736
737 /* successful completion */
738 dprintk(KERN_INFO "tf_device_ioctl(%p): Success\n", file);
739 break;
740
741 case IOCTL_TF_GET_DESCRIPTION: {
742 /* ioctl asking for the version information buffer */
743 struct tf_version_information_buffer *pInfoBuffer;
744
745 dprintk(KERN_INFO "IOCTL_TF_GET_DESCRIPTION:(%p, %u, %p)\n",
746 file, ioctl_num, (void *) ioctl_param);
747
748 pInfoBuffer =
749 ((struct tf_version_information_buffer *) ioctl_param);
750
751 dprintk(KERN_INFO "IOCTL_TF_GET_DESCRIPTION1: "
752 "driver_description=\"%64s\"\n", S_VERSION_STRING);
753
754 if (copy_to_user(pInfoBuffer->driver_description,
755 S_VERSION_STRING,
756 strlen(S_VERSION_STRING) + 1)) {
757 dprintk(KERN_ERR "tf_device_ioctl(%p): "
758 "Fail to copy back the driver description "
759 "to %p\n",
760 file, pInfoBuffer->driver_description);
761 result = -EFAULT;
762 goto exit;
763 }
764
765 dprintk(KERN_INFO "IOCTL_TF_GET_DESCRIPTION2: "
766 "secure_world_description=\"%64s\"\n",
767 tf_get_description(&g_tf_dev.sm));
768
769 if (copy_to_user(pInfoBuffer->secure_world_description,
770 tf_get_description(&g_tf_dev.sm),
771 TF_DESCRIPTION_BUFFER_LENGTH)) {
772 dprintk(KERN_WARNING "tf_device_ioctl(%p): "
773 "Failed to copy back the secure world "
774 "description to %p\n",
775 file, pInfoBuffer->secure_world_description);
776 result = -EFAULT;
777 goto exit;
778 }
779 break;
780 }
781
782 default:
783 dprintk(KERN_ERR "tf_device_ioctl(%p): "
784 "Unknown IOCTL code 0x%08x!\n",
785 file, ioctl_num);
786 result = -EOPNOTSUPP;
787 goto exit;
788 }
789
790exit:
791 return result;
792}
793
794/*----------------------------------------------------------------------------*/
795
796static int tf_device_shutdown(struct sys_device *sysdev)
797{
798
799 return tf_power_management(&g_tf_dev.sm,
800 TF_POWER_OPERATION_SHUTDOWN);
801}
802
803/*----------------------------------------------------------------------------*/
804
805static int tf_device_suspend(struct sys_device *sysdev, pm_message_t state)
806{
807 dprintk(KERN_INFO "tf_device_suspend: Enter\n");
808 return tf_power_management(&g_tf_dev.sm,
809 TF_POWER_OPERATION_HIBERNATE);
810}
811
812
813/*----------------------------------------------------------------------------*/
814
815static int tf_device_resume(struct sys_device *sysdev)
816{
817 return tf_power_management(&g_tf_dev.sm,
818 TF_POWER_OPERATION_RESUME);
819}
820
821
822/*----------------------------------------------------------------------------*/
823
824module_init(tf_device_register);
825
826MODULE_LICENSE("GPL");
827MODULE_AUTHOR("Trusted Logic S.A.");