11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2004 IBM Corporation
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Authors:
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Leendert van Doorn <leendert@watson.ibm.com>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dave Safford <safford@watson.ibm.com>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reiner Sailer <sailer@watson.ibm.com>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Kylene Hall <kjhall@us.ibm.com>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
108e81cc13a88ce486a6b0a6ca56aba6985824917aKent Yoder * Maintained by: <tpmdd-devel@lists.sourceforge.net>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Device driver for TCG/TCPA TPM (trusted platform module).
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Specifications at www.trustedcomputinggroup.org
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License as
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation, version 2 of the
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * License.
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note, the TPM chip is not interrupt driven (only polling)
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and can have very long timeouts (minutes!). Hence the unusual
22700d8bdcd0fa815b08638b1e4d43b66d60cc6a8dNishanth Aravamudan * calls to msleep.
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/poll.h>
275a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
28d081d470446900473f2f32b9203827809b8134f0Matthias Kaehlcke#include <linux/mutex.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h>
30fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade#include <linux/freezer.h>
31d081d470446900473f2f32b9203827809b8134f0Matthias Kaehlcke
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "tpm.h"
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
343122a88a242454efe72930e56a3e4d56ee534f3cKylene Hallenum tpm_const {
353122a88a242454efe72930e56a3e4d56ee534f3cKylene Hall	TPM_MINOR = 224,	/* officially assigned */
367f366784f5c2b8fc0658b5b374f4c63ee42c789fRajiv Andrade	TPM_BUFSIZE = 4096,
373122a88a242454efe72930e56a3e4d56ee534f3cKylene Hall	TPM_NUM_DEVICES = 256,
383122a88a242454efe72930e56a3e4d56ee534f3cKylene Hall};
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
409e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hallenum tpm_duration {
419e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT = 0,
429e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM = 1,
439e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG = 2,
449e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
459e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall};
469e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall
479e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall#define TPM_MAX_ORDINAL 243
489e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall#define TPM_MAX_PROTECTED_ORDINAL 12
499e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall#define TPM_PROTECTED_ORDINAL_MASK 0xFF
509e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall
519b3056cca09529d34af2d81305b2a9c6b622ca1bDmitry Torokhov/*
529b3056cca09529d34af2d81305b2a9c6b622ca1bDmitry Torokhov * Bug workaround - some TPM's don't flush the most
539b3056cca09529d34af2d81305b2a9c6b622ca1bDmitry Torokhov * recently changed pcr on suspend, so force the flush
549b3056cca09529d34af2d81305b2a9c6b622ca1bDmitry Torokhov * with an extend to the selected _unused_ non-volatile pcr.
559b3056cca09529d34af2d81305b2a9c6b622ca1bDmitry Torokhov */
569b3056cca09529d34af2d81305b2a9c6b622ca1bDmitry Torokhovstatic int tpm_suspend_pcr;
579b3056cca09529d34af2d81305b2a9c6b622ca1bDmitry Torokhovmodule_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644);
589b3056cca09529d34af2d81305b2a9c6b622ca1bDmitry TorokhovMODULE_PARM_DESC(suspend_pcr,
599b3056cca09529d34af2d81305b2a9c6b622ca1bDmitry Torokhov		 "PCR to use for dummy writes to faciltate flush on suspend.");
609b3056cca09529d34af2d81305b2a9c6b622ca1bDmitry Torokhov
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic LIST_HEAD(tpm_chip_list);
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(driver_lock);
6310685a95301d02fde2b10f6047e405c69d2af82aKylene Jo Hallstatic DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
659e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall/*
669e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall * Array with one entry per ordinal defining the maximum amount
679e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall * of time the chip could take to return the result.  The ordinal
689e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall * designation of short, medium or long is defined in a table in
699e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
709e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall * values of the SHORT, MEDIUM, and LONG durations are retrieved
719e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall * from the chip during initialization with a call to tpm_get_timeouts.
729e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall */
739e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hallstatic const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
749e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 0 */
759e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
769e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
779e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
789e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
799e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 5 */
809e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
819e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
829e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
839e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
849e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 10 */
859e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
869e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall};
879e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall
889e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hallstatic const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
899e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 0 */
909e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
919e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
929e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
939e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
949e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 5 */
959e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
969e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
979e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
989e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
999e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 10 */
1009e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1019e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1029e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG,
1039e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG,
1049e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,		/* 15 */
1059e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1069e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1079e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1089e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG,
1099e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 20 */
1109e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1119e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1129e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1139e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1149e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 25 */
1159e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1169e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1179e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1189e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1199e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,		/* 30 */
1209e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG,
1219e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1229e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1239e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1249e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 35 */
1259e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1269e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1279e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1289e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1299e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,		/* 40 */
1309e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG,
1319e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1329e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1339e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1349e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 45 */
1359e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1369e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1379e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1389e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG,
1399e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,		/* 50 */
1409e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1419e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1429e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1439e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1449e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 55 */
1459e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1469e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1479e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1489e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1499e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,		/* 60 */
1509e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1519e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1529e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1539e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1549e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,		/* 65 */
1559e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1569e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1579e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1589e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1599e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 70 */
1609e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1619e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1629e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1639e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1649e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 75 */
1659e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1669e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1679e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1689e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1699e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG,		/* 80 */
1709e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1719e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
1729e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG,
1739e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1749e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 85 */
1759e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1769e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1779e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1789e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1799e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 90 */
1809e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1819e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1829e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1839e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1849e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 95 */
1859e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1869e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1879e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1889e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1899e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,		/* 100 */
1909e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1919e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
1929e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1939e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1949e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 105 */
1959e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1969e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1979e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1989e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
1999e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 110 */
2009e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2019e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2029e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2039e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2049e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 115 */
2059e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2069e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2079e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2089e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2099e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG,		/* 120 */
2109e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG,
2119e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
2129e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2139e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2149e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 125 */
2159e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2169e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG,
2179e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2189e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2199e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 130 */
2209e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
2219e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2229e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2239e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
2249e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 135 */
2259e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2269e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2279e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2289e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2299e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 140 */
2309e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2319e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2329e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2339e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2349e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 145 */
2359e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2369e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2379e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2389e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2399e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 150 */
2409e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
2419e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
2429e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2439e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2449e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 155 */
2459e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2469e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2479e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2489e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2499e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 160 */
2509e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2519e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2529e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2539e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2549e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 165 */
2559e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2569e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2579e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2589e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2599e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG,		/* 170 */
2609e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2619e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2629e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2639e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2649e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 175 */
2659e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2669e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2679e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2689e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2699e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,		/* 180 */
2709e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2719e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
2729e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
2739e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
2749e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,		/* 185 */
2759e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2769e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2779e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2789e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2799e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 190 */
2809e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2819e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2829e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2839e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2849e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 195 */
2859e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2869e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2879e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2889e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2899e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 200 */
2909e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2919e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2929e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
2939e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2949e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 205 */
2959e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2969e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2979e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2989e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
2999e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,		/* 210 */
3009e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3019e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
3029e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
3039e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
3049e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 215 */
3059e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
3069e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3079e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3089e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
3099e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 220 */
3109e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
3119e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
3129e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
3139e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,
3149e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 225 */
3159e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3169e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3179e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3189e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3199e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 230 */
3209e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_LONG,
3219e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
3229e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3239e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3249e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,		/* 235 */
3259e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3269e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3279e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3289e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3299e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_SHORT,		/* 240 */
3309e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_UNDEFINED,
3319e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	TPM_MEDIUM,
3329e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall};
3339e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void user_reader_timeout(unsigned long ptr)
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tpm_chip *chip = (struct tpm_chip *) ptr;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33809e12f9f6bcd9af516d901223cebdbae58b32c9fKylene Jo Hall	schedule_work(&chip->work);
33909e12f9f6bcd9af516d901223cebdbae58b32c9fKylene Jo Hall}
34009e12f9f6bcd9af516d901223cebdbae58b32c9fKylene Jo Hall
341c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void timeout_work(struct work_struct *work)
34209e12f9f6bcd9af516d901223cebdbae58b32c9fKylene Jo Hall{
343c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells	struct tpm_chip *chip = container_of(work, struct tpm_chip, work);
34409e12f9f6bcd9af516d901223cebdbae58b32c9fKylene Jo Hall
345d081d470446900473f2f32b9203827809b8134f0Matthias Kaehlcke	mutex_lock(&chip->buffer_mutex);
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	atomic_set(&chip->data_pending, 0);
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(chip->data_buffer, 0, TPM_BUFSIZE);
348d081d470446900473f2f32b9203827809b8134f0Matthias Kaehlcke	mutex_unlock(&chip->buffer_mutex);
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3529e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall * Returns max number of jiffies to wait
3539e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall */
3549e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hallunsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
3559e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall					   u32 ordinal)
3569e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall{
3579e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	int duration_idx = TPM_UNDEFINED;
3589e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	int duration = 0;
3599e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall
3609e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	if (ordinal < TPM_MAX_ORDINAL)
3619e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall		duration_idx = tpm_ordinal_duration[ordinal];
3629e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
3639e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall		 TPM_MAX_PROTECTED_ORDINAL)
3649e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall		duration_idx =
3659e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall		    tpm_protected_ordinal_duration[ordinal &
3669e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall						   TPM_PROTECTED_ORDINAL_MASK];
3679e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall
3688d1dc20e8d689c7e6a0a4d2c94e36a99d5793ecbLinus Torvalds	if (duration_idx != TPM_UNDEFINED)
36936b20020e537036c4f9eb5b69140c88ead5da7dcKylene Jo Hall		duration = chip->vendor.duration[duration_idx];
3708d1dc20e8d689c7e6a0a4d2c94e36a99d5793ecbLinus Torvalds	if (duration <= 0)
3719e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall		return 2 * 60 * HZ;
3728d1dc20e8d689c7e6a0a4d2c94e36a99d5793ecbLinus Torvalds	else
3738d1dc20e8d689c7e6a0a4d2c94e36a99d5793ecbLinus Torvalds		return duration;
3749e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall}
3759e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo HallEXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
3769e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall
3779e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall/*
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Internal kernel interface to transmit TPM commands
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    size_t bufsiz)
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
383d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall	ssize_t rc;
3849e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	u32 count, ordinal;
385700d8bdcd0fa815b08638b1e4d43b66d60cc6a8dNishanth Aravamudan	unsigned long stop;
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3876b07d30aca7e52f2881b8c8c20c8a2cd28e8b3d3Peter Huewe	if (bufsiz > TPM_BUFSIZE)
3886b07d30aca7e52f2881b8c8c20c8a2cd28e8b3d3Peter Huewe		bufsiz = TPM_BUFSIZE;
3896b07d30aca7e52f2881b8c8c20c8a2cd28e8b3d3Peter Huewe
39081179bb6a54c2c626b4cbcc084ca974bb2d7f2a3Kylene Hall	count = be32_to_cpu(*((__be32 *) (buf + 2)));
3919e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count == 0)
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODATA;
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count > bufsiz) {
395e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hall		dev_err(chip->dev,
396b76be681f8b296c00f707220b9891934d5d74778Al Viro			"invalid count value %x %zx \n", count, bufsiz);
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -E2BIG;
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
400d081d470446900473f2f32b9203827809b8134f0Matthias Kaehlcke	mutex_lock(&chip->tpm_mutex);
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40290dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall	if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) {
403e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hall		dev_err(chip->dev,
404d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall			"tpm_transmit: tpm_send: error %zd\n", rc);
405d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall		goto out;
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40827084efee0c3dc0eb15b5ed750aa9f1adb3983c3Leendert van Doorn	if (chip->vendor.irq)
40927084efee0c3dc0eb15b5ed750aa9f1adb3983c3Leendert van Doorn		goto out_recv;
41027084efee0c3dc0eb15b5ed750aa9f1adb3983c3Leendert van Doorn
4119e18ee19179a7742999d0e2d4bfcba75b5562439Kylene Jo Hall	stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
41390dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall		u8 status = chip->vendor.status(chip);
41490dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall		if ((status & chip->vendor.req_complete_mask) ==
41590dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall		    chip->vendor.req_complete_val)
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out_recv;
417d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall
41890dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall		if ((status == chip->vendor.req_canceled)) {
419e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hall			dev_err(chip->dev, "Operation Canceled\n");
420d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall			rc = -ECANCELED;
421d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall			goto out;
422d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall		}
423d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall
424d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall		msleep(TPM_TIMEOUT);	/* CHECK */
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rmb();
426700d8bdcd0fa815b08638b1e4d43b66d60cc6a8dNishanth Aravamudan	} while (time_before(jiffies, stop));
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42890dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall	chip->vendor.cancel(chip);
429e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hall	dev_err(chip->dev, "Operation Timed out\n");
430d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall	rc = -ETIME;
431d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall	goto out;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_recv:
43490dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall	rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz);
435d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall	if (rc < 0)
436e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hall		dev_err(chip->dev,
437d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall			"tpm_transmit: tpm_recv: error %zd\n", rc);
438d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hallout:
439d081d470446900473f2f32b9203827809b8134f0Matthias Kaehlcke	mutex_unlock(&chip->tpm_mutex);
440d9e5b6bf9cf19e6e9f2825228136ea17bc9a051aKylene Hall	return rc;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TPM_DIGEST_SIZE 20
444beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall#define TPM_RET_CODE_IDX 6
445beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall
446beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hallenum tpm_capabilities {
4470883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	TPM_CAP_FLAG = cpu_to_be32(4),
4480883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	TPM_CAP_PROP = cpu_to_be32(5),
4490883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	CAP_VERSION_1_1 = cpu_to_be32(0x06),
4500883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	CAP_VERSION_1_2 = cpu_to_be32(0x1A)
451beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall};
452beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall
453beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hallenum tpm_sub_capabilities {
4540883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	TPM_CAP_PROP_PCR = cpu_to_be32(0x101),
4550883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	TPM_CAP_PROP_MANUFACTURER = cpu_to_be32(0x103),
4560883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	TPM_CAP_FLAG_PERM = cpu_to_be32(0x108),
4570883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	TPM_CAP_FLAG_VOL = cpu_to_be32(0x109),
4580883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	TPM_CAP_PROP_OWNER = cpu_to_be32(0x111),
4590883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115),
4600883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120),
461beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4640883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andradestatic ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
4650883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade			    int len, const char *desc)
466beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall{
467beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall	int err;
468beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall
4690883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	len = tpm_transmit(chip,(u8 *) cmd, len);
470beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall	if (len <  0)
471beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall		return len;
472b9e3238aa36db33aa0d0bd44ef85297c45627aacRajiv Andrade	else if (len < TPM_HEADER_SIZE)
473b9e3238aa36db33aa0d0bd44ef85297c45627aacRajiv Andrade		return -EFAULT;
474b9e3238aa36db33aa0d0bd44ef85297c45627aacRajiv Andrade
475b9e3238aa36db33aa0d0bd44ef85297c45627aacRajiv Andrade	err = be32_to_cpu(cmd->header.out.return_code);
476b9e3238aa36db33aa0d0bd44ef85297c45627aacRajiv Andrade	if (err != 0)
477b9e3238aa36db33aa0d0bd44ef85297c45627aacRajiv Andrade		dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
478b9e3238aa36db33aa0d0bd44ef85297c45627aacRajiv Andrade
479b9e3238aa36db33aa0d0bd44ef85297c45627aacRajiv Andrade	return err;
480beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall}
481beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall
4820883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade#define TPM_INTERNAL_RESULT_SIZE 200
4830883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade#define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
4840883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade#define TPM_ORD_GET_CAP cpu_to_be32(101)
4850883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade
4860883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andradestatic const struct tpm_input_header tpm_getcap_header = {
4870883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	.tag = TPM_TAG_RQU_COMMAND,
4880883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	.length = cpu_to_be32(22),
4890883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	.ordinal = TPM_ORD_GET_CAP
4900883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade};
4910883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade
4920883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andradessize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap,
4930883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		   const char *desc)
4940883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade{
4950883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	struct tpm_cmd_t tpm_cmd;
4960883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	int rc;
4970883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	struct tpm_chip *chip = dev_get_drvdata(dev);
4980883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade
4990883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.header.in = tpm_getcap_header;
5000883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) {
5010883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		tpm_cmd.params.getcap_in.cap = subcap_id;
5020883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		/*subcap field not necessary */
5030883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(0);
5040883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		tpm_cmd.header.in.length -= cpu_to_be32(sizeof(__be32));
5050883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	} else {
5060883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		if (subcap_id == TPM_CAP_FLAG_PERM ||
5070883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		    subcap_id == TPM_CAP_FLAG_VOL)
5080883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade			tpm_cmd.params.getcap_in.cap = TPM_CAP_FLAG;
5090883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		else
5100883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade			tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
5110883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
5120883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		tpm_cmd.params.getcap_in.subcap = subcap_id;
5130883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	}
5140883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc);
5150883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	if (!rc)
5160883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		*cap = tpm_cmd.params.getcap_out.cap;
5170883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	return rc;
5180883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade}
5190883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade
52008e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hallvoid tpm_gen_interrupt(struct tpm_chip *chip)
52108e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall{
5220883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	struct	tpm_cmd_t tpm_cmd;
52308e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	ssize_t rc;
52408e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
5250883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.header.in = tpm_getcap_header;
5260883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
5270883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
5280883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
52908e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
5300883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
53108e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall			"attempting to determine the timeouts");
53208e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall}
53308e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo HallEXPORT_SYMBOL_GPL(tpm_gen_interrupt);
53408e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
5352b30a90f6c358714b9d6e628ac92e514917f93a1Stefan Bergerint tpm_get_timeouts(struct tpm_chip *chip)
53608e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall{
5370883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	struct tpm_cmd_t tpm_cmd;
5380883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	struct timeout_t *timeout_cap;
5390883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	struct duration_t *duration_cap;
54008e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	ssize_t rc;
54108e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	u32 timeout;
542e3e1a1e169d4e7f73c60ded937ebe24526bc6427Stefan Berger	unsigned int scale = 1;
54308e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
5440883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.header.in = tpm_getcap_header;
5450883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
5460883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
5470883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
54808e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
5490883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
55008e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall			"attempting to determine the timeouts");
55108e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	if (rc)
55208e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall		goto duration;
55308e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
554829bf0675272d24ba0056f5f79e09544464f0c8dStefan Berger	if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
555829bf0675272d24ba0056f5f79e09544464f0c8dStefan Berger	    be32_to_cpu(tpm_cmd.header.out.length)
556829bf0675272d24ba0056f5f79e09544464f0c8dStefan Berger	    != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
5572b30a90f6c358714b9d6e628ac92e514917f93a1Stefan Berger		return -EINVAL;
55808e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
5590883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
56008e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	/* Don't overwrite default if value is 0 */
5610883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	timeout = be32_to_cpu(timeout_cap->a);
562e3e1a1e169d4e7f73c60ded937ebe24526bc6427Stefan Berger	if (timeout && timeout < 1000) {
563e3e1a1e169d4e7f73c60ded937ebe24526bc6427Stefan Berger		/* timeouts in msec rather usec */
564e3e1a1e169d4e7f73c60ded937ebe24526bc6427Stefan Berger		scale = 1000;
5656259210176510c64251a314ffb74834a790f09a0Stefan Berger		chip->vendor.timeout_adjusted = true;
566e3e1a1e169d4e7f73c60ded937ebe24526bc6427Stefan Berger	}
56708e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	if (timeout)
568e3e1a1e169d4e7f73c60ded937ebe24526bc6427Stefan Berger		chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale);
5690883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	timeout = be32_to_cpu(timeout_cap->b);
57008e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	if (timeout)
571e3e1a1e169d4e7f73c60ded937ebe24526bc6427Stefan Berger		chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale);
5720883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	timeout = be32_to_cpu(timeout_cap->c);
57308e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	if (timeout)
574e3e1a1e169d4e7f73c60ded937ebe24526bc6427Stefan Berger		chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale);
5750883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	timeout = be32_to_cpu(timeout_cap->d);
57608e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	if (timeout)
577e3e1a1e169d4e7f73c60ded937ebe24526bc6427Stefan Berger		chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale);
57808e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
57908e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hallduration:
5800883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.header.in = tpm_getcap_header;
5810883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
5820883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
5830883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION;
58408e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
5850883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
58608e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall			"attempting to determine the durations");
58708e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	if (rc)
5882b30a90f6c358714b9d6e628ac92e514917f93a1Stefan Berger		return rc;
58908e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
590979b140614a5459f340f5f8b1641ef77c863d899Stefan Berger	if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
591979b140614a5459f340f5f8b1641ef77c863d899Stefan Berger	    be32_to_cpu(tpm_cmd.header.out.length)
592979b140614a5459f340f5f8b1641ef77c863d899Stefan Berger	    != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32))
5932b30a90f6c358714b9d6e628ac92e514917f93a1Stefan Berger		return -EINVAL;
594979b140614a5459f340f5f8b1641ef77c863d899Stefan Berger
5950883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
59608e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	chip->vendor.duration[TPM_SHORT] =
5970883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short));
598e934acca1ee993e1d99d7dc203569a6e5cdfb392Stefan Berger	chip->vendor.duration[TPM_MEDIUM] =
599e934acca1ee993e1d99d7dc203569a6e5cdfb392Stefan Berger	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
600e934acca1ee993e1d99d7dc203569a6e5cdfb392Stefan Berger	chip->vendor.duration[TPM_LONG] =
601e934acca1ee993e1d99d7dc203569a6e5cdfb392Stefan Berger	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
602e934acca1ee993e1d99d7dc203569a6e5cdfb392Stefan Berger
603292cf4a8a989cb564a6a5f0ba7a66e08a095afa1Valdis Kletnieks	/* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
604292cf4a8a989cb564a6a5f0ba7a66e08a095afa1Valdis Kletnieks	 * value wrong and apparently reports msecs rather than usecs. So we
605292cf4a8a989cb564a6a5f0ba7a66e08a095afa1Valdis Kletnieks	 * fix up the resulting too-small TPM_SHORT value to make things work.
606e934acca1ee993e1d99d7dc203569a6e5cdfb392Stefan Berger	 * We also scale the TPM_MEDIUM and -_LONG values by 1000.
607292cf4a8a989cb564a6a5f0ba7a66e08a095afa1Valdis Kletnieks	 */
608e934acca1ee993e1d99d7dc203569a6e5cdfb392Stefan Berger	if (chip->vendor.duration[TPM_SHORT] < (HZ / 100)) {
609292cf4a8a989cb564a6a5f0ba7a66e08a095afa1Valdis Kletnieks		chip->vendor.duration[TPM_SHORT] = HZ;
610e934acca1ee993e1d99d7dc203569a6e5cdfb392Stefan Berger		chip->vendor.duration[TPM_MEDIUM] *= 1000;
611e934acca1ee993e1d99d7dc203569a6e5cdfb392Stefan Berger		chip->vendor.duration[TPM_LONG] *= 1000;
61204ab2293bbd36fc04060da93058cef7789414585Stefan Berger		chip->vendor.duration_adjusted = true;
613e934acca1ee993e1d99d7dc203569a6e5cdfb392Stefan Berger		dev_info(chip->dev, "Adjusting TPM timeout parameters.");
614e934acca1ee993e1d99d7dc203569a6e5cdfb392Stefan Berger	}
6152b30a90f6c358714b9d6e628ac92e514917f93a1Stefan Berger	return 0;
61608e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall}
61708e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo HallEXPORT_SYMBOL_GPL(tpm_get_timeouts);
61808e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
619d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger#define TPM_ORD_CONTINUE_SELFTEST 83
620d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger#define CONTINUE_SELFTEST_RESULT_SIZE 10
621d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger
622d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Bergerstatic struct tpm_input_header continue_selftest_header = {
623d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger	.tag = TPM_TAG_RQU_COMMAND,
624d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger	.length = cpu_to_be32(10),
625d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger	.ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST),
626d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger};
627d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger
628d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger/**
629d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger * tpm_continue_selftest -- run TPM's selftest
630d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger * @chip: TPM chip to use
631d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger *
632d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
633d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger * a TPM error code.
634d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger */
63568d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Bergerstatic int tpm_continue_selftest(struct tpm_chip *chip)
63608e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall{
637d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger	int rc;
638d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger	struct tpm_cmd_t cmd;
63908e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
640d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger	cmd.header.in = continue_selftest_header;
641d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger	rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
642d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger			  "continue selftest");
643d97c6ade5926afb6d52df36c33a3491d62cd0dc0Stefan Berger	return rc;
64408e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall}
64508e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
64608e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hallssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
64708e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall			char *buf)
64808e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall{
6490883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	cap_t cap;
65008e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	ssize_t rc;
65108e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
6520883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap,
6530883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade			 "attempting to determine the permanent enabled state");
6540883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	if (rc)
65508e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall		return 0;
656ec288bd37e1925f513db40871bc46115cf7fb733Marcin Obara
6570883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = sprintf(buf, "%d\n", !cap.perm_flags.disable);
658ec288bd37e1925f513db40871bc46115cf7fb733Marcin Obara	return rc;
65908e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall}
66008e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo HallEXPORT_SYMBOL_GPL(tpm_show_enabled);
66108e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
66208e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hallssize_t tpm_show_active(struct device * dev, struct device_attribute * attr,
66308e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall			char *buf)
66408e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall{
6650883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	cap_t cap;
66608e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	ssize_t rc;
66708e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
6680883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap,
6690883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade			 "attempting to determine the permanent active state");
6700883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	if (rc)
67108e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall		return 0;
672ec288bd37e1925f513db40871bc46115cf7fb733Marcin Obara
6730883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated);
674ec288bd37e1925f513db40871bc46115cf7fb733Marcin Obara	return rc;
67508e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall}
67608e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo HallEXPORT_SYMBOL_GPL(tpm_show_active);
67708e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
67808e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hallssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr,
67908e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall			char *buf)
68008e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall{
6810883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	cap_t cap;
68208e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	ssize_t rc;
68308e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
6840883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = tpm_getcap(dev, TPM_CAP_PROP_OWNER, &cap,
6850883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade			 "attempting to determine the owner state");
6860883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	if (rc)
68708e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall		return 0;
688ec288bd37e1925f513db40871bc46115cf7fb733Marcin Obara
6890883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = sprintf(buf, "%d\n", cap.owned);
690ec288bd37e1925f513db40871bc46115cf7fb733Marcin Obara	return rc;
69108e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall}
69208e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo HallEXPORT_SYMBOL_GPL(tpm_show_owned);
69308e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
69408e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hallssize_t tpm_show_temp_deactivated(struct device * dev,
69508e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall				struct device_attribute * attr, char *buf)
69608e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall{
6970883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	cap_t cap;
69808e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	ssize_t rc;
69908e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
7000883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = tpm_getcap(dev, TPM_CAP_FLAG_VOL, &cap,
7010883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade			 "attempting to determine the temporary state");
7020883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	if (rc)
70308e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall		return 0;
704ec288bd37e1925f513db40871bc46115cf7fb733Marcin Obara
7050883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated);
706ec288bd37e1925f513db40871bc46115cf7fb733Marcin Obara	return rc;
70708e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall}
70808e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo HallEXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
70908e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
710659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade/*
711659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * tpm_chip_find_get - return tpm_chip for given chip number
712659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade */
713659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andradestatic struct tpm_chip *tpm_chip_find_get(int chip_num)
714659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade{
7158920d5ad6ba74ae8ab020e90cc4d976980e68701Rajiv Andrade	struct tpm_chip *pos, *chip = NULL;
716659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade
717659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	rcu_read_lock();
718659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
719659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade		if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
720659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade			continue;
721659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade
7228920d5ad6ba74ae8ab020e90cc4d976980e68701Rajiv Andrade		if (try_module_get(pos->dev->driver->owner)) {
7238920d5ad6ba74ae8ab020e90cc4d976980e68701Rajiv Andrade			chip = pos;
724659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade			break;
7258920d5ad6ba74ae8ab020e90cc4d976980e68701Rajiv Andrade		}
726659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	}
727659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	rcu_read_unlock();
7288920d5ad6ba74ae8ab020e90cc4d976980e68701Rajiv Andrade	return chip;
729659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade}
730659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade
731659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade#define TPM_ORDINAL_PCRREAD cpu_to_be32(21)
732659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade#define READ_PCR_RESULT_SIZE 30
733659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andradestatic struct tpm_input_header pcrread_header = {
734659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	.tag = TPM_TAG_RQU_COMMAND,
735659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	.length = cpu_to_be32(14),
736659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	.ordinal = TPM_ORDINAL_PCRREAD
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
73968d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Bergerstatic int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
740659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade{
741659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	int rc;
742659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	struct tpm_cmd_t cmd;
743659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade
744659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	cmd.header.in = pcrread_header;
745659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
74623acb98de5a4109a60b5fe3f0439389218b039d7Rajiv Andrade	rc = transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE,
747659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade			  "attempting to read a pcr value");
748659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade
749659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	if (rc == 0)
750659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade		memcpy(res_buf, cmd.params.pcrread_out.pcr_result,
751659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade		       TPM_DIGEST_SIZE);
752659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	return rc;
753659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade}
754659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade
755659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade/**
756659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * tpm_pcr_read - read a pcr value
757659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * @chip_num: 	tpm idx # or ANY
758659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * @pcr_idx:	pcr idx to retrieve
759659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * @res_buf: 	TPM_PCR value
760659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * 		size of res_buf is 20 bytes (or NULL if you don't care)
761659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade *
762659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * The TPM driver should be built-in, but for whatever reason it
763659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * isn't, protect against the chip disappearing, by incrementing
764659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * the module usage count.
765659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade */
766659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andradeint tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf)
767659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade{
768659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	struct tpm_chip *chip;
769659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	int rc;
770659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade
771659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	chip = tpm_chip_find_get(chip_num);
772659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	if (chip == NULL)
773659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade		return -ENODEV;
774659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	rc = __tpm_pcr_read(chip, pcr_idx, res_buf);
775a0e39349d80d8b5deeb264fb190bd064f7063252Mimi Zohar	tpm_chip_put(chip);
776659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	return rc;
777659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade}
778659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv AndradeEXPORT_SYMBOL_GPL(tpm_pcr_read);
779659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade
780659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade/**
781659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * tpm_pcr_extend - extend pcr value with hash
782659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * @chip_num: 	tpm idx # or AN&
783659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * @pcr_idx:	pcr idx to extend
784659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * @hash: 	hash value used to extend pcr value
785659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade *
786659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * The TPM driver should be built-in, but for whatever reason it
787659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * isn't, protect against the chip disappearing, by incrementing
788659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade * the module usage count.
789659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade */
790659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade#define TPM_ORD_PCR_EXTEND cpu_to_be32(20)
7910afd9056f1b43c9fcbfdf933b263d72023d382feJason Gunthorpe#define EXTEND_PCR_RESULT_SIZE 34
792659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andradestatic struct tpm_input_header pcrextend_header = {
793659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	.tag = TPM_TAG_RQU_COMMAND,
794659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	.length = cpu_to_be32(34),
795659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	.ordinal = TPM_ORD_PCR_EXTEND
796659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade};
797659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade
798659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andradeint tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
799659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade{
800659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	struct tpm_cmd_t cmd;
801659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	int rc;
802659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	struct tpm_chip *chip;
803659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade
804659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	chip = tpm_chip_find_get(chip_num);
805659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	if (chip == NULL)
806659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade		return -ENODEV;
807659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade
808659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	cmd.header.in = pcrextend_header;
809659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
810659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
8110afd9056f1b43c9fcbfdf933b263d72023d382feJason Gunthorpe	rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
812659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade			  "attempting extend a PCR value");
813659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade
814a0e39349d80d8b5deeb264fb190bd064f7063252Mimi Zohar	tpm_chip_put(chip);
815659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	return rc;
816659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade}
817659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv AndradeEXPORT_SYMBOL_GPL(tpm_pcr_extend);
818659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade
81968d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger/**
82068d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger * tpm_do_selftest - have the TPM continue its selftest and wait until it
82168d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger *                   can receive further commands
82268d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger * @chip: TPM chip to use
82368d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger *
82468d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
82568d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger * a TPM error code.
82668d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger */
82768d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Bergerint tpm_do_selftest(struct tpm_chip *chip)
82868d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger{
82968d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	int rc;
83068d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	u8 digest[TPM_DIGEST_SIZE];
83168d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	unsigned int loops;
83268d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	unsigned int delay_msec = 1000;
83368d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	unsigned long duration;
83468d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger
83568d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	duration = tpm_calc_ordinal_duration(chip,
83668d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	                                     TPM_ORD_CONTINUE_SELFTEST);
83768d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger
83868d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	loops = jiffies_to_msecs(duration) / delay_msec;
83968d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger
84068d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	rc = tpm_continue_selftest(chip);
84168d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	/* This may fail if there was no TPM driver during a suspend/resume
84268d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	 * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST)
84368d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	 */
84468d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	if (rc)
84568d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger		return rc;
84668d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger
84768d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	do {
84868d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger		rc = __tpm_pcr_read(chip, 0, digest);
849be405411f712489f2f780ab085e1069e8fb85f19Stefan Berger		if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) {
850be405411f712489f2f780ab085e1069e8fb85f19Stefan Berger			dev_info(chip->dev,
851be405411f712489f2f780ab085e1069e8fb85f19Stefan Berger				 "TPM is disabled/deactivated (0x%X)\n", rc);
852be405411f712489f2f780ab085e1069e8fb85f19Stefan Berger			/* TPM is disabled and/or deactivated; driver can
853be405411f712489f2f780ab085e1069e8fb85f19Stefan Berger			 * proceed and TPM does handle commands for
854be405411f712489f2f780ab085e1069e8fb85f19Stefan Berger			 * suspend/resume correctly
855be405411f712489f2f780ab085e1069e8fb85f19Stefan Berger			 */
856be405411f712489f2f780ab085e1069e8fb85f19Stefan Berger			return 0;
857be405411f712489f2f780ab085e1069e8fb85f19Stefan Berger		}
85868d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger		if (rc != TPM_WARN_DOING_SELFTEST)
85968d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger			return rc;
86068d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger		msleep(delay_msec);
86168d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	} while (--loops > 0);
86268d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger
86368d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger	return rc;
86468d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger}
86568d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan BergerEXPORT_SYMBOL_GPL(tpm_do_selftest);
86668d6e6713fcb2ea6278661aaaf5f1c9c821b3751Stefan Berger
867c749ba912e87ccebd674ae24b97462176c63732eMimi Zoharint tpm_send(u32 chip_num, void *cmd, size_t buflen)
868c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar{
869c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar	struct tpm_chip *chip;
870c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar	int rc;
871c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar
872c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar	chip = tpm_chip_find_get(chip_num);
873c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar	if (chip == NULL)
874c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar		return -ENODEV;
875c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar
876c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar	rc = transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd");
877c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar
878c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar	tpm_chip_put(chip);
879c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar	return rc;
880c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar}
881c749ba912e87ccebd674ae24b97462176c63732eMimi ZoharEXPORT_SYMBOL_GPL(tpm_send);
882c749ba912e87ccebd674ae24b97462176c63732eMimi Zohar
8836659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hallssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
8846659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hall		      char *buf)
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8860883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	cap_t cap;
887659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade	u8 digest[TPM_DIGEST_SIZE];
888beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall	ssize_t rc;
88981179bb6a54c2c626b4cbcc084ca974bb2d7f2a3Kylene Hall	int i, j, num_pcrs;
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *str = buf;
891e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hall	struct tpm_chip *chip = dev_get_drvdata(dev);
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8930883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap,
894beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall			"attempting to determine the number of PCRS");
8950883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	if (rc)
896e234bc970451edc4021637fe2979b887da873f9aKylene Hall		return 0;
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8980883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	num_pcrs = be32_to_cpu(cap.num_pcrs);
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < num_pcrs; i++) {
900659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade		rc = __tpm_pcr_read(chip, i, digest);
901beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall		if (rc)
9020883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade			break;
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		str += sprintf(str, "PCR-%02d: ", i);
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (j = 0; j < TPM_DIGEST_SIZE; j++)
905659aaf2bb5496a425ba14036b5b5900f593e4484Rajiv Andrade			str += sprintf(str, "%02X ", digest[j]);
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		str += sprintf(str, "\n");
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return str - buf;
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9106659ca2ab6730c3bbb9fa495f2327b95b955decdKylene HallEXPORT_SYMBOL_GPL(tpm_show_pcrs);
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define  READ_PUBEK_RESULT_SIZE 314
9130883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade#define TPM_ORD_READPUBEK cpu_to_be32(124)
9140883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andradestruct tpm_input_header tpm_readpubek_header = {
9150883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	.tag = TPM_TAG_RQU_COMMAND,
9160883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	.length = cpu_to_be32(30),
9170883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	.ordinal = TPM_ORD_READPUBEK
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9206659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hallssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
9216659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hall		       char *buf)
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9232df7111fc6b0e050b06123379821ece2f8dd5bbcKylene Hall	u8 *data;
9240883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	struct tpm_cmd_t tpm_cmd;
925beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall	ssize_t err;
92681179bb6a54c2c626b4cbcc084ca974bb2d7f2a3Kylene Hall	int i, rc;
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *str = buf;
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
929e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hall	struct tpm_chip *chip = dev_get_drvdata(dev);
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9310883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	tpm_cmd.header.in = tpm_readpubek_header;
9320883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
933beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall			"attempting to read the PUBEK");
934beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall	if (err)
93534d6e07570ef74b965131452a862b13dfa779188Kylene Jo Hall		goto out;
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   ignore header 10 bytes
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   algorithm 32 bits (1 == RSA )
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   encscheme 16 bits
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   sigscheme 16 bits
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   parameters (RSA 12->bytes: keybit, #primes, expbit)
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   keylenbytes 32 bits
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   256 byte modulus
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   ignore checksum 20 bytes
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
9470883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	data = tpm_cmd.params.readpubek_out_buffer;
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	str +=
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    sprintf(str,
9505a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    "Algorithm: %02X %02X %02X %02X\n"
9515a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    "Encscheme: %02X %02X\n"
9525a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    "Sigscheme: %02X %02X\n"
9535a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    "Parameters: %02X %02X %02X %02X "
9545a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    "%02X %02X %02X %02X "
9555a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    "%02X %02X %02X %02X\n"
9565a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    "Modulus length: %d\n"
9575a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    "Modulus:\n",
9585a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    data[0], data[1], data[2], data[3],
9595a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    data[4], data[5],
9605a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    data[6], data[7],
9615a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    data[12], data[13], data[14], data[15],
9625a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    data[16], data[17], data[18], data[19],
9635a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    data[20], data[21], data[22], data[23],
9645a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		    be32_to_cpu(*((__be32 *) (data + 24))));
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 256; i++) {
9675a79444f24cb169b79f0f346482a42ab28329baeStefan Berger		str += sprintf(str, "%02X ", data[i + 28]);
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((i + 1) % 16 == 0)
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			str += sprintf(str, "\n");
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
97134d6e07570ef74b965131452a862b13dfa779188Kylene Jo Hallout:
972beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall	rc = str - buf;
9732df7111fc6b0e050b06123379821ece2f8dd5bbcKylene Hall	return rc;
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9756659ca2ab6730c3bbb9fa495f2327b95b955decdKylene HallEXPORT_SYMBOL_GPL(tpm_show_pubek);
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9786659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hallssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
9796659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hall		      char *buf)
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9810883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	cap_t cap;
982beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall	ssize_t rc;
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *str = buf;
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9850883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap,
986beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall			"attempting to determine the manufacturer");
9870883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	if (rc)
988beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall		return 0;
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	str += sprintf(str, "Manufacturer: 0x%x\n",
9900883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		       be32_to_cpu(cap.manufacturer_id));
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9920883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap,
9930883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		        "attempting to determine the 1.1 version");
994beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall	if (rc)
9950883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		return 0;
996beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall	str += sprintf(str,
997beed53a1aaeaae4eb93297c23f1598a726716adfKylene Jo Hall		       "TCG version: %d.%d\nFirmware version: %d.%d\n",
9980883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		       cap.tpm_version.Major, cap.tpm_version.Minor,
9990883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		       cap.tpm_version.revMajor, cap.tpm_version.revMinor);
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return str - buf;
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10026659ca2ab6730c3bbb9fa495f2327b95b955decdKylene HallEXPORT_SYMBOL_GPL(tpm_show_caps);
10036659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hall
100408e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hallssize_t tpm_show_caps_1_2(struct device * dev,
100508e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall			  struct device_attribute * attr, char *buf)
100608e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall{
10070883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	cap_t cap;
10080883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	ssize_t rc;
100908e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	char *str = buf;
101008e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
10110883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap,
10120883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade			"attempting to determine the manufacturer");
10130883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	if (rc)
101408e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall		return 0;
101508e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	str += sprintf(str, "Manufacturer: 0x%x\n",
10160883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		       be32_to_cpu(cap.manufacturer_id));
10170883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	rc = tpm_getcap(dev, CAP_VERSION_1_2, &cap,
10180883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade			 "attempting to determine the 1.2 version");
10190883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade	if (rc)
10200883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		return 0;
102108e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	str += sprintf(str,
102208e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall		       "TCG version: %d.%d\nFirmware version: %d.%d\n",
10230883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		       cap.tpm_version_1_2.Major, cap.tpm_version_1_2.Minor,
10240883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		       cap.tpm_version_1_2.revMajor,
10250883743825e34b81f3ff78aaee3a97cba57586c5Rajiv Andrade		       cap.tpm_version_1_2.revMinor);
102608e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall	return str - buf;
102708e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall}
102808e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo HallEXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
102908e96e486dd1345ae0ad70247387d0d4fd346889Kylene Jo Hall
103004ab2293bbd36fc04060da93058cef7789414585Stefan Bergerssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr,
103104ab2293bbd36fc04060da93058cef7789414585Stefan Berger			  char *buf)
103204ab2293bbd36fc04060da93058cef7789414585Stefan Berger{
103304ab2293bbd36fc04060da93058cef7789414585Stefan Berger	struct tpm_chip *chip = dev_get_drvdata(dev);
103404ab2293bbd36fc04060da93058cef7789414585Stefan Berger
1035403d1d0319ad73b5ccf251745af4c7000331a76bStefan Berger	if (chip->vendor.duration[TPM_LONG] == 0)
1036403d1d0319ad73b5ccf251745af4c7000331a76bStefan Berger		return 0;
1037403d1d0319ad73b5ccf251745af4c7000331a76bStefan Berger
103804ab2293bbd36fc04060da93058cef7789414585Stefan Berger	return sprintf(buf, "%d %d %d [%s]\n",
103904ab2293bbd36fc04060da93058cef7789414585Stefan Berger		       jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
104004ab2293bbd36fc04060da93058cef7789414585Stefan Berger		       jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
104104ab2293bbd36fc04060da93058cef7789414585Stefan Berger		       jiffies_to_usecs(chip->vendor.duration[TPM_LONG]),
104204ab2293bbd36fc04060da93058cef7789414585Stefan Berger		       chip->vendor.duration_adjusted
104304ab2293bbd36fc04060da93058cef7789414585Stefan Berger		       ? "adjusted" : "original");
104404ab2293bbd36fc04060da93058cef7789414585Stefan Berger}
104504ab2293bbd36fc04060da93058cef7789414585Stefan BergerEXPORT_SYMBOL_GPL(tpm_show_durations);
104604ab2293bbd36fc04060da93058cef7789414585Stefan Berger
10476259210176510c64251a314ffb74834a790f09a0Stefan Bergerssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr,
10486259210176510c64251a314ffb74834a790f09a0Stefan Berger			  char *buf)
10496259210176510c64251a314ffb74834a790f09a0Stefan Berger{
10506259210176510c64251a314ffb74834a790f09a0Stefan Berger	struct tpm_chip *chip = dev_get_drvdata(dev);
10516259210176510c64251a314ffb74834a790f09a0Stefan Berger
10526259210176510c64251a314ffb74834a790f09a0Stefan Berger	return sprintf(buf, "%d %d %d %d [%s]\n",
10536259210176510c64251a314ffb74834a790f09a0Stefan Berger		       jiffies_to_usecs(chip->vendor.timeout_a),
10546259210176510c64251a314ffb74834a790f09a0Stefan Berger		       jiffies_to_usecs(chip->vendor.timeout_b),
10556259210176510c64251a314ffb74834a790f09a0Stefan Berger		       jiffies_to_usecs(chip->vendor.timeout_c),
10566259210176510c64251a314ffb74834a790f09a0Stefan Berger		       jiffies_to_usecs(chip->vendor.timeout_d),
10576259210176510c64251a314ffb74834a790f09a0Stefan Berger		       chip->vendor.timeout_adjusted
10586259210176510c64251a314ffb74834a790f09a0Stefan Berger		       ? "adjusted" : "original");
10596259210176510c64251a314ffb74834a790f09a0Stefan Berger}
10606259210176510c64251a314ffb74834a790f09a0Stefan BergerEXPORT_SYMBOL_GPL(tpm_show_timeouts);
10616259210176510c64251a314ffb74834a790f09a0Stefan Berger
10626659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hallssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
10636659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hall			const char *buf, size_t count)
10646659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hall{
10656659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hall	struct tpm_chip *chip = dev_get_drvdata(dev);
10666659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hall	if (chip == NULL)
10676659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hall		return 0;
10686659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hall
106990dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall	chip->vendor.cancel(chip);
10706659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hall	return count;
10716659ca2ab6730c3bbb9fa495f2327b95b955decdKylene Hall}
10726659ca2ab6730c3bbb9fa495f2327b95b955decdKylene HallEXPORT_SYMBOL_GPL(tpm_store_cancel);
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1074fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andradeint wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
1075fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade			 wait_queue_head_t *queue)
1076fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade{
1077fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade	unsigned long stop;
1078fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade	long rc;
1079fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade	u8 status;
1080fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade
1081fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade	/* check current status */
1082fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade	status = chip->vendor.status(chip);
1083fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade	if ((status & mask) == mask)
1084fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade		return 0;
1085fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade
1086fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade	stop = jiffies + timeout;
1087fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade
1088fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade	if (chip->vendor.irq) {
1089fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andradeagain:
1090fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade		timeout = stop - jiffies;
1091fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade		if ((long)timeout <= 0)
1092fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade			return -ETIME;
1093fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade		rc = wait_event_interruptible_timeout(*queue,
1094fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade						      ((chip->vendor.status(chip)
1095fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade						      & mask) == mask),
1096fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade						      timeout);
1097fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade		if (rc > 0)
1098fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade			return 0;
1099fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade		if (rc == -ERESTARTSYS && freezing(current)) {
1100fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade			clear_thread_flag(TIF_SIGPENDING);
1101fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade			goto again;
1102fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade		}
1103fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade	} else {
1104fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade		do {
1105fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade			msleep(TPM_TIMEOUT);
1106fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade			status = chip->vendor.status(chip);
1107fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade			if ((status & mask) == mask)
1108fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade				return 0;
1109fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade		} while (time_before(jiffies, stop));
1110fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade	}
1111fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade	return -ETIME;
1112fd04886660208ab2e35baaca55588afa57d52c9cRajiv Andrade}
1113fd04886660208ab2e35baaca55588afa57d52c9cRajiv AndradeEXPORT_SYMBOL_GPL(wait_for_tpm_stat);
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Device file system interface to the TPM
1116f89c5edb86abfac4c914f4eb808b07684164eca0Rajiv Andrade *
1117f89c5edb86abfac4c914f4eb808b07684164eca0Rajiv Andrade * It's assured that the chip will be opened just once,
1118f89c5edb86abfac4c914f4eb808b07684164eca0Rajiv Andrade * by the check of is_open variable, which is protected
1119f89c5edb86abfac4c914f4eb808b07684164eca0Rajiv Andrade * by driver_lock.
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint tpm_open(struct inode *inode, struct file *file)
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1123f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade	int minor = iminor(inode);
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tpm_chip *chip = NULL, *pos;
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1126f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade	rcu_read_lock();
1127f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade	list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
112890dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall		if (pos->vendor.miscdev.minor == minor) {
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			chip = pos;
1130f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade			get_device(chip->dev);
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1134f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade	rcu_read_unlock();
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1136f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade	if (!chip)
1137f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade		return -ENODEV;
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1139dc36d32cc5bea5e985294c79995e10a159c3019aRajiv Andrade	if (test_and_set_bit(0, &chip->is_open)) {
1140b888c87b7498557d1dbb9de3d4b8402b1bb89193Andrew Morton		dev_dbg(chip->dev, "Another process owns this TPM\n");
1141f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade		put_device(chip->dev);
1142f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade		return -EBUSY;
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11451309d7afbed112f0e8e90be9af975550caa0076bPeter Huewe	chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chip->data_buffer == NULL) {
1147dc36d32cc5bea5e985294c79995e10a159c3019aRajiv Andrade		clear_bit(0, &chip->is_open);
1148e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hall		put_device(chip->dev);
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	atomic_set(&chip->data_pending, 0);
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	file->private_data = chip;
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(tpm_open);
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1159f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade/*
1160f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade * Called on file close
1161f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade */
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint tpm_release(struct inode *inode, struct file *file)
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tpm_chip *chip = file->private_data;
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11664bdec11f560b8f405a011288a50e65b1a81b3654Rajiv Andrade	del_singleshot_timer_sync(&chip->user_read_timer);
11672e5c44c92046c41607794666ffc0d6945945acb0Tejun Heo	flush_work_sync(&chip->work);
11685e976d5557d3dd1e835b8be52e6201556dcfa052Kylene Hall	file->private_data = NULL;
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	atomic_set(&chip->data_pending, 0);
1170f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade	kfree(chip->data_buffer);
1171dc36d32cc5bea5e985294c79995e10a159c3019aRajiv Andrade	clear_bit(0, &chip->is_open);
1172e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hall	put_device(chip->dev);
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(tpm_release);
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1177b888c87b7498557d1dbb9de3d4b8402b1bb89193Andrew Mortonssize_t tpm_write(struct file *file, const char __user *buf,
11783c2f606a098b07f053904ec8b8f4d0e101c28b35Kylene Jo Hall		  size_t size, loff_t *off)
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tpm_chip *chip = file->private_data;
11810147600172b4a5d261165d1aa5ef818d84da1557Michael Halcrow	size_t in_size = size, out_size;
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* cannot perform a write until the read has cleared
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   either via tpm_read or a user_read_timer timeout */
1185700d8bdcd0fa815b08638b1e4d43b66d60cc6a8dNishanth Aravamudan	while (atomic_read(&chip->data_pending) != 0)
1186700d8bdcd0fa815b08638b1e4d43b66d60cc6a8dNishanth Aravamudan		msleep(TPM_TIMEOUT);
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1188d081d470446900473f2f32b9203827809b8134f0Matthias Kaehlcke	mutex_lock(&chip->buffer_mutex);
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (in_size > TPM_BUFSIZE)
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		in_size = TPM_BUFSIZE;
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_from_user
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (chip->data_buffer, (void __user *) buf, in_size)) {
1195d081d470446900473f2f32b9203827809b8134f0Matthias Kaehlcke		mutex_unlock(&chip->buffer_mutex);
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* atomic tpm command send and result receive */
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	atomic_set(&chip->data_pending, out_size);
1203d081d470446900473f2f32b9203827809b8134f0Matthias Kaehlcke	mutex_unlock(&chip->buffer_mutex);
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set a timeout by which the reader must come claim the result */
1206fe3fd48384af79e7619d3c6b0a020f801ef63c3bKylene Hall	mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return in_size;
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(tpm_write);
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12123c2f606a098b07f053904ec8b8f4d0e101c28b35Kylene Jo Hallssize_t tpm_read(struct file *file, char __user *buf,
12133c2f606a098b07f053904ec8b8f4d0e101c28b35Kylene Jo Hall		 size_t size, loff_t *off)
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tpm_chip *chip = file->private_data;
12160147600172b4a5d261165d1aa5ef818d84da1557Michael Halcrow	ssize_t ret_size;
12173321c07ae5068568cd61ac9f4ba749006a7185c9Peter Huewe	int rc;
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12195b44bd58063f7839f42a4047843e93e1fbf73cdaKylene Hall	del_singleshot_timer_sync(&chip->user_read_timer);
12202e5c44c92046c41607794666ffc0d6945945acb0Tejun Heo	flush_work_sync(&chip->work);
12215b44bd58063f7839f42a4047843e93e1fbf73cdaKylene Hall	ret_size = atomic_read(&chip->data_pending);
12225b44bd58063f7839f42a4047843e93e1fbf73cdaKylene Hall	atomic_set(&chip->data_pending, 0);
12235b44bd58063f7839f42a4047843e93e1fbf73cdaKylene Hall	if (ret_size > 0) {	/* relay data */
12243ab1aff89477dafb1aaeafe8c8669114a02b7226Tim Gardner		ssize_t orig_ret_size = ret_size;
12255b44bd58063f7839f42a4047843e93e1fbf73cdaKylene Hall		if (size < ret_size)
12265b44bd58063f7839f42a4047843e93e1fbf73cdaKylene Hall			ret_size = size;
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1228d081d470446900473f2f32b9203827809b8134f0Matthias Kaehlcke		mutex_lock(&chip->buffer_mutex);
12293321c07ae5068568cd61ac9f4ba749006a7185c9Peter Huewe		rc = copy_to_user(buf, chip->data_buffer, ret_size);
12303ab1aff89477dafb1aaeafe8c8669114a02b7226Tim Gardner		memset(chip->data_buffer, 0, orig_ret_size);
12313321c07ae5068568cd61ac9f4ba749006a7185c9Peter Huewe		if (rc)
12325b44bd58063f7839f42a4047843e93e1fbf73cdaKylene Hall			ret_size = -EFAULT;
12333321c07ae5068568cd61ac9f4ba749006a7185c9Peter Huewe
1234d081d470446900473f2f32b9203827809b8134f0Matthias Kaehlcke		mutex_unlock(&chip->buffer_mutex);
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret_size;
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(tpm_read);
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1241e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hallvoid tpm_remove_hardware(struct device *dev)
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1243e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hall	struct tpm_chip *chip = dev_get_drvdata(dev);
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chip == NULL) {
1246e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hall		dev_err(dev, "No device data found\n");
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&driver_lock);
1251f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade	list_del_rcu(&chip->list);
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&driver_lock);
1253f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade	synchronize_rcu();
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
125590dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall	misc_deregister(&chip->vendor.miscdev);
125690dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall	sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
125755a82ab3181be039c6440d3f2f69260ad6fe2988Kylene Jo Hall	tpm_bios_log_teardown(chip->bios_dir);
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12595bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL	/* write it this way to be explicit (chip->dev == dev) */
12605bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL	put_device(chip->dev);
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1262e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo HallEXPORT_SYMBOL_GPL(tpm_remove_hardware);
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1264225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade#define TPM_ORD_SAVESTATE cpu_to_be32(152)
1265225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade#define SAVESTATE_RESULT_SIZE 10
1266225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade
1267225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andradestatic struct tpm_input_header savestate_header = {
1268225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade	.tag = TPM_TAG_RQU_COMMAND,
1269225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade	.length = cpu_to_be32(10),
1270225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade	.ordinal = TPM_ORD_SAVESTATE
1271225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade};
1272225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We are about to suspend. Save the TPM state
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * so that it can be restored.
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1277ce2c87d4f733b6fcd7b7fb1d5311c870339c9725Kylene Jo Hallint tpm_pm_suspend(struct device *dev, pm_message_t pm_state)
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1279ce2c87d4f733b6fcd7b7fb1d5311c870339c9725Kylene Jo Hall	struct tpm_chip *chip = dev_get_drvdata(dev);
1280225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade	struct tpm_cmd_t cmd;
1281225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade	int rc;
1282225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade
1283225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade	u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
12842490c681ea3d7f5ac3fb876f14567bf1a9e0aa87David Smith
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chip == NULL)
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1288225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade	/* for buggy tpm, flush pcrs with extend to selected dummy */
1289225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade	if (tpm_suspend_pcr) {
1290225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade		cmd.header.in = pcrextend_header;
1291225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade		cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr);
1292225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade		memcpy(cmd.params.pcrextend_in.hash, dummy_hash,
1293225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade		       TPM_DIGEST_SIZE);
1294225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade		rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
1295225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade				  "extending dummy pcr before suspend");
1296225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade	}
1297225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade
1298225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade	/* now do the actual savestate */
1299225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade	cmd.header.in = savestate_header;
1300225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade	rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE,
1301225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade			  "sending savestate before suspend");
1302225a9be24d799aa16d543c31fb09f0c9ed1d9caaRajiv Andrade	return rc;
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(tpm_pm_suspend);
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Resume from a power safe. The BIOS already restored
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the TPM state.
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1310ce2c87d4f733b6fcd7b7fb1d5311c870339c9725Kylene Jo Hallint tpm_pm_resume(struct device *dev)
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1312ce2c87d4f733b6fcd7b7fb1d5311c870339c9725Kylene Jo Hall	struct tpm_chip *chip = dev_get_drvdata(dev);
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chip == NULL)
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(tpm_pm_resume);
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andrade/* In case vendor provided release function, call it too.*/
1322253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andrade
1323253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andradevoid tpm_dev_vendor_release(struct tpm_chip *chip)
1324253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andrade{
1325253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andrade	if (chip->vendor.release)
1326253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andrade		chip->vendor.release(chip->dev);
1327253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andrade
1328253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andrade	clear_bit(chip->dev_num, dev_mask);
1329253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andrade	kfree(chip->vendor.miscdev.name);
1330253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andrade}
1331253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv AndradeEXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
1332253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andrade
1333253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andrade
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
13355bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL * Once all references to platform device are down to 0,
13365bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL * release all allocated structures.
13375bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL */
1338cbb2ed4ac61f3e3d1656db141cfced6ed38861d5Stephen Rothwellvoid tpm_dev_release(struct device *dev)
13395bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL{
13405bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL	struct tpm_chip *chip = dev_get_drvdata(dev);
13415bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL
1342253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andrade	tpm_dev_vendor_release(chip);
13435bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL
1344253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv Andrade	chip->release(dev);
13455bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL	kfree(chip);
13465bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL}
1347253115b71fa06330bd58afbe01ccaf763a8a0cf1Rajiv AndradeEXPORT_SYMBOL_GPL(tpm_dev_release);
13485bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL
13495bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL/*
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called from tpm_<specific>.c probe function only for devices
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the driver has determined it should claim.  Prior to calling
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this function the specific probe function has called pci_enable_device
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * upon errant exit from this function specific probe function should call
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_disable_device
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1356f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andradestruct tpm_chip *tpm_register_hardware(struct device *dev,
1357f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade					const struct tpm_vendor_specific *entry)
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13596f9beccb95a47a15e446f64fbb7041dc6edce4d9Kylene Jo Hall#define DEVNAME_SIZE 7
13606f9beccb95a47a15e446f64fbb7041dc6edce4d9Kylene Jo Hall
13616f9beccb95a47a15e446f64fbb7041dc6edce4d9Kylene Jo Hall	char *devname;
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tpm_chip *chip;
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Driver specific per-device data */
1365b888c87b7498557d1dbb9de3d4b8402b1bb89193Andrew Morton	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
13668e39c933b1b7df501dbb68879fb1640e277b8a5cParag Warudkar	devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
13678e39c933b1b7df501dbb68879fb1640e277b8a5cParag Warudkar
1368dd78c9439fc1e031835bccb934d27b978c72c536Andrew Morton	if (chip == NULL || devname == NULL)
1369dd78c9439fc1e031835bccb934d27b978c72c536Andrew Morton		goto out_free;
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1371d081d470446900473f2f32b9203827809b8134f0Matthias Kaehlcke	mutex_init(&chip->buffer_mutex);
1372d081d470446900473f2f32b9203827809b8134f0Matthias Kaehlcke	mutex_init(&chip->tpm_mutex);
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&chip->list);
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1375c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells	INIT_WORK(&chip->work, timeout_work);
137609e12f9f6bcd9af516d901223cebdbae58b32c9fKylene Jo Hall
137740565f1962c5be9b9e285e05af01ab7771534868Jiri Slaby	setup_timer(&chip->user_read_timer, user_reader_timeout,
137840565f1962c5be9b9e285e05af01ab7771534868Jiri Slaby			(unsigned long)chip);
1379fe3fd48384af79e7619d3c6b0a020f801ef63c3bKylene Hall
138090dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall	memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
138210685a95301d02fde2b10f6047e405c69d2af82aKylene Jo Hall	chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
138410685a95301d02fde2b10f6047e405c69d2af82aKylene Jo Hall	if (chip->dev_num >= TPM_NUM_DEVICES) {
1385b888c87b7498557d1dbb9de3d4b8402b1bb89193Andrew Morton		dev_err(dev, "No available tpm device numbers\n");
1386dd78c9439fc1e031835bccb934d27b978c72c536Andrew Morton		goto out_free;
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (chip->dev_num == 0)
138890dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall		chip->vendor.miscdev.minor = TPM_MINOR;
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
139090dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall		chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
139210685a95301d02fde2b10f6047e405c69d2af82aKylene Jo Hall	set_bit(chip->dev_num, dev_mask);
139310685a95301d02fde2b10f6047e405c69d2af82aKylene Jo Hall
13946f9beccb95a47a15e446f64fbb7041dc6edce4d9Kylene Jo Hall	scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
139590dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall	chip->vendor.miscdev.name = devname;
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
139794fbcded4ea0dc14cbfb222a5c68372f150d1476Greg Kroah-Hartman	chip->vendor.miscdev.parent = dev;
1398e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hall	chip->dev = get_device(dev);
13995bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL	chip->release = dev->release;
14005bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL	dev->release = tpm_dev_release;
14015bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL	dev_set_drvdata(dev, chip);
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
140390dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall	if (misc_register(&chip->vendor.miscdev)) {
1404e659a3fe2027b19ecd8abb7ad79253672763454bKylene Jo Hall		dev_err(chip->dev,
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"unable to misc_register %s, minor %d\n",
140690dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall			chip->vendor.miscdev.name,
140790dda520c1962d55a0e1d2571deed0d75fd6d6f1Kylene Jo Hall			chip->vendor.miscdev.minor);
14085bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL		put_device(chip->dev);
1409e0dd03caf20d040a0a86b6bd74028ec9bda545f5Kylene Jo Hall		return NULL;
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1412f33d9bd50478c9a969b65f58feb6b69a3ad478cbJeff Garzik	if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
14135d469ec0f40d65b2a0a704402990a43b2dafe197Neil Horman		misc_deregister(&chip->vendor.miscdev);
14145bd91f18be2fc0dd0384fbfca6d3cdd79a8050ddRichard MUSIL		put_device(chip->dev);
1415f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade
1416f33d9bd50478c9a969b65f58feb6b69a3ad478cbJeff Garzik		return NULL;
1417f33d9bd50478c9a969b65f58feb6b69a3ad478cbJeff Garzik	}
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
141955a82ab3181be039c6440d3f2f69260ad6fe2988Kylene Jo Hall	chip->bios_dir = tpm_bios_log_setup(devname);
142055a82ab3181be039c6440d3f2f69260ad6fe2988Kylene Jo Hall
1421f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade	/* Make chip available */
1422f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade	spin_lock(&driver_lock);
1423f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade	list_add_rcu(&chip->list, &tpm_chip_list);
1424f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade	spin_unlock(&driver_lock);
1425f02a93645e6200a9da0f26dac8ced28c612f5e86Rajiv Andrade
1426e0dd03caf20d040a0a86b6bd74028ec9bda545f5Kylene Jo Hall	return chip;
1427dd78c9439fc1e031835bccb934d27b978c72c536Andrew Morton
1428dd78c9439fc1e031835bccb934d27b978c72c536Andrew Mortonout_free:
1429dd78c9439fc1e031835bccb934d27b978c72c536Andrew Morton	kfree(chip);
1430dd78c9439fc1e031835bccb934d27b978c72c536Andrew Morton	kfree(devname);
1431dd78c9439fc1e031835bccb934d27b978c72c536Andrew Morton	return NULL;
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(tpm_register_hardware);
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("TPM Driver");
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_VERSION("2.0");
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1439