diff options
Diffstat (limited to 'drivers/char')
28 files changed, 1371 insertions, 1297 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 9d03b2ff5df6..2e2ffe7010aa 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -66,6 +66,14 @@ config TTY_PRINTK If unsure, say N. +config TTY_PRINTK_LEVEL + depends on TTY_PRINTK + int "ttyprintk log level (1-7)" + range 1 7 + default "6" + help + Printk log level to use for ttyprintk messages. + config PRINTER tristate "Parallel printer support" depends on PARPORT diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 38ffb281df97..004a3ce8ba72 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -115,9 +115,9 @@ static int agp_find_max(void) long memory, index, result; #if PAGE_SHIFT < 20 - memory = totalram_pages >> (20 - PAGE_SHIFT); + memory = totalram_pages() >> (20 - PAGE_SHIFT); #else - memory = totalram_pages << (PAGE_SHIFT - 20); + memory = totalram_pages() << (PAGE_SHIFT - 20); #endif index = 1; diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c index 14e728fbb8a0..ff5394f47587 100644 --- a/drivers/char/generic_nvram.c +++ b/drivers/char/generic_nvram.c @@ -44,7 +44,7 @@ static ssize_t read_nvram(struct file *file, char __user *buf, unsigned int i; char __user *p = buf; - if (!access_ok(VERIFY_WRITE, buf, count)) + if (!access_ok(buf, count)) return -EFAULT; if (*ppos >= nvram_len) return 0; @@ -62,7 +62,7 @@ static ssize_t write_nvram(struct file *file, const char __user *buf, const char __user *p = buf; char c; - if (!access_ok(VERIFY_READ, buf, count)) + if (!access_ok(buf, count)) return -EFAULT; if (*ppos >= nvram_len) return 0; diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c index 6767d965c36c..256b0b1d0f26 100644 --- a/drivers/char/hw_random/bcm2835-rng.c +++ b/drivers/char/hw_random/bcm2835-rng.c @@ -1,10 +1,7 @@ -/** +// SPDX-License-Identifier: GPL-2.0 +/* * Copyright (c) 2010-2012 Broadcom. All rights reserved. * Copyright (c) 2013 Lubomir Rintel - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License ("GPL") - * version 2, as published by the Free Software Foundation. */ #include <linux/hw_random.h> diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 677618e6f1f7..dc8603d34320 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2187,7 +2187,7 @@ static void shutdown_smi(void *send_info) * handlers might have been running before we freed the * interrupt. */ - synchronize_sched(); + synchronize_rcu(); /* * Timeouts are stopped, now make sure the interrupts are off diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 8c4dd1a3bb6a..5c8d780637bd 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -46,8 +46,8 @@ * lp=auto (assign lp devices to all ports that * have printers attached, as determined * by the IEEE-1284 autoprobe) - * - * lp=reset (reset the printer during + * + * lp=reset (reset the printer during * initialisation) * * lp=off (disable the printer driver entirely) @@ -141,6 +141,7 @@ static DEFINE_MUTEX(lp_mutex); static struct lp_struct lp_table[LP_NO]; +static int port_num[LP_NO]; static unsigned int lp_count = 0; static struct class *lp_class; @@ -166,7 +167,7 @@ static struct parport *console_registered; static void lp_claim_parport_or_block(struct lp_struct *this_lp) { if (!test_and_set_bit(LP_PARPORT_CLAIMED, &this_lp->bits)) { - parport_claim_or_block (this_lp->dev); + parport_claim_or_block(this_lp->dev); } } @@ -174,7 +175,7 @@ static void lp_claim_parport_or_block(struct lp_struct *this_lp) static void lp_release_parport(struct lp_struct *this_lp) { if (test_and_clear_bit(LP_PARPORT_CLAIMED, &this_lp->bits)) { - parport_release (this_lp->dev); + parport_release(this_lp->dev); } } @@ -184,37 +185,37 @@ static int lp_preempt(void *handle) { struct lp_struct *this_lp = (struct lp_struct *)handle; set_bit(LP_PREEMPT_REQUEST, &this_lp->bits); - return (1); + return 1; } -/* +/* * Try to negotiate to a new mode; if unsuccessful negotiate to * compatibility mode. Return the mode we ended up in. */ -static int lp_negotiate(struct parport * port, int mode) +static int lp_negotiate(struct parport *port, int mode) { - if (parport_negotiate (port, mode) != 0) { + if (parport_negotiate(port, mode) != 0) { mode = IEEE1284_MODE_COMPAT; - parport_negotiate (port, mode); + parport_negotiate(port, mode); } - return (mode); + return mode; } static int lp_reset(int minor) { int retval; - lp_claim_parport_or_block (&lp_table[minor]); + lp_claim_parport_or_block(&lp_table[minor]); w_ctr(minor, LP_PSELECP); - udelay (LP_DELAY); + udelay(LP_DELAY); w_ctr(minor, LP_PSELECP | LP_PINITP); retval = r_str(minor); - lp_release_parport (&lp_table[minor]); + lp_release_parport(&lp_table[minor]); return retval; } -static void lp_error (int minor) +static void lp_error(int minor) { DEFINE_WAIT(wait); int polling; @@ -223,12 +224,15 @@ static void lp_error (int minor) return; polling = lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE; - if (polling) lp_release_parport (&lp_table[minor]); + if (polling) + lp_release_parport(&lp_table[minor]); prepare_to_wait(&lp_table[minor].waitq, &wait, TASK_INTERRUPTIBLE); schedule_timeout(LP_TIMEOUT_POLLED); finish_wait(&lp_table[minor].waitq, &wait); - if (polling) lp_claim_parport_or_block (&lp_table[minor]); - else parport_yield_blocking (lp_table[minor].dev); + if (polling) + lp_claim_parport_or_block(&lp_table[minor]); + else + parport_yield_blocking(lp_table[minor].dev); } static int lp_check_status(int minor) @@ -259,7 +263,7 @@ static int lp_check_status(int minor) error = -EIO; } else { last = 0; /* Come here if LP_CAREFUL is set and no - errors are reported. */ + errors are reported. */ } lp_table[minor].last_error = last; @@ -276,14 +280,14 @@ static int lp_wait_ready(int minor, int nonblock) /* If we're not in compatibility mode, we're ready now! */ if (lp_table[minor].current_mode != IEEE1284_MODE_COMPAT) { - return (0); + return 0; } do { - error = lp_check_status (minor); + error = lp_check_status(minor); if (error && (nonblock || (LP_F(minor) & LP_ABORT))) break; - if (signal_pending (current)) { + if (signal_pending(current)) { error = -EINTR; break; } @@ -291,8 +295,8 @@ static int lp_wait_ready(int minor, int nonblock) return error; } -static ssize_t lp_write(struct file * file, const char __user * buf, - size_t count, loff_t *ppos) +static ssize_t lp_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) { unsigned int minor = iminor(file_inode(file)); struct parport *port = lp_table[minor].dev->port; @@ -317,26 +321,26 @@ static ssize_t lp_write(struct file * file, const char __user * buf, if (mutex_lock_interruptible(&lp_table[minor].port_mutex)) return -EINTR; - if (copy_from_user (kbuf, buf, copy_size)) { + if (copy_from_user(kbuf, buf, copy_size)) { retv = -EFAULT; goto out_unlock; } - /* Claim Parport or sleep until it becomes available - */ - lp_claim_parport_or_block (&lp_table[minor]); + /* Claim Parport or sleep until it becomes available + */ + lp_claim_parport_or_block(&lp_table[minor]); /* Go to the proper mode. */ - lp_table[minor].current_mode = lp_negotiate (port, - lp_table[minor].best_mode); + lp_table[minor].current_mode = lp_negotiate(port, + lp_table[minor].best_mode); - parport_set_timeout (lp_table[minor].dev, - (nonblock ? PARPORT_INACTIVITY_O_NONBLOCK - : lp_table[minor].timeout)); + parport_set_timeout(lp_table[minor].dev, + (nonblock ? PARPORT_INACTIVITY_O_NONBLOCK + : lp_table[minor].timeout)); - if ((retv = lp_wait_ready (minor, nonblock)) == 0) + if ((retv = lp_wait_ready(minor, nonblock)) == 0) do { /* Write the data. */ - written = parport_write (port, kbuf, copy_size); + written = parport_write(port, kbuf, copy_size); if (written > 0) { copy_size -= written; count -= written; @@ -344,7 +348,7 @@ static ssize_t lp_write(struct file * file, const char __user * buf, retv += written; } - if (signal_pending (current)) { + if (signal_pending(current)) { if (retv == 0) retv = -EINTR; @@ -355,11 +359,11 @@ static ssize_t lp_write(struct file * file, const char __user * buf, /* incomplete write -> check error ! */ int error; - parport_negotiate (lp_table[minor].dev->port, - IEEE1284_MODE_COMPAT); + parport_negotiate(lp_table[minor].dev->port, + IEEE1284_MODE_COMPAT); lp_table[minor].current_mode = IEEE1284_MODE_COMPAT; - error = lp_wait_ready (minor, nonblock); + error = lp_wait_ready(minor, nonblock); if (error) { if (retv == 0) @@ -371,13 +375,13 @@ static ssize_t lp_write(struct file * file, const char __user * buf, break; } - parport_yield_blocking (lp_table[minor].dev); - lp_table[minor].current_mode - = lp_negotiate (port, - lp_table[minor].best_mode); + parport_yield_blocking(lp_table[minor].dev); + lp_table[minor].current_mode + = lp_negotiate(port, + lp_table[minor].best_mode); } else if (need_resched()) - schedule (); + schedule(); if (count) { copy_size = count; @@ -389,27 +393,27 @@ static ssize_t lp_write(struct file * file, const char __user * buf, retv = -EFAULT; break; } - } + } } while (count > 0); - if (test_and_clear_bit(LP_PREEMPT_REQUEST, + if (test_and_clear_bit(LP_PREEMPT_REQUEST, &lp_table[minor].bits)) { printk(KERN_INFO "lp%d releasing parport\n", minor); - parport_negotiate (lp_table[minor].dev->port, - IEEE1284_MODE_COMPAT); + parport_negotiate(lp_table[minor].dev->port, + IEEE1284_MODE_COMPAT); lp_table[minor].current_mode = IEEE1284_MODE_COMPAT; - lp_release_parport (&lp_table[minor]); + lp_release_parport(&lp_table[minor]); } out_unlock: mutex_unlock(&lp_table[minor].port_mutex); - return retv; + return retv; } #ifdef CONFIG_PARPORT_1284 /* Status readback conforming to ieee1284 */ -static ssize_t lp_read(struct file * file, char __user * buf, +static ssize_t lp_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { DEFINE_WAIT(wait); @@ -426,21 +430,21 @@ static ssize_t lp_read(struct file * file, char __user * buf, if (mutex_lock_interruptible(&lp_table[minor].port_mutex)) return -EINTR; - lp_claim_parport_or_block (&lp_table[minor]); + lp_claim_parport_or_block(&lp_table[minor]); - parport_set_timeout (lp_table[minor].dev, - (nonblock ? PARPORT_INACTIVITY_O_NONBLOCK - : lp_table[minor].timeout)); + parport_set_timeout(lp_table[minor].dev, + (nonblock ? PARPORT_INACTIVITY_O_NONBLOCK + : lp_table[minor].timeout)); - parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); - if (parport_negotiate (lp_table[minor].dev->port, - IEEE1284_MODE_NIBBLE)) { + parport_negotiate(lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); + if (parport_negotiate(lp_table[minor].dev->port, + IEEE1284_MODE_NIBBLE)) { retval = -EIO; goto out; } while (retval == 0) { - retval = parport_read (port, kbuf, count); + retval = parport_read(port, kbuf, count); if (retval > 0) break; @@ -453,11 +457,11 @@ static ssize_t lp_read(struct file * file, char __user * buf, /* Wait for data. */ if (lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE) { - parport_negotiate (lp_table[minor].dev->port, - IEEE1284_MODE_COMPAT); - lp_error (minor); - if (parport_negotiate (lp_table[minor].dev->port, - IEEE1284_MODE_NIBBLE)) { + parport_negotiate(lp_table[minor].dev->port, + IEEE1284_MODE_COMPAT); + lp_error(minor); + if (parport_negotiate(lp_table[minor].dev->port, + IEEE1284_MODE_NIBBLE)) { retval = -EIO; goto out; } @@ -467,18 +471,18 @@ static ssize_t lp_read(struct file * file, char __user * buf, finish_wait(&lp_table[minor].waitq, &wait); } - if (signal_pending (current)) { + if (signal_pending(current)) { retval = -ERESTARTSYS; break; } - cond_resched (); + cond_resched(); } - parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); + parport_negotiate(lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); out: - lp_release_parport (&lp_table[minor]); + lp_release_parport(&lp_table[minor]); - if (retval > 0 && copy_to_user (buf, kbuf, retval)) + if (retval > 0 && copy_to_user(buf, kbuf, retval)) retval = -EFAULT; mutex_unlock(&lp_table[minor].port_mutex); @@ -488,7 +492,7 @@ static ssize_t lp_read(struct file * file, char __user * buf, #endif /* IEEE 1284 support */ -static int lp_open(struct inode * inode, struct file * file) +static int lp_open(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); int ret = 0; @@ -513,9 +517,9 @@ static int lp_open(struct inode * inode, struct file * file) should most likely only ever be used by the tunelp application. */ if ((LP_F(minor) & LP_ABORTOPEN) && !(file->f_flags & O_NONBLOCK)) { int status; - lp_claim_parport_or_block (&lp_table[minor]); + lp_claim_parport_or_block(&lp_table[minor]); status = r_str(minor); - lp_release_parport (&lp_table[minor]); + lp_release_parport(&lp_table[minor]); if (status & LP_POUTPA) { printk(KERN_INFO "lp%d out of paper\n", minor); LP_F(minor) &= ~LP_BUSY; @@ -540,32 +544,32 @@ static int lp_open(struct inode * inode, struct file * file) goto out; } /* Determine if the peripheral supports ECP mode */ - lp_claim_parport_or_block (&lp_table[minor]); + lp_claim_parport_or_block(&lp_table[minor]); if ( (lp_table[minor].dev->port->modes & PARPORT_MODE_ECP) && - !parport_negotiate (lp_table[minor].dev->port, - IEEE1284_MODE_ECP)) { - printk (KERN_INFO "lp%d: ECP mode\n", minor); + !parport_negotiate(lp_table[minor].dev->port, + IEEE1284_MODE_ECP)) { + printk(KERN_INFO "lp%d: ECP mode\n", minor); lp_table[minor].best_mode = IEEE1284_MODE_ECP; } else { lp_table[minor].best_mode = IEEE1284_MODE_COMPAT; } /* Leave peripheral in compatibility mode */ - parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); - lp_release_parport (&lp_table[minor]); + parport_negotiate(lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); + lp_release_parport(&lp_table[minor]); lp_table[minor].current_mode = IEEE1284_MODE_COMPAT; out: mutex_unlock(&lp_mutex); return ret; } -static int lp_release(struct inode * inode, struct file * file) +static int lp_release(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); - lp_claim_parport_or_block (&lp_table[minor]); - parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); + lp_claim_parport_or_block(&lp_table[minor]); + parport_negotiate(lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); lp_table[minor].current_mode = IEEE1284_MODE_COMPAT; - lp_release_parport (&lp_table[minor]); + lp_release_parport(&lp_table[minor]); kfree(lp_table[minor].lp_buffer); lp_table[minor].lp_buffer = NULL; LP_F(minor) &= ~LP_BUSY; @@ -615,7 +619,7 @@ static int lp_do_ioctl(unsigned int minor, unsigned int cmd, case LPWAIT: LP_WAIT(minor) = arg; break; - case LPSETIRQ: + case LPSETIRQ: return -EINVAL; break; case LPGETIRQ: @@ -626,9 +630,9 @@ static int lp_do_ioctl(unsigned int minor, unsigned int cmd, case LPGETSTATUS: if (mutex_lock_interruptible(&lp_table[minor].port_mutex)) return -EINTR; - lp_claim_parport_or_block (&lp_table[minor]); + lp_claim_parport_or_block(&lp_table[minor]); status = r_str(minor); - lp_release_parport (&lp_table[minor]); + lp_release_parport(&lp_table[minor]); mutex_unlock(&lp_table[minor].port_mutex); if (copy_to_user(argp, &status, sizeof(int))) @@ -647,8 +651,8 @@ static int lp_do_ioctl(unsigned int minor, unsigned int cmd, sizeof(struct lp_stats)); break; #endif - case LPGETFLAGS: - status = LP_F(minor); + case LPGETFLAGS: + status = LP_F(minor); if (copy_to_user(argp, &status, sizeof(int))) return -EFAULT; break; @@ -801,31 +805,31 @@ static const struct file_operations lp_fops = { /* The console must be locked when we get here. */ -static void lp_console_write (struct console *co, const char *s, - unsigned count) +static void lp_console_write(struct console *co, const char *s, + unsigned count) { struct pardevice *dev = lp_table[CONSOLE_LP].dev; struct parport *port = dev->port; ssize_t written; - if (parport_claim (dev)) + if (parport_claim(dev)) /* Nothing we can do. */ return; - parport_set_timeout (dev, 0); + parport_set_timeout(dev, 0); /* Go to compatibility mode. */ - parport_negotiate (port, IEEE1284_MODE_COMPAT); + parport_negotiate(port, IEEE1284_MODE_COMPAT); do { /* Write the data, converting LF->CRLF as we go. */ ssize_t canwrite = count; - char *lf = memchr (s, '\n', count); + char *lf = memchr(s, '\n', count); if (lf) canwrite = lf - s; if (canwrite > 0) { - written = parport_write (port, s, canwrite); + written = parport_write(port, s, canwrite); if (written <= 0) continue; @@ -843,14 +847,14 @@ static void lp_console_write (struct console *co, const char *s, s++; count--; do { - written = parport_write (port, crlf, i); + written = parport_write(port, crlf, i); if (written > 0) i -= written, crlf += written; } while (i > 0 && (CONSOLE_LP_STRICT || written > 0)); } } while (count > 0 && (CONSOLE_LP_STRICT || written > 0)); - parport_release (dev); + parport_release(dev); } static struct console lpcons = { @@ -871,7 +875,7 @@ module_param_array(parport, charp, NULL, 0); module_param(reset, bool, 0); #ifndef MODULE -static int __init lp_setup (char *str) +static int __init lp_setup(char *str) { static int parport_ptr; int x; @@ -908,9 +912,13 @@ static int __init lp_setup (char *str) static int lp_register(int nr, struct parport *port) { - lp_table[nr].dev = parport_register_device(port, "lp", - lp_preempt, NULL, NULL, 0, - (void *) &lp_table[nr]); + struct pardev_cb ppdev_cb; + + memset(&ppdev_cb, 0, sizeof(ppdev_cb)); + ppdev_cb.preempt = lp_preempt; + ppdev_cb.private = &lp_table[nr]; + lp_table[nr].dev = parport_register_dev_model(port, "lp", + &ppdev_cb, nr); if (lp_table[nr].dev == NULL) return 1; lp_table[nr].flags |= LP_EXIST; @@ -921,7 +929,7 @@ static int lp_register(int nr, struct parport *port) device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL, "lp%d", nr); - printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, + printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven"); #ifdef CONFIG_LP_CONSOLE @@ -929,17 +937,18 @@ static int lp_register(int nr, struct parport *port) if (port->modes & PARPORT_MODE_SAFEININT) { register_console(&lpcons); console_registered = port; - printk (KERN_INFO "lp%d: console ready\n", CONSOLE_LP); + printk(KERN_INFO "lp%d: console ready\n", CONSOLE_LP); } else - printk (KERN_ERR "lp%d: cannot run console on %s\n", - CONSOLE_LP, port->name); + printk(KERN_ERR "lp%d: cannot run console on %s\n", + CONSOLE_LP, port->name); } #endif + port_num[nr] = port->number; return 0; } -static void lp_attach (struct parport *port) +static void lp_attach(struct parport *port) { unsigned int i; @@ -953,7 +962,11 @@ static void lp_attach (struct parport *port) printk(KERN_INFO "lp: ignoring parallel port (max. %d)\n",LP_NO); return; } - if (!lp_register(lp_count, port)) + for (i = 0; i < LP_NO; i++) + if (port_num[i] == -1) + break; + + if (!lp_register(i, port)) lp_count++; break; @@ -969,8 +982,10 @@ static void lp_attach (struct parport *port) } } -static void lp_detach (struct parport *port) +static void lp_detach(struct parport *port) { + int n; + /* Write this some day. */ #ifdef CONFIG_LP_CONSOLE if (console_registered == port) { @@ -978,15 +993,25 @@ static void lp_detach (struct parport *port) console_registered = NULL; } #endif /* CONFIG_LP_CONSOLE */ + + for (n = 0; n < LP_NO; n++) { + if (port_num[n] == port->number) { + port_num[n] = -1; + lp_count--; + device_destroy(lp_class, MKDEV(LP_MAJOR, n)); + parport_unregister_device(lp_table[n].dev); + } + } } static struct parport_driver lp_driver = { .name = "lp", - .attach = lp_attach, + .match_port = lp_attach, .detach = lp_detach, + .devmodel = true, }; -static int __init lp_init (void) +static int __init lp_init(void) { int i, err = 0; @@ -1003,17 +1028,18 @@ static int __init lp_init (void) #ifdef LP_STATS lp_table[i].lastcall = 0; lp_table[i].runchars = 0; - memset (&lp_table[i].stats, 0, sizeof (struct lp_stats)); + memset(&lp_table[i].stats, 0, sizeof(struct lp_stats)); #endif lp_table[i].last_error = 0; - init_waitqueue_head (&lp_table[i].waitq); - init_waitqueue_head (&lp_table[i].dataq); + init_waitqueue_head(&lp_table[i].waitq); + init_waitqueue_head(&lp_table[i].dataq); mutex_init(&lp_table[i].port_mutex); lp_table[i].timeout = 10 * HZ; + port_num[i] = -1; } - if (register_chrdev (LP_MAJOR, "lp", &lp_fops)) { - printk (KERN_ERR "lp: unable to get major %d\n", LP_MAJOR); + if (register_chrdev(LP_MAJOR, "lp", &lp_fops)) { + printk(KERN_ERR "lp: unable to get major %d\n", LP_MAJOR); return -EIO; } @@ -1023,17 +1049,17 @@ static int __init lp_init (void) goto out_reg; } - if (parport_register_driver (&lp_driver)) { - printk (KERN_ERR "lp: unable to register with parport\n"); + if (parport_register_driver(&lp_driver)) { + printk(KERN_ERR "lp: unable to register with parport\n"); err = -EIO; goto out_class; } if (!lp_count) { - printk (KERN_INFO "lp: driver loaded but no devices found\n"); + printk(KERN_INFO "lp: driver loaded but no devices found\n"); #ifndef CONFIG_PARPORT_1284 if (parport_nr[0] == LP_PARPORT_AUTO) - printk (KERN_INFO "lp: (is IEEE 1284 support enabled?)\n"); + printk(KERN_INFO "lp: (is IEEE 1284 support enabled?)\n"); #endif } @@ -1046,7 +1072,7 @@ out_reg: return err; } -static int __init lp_init_module (void) +static int __init lp_init_module(void) { if (parport[0]) { /* The user gave some parameters. Let's see what they were. */ @@ -1060,7 +1086,7 @@ static int __init lp_init_module (void) else { char *ep; unsigned long r = simple_strtoul(parport[n], &ep, 0); - if (ep != parport[n]) + if (ep != parport[n]) parport_nr[n] = r; else { printk(KERN_ERR "lp: bad port specifier `%s'\n", parport[n]); @@ -1074,23 +1100,15 @@ static int __init lp_init_module (void) return lp_init(); } -static void lp_cleanup_module (void) +static void lp_cleanup_module(void) { - unsigned int offset; - - parport_unregister_driver (&lp_driver); + parport_unregister_driver(&lp_driver); #ifdef CONFIG_LP_CONSOLE - unregister_console (&lpcons); + unregister_console(&lpcons); #endif unregister_chrdev(LP_MAJOR, "lp"); - for (offset = 0; offset < LP_NO; offset++) { - if (lp_table[offset].dev == NULL) - continue; - parport_unregister_device(lp_table[offset].dev); - device_destroy(lp_class, MKDEV(LP_MAJOR, offset)); - } class_destroy(lp_class); } diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 7b4e4de778e4..b08dc50f9f26 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -609,7 +609,7 @@ static ssize_t read_port(struct file *file, char __user *buf, unsigned long i = *ppos; char __user *tmp = buf; - if (!access_ok(VERIFY_WRITE, buf, count)) + if (!access_ok(buf, count)) return -EFAULT; while (count-- > 0 && i < 65536) { if (__put_user(inb(i), tmp) < 0) @@ -627,7 +627,7 @@ static ssize_t write_port(struct file *file, const char __user *buf, unsigned long i = *ppos; const char __user *tmp = buf; - if (!access_ok(VERIFY_READ, buf, count)) + if (!access_ok(buf, count)) return -EFAULT; while (count-- > 0 && i < 65536) { char c; diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index a284ae25e69a..76fb434068d4 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -167,7 +167,7 @@ static ssize_t flash_write(struct file *file, const char __user *buf, if (count > gbFlashSize - p) count = gbFlashSize - p; - if (!access_ok(VERIFY_READ, buf, count)) + if (!access_ok(buf, count)) return -EFAULT; /* diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 809507bf8f1c..7a4eb86aedac 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -1445,11 +1445,11 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) _IOC_DIR(cmd), _IOC_READ, _IOC_WRITE, size, cmd); if (_IOC_DIR(cmd) & _IOC_READ) { - if (!access_ok(VERIFY_WRITE, argp, size)) + if (!access_ok(argp, size)) goto out; } if (_IOC_DIR(cmd) & _IOC_WRITE) { - if (!access_ok(VERIFY_READ, argp, size)) + if (!access_ok(argp, size)) goto out; } rc = 0; diff --git a/drivers/char/random.c b/drivers/char/random.c index 2eb70e76ed35..38c6d1af6d1c 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -265,7 +265,7 @@ #include <linux/syscalls.h> #include <linux/completion.h> #include <linux/uuid.h> -#include <crypto/chacha20.h> +#include <crypto/chacha.h> #include <asm/processor.h> #include <linux/uaccess.h> @@ -431,11 +431,10 @@ static int crng_init = 0; #define crng_ready() (likely(crng_init > 1)) static int crng_init_cnt = 0; static unsigned long crng_global_init_time = 0; -#define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) -static void _extract_crng(struct crng_state *crng, - __u8 out[CHACHA20_BLOCK_SIZE]); +#define CRNG_INIT_CNT_THRESH (2*CHACHA_KEY_SIZE) +static void _extract_crng(struct crng_state *crng, __u8 out[CHACHA_BLOCK_SIZE]); static void _crng_backtrack_protect(struct crng_state *crng, - __u8 tmp[CHACHA20_BLOCK_SIZE], int used); + __u8 tmp[CHACHA_BLOCK_SIZE], int used); static void process_random_ready_list(void); static void _get_random_bytes(void *buf, int nbytes); @@ -863,7 +862,7 @@ static int crng_fast_load(const char *cp, size_t len) } p = (unsigned char *) &primary_crng.state[4]; while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) { - p[crng_init_cnt % CHACHA20_KEY_SIZE] ^= *cp; + p[crng_init_cnt % CHACHA_KEY_SIZE] ^= *cp; cp++; crng_init_cnt++; len--; } spin_unlock_irqrestore(&primary_crng.lock, flags); @@ -895,7 +894,7 @@ static int crng_slow_load(const char *cp, size_t len) unsigned long flags; static unsigned char lfsr = 1; unsigned char tmp; - unsigned i, max = CHACHA20_KEY_SIZE; + unsigned i, max = CHACHA_KEY_SIZE; const char * src_buf = cp; char * dest_buf = (char *) &primary_crng.state[4]; @@ -913,8 +912,8 @@ static int crng_slow_load(const char *cp, size_t len) lfsr >>= 1; if (tmp & 1) lfsr ^= 0xE1; - tmp = dest_buf[i % CHACHA20_KEY_SIZE]; - dest_buf[i % CHACHA20_KEY_SIZE] ^= src_buf[i % len] ^ lfsr; + tmp = dest_buf[i % CHACHA_KEY_SIZE]; + dest_buf[i % CHACHA_KEY_SIZE] ^= src_buf[i % len] ^ lfsr; lfsr += (tmp << 3) | (tmp >> 5); } spin_unlock_irqrestore(&primary_crng.lock, flags); @@ -926,7 +925,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) unsigned long flags; int i, num; union { - __u8 block[CHACHA20_BLOCK_SIZE]; + __u8 block[CHACHA_BLOCK_SIZE]; __u32 key[8]; } buf; @@ -937,7 +936,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) } else { _extract_crng(&primary_crng, buf.block); _crng_backtrack_protect(&primary_crng, buf.block, - CHACHA20_KEY_SIZE); + CHACHA_KEY_SIZE); } spin_lock_irqsave(&crng->lock, flags); for (i = 0; i < 8; i++) { @@ -973,7 +972,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) } static void _extract_crng(struct crng_state *crng, - __u8 out[CHACHA20_BLOCK_SIZE]) + __u8 out[CHACHA_BLOCK_SIZE]) { unsigned long v, flags; @@ -990,7 +989,7 @@ static void _extract_crng(struct crng_state *crng, spin_unlock_irqrestore(&crng->lock, flags); } -static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]) +static void extract_crng(__u8 out[CHACHA_BLOCK_SIZE]) { struct crng_state *crng = NULL; @@ -1008,14 +1007,14 @@ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]) * enough) to mutate the CRNG key to provide backtracking protection. */ static void _crng_backtrack_protect(struct crng_state *crng, - __u8 tmp[CHACHA20_BLOCK_SIZE], int used) + __u8 tmp[CHACHA_BLOCK_SIZE], int used) { unsigned long flags; __u32 *s, *d; int i; used = round_up(used, sizeof(__u32)); - if (used + CHACHA20_KEY_SIZE > CHACHA20_BLOCK_SIZE) { + if (used + CHACHA_KEY_SIZE > CHACHA_BLOCK_SIZE) { extract_crng(tmp); used = 0; } @@ -1027,7 +1026,7 @@ static void _crng_backtrack_protect(struct crng_state *crng, spin_unlock_irqrestore(&crng->lock, flags); } -static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used) +static void crng_backtrack_protect(__u8 tmp[CHACHA_BLOCK_SIZE], int used) { struct crng_state *crng = NULL; @@ -1042,8 +1041,8 @@ static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used) static ssize_t extract_crng_user(void __user *buf, size_t nbytes) { - ssize_t ret = 0, i = CHACHA20_BLOCK_SIZE; - __u8 tmp[CHACHA20_BLOCK_SIZE] __aligned(4); + ssize_t ret = 0, i = CHACHA_BLOCK_SIZE; + __u8 tmp[CHACHA_BLOCK_SIZE] __aligned(4); int large_request = (nbytes > 256); while (nbytes) { @@ -1057,7 +1056,7 @@ static ssize_t extract_crng_user(void __user *buf, size_t nbytes) } extract_crng(tmp); - i = min_t(int, nbytes, CHACHA20_BLOCK_SIZE); + i = min_t(int, nbytes, CHACHA_BLOCK_SIZE); if (copy_to_user(buf, tmp, i)) { ret = -EFAULT; break; @@ -1622,14 +1621,14 @@ static void _warn_unseeded_randomness(const char *func_name, void *caller, */ static void _get_random_bytes(void *buf, int nbytes) { - __u8 tmp[CHACHA20_BLOCK_SIZE] __aligned(4); + __u8 tmp[CHACHA_BLOCK_SIZE] __aligned(4); trace_get_random_bytes(nbytes, _RET_IP_); - while (nbytes >= CHACHA20_BLOCK_SIZE) { + while (nbytes >= CHACHA_BLOCK_SIZE) { extract_crng(buf); - buf += CHACHA20_BLOCK_SIZE; - nbytes -= CHACHA20_BLOCK_SIZE; + buf += CHACHA_BLOCK_SIZE; + nbytes -= CHACHA_BLOCK_SIZE; } if (nbytes > 0) { @@ -1637,7 +1636,7 @@ static void _get_random_bytes(void *buf, int nbytes) memcpy(buf, tmp, nbytes); crng_backtrack_protect(tmp, nbytes); } else - crng_backtrack_protect(tmp, CHACHA20_BLOCK_SIZE); + crng_backtrack_protect(tmp, CHACHA_BLOCK_SIZE); memzero_explicit(tmp, sizeof(tmp)); } @@ -2208,8 +2207,8 @@ struct ctl_table random_table[] = { struct batched_entropy { union { - u64 entropy_u64[CHACHA20_BLOCK_SIZE / sizeof(u64)]; - u32 entropy_u32[CHACHA20_BLOCK_SIZE / sizeof(u32)]; + u64 entropy_u64[CHACHA_BLOCK_SIZE / sizeof(u64)]; + u32 entropy_u32[CHACHA_BLOCK_SIZE / sizeof(u32)]; }; unsigned int position; }; diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 4948c8bda6b1..c862d0b6b118 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -866,8 +866,8 @@ static int __init rtc_init(void) #ifdef CONFIG_SPARC32 for_each_node_by_name(ebus_dp, "ebus") { struct device_node *dp; - for (dp = ebus_dp; dp; dp = dp->sibling) { - if (!strcmp(dp->name, "rtc")) { + for_each_child_of_node(ebus_dp, dp) { + if (of_node_name_eq(dp, "rtc")) { op = of_find_device_by_node(dp); if (op) { rtc_port = op->resource[0].start; @@ -1125,11 +1125,10 @@ static int rtc_proc_show(struct seq_file *seq, void *v) * time or for Universal Standard Time (GMT). Probably local though. */ seq_printf(seq, - "rtc_time\t: %02d:%02d:%02d\n" - "rtc_date\t: %04d-%02d-%02d\n" + "rtc_time\t: %ptRt\n" + "rtc_date\t: %ptRd\n" "rtc_epoch\t: %04lu\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch); + &tm, &tm, epoch); get_rtc_alm_time(&tm); diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 8eeb4190207d..6d81bb3bb503 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c @@ -506,28 +506,28 @@ static ssize_t store_select_amcb2_transmit_clock(struct device *d, val = (unsigned char)tmp; spin_lock_irqsave(&event_lock, flags); - if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) { - SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x28); - SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val); - } else if (val >= CLK_8_592MHz) { - SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38); - switch (val) { - case CLK_8_592MHz: - SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); - break; - case CLK_11_184MHz: - SET_PORT_BITS(TLCLK_REG0, 0xfc, 0); - break; - case CLK_34_368MHz: - SET_PORT_BITS(TLCLK_REG0, 0xfc, 3); - break; - case CLK_44_736MHz: - SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); - break; - } - } else - SET_PORT_BITS(TLCLK_REG3, 0xc7, val << 3); - + if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) { + SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x28); + SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val); + } else if (val >= CLK_8_592MHz) { + SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38); + switch (val) { + case CLK_8_592MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); + break; + case CLK_11_184MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 0); + break; + case CLK_34_368MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 3); + break; + case CLK_44_736MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); + break; + } + } else { + SET_PORT_BITS(TLCLK_REG3, 0xc7, val << 3); + } spin_unlock_irqrestore(&event_lock, flags); return strnlen(buf, count); @@ -548,27 +548,28 @@ static ssize_t store_select_amcb1_transmit_clock(struct device *d, val = (unsigned char)tmp; spin_lock_irqsave(&event_lock, flags); - if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) { - SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x5); - SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val); - } else if (val >= CLK_8_592MHz) { - SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7); - switch (val) { - case CLK_8_592MHz: - SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); - break; - case CLK_11_184MHz: - SET_PORT_BITS(TLCLK_REG0, 0xfc, 0); - break; - case CLK_34_368MHz: - SET_PORT_BITS(TLCLK_REG0, 0xfc, 3); - break; - case CLK_44_736MHz: - SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); - break; - } - } else - SET_PORT_BITS(TLCLK_REG3, 0xf8, val); + if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) { + SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x5); + SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val); + } else if (val >= CLK_8_592MHz) { + SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7); + switch (val) { + case CLK_8_592MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); + break; + case CLK_11_184MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 0); + break; + case CLK_34_368MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 3); + break; + case CLK_44_736MHz: + SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); + break; + } + } else { + SET_PORT_BITS(TLCLK_REG3, 0xf8, val); + } spin_unlock_irqrestore(&event_lock, flags); return strnlen(buf, count); diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 4e9c33ca1f8f..a01c4cab902a 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -3,9 +3,19 @@ # Makefile for the kernel tpm device drivers. # obj-$(CONFIG_TCG_TPM) += tpm.o -tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \ - tpm-dev-common.o tpmrm-dev.o eventlog/common.o eventlog/tpm1.o \ - eventlog/tpm2.o tpm2-space.o +tpm-y := tpm-chip.o +tpm-y += tpm-dev-common.o +tpm-y += tpm-dev.o +tpm-y += tpm-interface.o +tpm-y += tpm1-cmd.o +tpm-y += tpm2-cmd.o +tpm-y += tpmrm-dev.o +tpm-y += tpm2-space.o +tpm-y += tpm-sysfs.o +tpm-y += eventlog/common.o +tpm-y += eventlog/tpm1.o +tpm-y += eventlog/tpm2.o + tpm-$(CONFIG_ACPI) += tpm_ppi.o eventlog/acpi.o tpm-$(CONFIG_EFI) += eventlog/efi.o tpm-$(CONFIG_OF) += eventlog/of.o diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c index abd675bec88c..64dc560859f2 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.c +++ b/drivers/char/tpm/st33zp24/st33zp24.c @@ -649,7 +649,7 @@ int st33zp24_pm_resume(struct device *dev) } else { ret = tpm_pm_resume(dev); if (!ret) - tpm_do_selftest(chip); + tpm1_do_selftest(chip); } return ret; } /* st33zp24_pm_resume() */ diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 46caadca916a..32db84683c40 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -451,14 +451,9 @@ int tpm_chip_register(struct tpm_chip *chip) { int rc; - if (chip->ops->flags & TPM_OPS_AUTO_STARTUP) { - if (chip->flags & TPM_CHIP_FLAG_TPM2) - rc = tpm2_auto_startup(chip); - else - rc = tpm1_auto_startup(chip); - if (rc) - return rc; - } + rc = tpm_auto_startup(chip); + if (rc) + return rc; tpm_sysfs_add_device(chip); diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index 99b5133a9d05..5eecad233ea1 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c @@ -40,7 +40,7 @@ static void tpm_async_work(struct work_struct *work) tpm_put_ops(priv->chip); if (ret > 0) { - priv->data_pending = ret; + priv->response_length = ret; mod_timer(&priv->user_read_timer, jiffies + (120 * HZ)); } mutex_unlock(&priv->buffer_mutex); @@ -63,7 +63,8 @@ static void tpm_timeout_work(struct work_struct *work) timeout_work); mutex_lock(&priv->buffer_mutex); - priv->data_pending = 0; + priv->response_read = true; + priv->response_length = 0; memset(priv->data_buffer, 0, sizeof(priv->data_buffer)); mutex_unlock(&priv->buffer_mutex); wake_up_interruptible(&priv->async_wait); @@ -74,6 +75,7 @@ void tpm_common_open(struct file *file, struct tpm_chip *chip, { priv->chip = chip; priv->space = space; + priv->response_read = true; mutex_init(&priv->buffer_mutex); timer_setup(&priv->user_read_timer, user_reader_timeout, 0); @@ -90,22 +92,35 @@ ssize_t tpm_common_read(struct file *file, char __user *buf, ssize_t ret_size = 0; int rc; - del_singleshot_timer_sync(&priv->user_read_timer); - flush_work(&priv->timeout_work); mutex_lock(&priv->buffer_mutex); - if (priv->data_pending) { - ret_size = min_t(ssize_t, size, priv->data_pending); - if (ret_size > 0) { - rc = copy_to_user(buf, priv->data_buffer, ret_size); - memset(priv->data_buffer, 0, priv->data_pending); - if (rc) - ret_size = -EFAULT; + if (priv->response_length) { + priv->response_read = true; + + ret_size = min_t(ssize_t, size, priv->response_length); + if (!ret_size) { + priv->response_length = 0; + goto out; } - priv->data_pending = 0; + rc = copy_to_user(buf, priv->data_buffer + *off, ret_size); + if (rc) { + memset(priv->data_buffer, 0, TPM_BUFSIZE); + priv->response_length = 0; + ret_size = -EFAULT; + } else { + memset(priv->data_buffer + *off, 0, ret_size); + priv->response_length -= ret_size; + *off += ret_size; + } } +out: + if (!priv->response_length) { + *off = 0; + del_singleshot_timer_sync(&priv->user_read_timer); + flush_work(&priv->timeout_work); + } mutex_unlock(&priv->buffer_mutex); return ret_size; } @@ -125,7 +140,8 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, * tpm_read or a user_read_timer timeout. This also prevents split * buffered writes from blocking here. */ - if (priv->data_pending != 0 || priv->command_enqueued) { + if ((!priv->response_read && priv->response_length) || + priv->command_enqueued) { ret = -EBUSY; goto out; } @@ -150,6 +166,10 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, goto out; } + priv->response_length = 0; + priv->response_read = false; + *off = 0; + /* * If in nonblocking mode schedule an async job to send * the command return the size. @@ -168,7 +188,7 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, tpm_put_ops(priv->chip); if (ret > 0) { - priv->data_pending = ret; + priv->response_length = ret; mod_timer(&priv->user_read_timer, jiffies + (120 * HZ)); ret = size; } @@ -184,7 +204,7 @@ __poll_t tpm_common_poll(struct file *file, poll_table *wait) poll_wait(file, &priv->async_wait, wait); - if (priv->data_pending) + if (!priv->response_read || priv->response_length) mask = EPOLLIN | EPOLLRDNORM; else mask = EPOLLOUT | EPOLLWRNORM; @@ -201,7 +221,7 @@ void tpm_common_release(struct file *file, struct file_priv *priv) del_singleshot_timer_sync(&priv->user_read_timer); flush_work(&priv->timeout_work); file->private_data = NULL; - priv->data_pending = 0; + priv->response_length = 0; } int __init tpm_dev_common_init(void) diff --git a/drivers/char/tpm/tpm-dev.h b/drivers/char/tpm/tpm-dev.h index a126b575cb8c..1089fc0bb290 100644 --- a/drivers/char/tpm/tpm-dev.h +++ b/drivers/char/tpm/tpm-dev.h @@ -9,14 +9,13 @@ struct file_priv { struct tpm_chip *chip; struct tpm_space *space; - /* Holds the amount of data passed or an error code from async op */ - ssize_t data_pending; struct mutex buffer_mutex; - struct timer_list user_read_timer; /* user needs to claim result */ struct work_struct timeout_work; struct work_struct async_work; wait_queue_head_t async_wait; + size_t response_length; + bool response_read; bool command_enqueued; u8 data_buffer[TPM_BUFSIZE]; diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 129f640424b7..d9439f9abe78 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -33,297 +33,32 @@ #include "tpm.h" -#define TPM_MAX_ORDINAL 243 -#define TSC_MAX_ORDINAL 12 -#define TPM_PROTECTED_COMMAND 0x00 -#define TPM_CONNECTION_COMMAND 0x40 - /* * Bug workaround - some TPM's don't flush the most * recently changed pcr on suspend, so force the flush * with an extend to the selected _unused_ non-volatile pcr. */ -static int tpm_suspend_pcr; +static u32 tpm_suspend_pcr; module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644); MODULE_PARM_DESC(suspend_pcr, "PCR to use for dummy writes to facilitate flush on suspend."); -/* - * Array with one entry per ordinal defining the maximum amount - * of time the chip could take to return the result. The ordinal - * designation of short, medium or long is defined in a table in - * TCG Specification TPM Main Part 2 TPM Structures Section 17. The - * values of the SHORT, MEDIUM, and LONG durations are retrieved - * from the chip during initialization with a call to tpm_get_timeouts. - */ -static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { - TPM_UNDEFINED, /* 0 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 5 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 10 */ - TPM_SHORT, - TPM_MEDIUM, - TPM_LONG, - TPM_LONG, - TPM_MEDIUM, /* 15 */ - TPM_SHORT, - TPM_SHORT, - TPM_MEDIUM, - TPM_LONG, - TPM_SHORT, /* 20 */ - TPM_SHORT, - TPM_MEDIUM, - TPM_MEDIUM, - TPM_MEDIUM, - TPM_SHORT, /* 25 */ - TPM_SHORT, - TPM_MEDIUM, - TPM_SHORT, - TPM_SHORT, - TPM_MEDIUM, /* 30 */ - TPM_LONG, - TPM_MEDIUM, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, /* 35 */ - TPM_MEDIUM, - TPM_MEDIUM, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_MEDIUM, /* 40 */ - TPM_LONG, - TPM_MEDIUM, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, /* 45 */ - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_LONG, - TPM_MEDIUM, /* 50 */ - TPM_MEDIUM, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 55 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_MEDIUM, /* 60 */ - TPM_MEDIUM, - TPM_MEDIUM, - TPM_SHORT, - TPM_SHORT, - TPM_MEDIUM, /* 65 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 70 */ - TPM_SHORT, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 75 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_LONG, /* 80 */ - TPM_UNDEFINED, - TPM_MEDIUM, - TPM_LONG, - TPM_SHORT, - TPM_UNDEFINED, /* 85 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 90 */ - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_UNDEFINED, /* 95 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_MEDIUM, /* 100 */ - TPM_SHORT, - TPM_SHORT, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 105 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 110 */ - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, /* 115 */ - TPM_SHORT, - TPM_SHORT, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_LONG, /* 120 */ - TPM_LONG, - TPM_MEDIUM, - TPM_UNDEFINED, - TPM_SHORT, - TPM_SHORT, /* 125 */ - TPM_SHORT, - TPM_LONG, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, /* 130 */ - TPM_MEDIUM, - TPM_UNDEFINED, - TPM_SHORT, - TPM_MEDIUM, - TPM_UNDEFINED, /* 135 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 140 */ - TPM_SHORT, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 145 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 150 */ - TPM_MEDIUM, - TPM_MEDIUM, - TPM_SHORT, - TPM_SHORT, - TPM_UNDEFINED, /* 155 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 160 */ - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 165 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_LONG, /* 170 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 175 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_MEDIUM, /* 180 */ - TPM_SHORT, - TPM_MEDIUM, - TPM_MEDIUM, - TPM_MEDIUM, - TPM_MEDIUM, /* 185 */ - TPM_SHORT, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 190 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 195 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 200 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, - TPM_SHORT, /* 205 */ - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_MEDIUM, /* 210 */ - TPM_UNDEFINED, - TPM_MEDIUM, - TPM_MEDIUM, - TPM_MEDIUM, - TPM_UNDEFINED, /* 215 */ - TPM_MEDIUM, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, - TPM_SHORT, /* 220 */ - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_UNDEFINED, /* 225 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 230 */ - TPM_LONG, - TPM_MEDIUM, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 235 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 240 */ - TPM_UNDEFINED, - TPM_MEDIUM, -}; - -/* - * Returns max number of jiffies to wait +/** + * tpm_calc_ordinal_duration() - calculate the maximum command duration + * @chip: TPM chip to use. + * @ordinal: TPM command ordinal. + * + * The function returns the maximum amount of time the chip could take + * to return the result for a particular ordinal in jiffies. + * + * Return: A maximal duration time for an ordinal in jiffies. */ -unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, - u32 ordinal) +unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) { - int duration_idx = TPM_UNDEFINED; - int duration = 0; - - /* - * We only have a duration table for protected commands, where the upper - * 16 bits are 0. For the few other ordinals the fallback will be used. - */ - if (ordinal < TPM_MAX_ORDINAL) - duration_idx = tpm_ordinal_duration[ordinal]; - - if (duration_idx != TPM_UNDEFINED) - duration = chip->duration[duration_idx]; - if (duration <= 0) - return 2 * 60 * HZ; + if (chip->flags & TPM_CHIP_FLAG_TPM2) + return tpm2_calc_ordinal_duration(chip, ordinal); else - return duration; + return tpm1_calc_ordinal_duration(chip, ordinal); } EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); @@ -477,13 +212,15 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, if (need_locality) { rc = tpm_request_locality(chip, flags); - if (rc < 0) - goto out_no_locality; + if (rc < 0) { + need_locality = false; + goto out_locality; + } } rc = tpm_cmd_ready(chip, flags); if (rc) - goto out; + goto out_locality; rc = tpm2_prepare_space(chip, space, ordinal, buf); if (rc) @@ -500,10 +237,7 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, if (chip->flags & TPM_CHIP_FLAG_IRQ) goto out_recv; - if (chip->flags & TPM_CHIP_FLAG_TPM2) - stop = jiffies + tpm2_calc_ordinal_duration(chip, ordinal); - else - stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); + stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); do { u8 status = chip->ops->status(chip); if ((status & chip->ops->req_complete_mask) == @@ -547,14 +281,13 @@ out_recv: dev_err(&chip->dev, "tpm2_commit_space: error %d\n", rc); out: - rc = tpm_go_idle(chip, flags); - if (rc) - goto out; + /* may fail but do not override previous error value in rc */ + tpm_go_idle(chip, flags); +out_locality: if (need_locality) tpm_relinquish_locality(chip, flags); -out_no_locality: if (chip->ops->clk_enable != NULL) chip->ops->clk_enable(chip, false); @@ -677,277 +410,18 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, } EXPORT_SYMBOL_GPL(tpm_transmit_cmd); -#define TPM_ORD_STARTUP 153 -#define TPM_ST_CLEAR 1 - -/** - * tpm_startup - turn on the TPM - * @chip: TPM chip to use - * - * Normally the firmware should start the TPM. This function is provided as a - * workaround if this does not happen. A legal case for this could be for - * example when a TPM emulator is used. - * - * Return: same as tpm_transmit_cmd() - */ -int tpm_startup(struct tpm_chip *chip) -{ - struct tpm_buf buf; - int rc; - - dev_info(&chip->dev, "starting up the TPM manually\n"); - - if (chip->flags & TPM_CHIP_FLAG_TPM2) { - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP); - if (rc < 0) - return rc; - - tpm_buf_append_u16(&buf, TPM2_SU_CLEAR); - } else { - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP); - if (rc < 0) - return rc; - - tpm_buf_append_u16(&buf, TPM_ST_CLEAR); - } - - rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, - "attempting to start the TPM"); - - tpm_buf_destroy(&buf); - return rc; -} - -#define TPM_DIGEST_SIZE 20 -#define TPM_RET_CODE_IDX 6 -#define TPM_INTERNAL_RESULT_SIZE 200 -#define TPM_ORD_GET_CAP 101 -#define TPM_ORD_GET_RANDOM 70 - -static const struct tpm_input_header tpm_getcap_header = { - .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), - .length = cpu_to_be32(22), - .ordinal = cpu_to_be32(TPM_ORD_GET_CAP) -}; - -ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, - const char *desc, size_t min_cap_length) -{ - struct tpm_buf buf; - int rc; - - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP); - if (rc) - return rc; - - if (subcap_id == TPM_CAP_VERSION_1_1 || - subcap_id == TPM_CAP_VERSION_1_2) { - tpm_buf_append_u32(&buf, subcap_id); - tpm_buf_append_u32(&buf, 0); - } else { - if (subcap_id == TPM_CAP_FLAG_PERM || - subcap_id == TPM_CAP_FLAG_VOL) - tpm_buf_append_u32(&buf, TPM_CAP_FLAG); - else - tpm_buf_append_u32(&buf, TPM_CAP_PROP); - - tpm_buf_append_u32(&buf, 4); - tpm_buf_append_u32(&buf, subcap_id); - } - rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, - min_cap_length, 0, desc); - if (!rc) - *cap = *(cap_t *)&buf.data[TPM_HEADER_SIZE + 4]; - - tpm_buf_destroy(&buf); - return rc; -} -EXPORT_SYMBOL_GPL(tpm_getcap); - int tpm_get_timeouts(struct tpm_chip *chip) { - cap_t cap; - unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4]; - ssize_t rc; - if (chip->flags & TPM_CHIP_FLAG_HAVE_TIMEOUTS) return 0; - if (chip->flags & TPM_CHIP_FLAG_TPM2) { - /* Fixed timeouts for TPM2 */ - chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A); - chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B); - chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C); - chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D); - chip->duration[TPM_SHORT] = - msecs_to_jiffies(TPM2_DURATION_SHORT); - chip->duration[TPM_MEDIUM] = - msecs_to_jiffies(TPM2_DURATION_MEDIUM); - chip->duration[TPM_LONG] = - msecs_to_jiffies(TPM2_DURATION_LONG); - chip->duration[TPM_LONG_LONG] = - msecs_to_jiffies(TPM2_DURATION_LONG_LONG); - - chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; - return 0; - } - - rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL, - sizeof(cap.timeout)); - if (rc == TPM_ERR_INVALID_POSTINIT) { - if (tpm_startup(chip)) - return rc; - - rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, - "attempting to determine the timeouts", - sizeof(cap.timeout)); - } - - if (rc) { - dev_err(&chip->dev, - "A TPM error (%zd) occurred attempting to determine the timeouts\n", - rc); - return rc; - } - - timeout_old[0] = jiffies_to_usecs(chip->timeout_a); - timeout_old[1] = jiffies_to_usecs(chip->timeout_b); - timeout_old[2] = jiffies_to_usecs(chip->timeout_c); - timeout_old[3] = jiffies_to_usecs(chip->timeout_d); - timeout_chip[0] = be32_to_cpu(cap.timeout.a); - timeout_chip[1] = be32_to_cpu(cap.timeout.b); - timeout_chip[2] = be32_to_cpu(cap.timeout.c); - timeout_chip[3] = be32_to_cpu(cap.timeout.d); - memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff)); - - /* - * Provide ability for vendor overrides of timeout values in case - * of misreporting. - */ - if (chip->ops->update_timeouts != NULL) - chip->timeout_adjusted = - chip->ops->update_timeouts(chip, timeout_eff); - - if (!chip->timeout_adjusted) { - /* Restore default if chip reported 0 */ - int i; - - for (i = 0; i < ARRAY_SIZE(timeout_eff); i++) { - if (timeout_eff[i]) - continue; - - timeout_eff[i] = timeout_old[i]; - chip->timeout_adjusted = true; - } - - if (timeout_eff[0] != 0 && timeout_eff[0] < 1000) { - /* timeouts in msec rather usec */ - for (i = 0; i != ARRAY_SIZE(timeout_eff); i++) - timeout_eff[i] *= 1000; - chip->timeout_adjusted = true; - } - } - - /* Report adjusted timeouts */ - if (chip->timeout_adjusted) { - dev_info(&chip->dev, - HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n", - timeout_chip[0], timeout_eff[0], - timeout_chip[1], timeout_eff[1], - timeout_chip[2], timeout_eff[2], - timeout_chip[3], timeout_eff[3]); - } - - chip->timeout_a = usecs_to_jiffies(timeout_eff[0]); - chip->timeout_b = usecs_to_jiffies(timeout_eff[1]); - chip->timeout_c = usecs_to_jiffies(timeout_eff[2]); - chip->timeout_d = usecs_to_jiffies(timeout_eff[3]); - - rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_DURATION, &cap, - "attempting to determine the durations", - sizeof(cap.duration)); - if (rc) - return rc; - - chip->duration[TPM_SHORT] = - usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_short)); - chip->duration[TPM_MEDIUM] = - usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_medium)); - chip->duration[TPM_LONG] = - usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_long)); - chip->duration[TPM_LONG_LONG] = 0; /* not used under 1.2 */ - - /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above - * value wrong and apparently reports msecs rather than usecs. So we - * fix up the resulting too-small TPM_SHORT value to make things work. - * We also scale the TPM_MEDIUM and -_LONG values by 1000. - */ - if (chip->duration[TPM_SHORT] < (HZ / 100)) { - chip->duration[TPM_SHORT] = HZ; - chip->duration[TPM_MEDIUM] *= 1000; - chip->duration[TPM_LONG] *= 1000; - chip->duration_adjusted = true; - dev_info(&chip->dev, "Adjusting TPM timeout parameters."); - } - - chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; - return 0; + if (chip->flags & TPM_CHIP_FLAG_TPM2) + return tpm2_get_timeouts(chip); + else + return tpm1_get_timeouts(chip); } EXPORT_SYMBOL_GPL(tpm_get_timeouts); -#define TPM_ORD_CONTINUE_SELFTEST 83 -#define CONTINUE_SELFTEST_RESULT_SIZE 10 - -static const struct tpm_input_header continue_selftest_header = { - .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), - .length = cpu_to_be32(10), - .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST), -}; - -/** - * tpm_continue_selftest -- run TPM's selftest - * @chip: TPM chip to use - * - * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing - * a TPM error code. - */ -static int tpm_continue_selftest(struct tpm_chip *chip) -{ - int rc; - struct tpm_cmd_t cmd; - - cmd.header.in = continue_selftest_header; - rc = tpm_transmit_cmd(chip, NULL, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, - 0, 0, "continue selftest"); - return rc; -} - -#define TPM_ORDINAL_PCRREAD 21 -#define READ_PCR_RESULT_SIZE 30 -#define READ_PCR_RESULT_BODY_SIZE 20 -static const struct tpm_input_header pcrread_header = { - .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), - .length = cpu_to_be32(14), - .ordinal = cpu_to_be32(TPM_ORDINAL_PCRREAD) -}; - -int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) -{ - int rc; - struct tpm_cmd_t cmd; - - cmd.header.in = pcrread_header; - cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); - rc = tpm_transmit_cmd(chip, NULL, &cmd, READ_PCR_RESULT_SIZE, - READ_PCR_RESULT_BODY_SIZE, 0, - "attempting to read a pcr value"); - - if (rc == 0) - memcpy(res_buf, cmd.params.pcrread_out.pcr_result, - TPM_DIGEST_SIZE); - return rc; -} - /** * tpm_is_tpm2 - do we a have a TPM2 chip? * @chip: a &struct tpm_chip instance, %NULL for the default chip @@ -981,50 +455,24 @@ EXPORT_SYMBOL_GPL(tpm_is_tpm2); * * Return: same as with tpm_transmit_cmd() */ -int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) +int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) { int rc; chip = tpm_find_get_ops(chip); if (!chip) return -ENODEV; + if (chip->flags & TPM_CHIP_FLAG_TPM2) rc = tpm2_pcr_read(chip, pcr_idx, res_buf); else - rc = tpm_pcr_read_dev(chip, pcr_idx, res_buf); + rc = tpm1_pcr_read(chip, pcr_idx, res_buf); + tpm_put_ops(chip); return rc; } EXPORT_SYMBOL_GPL(tpm_pcr_read); -#define TPM_ORD_PCR_EXTEND 20 -#define EXTEND_PCR_RESULT_SIZE 34 -#define EXTEND_PCR_RESULT_BODY_SIZE 20 -static const struct tpm_input_header pcrextend_header = { - .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), - .length = cpu_to_be32(34), - .ordinal = cpu_to_be32(TPM_ORD_PCR_EXTEND) -}; - -static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash, - char *log_msg) -{ - struct tpm_buf buf; - int rc; - - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND); - if (rc) - return rc; - - tpm_buf_append_u32(&buf, pcr_idx); - tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE); - - rc = tpm_transmit_cmd(chip, NULL, buf.data, EXTEND_PCR_RESULT_SIZE, - EXTEND_PCR_RESULT_BODY_SIZE, 0, log_msg); - tpm_buf_destroy(&buf); - return rc; -} - /** * tpm_pcr_extend - extend a PCR value in SHA1 bank. * @chip: a &struct tpm_chip instance, %NULL for the default chip @@ -1037,7 +485,7 @@ static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash, * * Return: same as with tpm_transmit_cmd() */ -int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash) +int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash) { int rc; struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)]; @@ -1071,97 +519,6 @@ int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash) EXPORT_SYMBOL_GPL(tpm_pcr_extend); /** - * tpm_do_selftest - have the TPM continue its selftest and wait until it - * can receive further commands - * @chip: TPM chip to use - * - * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing - * a TPM error code. - */ -int tpm_do_selftest(struct tpm_chip *chip) -{ - int rc; - unsigned int loops; - unsigned int delay_msec = 100; - unsigned long duration; - u8 dummy[TPM_DIGEST_SIZE]; - - duration = tpm_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST); - - loops = jiffies_to_msecs(duration) / delay_msec; - - rc = tpm_continue_selftest(chip); - if (rc == TPM_ERR_INVALID_POSTINIT) { - chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; - dev_info(&chip->dev, "TPM not ready (%d)\n", rc); - } - /* This may fail if there was no TPM driver during a suspend/resume - * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) - */ - if (rc) - return rc; - - do { - /* Attempt to read a PCR value */ - rc = tpm_pcr_read_dev(chip, 0, dummy); - - /* Some buggy TPMs will not respond to tpm_tis_ready() for - * around 300ms while the self test is ongoing, keep trying - * until the self test duration expires. */ - if (rc == -ETIME) { - dev_info( - &chip->dev, HW_ERR - "TPM command timed out during continue self test"); - tpm_msleep(delay_msec); - continue; - } - - if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { - dev_info(&chip->dev, - "TPM is disabled/deactivated (0x%X)\n", rc); - /* TPM is disabled and/or deactivated; driver can - * proceed and TPM does handle commands for - * suspend/resume correctly - */ - return 0; - } - if (rc != TPM_WARN_DOING_SELFTEST) - return rc; - tpm_msleep(delay_msec); - } while (--loops > 0); - - return rc; -} -EXPORT_SYMBOL_GPL(tpm_do_selftest); - -/** - * tpm1_auto_startup - Perform the standard automatic TPM initialization - * sequence - * @chip: TPM chip to use - * - * Returns 0 on success, < 0 in case of fatal error. - */ -int tpm1_auto_startup(struct tpm_chip *chip) -{ - int rc; - - rc = tpm_get_timeouts(chip); - if (rc) - goto out; - rc = tpm_do_selftest(chip); - if (rc) { - dev_err(&chip->dev, "TPM self test failed\n"); - goto out; - } - - return rc; -out: - if (rc > 0) - rc = -ENODEV; - return rc; -} - -/** * tpm_send - send a TPM command * @chip: a &struct tpm_chip instance, %NULL for the default chip * @cmd: a TPM command buffer @@ -1184,14 +541,20 @@ int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen) } EXPORT_SYMBOL_GPL(tpm_send); -#define TPM_ORD_SAVESTATE 152 -#define SAVESTATE_RESULT_SIZE 10 +int tpm_auto_startup(struct tpm_chip *chip) +{ + int rc; -static const struct tpm_input_header savestate_header = { - .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), - .length = cpu_to_be32(10), - .ordinal = cpu_to_be32(TPM_ORD_SAVESTATE) -}; + if (!(chip->ops->flags & TPM_OPS_AUTO_STARTUP)) + return 0; + + if (chip->flags & TPM_CHIP_FLAG_TPM2) + rc = tpm2_auto_startup(chip); + else + rc = tpm1_auto_startup(chip); + + return rc; +} /* * We are about to suspend. Save the TPM state @@ -1200,54 +563,18 @@ static const struct tpm_input_header savestate_header = { int tpm_pm_suspend(struct device *dev) { struct tpm_chip *chip = dev_get_drvdata(dev); - struct tpm_cmd_t cmd; - int rc, try; + int rc = 0; - u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; - - if (chip == NULL) + if (!chip) return -ENODEV; if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED) return 0; - if (chip->flags & TPM_CHIP_FLAG_TPM2) { + if (chip->flags & TPM_CHIP_FLAG_TPM2) tpm2_shutdown(chip, TPM2_SU_STATE); - return 0; - } - - /* for buggy tpm, flush pcrs with extend to selected dummy */ - if (tpm_suspend_pcr) - rc = tpm1_pcr_extend(chip, tpm_suspend_pcr, dummy_hash, - "extending dummy pcr before suspend"); - - /* now do the actual savestate */ - for (try = 0; try < TPM_RETRY; try++) { - cmd.header.in = savestate_header; - rc = tpm_transmit_cmd(chip, NULL, &cmd, SAVESTATE_RESULT_SIZE, - 0, 0, NULL); - - /* - * If the TPM indicates that it is too busy to respond to - * this command then retry before giving up. It can take - * several seconds for this TPM to be ready. - * - * This can happen if the TPM has already been sent the - * SaveState command before the driver has loaded. TCG 1.2 - * specification states that any communication after SaveState - * may cause the TPM to invalidate previously saved state. - */ - if (rc != TPM_WARN_RETRY) - break; - tpm_msleep(TPM_TIMEOUT_RETRY); - } - - if (rc) - dev_err(&chip->dev, - "Error (%d) sending savestate before suspend\n", rc); - else if (try > 0) - dev_warn(&chip->dev, "TPM savestate took %dms\n", - try * TPM_TIMEOUT_RETRY); + else + rc = tpm1_pm_suspend(chip, tpm_suspend_pcr); return rc; } @@ -1268,75 +595,32 @@ int tpm_pm_resume(struct device *dev) } EXPORT_SYMBOL_GPL(tpm_pm_resume); -#define TPM_GETRANDOM_RESULT_SIZE 18 -static const struct tpm_input_header tpm_getrandom_header = { - .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), - .length = cpu_to_be32(14), - .ordinal = cpu_to_be32(TPM_ORD_GET_RANDOM) -}; - /** * tpm_get_random() - get random bytes from the TPM's RNG * @chip: a &struct tpm_chip instance, %NULL for the default chip * @out: destination buffer for the random bytes * @max: the max number of bytes to write to @out * - * Return: same as with tpm_transmit_cmd() + * Return: number of random bytes read or a negative error value. */ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max) { - struct tpm_cmd_t tpm_cmd; - u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA), rlength; - int err, total = 0, retries = 5; - u8 *dest = out; + int rc; - if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) + if (!out || max > TPM_MAX_RNG_DATA) return -EINVAL; chip = tpm_find_get_ops(chip); if (!chip) return -ENODEV; - if (chip->flags & TPM_CHIP_FLAG_TPM2) { - err = tpm2_get_random(chip, out, max); - tpm_put_ops(chip); - return err; - } - - do { - tpm_cmd.header.in = tpm_getrandom_header; - tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); - - err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, - TPM_GETRANDOM_RESULT_SIZE + num_bytes, - offsetof(struct tpm_getrandom_out, - rng_data), - 0, "attempting get random"); - if (err) - break; - - recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len); - if (recd > num_bytes) { - total = -EFAULT; - break; - } - - rlength = be32_to_cpu(tpm_cmd.header.out.length); - if (rlength < TPM_HEADER_SIZE + - offsetof(struct tpm_getrandom_out, rng_data) + - recd) { - total = -EFAULT; - break; - } - memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd); - - dest += recd; - total += recd; - num_bytes -= recd; - } while (retries-- && total < max); + if (chip->flags & TPM_CHIP_FLAG_TPM2) + rc = tpm2_get_random(chip, out, max); + else + rc = tpm1_get_random(chip, out, max); tpm_put_ops(chip); - return total ? total : -EIO; + return rc; } EXPORT_SYMBOL_GPL(tpm_get_random); diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index 83a77a445538..b88e08ec2c59 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c @@ -102,19 +102,19 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr, cap_t cap; u8 digest[TPM_DIGEST_SIZE]; ssize_t rc; - int i, j, num_pcrs; + u32 i, j, num_pcrs; char *str = buf; struct tpm_chip *chip = to_tpm_chip(dev); - rc = tpm_getcap(chip, TPM_CAP_PROP_PCR, &cap, - "attempting to determine the number of PCRS", - sizeof(cap.num_pcrs)); + rc = tpm1_getcap(chip, TPM_CAP_PROP_PCR, &cap, + "attempting to determine the number of PCRS", + sizeof(cap.num_pcrs)); if (rc) return 0; num_pcrs = be32_to_cpu(cap.num_pcrs); for (i = 0; i < num_pcrs; i++) { - rc = tpm_pcr_read_dev(chip, i, digest); + rc = tpm1_pcr_read(chip, i, digest); if (rc) break; str += sprintf(str, "PCR-%02d: ", i); @@ -132,9 +132,9 @@ static ssize_t enabled_show(struct device *dev, struct device_attribute *attr, cap_t cap; ssize_t rc; - rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap, - "attempting to determine the permanent enabled state", - sizeof(cap.perm_flags)); + rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap, + "attempting to determine the permanent enabled state", + sizeof(cap.perm_flags)); if (rc) return 0; @@ -149,9 +149,9 @@ static ssize_t active_show(struct device *dev, struct device_attribute *attr, cap_t cap; ssize_t rc; - rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap, - "attempting to determine the permanent active state", - sizeof(cap.perm_flags)); + rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap, + "attempting to determine the permanent active state", + sizeof(cap.perm_flags)); if (rc) return 0; @@ -166,9 +166,9 @@ static ssize_t owned_show(struct device *dev, struct device_attribute *attr, cap_t cap; ssize_t rc; - rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap, - "attempting to determine the owner state", - sizeof(cap.owned)); + rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap, + "attempting to determine the owner state", + sizeof(cap.owned)); if (rc) return 0; @@ -183,9 +183,9 @@ static ssize_t temp_deactivated_show(struct device *dev, cap_t cap; ssize_t rc; - rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap, - "attempting to determine the temporary state", - sizeof(cap.stclear_flags)); + rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap, + "attempting to determine the temporary state", + sizeof(cap.stclear_flags)); if (rc) return 0; @@ -202,18 +202,18 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr, ssize_t rc; char *str = buf; - rc = tpm_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap, - "attempting to determine the manufacturer", - sizeof(cap.manufacturer_id)); + rc = tpm1_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap, + "attempting to determine the manufacturer", + sizeof(cap.manufacturer_id)); if (rc) return 0; str += sprintf(str, "Manufacturer: 0x%x\n", be32_to_cpu(cap.manufacturer_id)); /* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */ - rc = tpm_getcap(chip, TPM_CAP_VERSION_1_2, &cap, - "attempting to determine the 1.2 version", - sizeof(cap.tpm_version_1_2)); + rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_2, &cap, + "attempting to determine the 1.2 version", + sizeof(cap.tpm_version_1_2)); if (!rc) { str += sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n", @@ -223,9 +223,9 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr, cap.tpm_version_1_2.revMinor); } else { /* Otherwise just use TPM_STRUCT_VER */ - rc = tpm_getcap(chip, TPM_CAP_VERSION_1_1, &cap, - "attempting to determine the 1.1 version", - sizeof(cap.tpm_version)); + rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_1, &cap, + "attempting to determine the 1.1 version", + sizeof(cap.tpm_version)); if (rc) return 0; str += sprintf(str, diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index f20dc8ece348..f27d1f38a93d 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -134,22 +134,31 @@ enum tpm2_algorithms { }; enum tpm2_command_codes { - TPM2_CC_FIRST = 0x011F, - TPM2_CC_CREATE_PRIMARY = 0x0131, - TPM2_CC_SELF_TEST = 0x0143, - TPM2_CC_STARTUP = 0x0144, - TPM2_CC_SHUTDOWN = 0x0145, - TPM2_CC_CREATE = 0x0153, - TPM2_CC_LOAD = 0x0157, - TPM2_CC_UNSEAL = 0x015E, - TPM2_CC_CONTEXT_LOAD = 0x0161, - TPM2_CC_CONTEXT_SAVE = 0x0162, - TPM2_CC_FLUSH_CONTEXT = 0x0165, - TPM2_CC_GET_CAPABILITY = 0x017A, - TPM2_CC_GET_RANDOM = 0x017B, - TPM2_CC_PCR_READ = 0x017E, - TPM2_CC_PCR_EXTEND = 0x0182, - TPM2_CC_LAST = 0x018F, + TPM2_CC_FIRST = 0x011F, + TPM2_CC_HIERARCHY_CONTROL = 0x0121, + TPM2_CC_HIERARCHY_CHANGE_AUTH = 0x0129, + TPM2_CC_CREATE_PRIMARY = 0x0131, + TPM2_CC_SEQUENCE_COMPLETE = 0x013E, + TPM2_CC_SELF_TEST = 0x0143, + TPM2_CC_STARTUP = 0x0144, + TPM2_CC_SHUTDOWN = 0x0145, + TPM2_CC_NV_READ = 0x014E, + TPM2_CC_CREATE = 0x0153, + TPM2_CC_LOAD = 0x0157, + TPM2_CC_SEQUENCE_UPDATE = 0x015C, + TPM2_CC_UNSEAL = 0x015E, + TPM2_CC_CONTEXT_LOAD = 0x0161, + TPM2_CC_CONTEXT_SAVE = 0x0162, + TPM2_CC_FLUSH_CONTEXT = 0x0165, + TPM2_CC_VERIFY_SIGNATURE = 0x0177, + TPM2_CC_GET_CAPABILITY = 0x017A, + TPM2_CC_GET_RANDOM = 0x017B, + TPM2_CC_PCR_READ = 0x017E, + TPM2_CC_PCR_EXTEND = 0x0182, + TPM2_CC_EVENT_SEQUENCE_COMPLETE = 0x0185, + TPM2_CC_HASH_SEQUENCE_START = 0x0186, + TPM2_CC_CREATE_LOADED = 0x0191, + TPM2_CC_LAST = 0x0193, /* Spec 1.36 */ }; enum tpm2_permanent_handles { @@ -368,18 +377,6 @@ enum tpm_sub_capabilities { TPM_CAP_PROP_TIS_DURATION = 0x120, }; -typedef union { - struct tpm_input_header in; - struct tpm_output_header out; -} tpm_cmd_header; - -struct tpm_pcrread_out { - u8 pcr_result[TPM_DIGEST_SIZE]; -} __packed; - -struct tpm_pcrread_in { - __be32 pcr_idx; -} __packed; /* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18 * bytes, but 128 is still a relatively large number of random bytes and @@ -387,28 +384,6 @@ struct tpm_pcrread_in { * compiler warnings about stack frame size. */ #define TPM_MAX_RNG_DATA 128 -struct tpm_getrandom_out { - __be32 rng_data_len; - u8 rng_data[TPM_MAX_RNG_DATA]; -} __packed; - -struct tpm_getrandom_in { - __be32 num_bytes; -} __packed; - -typedef union { - struct tpm_pcrread_in pcrread_in; - struct tpm_pcrread_out pcrread_out; - struct tpm_getrandom_in getrandom_in; - struct tpm_getrandom_out getrandom_out; -} tpm_cmd_params; - -struct tpm_cmd_t { - tpm_cmd_header header; - tpm_cmd_params params; -} __packed; - - /* A string buffer type for constructing TPM commands. This is based on the * ideas of string buffer code in security/keys/trusted.h but is heap based * in order to keep the stack usage minimal. @@ -531,12 +506,20 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, void *buf, size_t bufsiz, size_t min_rsp_body_length, unsigned int flags, const char *desc); -int tpm_startup(struct tpm_chip *chip); -ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, - const char *desc, size_t min_cap_length); int tpm_get_timeouts(struct tpm_chip *); +int tpm_auto_startup(struct tpm_chip *chip); + +int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr); int tpm1_auto_startup(struct tpm_chip *chip); -int tpm_do_selftest(struct tpm_chip *chip); +int tpm1_do_selftest(struct tpm_chip *chip); +int tpm1_get_timeouts(struct tpm_chip *chip); +unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); +int tpm1_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash, + const char *log_msg); +int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf); +ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, + const char *desc, size_t min_cap_length); +int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max); unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); int tpm_pm_suspend(struct device *dev); int tpm_pm_resume(struct device *dev); @@ -560,7 +543,6 @@ void tpm_chip_unregister(struct tpm_chip *chip); void tpm_sysfs_add_device(struct tpm_chip *chip); -int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); #ifdef CONFIG_ACPI extern void tpm_add_ppi(struct tpm_chip *chip); @@ -575,8 +557,9 @@ static inline u32 tpm2_rc_value(u32 rc) return (rc & BIT(7)) ? rc & 0xff : rc; } -int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); -int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count, +int tpm2_get_timeouts(struct tpm_chip *chip); +int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf); +int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, u32 count, struct tpm2_digest *digests); int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max); void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c new file mode 100644 index 000000000000..6f306338953b --- /dev/null +++ b/drivers/char/tpm/tpm1-cmd.c @@ -0,0 +1,781 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2004 IBM Corporation + * Copyright (C) 2014 Intel Corporation + * + * Authors: + * Leendert van Doorn <leendert@watson.ibm.com> + * Dave Safford <safford@watson.ibm.com> + * Reiner Sailer <sailer@watson.ibm.com> + * Kylene Hall <kjhall@us.ibm.com> + * + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + */ + +#include <linux/poll.h> +#include <linux/slab.h> +#include <linux/mutex.h> +#include <linux/spinlock.h> +#include <linux/freezer.h> +#include <linux/tpm_eventlog.h> + +#include "tpm.h" + +#define TPM_MAX_ORDINAL 243 + +/* + * Array with one entry per ordinal defining the maximum amount + * of time the chip could take to return the result. The ordinal + * designation of short, medium or long is defined in a table in + * TCG Specification TPM Main Part 2 TPM Structures Section 17. The + * values of the SHORT, MEDIUM, and LONG durations are retrieved + * from the chip during initialization with a call to tpm_get_timeouts. + */ +static const u8 tpm1_ordinal_duration[TPM_MAX_ORDINAL] = { + TPM_UNDEFINED, /* 0 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 5 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 10 */ + TPM_SHORT, + TPM_MEDIUM, + TPM_LONG, + TPM_LONG, + TPM_MEDIUM, /* 15 */ + TPM_SHORT, + TPM_SHORT, + TPM_MEDIUM, + TPM_LONG, + TPM_SHORT, /* 20 */ + TPM_SHORT, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_SHORT, /* 25 */ + TPM_SHORT, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_MEDIUM, /* 30 */ + TPM_LONG, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, /* 35 */ + TPM_MEDIUM, + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_MEDIUM, /* 40 */ + TPM_LONG, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, /* 45 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_LONG, + TPM_MEDIUM, /* 50 */ + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 55 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_MEDIUM, /* 60 */ + TPM_MEDIUM, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_MEDIUM, /* 65 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 70 */ + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 75 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_LONG, /* 80 */ + TPM_UNDEFINED, + TPM_MEDIUM, + TPM_LONG, + TPM_SHORT, + TPM_UNDEFINED, /* 85 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 90 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, /* 95 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_MEDIUM, /* 100 */ + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 105 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 110 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, /* 115 */ + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_LONG, /* 120 */ + TPM_LONG, + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_SHORT, + TPM_SHORT, /* 125 */ + TPM_SHORT, + TPM_LONG, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, /* 130 */ + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_SHORT, + TPM_MEDIUM, + TPM_UNDEFINED, /* 135 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 140 */ + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 145 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 150 */ + TPM_MEDIUM, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, /* 155 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 160 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 165 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_LONG, /* 170 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 175 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_MEDIUM, /* 180 */ + TPM_SHORT, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_MEDIUM, /* 185 */ + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 190 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 195 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 200 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, + TPM_SHORT, /* 205 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_MEDIUM, /* 210 */ + TPM_UNDEFINED, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_UNDEFINED, /* 215 */ + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, + TPM_SHORT, /* 220 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, /* 225 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 230 */ + TPM_LONG, + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 235 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 240 */ + TPM_UNDEFINED, + TPM_MEDIUM, +}; + +/** + * tpm1_calc_ordinal_duration() - calculate the maximum command duration + * @chip: TPM chip to use. + * @ordinal: TPM command ordinal. + * + * The function returns the maximum amount of time the chip could take + * to return the result for a particular ordinal in jiffies. + * + * Return: A maximal duration time for an ordinal in jiffies. + */ +unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) +{ + int duration_idx = TPM_UNDEFINED; + int duration = 0; + + /* + * We only have a duration table for protected commands, where the upper + * 16 bits are 0. For the few other ordinals the fallback will be used. + */ + if (ordinal < TPM_MAX_ORDINAL) + duration_idx = tpm1_ordinal_duration[ordinal]; + + if (duration_idx != TPM_UNDEFINED) + duration = chip->duration[duration_idx]; + if (duration <= 0) + return 2 * 60 * HZ; + else + return duration; +} + +#define TPM_ORD_STARTUP 153 +#define TPM_ST_CLEAR 1 + +/** + * tpm_startup() - turn on the TPM + * @chip: TPM chip to use + * + * Normally the firmware should start the TPM. This function is provided as a + * workaround if this does not happen. A legal case for this could be for + * example when a TPM emulator is used. + * + * Return: same as tpm_transmit_cmd() + */ +static int tpm1_startup(struct tpm_chip *chip) +{ + struct tpm_buf buf; + int rc; + + dev_info(&chip->dev, "starting up the TPM manually\n"); + + rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP); + if (rc < 0) + return rc; + + tpm_buf_append_u16(&buf, TPM_ST_CLEAR); + + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, + "attempting to start the TPM"); + + tpm_buf_destroy(&buf); + + return rc; +} + +int tpm1_get_timeouts(struct tpm_chip *chip) +{ + cap_t cap; + unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4]; + ssize_t rc; + + rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL, + sizeof(cap.timeout)); + if (rc == TPM_ERR_INVALID_POSTINIT) { + if (tpm1_startup(chip)) + return rc; + + rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, + "attempting to determine the timeouts", + sizeof(cap.timeout)); + } + + if (rc) { + dev_err(&chip->dev, "A TPM error (%zd) occurred attempting to determine the timeouts\n", + rc); + return rc; + } + + timeout_old[0] = jiffies_to_usecs(chip->timeout_a); + timeout_old[1] = jiffies_to_usecs(chip->timeout_b); + timeout_old[2] = jiffies_to_usecs(chip->timeout_c); + timeout_old[3] = jiffies_to_usecs(chip->timeout_d); + timeout_chip[0] = be32_to_cpu(cap.timeout.a); + timeout_chip[1] = be32_to_cpu(cap.timeout.b); + timeout_chip[2] = be32_to_cpu(cap.timeout.c); + timeout_chip[3] = be32_to_cpu(cap.timeout.d); + memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff)); + + /* + * Provide ability for vendor overrides of timeout values in case + * of misreporting. + */ + if (chip->ops->update_timeouts) + chip->timeout_adjusted = + chip->ops->update_timeouts(chip, timeout_eff); + + if (!chip->timeout_adjusted) { + /* Restore default if chip reported 0 */ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(timeout_eff); i++) { + if (timeout_eff[i]) + continue; + + timeout_eff[i] = timeout_old[i]; + chip->timeout_adjusted = true; + } + + if (timeout_eff[0] != 0 && timeout_eff[0] < 1000) { + /* timeouts in msec rather usec */ + for (i = 0; i != ARRAY_SIZE(timeout_eff); i++) + timeout_eff[i] *= 1000; + chip->timeout_adjusted = true; + } + } + + /* Report adjusted timeouts */ + if (chip->timeout_adjusted) { + dev_info(&chip->dev, HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n", + timeout_chip[0], timeout_eff[0], + timeout_chip[1], timeout_eff[1], + timeout_chip[2], timeout_eff[2], + timeout_chip[3], timeout_eff[3]); + } + + chip->timeout_a = usecs_to_jiffies(timeout_eff[0]); + chip->timeout_b = usecs_to_jiffies(timeout_eff[1]); + chip->timeout_c = usecs_to_jiffies(timeout_eff[2]); + chip->timeout_d = usecs_to_jiffies(timeout_eff[3]); + + rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_DURATION, &cap, + "attempting to determine the durations", + sizeof(cap.duration)); + if (rc) + return rc; + + chip->duration[TPM_SHORT] = + usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_short)); + chip->duration[TPM_MEDIUM] = + usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_medium)); + chip->duration[TPM_LONG] = + usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_long)); + chip->duration[TPM_LONG_LONG] = 0; /* not used under 1.2 */ + + /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above + * value wrong and apparently reports msecs rather than usecs. So we + * fix up the resulting too-small TPM_SHORT value to make things work. + * We also scale the TPM_MEDIUM and -_LONG values by 1000. + */ + if (chip->duration[TPM_SHORT] < (HZ / 100)) { + chip->duration[TPM_SHORT] = HZ; + chip->duration[TPM_MEDIUM] *= 1000; + chip->duration[TPM_LONG] *= 1000; + chip->duration_adjusted = true; + dev_info(&chip->dev, "Adjusting TPM timeout parameters."); + } + + chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; + return 0; +} + +#define TPM_ORD_PCR_EXTEND 20 +int tpm1_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash, + const char *log_msg) +{ + struct tpm_buf buf; + int rc; + + rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND); + if (rc) + return rc; + + tpm_buf_append_u32(&buf, pcr_idx); + tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE); + + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, + TPM_DIGEST_SIZE, 0, log_msg); + + tpm_buf_destroy(&buf); + return rc; +} + +#define TPM_ORD_GET_CAP 101 +ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, + const char *desc, size_t min_cap_length) +{ + struct tpm_buf buf; + int rc; + + rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP); + if (rc) + return rc; + + if (subcap_id == TPM_CAP_VERSION_1_1 || + subcap_id == TPM_CAP_VERSION_1_2) { + tpm_buf_append_u32(&buf, subcap_id); + tpm_buf_append_u32(&buf, 0); + } else { + if (subcap_id == TPM_CAP_FLAG_PERM || + subcap_id == TPM_CAP_FLAG_VOL) + tpm_buf_append_u32(&buf, TPM_CAP_FLAG); + else + tpm_buf_append_u32(&buf, TPM_CAP_PROP); + + tpm_buf_append_u32(&buf, 4); + tpm_buf_append_u32(&buf, subcap_id); + } + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, + min_cap_length, 0, desc); + if (!rc) + *cap = *(cap_t *)&buf.data[TPM_HEADER_SIZE + 4]; + + tpm_buf_destroy(&buf); + return rc; +} +EXPORT_SYMBOL_GPL(tpm1_getcap); + +#define TPM_ORD_GET_RANDOM 70 +struct tpm1_get_random_out { + __be32 rng_data_len; + u8 rng_data[TPM_MAX_RNG_DATA]; +} __packed; + +/** + * tpm1_get_random() - get random bytes from the TPM's RNG + * @chip: a &struct tpm_chip instance + * @dest: destination buffer for the random bytes + * @max: the maximum number of bytes to write to @dest + * + * Return: + * * number of bytes read + * * -errno or a TPM return code otherwise + */ +int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max) +{ + struct tpm1_get_random_out *out; + u32 num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA); + struct tpm_buf buf; + u32 total = 0; + int retries = 5; + u32 recd; + int rc; + + rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); + if (rc) + return rc; + + do { + tpm_buf_append_u32(&buf, num_bytes); + + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, + sizeof(out->rng_data_len), 0, + "attempting get random"); + if (rc) + goto out; + + out = (struct tpm1_get_random_out *)&buf.data[TPM_HEADER_SIZE]; + + recd = be32_to_cpu(out->rng_data_len); + if (recd > num_bytes) { + rc = -EFAULT; + goto out; + } + + if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + + sizeof(out->rng_data_len) + recd) { + rc = -EFAULT; + goto out; + } + memcpy(dest, out->rng_data, recd); + + dest += recd; + total += recd; + num_bytes -= recd; + + tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); + } while (retries-- && total < max); + + rc = total ? (int)total : -EIO; +out: + tpm_buf_destroy(&buf); + return rc; +} + +#define TPM_ORD_PCRREAD 21 +int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) +{ + struct tpm_buf buf; + int rc; + + rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCRREAD); + if (rc) + return rc; + + tpm_buf_append_u32(&buf, pcr_idx); + + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, + TPM_DIGEST_SIZE, 0, + "attempting to read a pcr value"); + if (rc) + goto out; + + if (tpm_buf_length(&buf) < TPM_DIGEST_SIZE) { + rc = -EFAULT; + goto out; + } + + memcpy(res_buf, &buf.data[TPM_HEADER_SIZE], TPM_DIGEST_SIZE); + +out: + tpm_buf_destroy(&buf); + return rc; +} + +#define TPM_ORD_CONTINUE_SELFTEST 83 +/** + * tpm_continue_selftest() - run TPM's selftest + * @chip: TPM chip to use + * + * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing + * a TPM error code. + */ +static int tpm1_continue_selftest(struct tpm_chip *chip) +{ + struct tpm_buf buf; + int rc; + + rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST); + if (rc) + return rc; + + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, + 0, 0, "continue selftest"); + + tpm_buf_destroy(&buf); + + return rc; +} + +/** + * tpm1_do_selftest - have the TPM continue its selftest and wait until it + * can receive further commands + * @chip: TPM chip to use + * + * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing + * a TPM error code. + */ +int tpm1_do_selftest(struct tpm_chip *chip) +{ + int rc; + unsigned int loops; + unsigned int delay_msec = 100; + unsigned long duration; + u8 dummy[TPM_DIGEST_SIZE]; + + duration = tpm1_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST); + + loops = jiffies_to_msecs(duration) / delay_msec; + + rc = tpm1_continue_selftest(chip); + if (rc == TPM_ERR_INVALID_POSTINIT) { + chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; + dev_info(&chip->dev, "TPM not ready (%d)\n", rc); + } + /* This may fail if there was no TPM driver during a suspend/resume + * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) + */ + if (rc) + return rc; + + do { + /* Attempt to read a PCR value */ + rc = tpm1_pcr_read(chip, 0, dummy); + + /* Some buggy TPMs will not respond to tpm_tis_ready() for + * around 300ms while the self test is ongoing, keep trying + * until the self test duration expires. + */ + if (rc == -ETIME) { + dev_info(&chip->dev, HW_ERR "TPM command timed out during continue self test"); + tpm_msleep(delay_msec); + continue; + } + + if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { + dev_info(&chip->dev, "TPM is disabled/deactivated (0x%X)\n", + rc); + /* TPM is disabled and/or deactivated; driver can + * proceed and TPM does handle commands for + * suspend/resume correctly + */ + return 0; + } + if (rc != TPM_WARN_DOING_SELFTEST) + return rc; + tpm_msleep(delay_msec); + } while (--loops > 0); + + return rc; +} +EXPORT_SYMBOL_GPL(tpm1_do_selftest); + +/** + * tpm1_auto_startup - Perform the standard automatic TPM initialization + * sequence + * @chip: TPM chip to use + * + * Returns 0 on success, < 0 in case of fatal error. + */ +int tpm1_auto_startup(struct tpm_chip *chip) +{ + int rc; + + rc = tpm1_get_timeouts(chip); + if (rc) + goto out; + rc = tpm1_do_selftest(chip); + if (rc) { + dev_err(&chip->dev, "TPM self test failed\n"); + goto out; + } + + return rc; +out: + if (rc > 0) + rc = -ENODEV; + return rc; +} + +#define TPM_ORD_SAVESTATE 152 + +/** + * tpm1_pm_suspend() - pm suspend handler + * @chip: TPM chip to use. + * @tpm_suspend_pcr: flush pcr for buggy TPM chips. + * + * The functions saves the TPM state to be restored on resume. + * + * Return: + * * 0 on success, + * * < 0 on error. + */ +int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr) +{ + u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; + struct tpm_buf buf; + unsigned int try; + int rc; + + + /* for buggy tpm, flush pcrs with extend to selected dummy */ + if (tpm_suspend_pcr) + rc = tpm1_pcr_extend(chip, tpm_suspend_pcr, dummy_hash, + "extending dummy pcr before suspend"); + + rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE); + if (rc) + return rc; + /* now do the actual savestate */ + for (try = 0; try < TPM_RETRY; try++) { + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, + 0, 0, NULL); + + /* + * If the TPM indicates that it is too busy to respond to + * this command then retry before giving up. It can take + * several seconds for this TPM to be ready. + * + * This can happen if the TPM has already been sent the + * SaveState command before the driver has loaded. TCG 1.2 + * specification states that any communication after SaveState + * may cause the TPM to invalidate previously saved state. + */ + if (rc != TPM_WARN_RETRY) + break; + tpm_msleep(TPM_TIMEOUT_RETRY); + + tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE); + } + + if (rc) + dev_err(&chip->dev, "Error (%d) sending savestate before suspend\n", + rc); + else if (try > 0) + dev_warn(&chip->dev, "TPM savestate took %dms\n", + try * TPM_TIMEOUT_RETRY); + + tpm_buf_destroy(&buf); + + return rc; +} + diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 3acf4fd4e5a5..a6bec13afa69 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -40,129 +40,121 @@ static struct tpm2_hash tpm2_hash_map[] = { {HASH_ALGO_SM3_256, TPM2_ALG_SM3_256}, }; -/* - * Array with one entry per ordinal defining the maximum amount - * of time the chip could take to return the result. The values - * of the SHORT, MEDIUM, and LONG durations are taken from the - * PC Client Profile (PTP) specification. - * LONG_LONG is for commands that generates keys which empirically - * takes longer time on some systems. +int tpm2_get_timeouts(struct tpm_chip *chip) +{ + /* Fixed timeouts for TPM2 */ + chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A); + chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B); + chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C); + chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D); + + /* PTP spec timeouts */ + chip->duration[TPM_SHORT] = msecs_to_jiffies(TPM2_DURATION_SHORT); + chip->duration[TPM_MEDIUM] = msecs_to_jiffies(TPM2_DURATION_MEDIUM); + chip->duration[TPM_LONG] = msecs_to_jiffies(TPM2_DURATION_LONG); + + /* Key creation commands long timeouts */ + chip->duration[TPM_LONG_LONG] = + msecs_to_jiffies(TPM2_DURATION_LONG_LONG); + + chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; + + return 0; +} + +/** + * tpm2_ordinal_duration_index() - returns an index to the chip duration table + * @ordinal: TPM command ordinal. + * + * The function returns an index to the chip duration table + * (enum tpm_duration), that describes the maximum amount of + * time the chip could take to return the result for a particular ordinal. + * + * The values of the MEDIUM, and LONG durations are taken + * from the PC Client Profile (PTP) specification (750, 2000 msec) + * + * LONG_LONG is for commands that generates keys which empirically takes + * a longer time on some systems. + * + * Return: + * * TPM_MEDIUM + * * TPM_LONG + * * TPM_LONG_LONG + * * TPM_UNDEFINED */ -static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { - TPM_UNDEFINED, /* 11F */ - TPM_UNDEFINED, /* 120 */ - TPM_LONG, /* 121 */ - TPM_UNDEFINED, /* 122 */ - TPM_UNDEFINED, /* 123 */ - TPM_UNDEFINED, /* 124 */ - TPM_UNDEFINED, /* 125 */ - TPM_UNDEFINED, /* 126 */ - TPM_UNDEFINED, /* 127 */ - TPM_UNDEFINED, /* 128 */ - TPM_LONG, /* 129 */ - TPM_UNDEFINED, /* 12a */ - TPM_UNDEFINED, /* 12b */ - TPM_UNDEFINED, /* 12c */ - TPM_UNDEFINED, /* 12d */ - TPM_UNDEFINED, /* 12e */ - TPM_UNDEFINED, /* 12f */ - TPM_UNDEFINED, /* 130 */ - TPM_LONG_LONG, /* 131 */ - TPM_UNDEFINED, /* 132 */ - TPM_UNDEFINED, /* 133 */ - TPM_UNDEFINED, /* 134 */ - TPM_UNDEFINED, /* 135 */ - TPM_UNDEFINED, /* 136 */ - TPM_UNDEFINED, /* 137 */ - TPM_UNDEFINED, /* 138 */ - TPM_UNDEFINED, /* 139 */ - TPM_UNDEFINED, /* 13a */ - TPM_UNDEFINED, /* 13b */ - TPM_UNDEFINED, /* 13c */ - TPM_UNDEFINED, /* 13d */ - TPM_MEDIUM, /* 13e */ - TPM_UNDEFINED, /* 13f */ - TPM_UNDEFINED, /* 140 */ - TPM_UNDEFINED, /* 141 */ - TPM_UNDEFINED, /* 142 */ - TPM_LONG, /* 143 */ - TPM_MEDIUM, /* 144 */ - TPM_UNDEFINED, /* 145 */ - TPM_UNDEFINED, /* 146 */ - TPM_UNDEFINED, /* 147 */ - TPM_UNDEFINED, /* 148 */ - TPM_UNDEFINED, /* 149 */ - TPM_UNDEFINED, /* 14a */ - TPM_UNDEFINED, /* 14b */ - TPM_UNDEFINED, /* 14c */ - TPM_UNDEFINED, /* 14d */ - TPM_LONG, /* 14e */ - TPM_UNDEFINED, /* 14f */ - TPM_UNDEFINED, /* 150 */ - TPM_UNDEFINED, /* 151 */ - TPM_UNDEFINED, /* 152 */ - TPM_LONG_LONG, /* 153 */ - TPM_UNDEFINED, /* 154 */ - TPM_UNDEFINED, /* 155 */ - TPM_UNDEFINED, /* 156 */ - TPM_UNDEFINED, /* 157 */ - TPM_UNDEFINED, /* 158 */ - TPM_UNDEFINED, /* 159 */ - TPM_UNDEFINED, /* 15a */ - TPM_UNDEFINED, /* 15b */ - TPM_MEDIUM, /* 15c */ - TPM_UNDEFINED, /* 15d */ - TPM_UNDEFINED, /* 15e */ - TPM_UNDEFINED, /* 15f */ - TPM_UNDEFINED, /* 160 */ - TPM_UNDEFINED, /* 161 */ - TPM_UNDEFINED, /* 162 */ - TPM_UNDEFINED, /* 163 */ - TPM_UNDEFINED, /* 164 */ - TPM_UNDEFINED, /* 165 */ - TPM_UNDEFINED, /* 166 */ - TPM_UNDEFINED, /* 167 */ - TPM_UNDEFINED, /* 168 */ - TPM_UNDEFINED, /* 169 */ - TPM_UNDEFINED, /* 16a */ - TPM_UNDEFINED, /* 16b */ - TPM_UNDEFINED, /* 16c */ - TPM_UNDEFINED, /* 16d */ - TPM_UNDEFINED, /* 16e */ - TPM_UNDEFINED, /* 16f */ - TPM_UNDEFINED, /* 170 */ - TPM_UNDEFINED, /* 171 */ - TPM_UNDEFINED, /* 172 */ - TPM_UNDEFINED, /* 173 */ - TPM_UNDEFINED, /* 174 */ - TPM_UNDEFINED, /* 175 */ - TPM_UNDEFINED, /* 176 */ - TPM_LONG, /* 177 */ - TPM_UNDEFINED, /* 178 */ - TPM_UNDEFINED, /* 179 */ - TPM_MEDIUM, /* 17a */ - TPM_LONG, /* 17b */ - TPM_UNDEFINED, /* 17c */ - TPM_UNDEFINED, /* 17d */ - TPM_UNDEFINED, /* 17e */ - TPM_UNDEFINED, /* 17f */ - TPM_UNDEFINED, /* 180 */ - TPM_UNDEFINED, /* 181 */ - TPM_MEDIUM, /* 182 */ - TPM_UNDEFINED, /* 183 */ - TPM_UNDEFINED, /* 184 */ - TPM_MEDIUM, /* 185 */ - TPM_MEDIUM, /* 186 */ - TPM_UNDEFINED, /* 187 */ - TPM_UNDEFINED, /* 188 */ - TPM_UNDEFINED, /* 189 */ - TPM_UNDEFINED, /* 18a */ - TPM_UNDEFINED, /* 18b */ - TPM_UNDEFINED, /* 18c */ - TPM_UNDEFINED, /* 18d */ - TPM_UNDEFINED, /* 18e */ - TPM_UNDEFINED /* 18f */ -}; +static u8 tpm2_ordinal_duration_index(u32 ordinal) +{ + switch (ordinal) { + /* Startup */ + case TPM2_CC_STARTUP: /* 144 */ + return TPM_MEDIUM; + + case TPM2_CC_SELF_TEST: /* 143 */ + return TPM_LONG; + + case TPM2_CC_GET_RANDOM: /* 17B */ + return TPM_LONG; + + case TPM2_CC_SEQUENCE_UPDATE: /* 15C */ + return TPM_MEDIUM; + case TPM2_CC_SEQUENCE_COMPLETE: /* 13E */ + return TPM_MEDIUM; + case TPM2_CC_EVENT_SEQUENCE_COMPLETE: /* 185 */ + return TPM_MEDIUM; + case TPM2_CC_HASH_SEQUENCE_START: /* 186 */ + return TPM_MEDIUM; + + case TPM2_CC_VERIFY_SIGNATURE: /* 177 */ + return TPM_LONG; + + case TPM2_CC_PCR_EXTEND: /* 182 */ + return TPM_MEDIUM; + + case TPM2_CC_HIERARCHY_CONTROL: /* 121 */ + return TPM_LONG; + case TPM2_CC_HIERARCHY_CHANGE_AUTH: /* 129 */ + return TPM_LONG; + + case TPM2_CC_GET_CAPABILITY: /* 17A */ + return TPM_MEDIUM; + + case TPM2_CC_NV_READ: /* 14E */ + return TPM_LONG; + + case TPM2_CC_CREATE_PRIMARY: /* 131 */ + return TPM_LONG_LONG; + case TPM2_CC_CREATE: /* 153 */ + return TPM_LONG_LONG; + case TPM2_CC_CREATE_LOADED: /* 191 */ + return TPM_LONG_LONG; + + default: + return TPM_UNDEFINED; + } +} + +/** + * tpm2_calc_ordinal_duration() - calculate the maximum command duration + * @chip: TPM chip to use. + * @ordinal: TPM command ordinal. + * + * The function returns the maximum amount of time the chip could take + * to return the result for a particular ordinal in jiffies. + * + * Return: A maximal duration time for an ordinal in jiffies. + */ +unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) +{ + unsigned int index; + + index = tpm2_ordinal_duration_index(ordinal); + + if (index != TPM_UNDEFINED) + return chip->duration[index]; + else + return msecs_to_jiffies(TPM2_DURATION_DEFAULT); +} + struct tpm2_pcr_read_out { __be32 update_cnt; @@ -183,7 +175,7 @@ struct tpm2_pcr_read_out { * * Return: Same as with tpm_transmit_cmd. */ -int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) +int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) { int rc; struct tpm_buf buf; @@ -233,7 +225,7 @@ struct tpm2_null_auth_area { * * Return: Same as with tpm_transmit_cmd. */ -int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count, +int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, u32 count, struct tpm2_digest *digests) { struct tpm_buf buf; @@ -280,7 +272,6 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count, return rc; } - struct tpm2_get_random_out { __be16 size; u8 buffer[TPM_MAX_RNG_DATA]; @@ -351,11 +342,10 @@ out: /** * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command - * @chip: TPM chip to use - * @payload: the key data in clear and encrypted form - * @options: authentication values and other options + * @chip: TPM chip to use + * @handle: context handle + * @flags: tpm transmit flags - bitmap * - * Return: same as with tpm_transmit_cmd */ void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, unsigned int flags) @@ -748,32 +738,6 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) tpm_buf_destroy(&buf); } -/* - * tpm2_calc_ordinal_duration() - maximum duration for a command - * - * @chip: TPM chip to use. - * @ordinal: command code number. - * - * Return: maximum duration for a command - */ -unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) -{ - int index = TPM_UNDEFINED; - int duration = 0; - - if (ordinal >= TPM2_CC_FIRST && ordinal <= TPM2_CC_LAST) - index = tpm2_ordinal_duration[ordinal - TPM2_CC_FIRST]; - - if (index != TPM_UNDEFINED) - duration = chip->duration[index]; - - if (duration <= 0) - duration = msecs_to_jiffies(TPM2_DURATION_DEFAULT); - - return duration; -} -EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration); - /** * tpm2_do_selftest() - ensure that all self tests have passed * @@ -983,6 +947,36 @@ out: } /** + * tpm2_startup - turn on the TPM + * @chip: TPM chip to use + * + * Normally the firmware should start the TPM. This function is provided as a + * workaround if this does not happen. A legal case for this could be for + * example when a TPM emulator is used. + * + * Return: same as tpm_transmit_cmd() + */ + +static int tpm2_startup(struct tpm_chip *chip) +{ + struct tpm_buf buf; + int rc; + + dev_info(&chip->dev, "starting up the TPM manually\n"); + + rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP); + if (rc < 0) + return rc; + + tpm_buf_append_u16(&buf, TPM2_SU_CLEAR); + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, + "attempting to start the TPM"); + tpm_buf_destroy(&buf); + + return rc; +} + +/** * tpm2_auto_startup - Perform the standard automatic TPM initialization * sequence * @chip: TPM chip to use @@ -993,7 +987,7 @@ int tpm2_auto_startup(struct tpm_chip *chip) { int rc; - rc = tpm_get_timeouts(chip); + rc = tpm2_get_timeouts(chip); if (rc) goto out; @@ -1002,7 +996,7 @@ int tpm2_auto_startup(struct tpm_chip *chip) goto out; if (rc == TPM2_RC_INITIALIZE) { - rc = tpm_startup(chip); + rc = tpm2_startup(chip); if (rc) goto out; diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index d2e101b32482..dcdfde3c253e 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c @@ -373,7 +373,7 @@ static int tpm2_map_response_header(struct tpm_chip *chip, u32 cc, u8 *rsp, dev_err(&chip->dev, "%s: unknown handle 0x%08X\n", __func__, phandle); break; - }; + } return 0; out_no_slots: diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c index caa86b19c76d..217f7f1cbde8 100644 --- a/drivers/char/tpm/tpm_i2c_nuvoton.c +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c @@ -369,6 +369,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len) struct device *dev = chip->dev.parent; struct i2c_client *client = to_i2c_client(dev); u32 ordinal; + unsigned long duration; size_t count = 0; int burst_count, bytes2write, retries, rc = -EIO; @@ -455,12 +456,12 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len) return rc; } ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); - rc = i2c_nuvoton_wait_for_data_avail(chip, - tpm_calc_ordinal_duration(chip, - ordinal), - &priv->read_queue); + duration = tpm_calc_ordinal_duration(chip, ordinal); + + rc = i2c_nuvoton_wait_for_data_avail(chip, duration, &priv->read_queue); if (rc) { - dev_err(dev, "%s() timeout command duration\n", __func__); + dev_err(dev, "%s() timeout command duration %ld\n", + __func__, duration); i2c_nuvoton_ready(chip); return rc; } diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c index 25f6e2665385..07b5a487d0c8 100644 --- a/drivers/char/tpm/tpm_ibmvtpm.c +++ b/drivers/char/tpm/tpm_ibmvtpm.c @@ -39,8 +39,7 @@ static const struct vio_device_id tpm_ibmvtpm_device_table[] = { MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table); /** - * - * ibmvtpm_send_crq_word - Send a CRQ request + * ibmvtpm_send_crq_word() - Send a CRQ request * @vdev: vio device struct * @w1: pre-constructed first word of tpm crq (second word is reserved) * @@ -54,8 +53,7 @@ static int ibmvtpm_send_crq_word(struct vio_dev *vdev, u64 w1) } /** - * - * ibmvtpm_send_crq - Send a CRQ request + * ibmvtpm_send_crq() - Send a CRQ request * * @vdev: vio device struct * @valid: Valid field diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index d2345d9fd7b5..bf7e49cfa643 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -473,11 +473,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) if (chip->flags & TPM_CHIP_FLAG_IRQ) { ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); - if (chip->flags & TPM_CHIP_FLAG_TPM2) - dur = tpm2_calc_ordinal_duration(chip, ordinal); - else - dur = tpm_calc_ordinal_duration(chip, ordinal); - + dur = tpm_calc_ordinal_duration(chip, ordinal); if (wait_for_tpm_stat (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, &priv->read_queue, false) < 0) { @@ -668,7 +664,7 @@ static int tpm_tis_gen_interrupt(struct tpm_chip *chip) if (chip->flags & TPM_CHIP_FLAG_TPM2) return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc); else - return tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, + return tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, 0); } @@ -1060,7 +1056,7 @@ int tpm_tis_resume(struct device *dev) * an error code but for unknown reason it isn't handled. */ if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) - tpm_do_selftest(chip); + tpm1_do_selftest(chip); return 0; } diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index 67549ce88cc9..88808dbba486 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -37,6 +37,8 @@ static struct ttyprintk_port tpk_port; */ #define TPK_STR_SIZE 508 /* should be bigger then max expected line length */ #define TPK_MAX_ROOM 4096 /* we could assume 4K for instance */ +#define TPK_PREFIX KERN_SOH __stringify(CONFIG_TTY_PRINTK_LEVEL) + static int tpk_curr; static char tpk_buffer[TPK_STR_SIZE + 4]; @@ -45,7 +47,7 @@ static void tpk_flush(void) { if (tpk_curr > 0) { tpk_buffer[tpk_curr] = '\0'; - pr_info("[U] %s\n", tpk_buffer); + printk(TPK_PREFIX "[U] %s\n", tpk_buffer); tpk_curr = 0; } } diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 5b5b5d72eab7..fbeb71953526 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1309,7 +1309,7 @@ static const struct attribute_group port_attribute_group = { .attrs = port_sysfs_entries, }; -static int debugfs_show(struct seq_file *s, void *data) +static int port_debugfs_show(struct seq_file *s, void *data) { struct port *port = s->private; @@ -1327,18 +1327,7 @@ static int debugfs_show(struct seq_file *s, void *data) return 0; } -static int debugfs_open(struct inode *inode, struct file *file) -{ - return single_open(file, debugfs_show, inode->i_private); -} - -static const struct file_operations port_debugfs_ops = { - .owner = THIS_MODULE, - .open = debugfs_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(port_debugfs); static void set_console_size(struct port *port, u16 rows, u16 cols) { @@ -1490,7 +1479,7 @@ static int add_port(struct ports_device *portdev, u32 id) port->debugfs_file = debugfs_create_file(debugfs_name, 0444, pdrvdata.debugfs_dir, port, - &port_debugfs_ops); + &port_debugfs_fops); } return 0; |