diff options
author | James Morris <james.morris@microsoft.com> | 2018-05-18 20:40:37 +0300 |
---|---|---|
committer | James Morris <james.morris@microsoft.com> | 2018-05-18 20:40:37 +0300 |
commit | 82e5b03236e0eada87a59f4636c986dc319c6e78 (patch) | |
tree | bec5f1a1d99a56bbea7dfbf6f02156816353cde7 /drivers | |
parent | 890e2abe1028c39e5399101a2c277219cd637aaa (diff) | |
parent | 424eaf910c329ab06ad03a527ef45dcf6a328f00 (diff) | |
download | linux-82e5b03236e0eada87a59f4636c986dc319c6e78.tar.xz |
Merge tag 'tpmdd-next-20180518' of git://git.infradead.org/users/jjs/linux-tpmdd into next-tpm
tpmdd updates for Linux 4.18
This purely a bug fix release. The only major change is to move
the event log code to its own subdirectory because there starts to be
so much of it.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/tpm/Makefile | 10 | ||||
-rw-r--r-- | drivers/char/tpm/eventlog/acpi.c (renamed from drivers/char/tpm/tpm_eventlog_acpi.c) | 3 | ||||
-rw-r--r-- | drivers/char/tpm/eventlog/common.c | 195 | ||||
-rw-r--r-- | drivers/char/tpm/eventlog/common.h | 35 | ||||
-rw-r--r-- | drivers/char/tpm/eventlog/efi.c (renamed from drivers/char/tpm/tpm_eventlog_efi.c) | 6 | ||||
-rw-r--r-- | drivers/char/tpm/eventlog/of.c (renamed from drivers/char/tpm/tpm_eventlog_of.c) | 11 | ||||
-rw-r--r-- | drivers/char/tpm/eventlog/tpm1.c (renamed from drivers/char/tpm/tpm1_eventlog.c) | 200 | ||||
-rw-r--r-- | drivers/char/tpm/eventlog/tpm2.c (renamed from drivers/char/tpm/tpm2_eventlog.c) | 3 | ||||
-rw-r--r-- | drivers/char/tpm/st33zp24/spi.c | 4 | ||||
-rw-r--r-- | drivers/char/tpm/st33zp24/st33zp24.c | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-interface.c | 5 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 32 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-space.c | 3 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_crb.c | 10 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis_core.c | 58 |
15 files changed, 331 insertions, 246 deletions
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index acd758381c58..4e9c33ca1f8f 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -4,11 +4,11 @@ # 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 tpm1_eventlog.o tpm2_eventlog.o \ - tpm2-space.o -tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_eventlog_acpi.o -tpm-$(CONFIG_EFI) += tpm_eventlog_efi.o -tpm-$(CONFIG_OF) += tpm_eventlog_of.o + tpm-dev-common.o tpmrm-dev.o eventlog/common.o eventlog/tpm1.o \ + eventlog/tpm2.o tpm2-space.o +tpm-$(CONFIG_ACPI) += tpm_ppi.o eventlog/acpi.o +tpm-$(CONFIG_EFI) += eventlog/efi.o +tpm-$(CONFIG_OF) += eventlog/of.o obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o obj-$(CONFIG_TCG_TIS) += tpm_tis.o obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o diff --git a/drivers/char/tpm/tpm_eventlog_acpi.c b/drivers/char/tpm/eventlog/acpi.c index 66f19e93c216..7c53b1973b62 100644 --- a/drivers/char/tpm/tpm_eventlog_acpi.c +++ b/drivers/char/tpm/eventlog/acpi.c @@ -27,7 +27,8 @@ #include <linux/acpi.h> #include <linux/tpm_eventlog.h> -#include "tpm.h" +#include "../tpm.h" +#include "common.h" struct acpi_tcpa { struct acpi_table_header hdr; diff --git a/drivers/char/tpm/eventlog/common.c b/drivers/char/tpm/eventlog/common.c new file mode 100644 index 000000000000..5a8720df2b51 --- /dev/null +++ b/drivers/char/tpm/eventlog/common.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2005, 2012 IBM Corporation + * + * Authors: + * Kent Yoder <key@linux.vnet.ibm.com> + * Seiji Munetoh <munetoh@jp.ibm.com> + * Stefan Berger <stefanb@us.ibm.com> + * Reiner Sailer <sailer@watson.ibm.com> + * Kylene Hall <kjhall@us.ibm.com> + * Nayna Jain <nayna@linux.vnet.ibm.com> + * + * Access to the event log created by a system's firmware / BIOS + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include <linux/seq_file.h> +#include <linux/fs.h> +#include <linux/security.h> +#include <linux/module.h> +#include <linux/tpm_eventlog.h> + +#include "../tpm.h" +#include "common.h" + +static int tpm_bios_measurements_open(struct inode *inode, + struct file *file) +{ + int err; + struct seq_file *seq; + struct tpm_chip_seqops *chip_seqops; + const struct seq_operations *seqops; + struct tpm_chip *chip; + + inode_lock(inode); + if (!inode->i_private) { + inode_unlock(inode); + return -ENODEV; + } + chip_seqops = (struct tpm_chip_seqops *)inode->i_private; + seqops = chip_seqops->seqops; + chip = chip_seqops->chip; + get_device(&chip->dev); + inode_unlock(inode); + + /* now register seq file */ + err = seq_open(file, seqops); + if (!err) { + seq = file->private_data; + seq->private = chip; + } + + return err; +} + +static int tpm_bios_measurements_release(struct inode *inode, + struct file *file) +{ + struct seq_file *seq = (struct seq_file *)file->private_data; + struct tpm_chip *chip = (struct tpm_chip *)seq->private; + + put_device(&chip->dev); + + return seq_release(inode, file); +} + +static const struct file_operations tpm_bios_measurements_ops = { + .owner = THIS_MODULE, + .open = tpm_bios_measurements_open, + .read = seq_read, + .llseek = seq_lseek, + .release = tpm_bios_measurements_release, +}; + +static int tpm_read_log(struct tpm_chip *chip) +{ + int rc; + + if (chip->log.bios_event_log != NULL) { + dev_dbg(&chip->dev, + "%s: ERROR - event log already initialized\n", + __func__); + return -EFAULT; + } + + rc = tpm_read_log_acpi(chip); + if (rc != -ENODEV) + return rc; + + rc = tpm_read_log_efi(chip); + if (rc != -ENODEV) + return rc; + + return tpm_read_log_of(chip); +} + +/* + * tpm_bios_log_setup() - Read the event log from the firmware + * @chip: TPM chip to use. + * + * If an event log is found then the securityfs files are setup to + * export it to userspace, otherwise nothing is done. + * + * Returns -ENODEV if the firmware has no event log or securityfs is not + * supported. + */ +int tpm_bios_log_setup(struct tpm_chip *chip) +{ + const char *name = dev_name(&chip->dev); + unsigned int cnt; + int log_version; + int rc = 0; + + rc = tpm_read_log(chip); + if (rc < 0) + return rc; + log_version = rc; + + cnt = 0; + chip->bios_dir[cnt] = securityfs_create_dir(name, NULL); + /* NOTE: securityfs_create_dir can return ENODEV if securityfs is + * compiled out. The caller should ignore the ENODEV return code. + */ + if (IS_ERR(chip->bios_dir[cnt])) + goto err; + cnt++; + + chip->bin_log_seqops.chip = chip; + if (log_version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) + chip->bin_log_seqops.seqops = + &tpm2_binary_b_measurements_seqops; + else + chip->bin_log_seqops.seqops = + &tpm1_binary_b_measurements_seqops; + + + chip->bios_dir[cnt] = + securityfs_create_file("binary_bios_measurements", + 0440, chip->bios_dir[0], + (void *)&chip->bin_log_seqops, + &tpm_bios_measurements_ops); + if (IS_ERR(chip->bios_dir[cnt])) + goto err; + cnt++; + + if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { + + chip->ascii_log_seqops.chip = chip; + chip->ascii_log_seqops.seqops = + &tpm1_ascii_b_measurements_seqops; + + chip->bios_dir[cnt] = + securityfs_create_file("ascii_bios_measurements", + 0440, chip->bios_dir[0], + (void *)&chip->ascii_log_seqops, + &tpm_bios_measurements_ops); + if (IS_ERR(chip->bios_dir[cnt])) + goto err; + cnt++; + } + + return 0; + +err: + rc = PTR_ERR(chip->bios_dir[cnt]); + chip->bios_dir[cnt] = NULL; + tpm_bios_log_teardown(chip); + return rc; +} + +void tpm_bios_log_teardown(struct tpm_chip *chip) +{ + int i; + struct inode *inode; + + /* securityfs_remove currently doesn't take care of handling sync + * between removal and opening of pseudo files. To handle this, a + * workaround is added by making i_private = NULL here during removal + * and to check it during open(), both within inode_lock()/unlock(). + * This design ensures that open() either safely gets kref or fails. + */ + for (i = (TPM_NUM_EVENT_LOG_FILES - 1); i >= 0; i--) { + if (chip->bios_dir[i]) { + inode = d_inode(chip->bios_dir[i]); + inode_lock(inode); + inode->i_private = NULL; + inode_unlock(inode); + securityfs_remove(chip->bios_dir[i]); + } + } +} diff --git a/drivers/char/tpm/eventlog/common.h b/drivers/char/tpm/eventlog/common.h new file mode 100644 index 000000000000..47ff8136ceb5 --- /dev/null +++ b/drivers/char/tpm/eventlog/common.h @@ -0,0 +1,35 @@ +#ifndef __TPM_EVENTLOG_COMMON_H__ +#define __TPM_EVENTLOG_COMMON_H__ + +#include "../tpm.h" + +extern const struct seq_operations tpm1_ascii_b_measurements_seqops; +extern const struct seq_operations tpm1_binary_b_measurements_seqops; +extern const struct seq_operations tpm2_binary_b_measurements_seqops; + +#if defined(CONFIG_ACPI) +int tpm_read_log_acpi(struct tpm_chip *chip); +#else +static inline int tpm_read_log_acpi(struct tpm_chip *chip) +{ + return -ENODEV; +} +#endif +#if defined(CONFIG_OF) +int tpm_read_log_of(struct tpm_chip *chip); +#else +static inline int tpm_read_log_of(struct tpm_chip *chip) +{ + return -ENODEV; +} +#endif +#if defined(CONFIG_EFI) +int tpm_read_log_efi(struct tpm_chip *chip); +#else +static inline int tpm_read_log_efi(struct tpm_chip *chip) +{ + return -ENODEV; +} +#endif + +#endif diff --git a/drivers/char/tpm/tpm_eventlog_efi.c b/drivers/char/tpm/eventlog/efi.c index e3f9ffd341d2..3e673ab22cb4 100644 --- a/drivers/char/tpm/tpm_eventlog_efi.c +++ b/drivers/char/tpm/eventlog/efi.c @@ -14,7 +14,8 @@ #include <linux/efi.h> #include <linux/tpm_eventlog.h> -#include "tpm.h" +#include "../tpm.h" +#include "common.h" /* read binary bios log from EFI configuration table */ int tpm_read_log_efi(struct tpm_chip *chip) @@ -50,10 +51,9 @@ int tpm_read_log_efi(struct tpm_chip *chip) } /* malloc EventLog space */ - log->bios_event_log = kmalloc(log_size, GFP_KERNEL); + log->bios_event_log = kmemdup(log_tbl->log, log_size, GFP_KERNEL); if (!log->bios_event_log) goto err_memunmap; - memcpy(log->bios_event_log, log_tbl->log, log_size); log->bios_event_log_end = log->bios_event_log + log_size; tpm_log_version = log_tbl->version; diff --git a/drivers/char/tpm/tpm_eventlog_of.c b/drivers/char/tpm/eventlog/of.c index 96fd5646f866..bba5fba6cb3b 100644 --- a/drivers/char/tpm/tpm_eventlog_of.c +++ b/drivers/char/tpm/eventlog/of.c @@ -19,7 +19,8 @@ #include <linux/of.h> #include <linux/tpm_eventlog.h> -#include "tpm.h" +#include "../tpm.h" +#include "common.h" int tpm_read_log_of(struct tpm_chip *chip) { @@ -56,8 +57,8 @@ int tpm_read_log_of(struct tpm_chip *chip) * but physical tpm needs the conversion. */ if (of_property_match_string(np, "compatible", "IBM,vtpm") < 0) { - size = be32_to_cpup(sizep); - base = be64_to_cpup(basep); + size = be32_to_cpup((__force __be32 *)sizep); + base = be64_to_cpup((__force __be64 *)basep); } else { size = *sizep; base = *basep; @@ -68,14 +69,12 @@ int tpm_read_log_of(struct tpm_chip *chip) return -EIO; } - log->bios_event_log = kmalloc(size, GFP_KERNEL); + log->bios_event_log = kmemdup(__va(base), size, GFP_KERNEL); if (!log->bios_event_log) return -ENOMEM; log->bios_event_log_end = log->bios_event_log + size; - memcpy(log->bios_event_log, __va(base), size); - if (chip->flags & TPM_CHIP_FLAG_TPM2) return EFI_TCG2_EVENT_LOG_FORMAT_TCG_2; return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; diff --git a/drivers/char/tpm/tpm1_eventlog.c b/drivers/char/tpm/eventlog/tpm1.c index add798bd69d0..58c84784ba25 100644 --- a/drivers/char/tpm/tpm1_eventlog.c +++ b/drivers/char/tpm/eventlog/tpm1.c @@ -28,7 +28,8 @@ #include <linux/slab.h> #include <linux/tpm_eventlog.h> -#include "tpm.h" +#include "../tpm.h" +#include "common.h" static const char* tcpa_event_type_strings[] = { @@ -71,7 +72,7 @@ static const char* tcpa_pc_event_id_strings[] = { }; /* returns pointer to start of pos. entry of tcg log */ -static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos) +static void *tpm1_bios_measurements_start(struct seq_file *m, loff_t *pos) { loff_t i; struct tpm_chip *chip = m->private; @@ -118,7 +119,7 @@ static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos) return addr; } -static void *tpm_bios_measurements_next(struct seq_file *m, void *v, +static void *tpm1_bios_measurements_next(struct seq_file *m, void *v, loff_t *pos) { struct tcpa_event *event = v; @@ -149,7 +150,7 @@ static void *tpm_bios_measurements_next(struct seq_file *m, void *v, return v; } -static void tpm_bios_measurements_stop(struct seq_file *m, void *v) +static void tpm1_bios_measurements_stop(struct seq_file *m, void *v) { } @@ -232,7 +233,7 @@ static int get_event_name(char *dest, struct tcpa_event *event, } -static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) +static int tpm1_binary_bios_measurements_show(struct seq_file *m, void *v) { struct tcpa_event *event = v; struct tcpa_event temp_event; @@ -261,18 +262,7 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) } -static int tpm_bios_measurements_release(struct inode *inode, - struct file *file) -{ - struct seq_file *seq = (struct seq_file *)file->private_data; - struct tpm_chip *chip = (struct tpm_chip *)seq->private; - - put_device(&chip->dev); - - return seq_release(inode, file); -} - -static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v) +static int tpm1_ascii_bios_measurements_show(struct seq_file *m, void *v) { int len = 0; char *eventname; @@ -305,172 +295,16 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v) return 0; } -static const struct seq_operations tpm_ascii_b_measurements_seqops = { - .start = tpm_bios_measurements_start, - .next = tpm_bios_measurements_next, - .stop = tpm_bios_measurements_stop, - .show = tpm_ascii_bios_measurements_show, +const struct seq_operations tpm1_ascii_b_measurements_seqops = { + .start = tpm1_bios_measurements_start, + .next = tpm1_bios_measurements_next, + .stop = tpm1_bios_measurements_stop, + .show = tpm1_ascii_bios_measurements_show, }; -static const struct seq_operations tpm_binary_b_measurements_seqops = { - .start = tpm_bios_measurements_start, - .next = tpm_bios_measurements_next, - .stop = tpm_bios_measurements_stop, - .show = tpm_binary_bios_measurements_show, -}; - -static int tpm_bios_measurements_open(struct inode *inode, - struct file *file) -{ - int err; - struct seq_file *seq; - struct tpm_chip_seqops *chip_seqops; - const struct seq_operations *seqops; - struct tpm_chip *chip; - - inode_lock(inode); - if (!inode->i_private) { - inode_unlock(inode); - return -ENODEV; - } - chip_seqops = (struct tpm_chip_seqops *)inode->i_private; - seqops = chip_seqops->seqops; - chip = chip_seqops->chip; - get_device(&chip->dev); - inode_unlock(inode); - - /* now register seq file */ - err = seq_open(file, seqops); - if (!err) { - seq = file->private_data; - seq->private = chip; - } - - return err; -} - -static const struct file_operations tpm_bios_measurements_ops = { - .owner = THIS_MODULE, - .open = tpm_bios_measurements_open, - .read = seq_read, - .llseek = seq_lseek, - .release = tpm_bios_measurements_release, +const struct seq_operations tpm1_binary_b_measurements_seqops = { + .start = tpm1_bios_measurements_start, + .next = tpm1_bios_measurements_next, + .stop = tpm1_bios_measurements_stop, + .show = tpm1_binary_bios_measurements_show, }; - -static int tpm_read_log(struct tpm_chip *chip) -{ - int rc; - - if (chip->log.bios_event_log != NULL) { - dev_dbg(&chip->dev, - "%s: ERROR - event log already initialized\n", - __func__); - return -EFAULT; - } - - rc = tpm_read_log_acpi(chip); - if (rc != -ENODEV) - return rc; - - rc = tpm_read_log_efi(chip); - if (rc != -ENODEV) - return rc; - - return tpm_read_log_of(chip); -} - -/* - * tpm_bios_log_setup() - Read the event log from the firmware - * @chip: TPM chip to use. - * - * If an event log is found then the securityfs files are setup to - * export it to userspace, otherwise nothing is done. - * - * Returns -ENODEV if the firmware has no event log or securityfs is not - * supported. - */ -int tpm_bios_log_setup(struct tpm_chip *chip) -{ - const char *name = dev_name(&chip->dev); - unsigned int cnt; - int log_version; - int rc = 0; - - rc = tpm_read_log(chip); - if (rc < 0) - return rc; - log_version = rc; - - cnt = 0; - chip->bios_dir[cnt] = securityfs_create_dir(name, NULL); - /* NOTE: securityfs_create_dir can return ENODEV if securityfs is - * compiled out. The caller should ignore the ENODEV return code. - */ - if (IS_ERR(chip->bios_dir[cnt])) - goto err; - cnt++; - - chip->bin_log_seqops.chip = chip; - if (log_version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) - chip->bin_log_seqops.seqops = - &tpm2_binary_b_measurements_seqops; - else - chip->bin_log_seqops.seqops = - &tpm_binary_b_measurements_seqops; - - - chip->bios_dir[cnt] = - securityfs_create_file("binary_bios_measurements", - 0440, chip->bios_dir[0], - (void *)&chip->bin_log_seqops, - &tpm_bios_measurements_ops); - if (IS_ERR(chip->bios_dir[cnt])) - goto err; - cnt++; - - if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { - - chip->ascii_log_seqops.chip = chip; - chip->ascii_log_seqops.seqops = - &tpm_ascii_b_measurements_seqops; - - chip->bios_dir[cnt] = - securityfs_create_file("ascii_bios_measurements", - 0440, chip->bios_dir[0], - (void *)&chip->ascii_log_seqops, - &tpm_bios_measurements_ops); - if (IS_ERR(chip->bios_dir[cnt])) - goto err; - cnt++; - } - - return 0; - -err: - rc = PTR_ERR(chip->bios_dir[cnt]); - chip->bios_dir[cnt] = NULL; - tpm_bios_log_teardown(chip); - return rc; -} - -void tpm_bios_log_teardown(struct tpm_chip *chip) -{ - int i; - struct inode *inode; - - /* securityfs_remove currently doesn't take care of handling sync - * between removal and opening of pseudo files. To handle this, a - * workaround is added by making i_private = NULL here during removal - * and to check it during open(), both within inode_lock()/unlock(). - * This design ensures that open() either safely gets kref or fails. - */ - for (i = (TPM_NUM_EVENT_LOG_FILES - 1); i >= 0; i--) { - if (chip->bios_dir[i]) { - inode = d_inode(chip->bios_dir[i]); - inode_lock(inode); - inode->i_private = NULL; - inode_unlock(inode); - securityfs_remove(chip->bios_dir[i]); - } - } -} diff --git a/drivers/char/tpm/tpm2_eventlog.c b/drivers/char/tpm/eventlog/tpm2.c index 1ce4411292ba..1b8fa9de2cac 100644 --- a/drivers/char/tpm/tpm2_eventlog.c +++ b/drivers/char/tpm/eventlog/tpm2.c @@ -23,7 +23,8 @@ #include <linux/slab.h> #include <linux/tpm_eventlog.h> -#include "tpm.h" +#include "../tpm.h" +#include "common.h" /* * calc_tpm2_event_size() - calculate the event size, where event diff --git a/drivers/char/tpm/st33zp24/spi.c b/drivers/char/tpm/st33zp24/spi.c index 0fc4f20b5f83..d7909ab287a8 100644 --- a/drivers/char/tpm/st33zp24/spi.c +++ b/drivers/char/tpm/st33zp24/spi.c @@ -40,7 +40,7 @@ #define ST33ZP24_OK 0x5A #define ST33ZP24_UNDEFINED_ERR 0x80 #define ST33ZP24_BADLOCALITY 0x81 -#define ST33ZP24_TISREGISTER_UKNOWN 0x82 +#define ST33ZP24_TISREGISTER_UNKNOWN 0x82 #define ST33ZP24_LOCALITY_NOT_ACTIVATED 0x83 #define ST33ZP24_HASH_END_BEFORE_HASH_START 0x84 #define ST33ZP24_BAD_COMMAND_ORDER 0x85 @@ -84,7 +84,7 @@ static int st33zp24_status_to_errno(u8 code) return 0; case ST33ZP24_UNDEFINED_ERR: case ST33ZP24_BADLOCALITY: - case ST33ZP24_TISREGISTER_UKNOWN: + case ST33ZP24_TISREGISTER_UNKNOWN: case ST33ZP24_LOCALITY_NOT_ACTIVATED: case ST33ZP24_HASH_END_BEFORE_HASH_START: case ST33ZP24_BAD_COMMAND_ORDER: diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c index f95b9c75175b..abd675bec88c 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.c +++ b/drivers/char/tpm/st33zp24/st33zp24.c @@ -373,8 +373,6 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf, int ret; u8 data; - if (!chip) - return -EBUSY; if (len < TPM_HEADER_SIZE) return -EBUSY; diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index c43a9e28995e..e32f6e85dc6d 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -489,7 +489,7 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, goto out; } - tpm_msleep(TPM_TIMEOUT); + tpm_msleep(TPM_TIMEOUT_POLL); rmb(); } while (time_before(jiffies, stop)); @@ -587,7 +587,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, */ if (rc == TPM2_RC_TESTING && cc == TPM2_CC_SELF_TEST) break; - delay_msec *= 2; + if (delay_msec > TPM2_DURATION_LONG) { if (rc == TPM2_RC_RETRY) dev_err(&chip->dev, "in retry loop\n"); @@ -597,6 +597,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, break; } tpm_msleep(delay_msec); + delay_msec *= 2; memcpy(buf, save, save_size); } return ret; diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 7f2d0f489e9c..4426649e431c 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -53,7 +53,10 @@ enum tpm_const { enum tpm_timeout { TPM_TIMEOUT = 5, /* msecs */ TPM_TIMEOUT_RETRY = 100, /* msecs */ - TPM_TIMEOUT_RANGE_US = 300 /* usecs */ + TPM_TIMEOUT_RANGE_US = 300, /* usecs */ + TPM_TIMEOUT_POLL = 1, /* msecs */ + TPM_TIMEOUT_USECS_MIN = 100, /* usecs */ + TPM_TIMEOUT_USECS_MAX = 500 /* usecs */ }; /* TPM addresses */ @@ -590,33 +593,6 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc, int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc, u8 *buf, size_t *bufsiz); -extern const struct seq_operations tpm2_binary_b_measurements_seqops; - -#if defined(CONFIG_ACPI) -int tpm_read_log_acpi(struct tpm_chip *chip); -#else -static inline int tpm_read_log_acpi(struct tpm_chip *chip) -{ - return -ENODEV; -} -#endif -#if defined(CONFIG_OF) -int tpm_read_log_of(struct tpm_chip *chip); -#else -static inline int tpm_read_log_of(struct tpm_chip *chip) -{ - return -ENODEV; -} -#endif -#if defined(CONFIG_EFI) -int tpm_read_log_efi(struct tpm_chip *chip); -#else -static inline int tpm_read_log_efi(struct tpm_chip *chip) -{ - return -ENODEV; -} -#endif - int tpm_bios_log_setup(struct tpm_chip *chip); void tpm_bios_log_teardown(struct tpm_chip *chip); #endif diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index 4e4014eabdb9..6122d3276f72 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c @@ -102,8 +102,9 @@ static int tpm2_load_context(struct tpm_chip *chip, u8 *buf, * TPM_RC_REFERENCE_H0 means the session has been * flushed outside the space */ - rc = -ENOENT; + *handle = 0; tpm_buf_destroy(&tbuf); + return -ENOENT; } else if (rc > 0) { dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n", __func__, rc); diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 7f78482cd157..34fbc6cb097b 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -511,8 +511,10 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address, sizeof(struct crb_regs_tail)); - if (IS_ERR(priv->regs_t)) - return PTR_ERR(priv->regs_t); + if (IS_ERR(priv->regs_t)) { + ret = PTR_ERR(priv->regs_t); + goto out_relinquish_locality; + } /* * PTT HW bug w/a: wake up the device to access @@ -520,7 +522,7 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, */ ret = crb_cmd_ready(dev, priv); if (ret) - return ret; + goto out_relinquish_locality; pa_high = ioread32(&priv->regs_t->ctrl_cmd_pa_high); pa_low = ioread32(&priv->regs_t->ctrl_cmd_pa_low); @@ -565,6 +567,8 @@ out: crb_go_idle(dev, priv); +out_relinquish_locality: + __crb_relinquish_locality(dev, priv, 0); return ret; diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 5a1f47b43947..8b46aaa9e049 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -31,12 +31,6 @@ #include "tpm.h" #include "tpm_tis_core.h" -/* This is a polling delay to check for status and burstcount. - * As per ddwg input, expectation is that status check and burstcount - * check should return within few usecs. - */ -#define TPM_POLL_SLEEP 1 /* msec */ - static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value); static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, @@ -90,7 +84,8 @@ again: } } else { do { - tpm_msleep(TPM_POLL_SLEEP); + usleep_range(TPM_TIMEOUT_USECS_MIN, + TPM_TIMEOUT_USECS_MAX); status = chip->ops->status(chip); if ((status & mask) == mask) return 0; @@ -143,13 +138,58 @@ static bool check_locality(struct tpm_chip *chip, int l) return false; } +static bool locality_inactive(struct tpm_chip *chip, int l) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + int rc; + u8 access; + + rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); + if (rc < 0) + return false; + + if ((access & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) + == TPM_ACCESS_VALID) + return true; + + return false; +} + static int release_locality(struct tpm_chip *chip, int l) { struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + unsigned long stop, timeout; + long rc; tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); - return 0; + stop = jiffies + chip->timeout_a; + + if (chip->flags & TPM_CHIP_FLAG_IRQ) { +again: + timeout = stop - jiffies; + if ((long)timeout <= 0) + return -1; + + rc = wait_event_interruptible_timeout(priv->int_queue, + (locality_inactive(chip, l)), + timeout); + + if (rc > 0) + return 0; + + if (rc == -ERESTARTSYS && freezing(current)) { + clear_thread_flag(TIF_SIGPENDING); + goto again; + } + } else { + do { + if (locality_inactive(chip, l)) + return 0; + tpm_msleep(TPM_TIMEOUT); + } while (time_before(jiffies, stop)); + } + return -1; } static int request_locality(struct tpm_chip *chip, int l) @@ -234,7 +274,7 @@ static int get_burstcount(struct tpm_chip *chip) burstcnt = (value >> 8) & 0xFFFF; if (burstcnt) return burstcnt; - tpm_msleep(TPM_POLL_SLEEP); + usleep_range(TPM_TIMEOUT_USECS_MIN, TPM_TIMEOUT_USECS_MAX); } while (time_before(jiffies, stop)); return -EBUSY; } |