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