From: Stefan Berger <stefanb@linux.vnet.ibm.com>
To: John Hughes <john@calvaedi.com>
Cc: Jonathan Nieder <jrnieder@gmail.com>,
John Hughes <john@atlantech.com>,
Jeff Layton <jlayton@poochiereds.net>,
linux-kernel@vger.kernel.org, tpmdd-devel@lists.sourceforge.net,
Rajiv Andrade <srajiv@linux.vnet.ibm.com>,
Eric Paris <eparis@redhat.com>
Subject: Re: [Sony Vaio TX3] TPM chip prevents machine from suspending a second time
Date: Sun, 29 Jan 2012 13:22:04 -0500 [thread overview]
Message-ID: <4F258E4C.8020606@linux.vnet.ibm.com> (raw)
In-Reply-To: <4F252441.3090507@calvaedi.com>
[-- Attachment #1: Type: text/plain, Size: 1548 bytes --]
On 01/29/2012 05:49 AM, John Hughes wrote:
> On 23/01/12 21:52, Stefan Berger wrote:
>>
>> Can you apply the patch below to your tpm_tis.c (or somewhere else in
>> the kernel) and let me/us know what it reports in 'dmesg' upon a
>> 'modprobe tpm_tis'?
>
> [ 48.826151] tpm_tis 00:07: dmi: 0: (null)
> [ 48.826157] tpm_tis 00:07: dmi: 1: Phoenix Technologies LTD
> [ 48.826161] tpm_tis 00:07: dmi: 2: R0021N3
> [ 48.826165] tpm_tis 00:07: dmi: 3: 05/09/2006
> [ 48.826169] tpm_tis 00:07: dmi: 4: Sony Corporation
> [ 48.826173] tpm_tis 00:07: dmi: 5: VGN-TX3XP_B
> [ 48.826177] tpm_tis 00:07: dmi: 6: J001QHZL
> [ 48.826181] tpm_tis 00:07: dmi: 7: 28244651-5000176
> [ 48.826186] tpm_tis 00:07: dmi: 8:
> DC744BA0-5B3C-11D9-8822-0013A93CCD4D
> [ 48.826190] tpm_tis 00:07: dmi: 9: Sony Corporation
> [ 48.826195] tpm_tis 00:07: dmi: 10: VAIO
> [ 48.826199] tpm_tis 00:07: dmi: 11: N/A
> [ 48.826204] tpm_tis 00:07: dmi: 12: N/A
> [ 48.826208] tpm_tis 00:07: dmi: 13: N/A
> [ 48.826213] tpm_tis 00:07: dmi: 14: Sony Corporation
> [ 48.826217] tpm_tis 00:07: dmi: 15: 10
> [ 48.826221] tpm_tis 00:07: dmi: 16: N/A
> [ 48.826225] tpm_tis 00:07: dmi: 17: J001QHZL
> [ 48.826229] tpm_tis 00:07: dmi: 18:
> [ 48.826235] tpm_tis 00:07: 1.2 TPM (device-id 0xB, rev-id 16)
>
Thanks. Please try the attached patch.
I am not sure whether this is the right way to go, though: Is it a
problem particular to this BIOS + Board or a general problem of this
BIOS? Is it specific to the TX3 or to all VAIOs?
Stefan
[-- Attachment #2: tpm_resume_quirks.diff --]
[-- Type: text/plain, Size: 5699 bytes --]
Add a TPM resume quirk for machines where the BIOS doesn't send the
TPM_Startup(ST_STATE) to the TPM and subsequent suspends fail due
to this. Identify machines by their SMBIOS data and only apply the quirk
on those known to need it.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
drivers/char/tpm/tpm.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++++
drivers/char/tpm/tpm.h | 8 ++
2 files changed, 161 insertions(+)
Index: linux-2.6/drivers/char/tpm/tpm.c
===================================================================
--- linux-2.6.orig/drivers/char/tpm/tpm.c
+++ linux-2.6/drivers/char/tpm/tpm.c
@@ -28,6 +28,7 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/freezer.h>
+#include <linux/dmi.h>
#include "tpm.h"
@@ -62,6 +63,131 @@ static LIST_HEAD(tpm_chip_list);
static DEFINE_SPINLOCK(driver_lock);
static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
+/***** tpm quirks *****/
+
+#ifdef CONFIG_DMI
+
+struct tpm_dmi_entry {
+ enum dmi_field id;
+ const char **value;
+};
+
+struct tpm_resume_quirks {
+ const char *quirk_name;
+ const struct tpm_dmi_entry *dmi_entry;
+};
+
+#define TPM_DMI_ENTRY_LAST \
+ { .id = DMI_NONE, .value = (const char*[]) { NULL }, }
+
+static const struct tpm_resume_quirks tpm_resume_quirks[] = {
+ {
+ .quirk_name = "Sony Vaio TX3",
+ .dmi_entry = (struct tpm_dmi_entry[]) {
+ {
+ .id = DMI_BIOS_VENDOR,
+ .value = (const char*[]) {
+ "Phoenix Technologies LTD",
+ NULL,
+ },
+ },
+ {
+ .id = DMI_SYS_VENDOR,
+ .value = (const char*[]) {
+ "Sony Corporation",
+ NULL,
+ },
+ },
+ {
+ .id = DMI_PRODUCT_NAME,
+ .value = (const char*[]) {
+ "VGN-TX3XP_B",
+ NULL,
+ },
+ },
+ {
+ .id = DMI_BOARD_NAME,
+ .value = (const char*[]) {
+ "VAIO",
+ NULL,
+ },
+ },
+ TPM_DMI_ENTRY_LAST
+ }
+ }
+};
+
+bool find_str_in_array(const char **array, const char *val)
+{
+ int i = 0;
+
+ while (array[i]) {
+ if (!strcmp(array[i++], val))
+ return true;
+ }
+
+ return false;
+}
+
+static bool tpm_resume_quirk_dmi(struct tpm_chip *chip)
+{
+ int i, j, rc;
+ bool found = false, handled = false;
+ const char *val;
+ const struct tpm_dmi_entry *dmi_entry;
+
+ for (i = 0; i < ARRAY_SIZE(tpm_resume_quirks) && !handled; i++) {
+ j = 0;
+ found = true;
+
+ while (true) {
+ dmi_entry = &tpm_resume_quirks[i].dmi_entry[j];
+
+ if (dmi_entry->id == DMI_NONE)
+ break;
+
+ val = dmi_get_system_info(dmi_entry->id);
+ if (!val) {
+ found = false;
+ break;
+ }
+
+ found = find_str_in_array(dmi_entry->value, val);
+ if (!found)
+ break;
+ j++;
+ }
+
+ if (found) {
+ dev_info(chip->dev,
+ "Using tpm resume quirk '%s'.\n",
+ tpm_resume_quirks[i].quirk_name);
+ rc = tpm_startup_ststate(chip);
+ if (rc < 0)
+ dev_err(chip->dev,
+ "quirk: TPM startup(ST_STATE) "
+ "failed.\n");
+ handled = true;
+ break;
+ }
+ }
+ return handled;
+}
+
+#else
+
+static bool tpm_resume_quirk_dmi(struct tpm_chip *tpm_chip)
+{
+ return false;
+}
+
+#endif
+
+static void tpm_resume_quirk(struct tpm_chip *tpm_chip)
+{
+ tpm_resume_quirk_dmi(tpm_chip);
+}
+
/*
* Array with one entry per ordinal defining the maximum amount
* of time the chip could take to return the result. The ordinal
@@ -864,6 +990,31 @@ int tpm_do_selftest(struct tpm_chip *chi
}
EXPORT_SYMBOL_GPL(tpm_do_selftest);
+/**
+ * tpm_startup_ststate - send a ststartup to the TPM
+ */
+#define TPM_ORD_STARTUP 153
+#define STARTUP_RESULT_SIZE 10
+
+static struct tpm_input_header startup_ststate_header = {
+ .tag = TPM_TAG_RQU_COMMAND,
+ .length = cpu_to_be32(10),
+ .ordinal = cpu_to_be32(TPM_ORD_STARTUP),
+};
+
+int tpm_startup_ststate(struct tpm_chip *chip)
+{
+ int rc;
+ struct tpm_cmd_t cmd;
+
+ cmd.header.in = startup_ststate_header;
+ cmd.params.startup_in.state = cpu_to_be16(TPM_ST_STATE);
+ rc = transmit_cmd(chip, &cmd, STARTUP_RESULT_SIZE,
+ "startup(st_state)");
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_startup_ststate);
+
int tpm_send(u32 chip_num, void *cmd, size_t buflen)
{
struct tpm_chip *chip;
@@ -1313,6 +1464,8 @@ int tpm_pm_resume(struct device *dev)
if (chip == NULL)
return -ENODEV;
+ tpm_resume_quirk(chip);
+
return 0;
}
EXPORT_SYMBOL_GPL(tpm_pm_resume);
Index: linux-2.6/drivers/char/tpm/tpm.h
===================================================================
--- linux-2.6.orig/drivers/char/tpm/tpm.h
+++ linux-2.6/drivers/char/tpm/tpm.h
@@ -42,6 +42,8 @@ enum tpm_addr {
#define TPM_ERR_DEACTIVATED 0x6
#define TPM_ERR_DISABLED 0x7
+#define TPM_ST_STATE 0x2
+
#define TPM_HEADER_SIZE 10
extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
char *);
@@ -269,6 +271,10 @@ struct tpm_pcrextend_in {
u8 hash[TPM_DIGEST_SIZE];
}__attribute__((packed));
+struct tpm_startup_in {
+ __be16 state;
+} __packed;
+
typedef union {
struct tpm_getcap_params_out getcap_out;
struct tpm_readpubek_params_out readpubek_out;
@@ -277,6 +283,7 @@ typedef union {
struct tpm_pcrread_in pcrread_in;
struct tpm_pcrread_out pcrread_out;
struct tpm_pcrextend_in pcrextend_in;
+ struct tpm_startup_in startup_in;
} tpm_cmd_params;
struct tpm_cmd_t {
@@ -289,6 +296,7 @@ ssize_t tpm_getcap(struct device *, __be
extern int tpm_get_timeouts(struct tpm_chip *);
extern void tpm_gen_interrupt(struct tpm_chip *);
extern int tpm_do_selftest(struct tpm_chip *);
+extern int tpm_startup_ststate(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 *);
next prev parent reply other threads:[~2012-01-29 18:22 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-28 14:08 TPM chip prevents machine from suspending Jeff Layton
2011-03-28 17:25 ` Stefan Berger
2011-03-28 18:12 ` Jeff Layton
2011-03-28 19:45 ` Jeff Layton
2011-03-28 19:57 ` Sisir Koppaka
2011-03-28 20:16 ` Jeff Layton
2011-03-28 20:32 ` Sisir Koppaka
2011-03-28 23:10 ` Stefan Berger
2011-03-29 0:19 ` Stefan Berger
2011-03-29 12:08 ` Jeff Layton
2011-03-29 12:25 ` Stefan Berger
2011-03-29 12:30 ` Jeff Layton
2011-03-29 14:30 ` Rajiv Andrade
2011-03-29 15:03 ` Stefan Berger
2011-03-30 19:43 ` [tpmdd-devel] " Eric Paris
2012-01-21 17:01 ` [Sony Vaio TX3] TPM chip prevents machine from suspending a second time Jonathan Nieder
2012-01-23 20:52 ` Stefan Berger
2012-01-29 10:49 ` John Hughes
2012-01-29 18:22 ` Stefan Berger [this message]
2012-01-30 9:10 ` John Hughes
2012-02-26 15:44 ` Jonathan Nieder
2012-05-03 15:34 ` John Hughes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F258E4C.8020606@linux.vnet.ibm.com \
--to=stefanb@linux.vnet.ibm.com \
--cc=eparis@redhat.com \
--cc=jlayton@poochiereds.net \
--cc=john@atlantech.com \
--cc=john@calvaedi.com \
--cc=jrnieder@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=srajiv@linux.vnet.ibm.com \
--cc=tpmdd-devel@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.