From 2b30a90f6c358714b9d6e628ac92e514917f93a1 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 11 Nov 2011 12:57:02 -0500 Subject: tpm: Have tpm_get_timeouts return an error code Have the tpm_get_timeouts function return an error code. Signed-off-by: Stefan Berger --- drivers/char/tpm/tpm.c | 9 +++++---- drivers/char/tpm/tpm.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index e53af7638186..b6c4a320cfde 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -527,7 +527,7 @@ void tpm_gen_interrupt(struct tpm_chip *chip) } EXPORT_SYMBOL_GPL(tpm_gen_interrupt); -void tpm_get_timeouts(struct tpm_chip *chip) +int tpm_get_timeouts(struct tpm_chip *chip) { struct tpm_cmd_t tpm_cmd; struct timeout_t *timeout_cap; @@ -549,7 +549,7 @@ void tpm_get_timeouts(struct tpm_chip *chip) if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || be32_to_cpu(tpm_cmd.header.out.length) != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) - return; + return -EINVAL; timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; /* Don't overwrite default if value is 0 */ @@ -580,12 +580,12 @@ duration: rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the durations"); if (rc) - return; + return rc; if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || be32_to_cpu(tpm_cmd.header.out.length) != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) - return; + return -EINVAL; duration_cap = &tpm_cmd.params.getcap_out.cap.duration; chip->vendor.duration[TPM_SHORT] = @@ -607,6 +607,7 @@ duration: chip->vendor.duration_adjusted = true; dev_info(chip->dev, "Adjusting TPM timeout parameters."); } + return 0; } EXPORT_SYMBOL_GPL(tpm_get_timeouts); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 9c4163cfa3ce..4747b68c0c1b 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -279,7 +279,7 @@ struct tpm_cmd_t { ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); -extern void tpm_get_timeouts(struct tpm_chip *); +extern int tpm_get_timeouts(struct tpm_chip *); extern void tpm_gen_interrupt(struct tpm_chip *); extern void tpm_continue_selftest(struct tpm_chip *); extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); -- cgit v1.2.1 From d97c6ade5926afb6d52df36c33a3491d62cd0dc0 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 11 Nov 2011 12:57:03 -0500 Subject: tpm: Cleanup tpm_continue_selftest Cleanup the tpm_continue_selftest function. Signed-off-by: Stefan Berger --- drivers/char/tpm/tpm.c | 30 +++++++++++++++++++++++------- drivers/char/tpm/tpm.h | 2 +- 2 files changed, 24 insertions(+), 8 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index b6c4a320cfde..9bd4668e2855 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -611,15 +611,31 @@ duration: } EXPORT_SYMBOL_GPL(tpm_get_timeouts); -void tpm_continue_selftest(struct tpm_chip *chip) +#define TPM_ORD_CONTINUE_SELFTEST 83 +#define CONTINUE_SELFTEST_RESULT_SIZE 10 + +static struct tpm_input_header continue_selftest_header = { + .tag = 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. + */ +int tpm_continue_selftest(struct tpm_chip *chip) { - u8 data[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 10, /* length */ - 0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */ - }; + int rc; + struct tpm_cmd_t cmd; - tpm_transmit(chip, data, sizeof(data)); + cmd.header.in = continue_selftest_header; + rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, + "continue selftest"); + return rc; } EXPORT_SYMBOL_GPL(tpm_continue_selftest); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 4747b68c0c1b..5d2be8ae1b48 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -281,7 +281,7 @@ ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); extern int tpm_get_timeouts(struct tpm_chip *); extern void tpm_gen_interrupt(struct tpm_chip *); -extern void tpm_continue_selftest(struct tpm_chip *); +extern int tpm_continue_selftest(struct tpm_chip *); extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); extern struct tpm_chip* tpm_register_hardware(struct device *, const struct tpm_vendor_specific *); -- cgit v1.2.1 From 68d6e6713fcb2ea6278661aaaf5f1c9c821b3751 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 11 Nov 2011 12:57:04 -0500 Subject: tpm: Introduce function to poll for result of self test This patch introduces a function that runs the TPM_ContinueSelfTest() function and then polls the TPM to check whether it finished the selftest and can receive new commands. Signed-off-by: Stefan Berger --- drivers/char/tpm/tpm.c | 44 +++++++++++++++++++++++++++++++++++++++++--- drivers/char/tpm/tpm.h | 4 +++- drivers/char/tpm/tpm_tis.c | 9 +++++++-- 3 files changed, 51 insertions(+), 6 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 9bd4668e2855..2e12b3f98139 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -627,7 +627,7 @@ static struct tpm_input_header continue_selftest_header = { * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing * a TPM error code. */ -int tpm_continue_selftest(struct tpm_chip *chip) +static int tpm_continue_selftest(struct tpm_chip *chip) { int rc; struct tpm_cmd_t cmd; @@ -637,7 +637,6 @@ int tpm_continue_selftest(struct tpm_chip *chip) "continue selftest"); return rc; } -EXPORT_SYMBOL_GPL(tpm_continue_selftest); ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, char *buf) @@ -732,7 +731,7 @@ static struct tpm_input_header pcrread_header = { .ordinal = TPM_ORDINAL_PCRREAD }; -int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) +static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) { int rc; struct tpm_cmd_t cmd; @@ -812,6 +811,45 @@ int tpm_pcr_extend(u32 chip_num, 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; + u8 digest[TPM_DIGEST_SIZE]; + unsigned int loops; + unsigned int delay_msec = 1000; + unsigned long duration; + + duration = tpm_calc_ordinal_duration(chip, + TPM_ORD_CONTINUE_SELFTEST); + + loops = jiffies_to_msecs(duration) / delay_msec; + + rc = tpm_continue_selftest(chip); + /* 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 { + rc = __tpm_pcr_read(chip, 0, digest); + if (rc != TPM_WARN_DOING_SELFTEST) + return rc; + msleep(delay_msec); + } while (--loops > 0); + + return rc; +} +EXPORT_SYMBOL_GPL(tpm_do_selftest); + int tpm_send(u32 chip_num, void *cmd, size_t buflen) { struct tpm_chip *chip; diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 5d2be8ae1b48..e264de16285f 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -38,6 +38,8 @@ enum tpm_addr { TPM_ADDR = 0x4E, }; +#define TPM_WARN_DOING_SELFTEST 0x802 + extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, char *); extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, @@ -281,7 +283,7 @@ ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); extern int tpm_get_timeouts(struct tpm_chip *); extern void tpm_gen_interrupt(struct tpm_chip *); -extern int tpm_continue_selftest(struct tpm_chip *); +extern int tpm_do_selftest(struct tpm_chip *); extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); extern struct tpm_chip* tpm_register_hardware(struct device *, const struct tpm_vendor_specific *); diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 3f4051a7c5a7..d30d5c3c6c02 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -616,6 +616,12 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, /* get the timeouts before testing for irqs */ tpm_get_timeouts(chip); + if (tpm_do_selftest(chip)) { + dev_err(dev, "TPM self test failed\n"); + rc = -ENODEV; + goto out_err; + } + /* INTERRUPT Setup */ init_waitqueue_head(&chip->vendor.read_queue); init_waitqueue_head(&chip->vendor.int_queue); @@ -722,7 +728,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, list_add(&chip->vendor.list, &tis_chips); spin_unlock(&tis_lock); - tpm_continue_selftest(chip); return 0; out_err: @@ -790,7 +795,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev) ret = tpm_pm_resume(&dev->dev); if (!ret) - tpm_continue_selftest(chip); + tpm_do_selftest(chip); return ret; } -- cgit v1.2.1 From 7f326ed7ff221a109bf89288bf6c8f0142e3e75c Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 11 Nov 2011 12:57:05 -0500 Subject: tpm_tis: Check return code from getting timeouts/durations Check the return code from getting the TPM's timeouts and durations and reject the driver if they could not be read. Signed-off-by: Stefan Berger --- drivers/char/tpm/tpm_tis.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index d30d5c3c6c02..34832bc74649 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -614,7 +614,11 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, dev_dbg(dev, "\tData Avail Int Support\n"); /* get the timeouts before testing for irqs */ - tpm_get_timeouts(chip); + if (tpm_get_timeouts(chip)) { + dev_err(dev, "Could not get TPM timeouts and durations\n"); + rc = -ENODEV; + goto out_err; + } if (tpm_do_selftest(chip)) { dev_err(dev, "TPM self test failed\n"); -- cgit v1.2.1 From a927b8131794ee449b7f6666e7ab61301949b20f Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 11 Nov 2011 12:57:06 -0500 Subject: tpm_tis: add delay after aborting command This patch adds a delay after aborting a command. Some TPMs need this and will not process the subsequent command correctly otherwise. Signed-off-by: Stefan Berger --- drivers/char/tpm/tpm_tis.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 34832bc74649..d93bafde3120 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -432,6 +432,9 @@ static int probe_itpm(struct tpm_chip *chip) out: itpm = rem_itpm; tpm_tis_ready(chip); + /* some TPMs need a break here otherwise they will not work + * correctly on the immediately subsequent command */ + msleep(chip->vendor.timeout_b); release_locality(chip, chip->vendor.locality, 0); return rc; -- cgit v1.2.1 From 9efa54f002cc03fdb4e9d8d508aa996af01c48d0 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Fri, 16 Sep 2011 14:34:37 -0300 Subject: TPM: Use vendor specific function for status probe Moved from using tpm_tis_status() to the vendor specific one in wait_for_stat(). This way other TPM drivers can use it instead of reimplementing another. Signed-off-by: Rajiv Andrade --- drivers/char/tpm/tpm_tis.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index d93bafde3120..e4553eb6e542 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -201,7 +201,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, u8 status; /* check current status */ - status = tpm_tis_status(chip); + status = chip->vendor.status(chip); if ((status & mask) == mask) return 0; @@ -213,9 +213,9 @@ again: if ((long)timeout <= 0) return -ETIME; rc = wait_event_interruptible_timeout(*queue, - ((tpm_tis_status - (chip) & mask) == - mask), timeout); + ((chip->vendor.status(chip) + & mask) == mask), + timeout); if (rc > 0) return 0; if (rc == -ERESTARTSYS && freezing(current)) { @@ -225,7 +225,7 @@ again: } else { do { msleep(TPM_TIMEOUT); - status = tpm_tis_status(chip); + status = chip->vendor.status(chip); if ((status & mask) == mask) return 0; } while (time_before(jiffies, stop)); -- cgit v1.2.1 From fd04886660208ab2e35baaca55588afa57d52c9c Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Fri, 16 Sep 2011 14:39:40 -0300 Subject: TPM: Export wait_for_stat for other vendor specific drivers Moved wait_for_stat to tpm.c so that other drivers can use it. Also renamed it to avoid future namespace conflicts. Signed-off-by: Rajiv Andrade --- drivers/char/tpm/tpm.c | 41 +++++++++++++++++++++++++++++ drivers/char/tpm/tpm.h | 3 ++- drivers/char/tpm/tpm_tis.c | 64 +++++++++------------------------------------- 3 files changed, 55 insertions(+), 53 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 2e12b3f98139..efd24bbb5cb1 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "tpm.h" @@ -1057,6 +1058,46 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, } EXPORT_SYMBOL_GPL(tpm_store_cancel); +int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, + wait_queue_head_t *queue) +{ + unsigned long stop; + long rc; + u8 status; + + /* check current status */ + status = chip->vendor.status(chip); + if ((status & mask) == mask) + return 0; + + stop = jiffies + timeout; + + if (chip->vendor.irq) { +again: + timeout = stop - jiffies; + if ((long)timeout <= 0) + return -ETIME; + rc = wait_event_interruptible_timeout(*queue, + ((chip->vendor.status(chip) + & mask) == mask), + timeout); + if (rc > 0) + return 0; + if (rc == -ERESTARTSYS && freezing(current)) { + clear_thread_flag(TIF_SIGPENDING); + goto again; + } + } else { + do { + msleep(TPM_TIMEOUT); + status = chip->vendor.status(chip); + if ((status & mask) == mask) + return 0; + } while (time_before(jiffies, stop)); + } + return -ETIME; +} +EXPORT_SYMBOL_GPL(wait_for_tpm_stat); /* * Device file system interface to the TPM * diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index e264de16285f..9deb65c0ab61 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -296,7 +296,8 @@ extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *); extern void tpm_remove_hardware(struct device *); extern int tpm_pm_suspend(struct device *, pm_message_t); extern int tpm_pm_resume(struct device *); - +extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long, + wait_queue_head_t *); #ifdef CONFIG_ACPI extern struct dentry ** tpm_bios_log_setup(char *); extern void tpm_bios_log_teardown(struct dentry **); diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index e4553eb6e542..92f9f34e88f7 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -193,54 +193,14 @@ static int get_burstcount(struct tpm_chip *chip) return -EBUSY; } -static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, - wait_queue_head_t *queue) -{ - unsigned long stop; - long rc; - u8 status; - - /* check current status */ - status = chip->vendor.status(chip); - if ((status & mask) == mask) - return 0; - - stop = jiffies + timeout; - - if (chip->vendor.irq) { -again: - timeout = stop - jiffies; - if ((long)timeout <= 0) - return -ETIME; - rc = wait_event_interruptible_timeout(*queue, - ((chip->vendor.status(chip) - & mask) == mask), - timeout); - if (rc > 0) - return 0; - if (rc == -ERESTARTSYS && freezing(current)) { - clear_thread_flag(TIF_SIGPENDING); - goto again; - } - } else { - do { - msleep(TPM_TIMEOUT); - status = chip->vendor.status(chip); - if ((status & mask) == mask) - return 0; - } while (time_before(jiffies, stop)); - } - return -ETIME; -} - static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) { int size = 0, burstcnt; while (size < count && - wait_for_stat(chip, - TPM_STS_DATA_AVAIL | TPM_STS_VALID, - chip->vendor.timeout_c, - &chip->vendor.read_queue) + wait_for_tpm_stat(chip, + TPM_STS_DATA_AVAIL | TPM_STS_VALID, + chip->vendor.timeout_c, + &chip->vendor.read_queue) == 0) { burstcnt = get_burstcount(chip); for (; burstcnt > 0 && size < count; burstcnt--) @@ -282,8 +242,8 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) goto out; } - wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, - &chip->vendor.int_queue); + wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, + &chip->vendor.int_queue); status = tpm_tis_status(chip); if (status & TPM_STS_DATA_AVAIL) { /* retry? */ dev_err(chip->dev, "Error left over data\n"); @@ -317,7 +277,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) status = tpm_tis_status(chip); if ((status & TPM_STS_COMMAND_READY) == 0) { tpm_tis_ready(chip); - if (wait_for_stat + if (wait_for_tpm_stat (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, &chip->vendor.int_queue) < 0) { rc = -ETIME; @@ -333,8 +293,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) count++; } - wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, - &chip->vendor.int_queue); + wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, + &chip->vendor.int_queue); status = tpm_tis_status(chip); if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { rc = -EIO; @@ -345,8 +305,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) /* write last byte */ iowrite8(buf[count], chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality)); - wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, - &chip->vendor.int_queue); + wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, + &chip->vendor.int_queue); status = tpm_tis_status(chip); if ((status & TPM_STS_DATA_EXPECT) != 0) { rc = -EIO; @@ -381,7 +341,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) if (chip->vendor.irq) { ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); - if (wait_for_stat + if (wait_for_tpm_stat (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, tpm_calc_ordinal_duration(chip, ordinal), &chip->vendor.read_queue) < 0) { -- cgit v1.2.1 From 2f592f2a7d74c66763a6903edd04109132674d73 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Tue, 1 Nov 2011 09:42:58 -0200 Subject: TPM: NSC and TIS drivers X86 dependency fix A previous commit removed its PNP dependency, that in fact wasn't necessary, but also allowed it be built for other architectures not supported by it. This then caused kernel oops on PPC based machines. I'm placing a x86 dependency back correctly. Signed-off-by: Rajiv Andrade --- drivers/char/tpm/Kconfig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index f6595aba4f0f..4d9273a1a781 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -27,6 +27,7 @@ if TCG_TPM config TCG_TIS tristate "TPM Interface Specification 1.2 Interface" + depends on X86 ---help--- If you have a TPM security chip that is compliant with the TCG TIS 1.2 TPM specification say Yes and it will be accessible @@ -35,6 +36,7 @@ config TCG_TIS config TCG_NSC tristate "National Semiconductor TPM Interface" + depends on X86 ---help--- If you have a TPM security chip from National Semiconductor say Yes and it will be accessible from within Linux. To -- cgit v1.2.1 From b9e3238aa36db33aa0d0bd44ef85297c45627aac Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Tue, 1 Nov 2011 17:00:52 -0200 Subject: TPM: fix transmit_cmd error logic It's incorrect to assume that buffers returned by the TPM 10 bytes long are always error reports. This patches parses the error field in its header instead. The error report is now being printed using dev_err() instead of dev_dbg(), making it easier for users to provide more detailed bug reports. Signed-off-by: Rajiv Andrade --- drivers/char/tpm/tpm.c | 15 ++++++++------- drivers/char/tpm/tpm.h | 2 +- drivers/char/tpm/tpm_tis.c | 2 -- 3 files changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index efd24bbb5cb1..67335af0ec2a 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -438,7 +438,6 @@ out: } #define TPM_DIGEST_SIZE 20 -#define TPM_ERROR_SIZE 10 #define TPM_RET_CODE_IDX 6 enum tpm_capabilities { @@ -467,12 +466,14 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, len = tpm_transmit(chip,(u8 *) cmd, len); if (len < 0) return len; - if (len == TPM_ERROR_SIZE) { - err = be32_to_cpu(cmd->header.out.return_code); - dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); - return err; - } - return 0; + else if (len < TPM_HEADER_SIZE) + return -EFAULT; + + err = be32_to_cpu(cmd->header.out.return_code); + if (err != 0) + dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); + + return err; } #define TPM_INTERNAL_RESULT_SIZE 200 diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 9deb65c0ab61..8c1df302fbb6 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -39,7 +39,7 @@ enum tpm_addr { }; #define TPM_WARN_DOING_SELFTEST 0x802 - +#define TPM_HEADER_SIZE 10 extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, char *); extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 92f9f34e88f7..10cc44ceb5d1 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -29,8 +29,6 @@ #include #include "tpm.h" -#define TPM_HEADER_SIZE 10 - enum tis_access { TPM_ACCESS_VALID = 0x80, TPM_ACCESS_ACTIVE_LOCALITY = 0x20, -- cgit v1.2.1