Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2004 IBM Corporation |
| 3 | * Authors: |
| 4 | * Leendert van Doorn <leendert@watson.ibm.com> |
| 5 | * Dave Safford <safford@watson.ibm.com> |
| 6 | * Reiner Sailer <sailer@watson.ibm.com> |
| 7 | * Kylene Hall <kjhall@us.ibm.com> |
| 8 | * |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 9 | * Copyright (C) 2013 Obsidian Research Corp |
| 10 | * Jason Gunthorpe <jgunthorpe@obsidianresearch.com> |
| 11 | * |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 12 | * sysfs filesystem inspection interface to the TPM |
| 13 | * |
| 14 | * This program is free software; you can redistribute it and/or |
| 15 | * modify it under the terms of the GNU General Public License as |
| 16 | * published by the Free Software Foundation, version 2 of the |
| 17 | * License. |
| 18 | * |
| 19 | */ |
| 20 | #include <linux/device.h> |
| 21 | #include "tpm.h" |
| 22 | |
Jarkko Sakkinen | da379f3 | 2017-06-20 11:38:03 +0200 | [diff] [blame] | 23 | struct tpm_readpubek_out { |
| 24 | u8 algorithm[4]; |
| 25 | u8 encscheme[2]; |
| 26 | u8 sigscheme[2]; |
| 27 | __be32 paramsize; |
| 28 | u8 parameters[12]; |
| 29 | __be32 keysize; |
| 30 | u8 modulus[256]; |
| 31 | u8 checksum[20]; |
| 32 | } __packed; |
| 33 | |
Stefan Berger | c659af7 | 2017-01-19 07:19:12 -0500 | [diff] [blame] | 34 | #define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256) |
Roberto Sassu | a69faeb | 2017-05-03 18:19:10 +0200 | [diff] [blame] | 35 | #define TPM_ORD_READPUBEK 124 |
Jarkko Sakkinen | da379f3 | 2017-06-20 11:38:03 +0200 | [diff] [blame] | 36 | |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 37 | static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, |
| 38 | char *buf) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 39 | { |
Jarkko Sakkinen | da379f3 | 2017-06-20 11:38:03 +0200 | [diff] [blame] | 40 | struct tpm_buf tpm_buf; |
| 41 | struct tpm_readpubek_out *out; |
Jarkko Sakkinen | da379f3 | 2017-06-20 11:38:03 +0200 | [diff] [blame] | 42 | int i; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 43 | char *str = buf; |
Jason Gunthorpe | 062807f | 2016-04-18 13:26:13 -0400 | [diff] [blame] | 44 | struct tpm_chip *chip = to_tpm_chip(dev); |
Jarkko Sakkinen | da379f3 | 2017-06-20 11:38:03 +0200 | [diff] [blame] | 45 | char anti_replay[20]; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 46 | |
Jarkko Sakkinen | da379f3 | 2017-06-20 11:38:03 +0200 | [diff] [blame] | 47 | memset(&anti_replay, 0, sizeof(anti_replay)); |
Jarkko Sakkinen | 13b47cf | 2017-06-20 11:38:02 +0200 | [diff] [blame] | 48 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 49 | if (tpm_try_get_ops(chip)) |
Jarkko Sakkinen | c628610 | 2018-11-04 12:39:02 +0200 | [diff] [blame] | 50 | return 0; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 51 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 52 | if (tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK)) |
| 53 | goto out_ops; |
| 54 | |
Jarkko Sakkinen | da379f3 | 2017-06-20 11:38:03 +0200 | [diff] [blame] | 55 | tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay)); |
| 56 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 57 | if (tpm_transmit_cmd(chip, &tpm_buf, READ_PUBEK_RESULT_MIN_BODY_SIZE, |
| 58 | 0, "attempting to read the PUBEK")) |
| 59 | goto out_buf; |
Jarkko Sakkinen | da379f3 | 2017-06-20 11:38:03 +0200 | [diff] [blame] | 60 | |
| 61 | out = (struct tpm_readpubek_out *)&tpm_buf.data[10]; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 62 | str += |
| 63 | sprintf(str, |
| 64 | "Algorithm: %02X %02X %02X %02X\n" |
| 65 | "Encscheme: %02X %02X\n" |
| 66 | "Sigscheme: %02X %02X\n" |
| 67 | "Parameters: %02X %02X %02X %02X " |
| 68 | "%02X %02X %02X %02X " |
| 69 | "%02X %02X %02X %02X\n" |
| 70 | "Modulus length: %d\n" |
| 71 | "Modulus:\n", |
Jarkko Sakkinen | da379f3 | 2017-06-20 11:38:03 +0200 | [diff] [blame] | 72 | out->algorithm[0], out->algorithm[1], out->algorithm[2], |
| 73 | out->algorithm[3], |
| 74 | out->encscheme[0], out->encscheme[1], |
| 75 | out->sigscheme[0], out->sigscheme[1], |
| 76 | out->parameters[0], out->parameters[1], |
| 77 | out->parameters[2], out->parameters[3], |
| 78 | out->parameters[4], out->parameters[5], |
| 79 | out->parameters[6], out->parameters[7], |
| 80 | out->parameters[8], out->parameters[9], |
| 81 | out->parameters[10], out->parameters[11], |
| 82 | be32_to_cpu(out->keysize)); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 83 | |
| 84 | for (i = 0; i < 256; i++) { |
Jarkko Sakkinen | da379f3 | 2017-06-20 11:38:03 +0200 | [diff] [blame] | 85 | str += sprintf(str, "%02X ", out->modulus[i]); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 86 | if ((i + 1) % 16 == 0) |
| 87 | str += sprintf(str, "\n"); |
| 88 | } |
Jarkko Sakkinen | da379f3 | 2017-06-20 11:38:03 +0200 | [diff] [blame] | 89 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 90 | out_buf: |
Jarkko Sakkinen | da379f3 | 2017-06-20 11:38:03 +0200 | [diff] [blame] | 91 | tpm_buf_destroy(&tpm_buf); |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 92 | out_ops: |
| 93 | tpm_put_ops(chip); |
| 94 | return str - buf; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 95 | } |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 96 | static DEVICE_ATTR_RO(pubek); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 97 | |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 98 | static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr, |
| 99 | char *buf) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 100 | { |
| 101 | cap_t cap; |
| 102 | u8 digest[TPM_DIGEST_SIZE]; |
Tomas Winkler | 95adc6b | 2018-10-19 21:23:07 +0300 | [diff] [blame] | 103 | u32 i, j, num_pcrs; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 104 | char *str = buf; |
Jason Gunthorpe | 062807f | 2016-04-18 13:26:13 -0400 | [diff] [blame] | 105 | struct tpm_chip *chip = to_tpm_chip(dev); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 106 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 107 | if (tpm_try_get_ops(chip)) |
| 108 | return 0; |
| 109 | |
Jarkko Sakkinen | 4148467 | 2018-11-04 14:42:29 +0200 | [diff] [blame] | 110 | if (tpm1_getcap(chip, TPM_CAP_PROP_PCR, &cap, |
| 111 | "attempting to determine the number of PCRS", |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 112 | sizeof(cap.num_pcrs))) { |
| 113 | tpm_put_ops(chip); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 114 | return 0; |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 115 | } |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 116 | |
| 117 | num_pcrs = be32_to_cpu(cap.num_pcrs); |
| 118 | for (i = 0; i < num_pcrs; i++) { |
Jarkko Sakkinen | 4148467 | 2018-11-04 14:42:29 +0200 | [diff] [blame] | 119 | if (tpm1_pcr_read(chip, i, digest)) { |
| 120 | str = buf; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 121 | break; |
Jarkko Sakkinen | 4148467 | 2018-11-04 14:42:29 +0200 | [diff] [blame] | 122 | } |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 123 | str += sprintf(str, "PCR-%02d: ", i); |
| 124 | for (j = 0; j < TPM_DIGEST_SIZE; j++) |
| 125 | str += sprintf(str, "%02X ", digest[j]); |
| 126 | str += sprintf(str, "\n"); |
| 127 | } |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 128 | tpm_put_ops(chip); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 129 | return str - buf; |
| 130 | } |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 131 | static DEVICE_ATTR_RO(pcrs); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 132 | |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 133 | static ssize_t enabled_show(struct device *dev, struct device_attribute *attr, |
| 134 | char *buf) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 135 | { |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 136 | struct tpm_chip *chip = to_tpm_chip(dev); |
| 137 | ssize_t rc = 0; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 138 | cap_t cap; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 139 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 140 | if (tpm_try_get_ops(chip)) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 141 | return 0; |
| 142 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 143 | if (tpm1_getcap(chip, TPM_CAP_FLAG_PERM, &cap, |
| 144 | "attempting to determine the permanent enabled state", |
| 145 | sizeof(cap.perm_flags))) |
| 146 | goto out_ops; |
| 147 | |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 148 | rc = sprintf(buf, "%d\n", !cap.perm_flags.disable); |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 149 | out_ops: |
| 150 | tpm_put_ops(chip); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 151 | return rc; |
| 152 | } |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 153 | static DEVICE_ATTR_RO(enabled); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 154 | |
Fengguang Wu | 5f64822 | 2013-12-07 16:10:26 +0100 | [diff] [blame] | 155 | static ssize_t active_show(struct device *dev, struct device_attribute *attr, |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 156 | char *buf) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 157 | { |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 158 | struct tpm_chip *chip = to_tpm_chip(dev); |
| 159 | ssize_t rc = 0; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 160 | cap_t cap; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 161 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 162 | if (tpm_try_get_ops(chip)) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 163 | return 0; |
| 164 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 165 | if (tpm1_getcap(chip, TPM_CAP_FLAG_PERM, &cap, |
| 166 | "attempting to determine the permanent active state", |
| 167 | sizeof(cap.perm_flags))) |
| 168 | goto out_ops; |
| 169 | |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 170 | rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated); |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 171 | out_ops: |
| 172 | tpm_put_ops(chip); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 173 | return rc; |
| 174 | } |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 175 | static DEVICE_ATTR_RO(active); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 176 | |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 177 | static ssize_t owned_show(struct device *dev, struct device_attribute *attr, |
| 178 | char *buf) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 179 | { |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 180 | struct tpm_chip *chip = to_tpm_chip(dev); |
| 181 | ssize_t rc = 0; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 182 | cap_t cap; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 183 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 184 | if (tpm_try_get_ops(chip)) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 185 | return 0; |
| 186 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 187 | if (tpm1_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap, |
| 188 | "attempting to determine the owner state", |
| 189 | sizeof(cap.owned))) |
| 190 | goto out_ops; |
| 191 | |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 192 | rc = sprintf(buf, "%d\n", cap.owned); |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 193 | out_ops: |
| 194 | tpm_put_ops(chip); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 195 | return rc; |
| 196 | } |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 197 | static DEVICE_ATTR_RO(owned); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 198 | |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 199 | static ssize_t temp_deactivated_show(struct device *dev, |
| 200 | struct device_attribute *attr, char *buf) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 201 | { |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 202 | struct tpm_chip *chip = to_tpm_chip(dev); |
| 203 | ssize_t rc = 0; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 204 | cap_t cap; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 205 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 206 | if (tpm_try_get_ops(chip)) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 207 | return 0; |
| 208 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 209 | if (tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap, |
| 210 | "attempting to determine the temporary state", |
| 211 | sizeof(cap.stclear_flags))) |
| 212 | goto out_ops; |
| 213 | |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 214 | rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated); |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 215 | out_ops: |
| 216 | tpm_put_ops(chip); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 217 | return rc; |
| 218 | } |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 219 | static DEVICE_ATTR_RO(temp_deactivated); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 220 | |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 221 | static ssize_t caps_show(struct device *dev, struct device_attribute *attr, |
| 222 | char *buf) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 223 | { |
Jason Gunthorpe | 062807f | 2016-04-18 13:26:13 -0400 | [diff] [blame] | 224 | struct tpm_chip *chip = to_tpm_chip(dev); |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 225 | ssize_t rc = 0; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 226 | char *str = buf; |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 227 | cap_t cap; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 228 | |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 229 | if (tpm_try_get_ops(chip)) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 230 | return 0; |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 231 | |
| 232 | if (tpm1_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap, |
| 233 | "attempting to determine the manufacturer", |
| 234 | sizeof(cap.manufacturer_id))) |
| 235 | goto out_ops; |
| 236 | |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 237 | str += sprintf(str, "Manufacturer: 0x%x\n", |
| 238 | be32_to_cpu(cap.manufacturer_id)); |
| 239 | |
| 240 | /* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */ |
Tomas Winkler | f4d916b | 2018-10-19 21:22:54 +0300 | [diff] [blame] | 241 | rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_2, &cap, |
| 242 | "attempting to determine the 1.2 version", |
| 243 | sizeof(cap.tpm_version_1_2)); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 244 | if (!rc) { |
| 245 | str += sprintf(str, |
| 246 | "TCG version: %d.%d\nFirmware version: %d.%d\n", |
| 247 | cap.tpm_version_1_2.Major, |
| 248 | cap.tpm_version_1_2.Minor, |
| 249 | cap.tpm_version_1_2.revMajor, |
| 250 | cap.tpm_version_1_2.revMinor); |
| 251 | } else { |
| 252 | /* Otherwise just use TPM_STRUCT_VER */ |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 253 | if (tpm1_getcap(chip, TPM_CAP_VERSION_1_1, &cap, |
| 254 | "attempting to determine the 1.1 version", |
| 255 | sizeof(cap.tpm_version))) |
| 256 | goto out_ops; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 257 | str += sprintf(str, |
| 258 | "TCG version: %d.%d\nFirmware version: %d.%d\n", |
| 259 | cap.tpm_version.Major, |
| 260 | cap.tpm_version.Minor, |
| 261 | cap.tpm_version.revMajor, |
| 262 | cap.tpm_version.revMinor); |
| 263 | } |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 264 | rc = str - buf; |
| 265 | out_ops: |
| 266 | tpm_put_ops(chip); |
| 267 | return rc; |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 268 | } |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 269 | static DEVICE_ATTR_RO(caps); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 270 | |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 271 | static ssize_t cancel_store(struct device *dev, struct device_attribute *attr, |
| 272 | const char *buf, size_t count) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 273 | { |
Jason Gunthorpe | 062807f | 2016-04-18 13:26:13 -0400 | [diff] [blame] | 274 | struct tpm_chip *chip = to_tpm_chip(dev); |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 275 | |
| 276 | if (tpm_try_get_ops(chip)) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 277 | return 0; |
| 278 | |
Jason Gunthorpe | 5f82e9f | 2013-11-26 13:30:44 -0700 | [diff] [blame] | 279 | chip->ops->cancel(chip); |
Jarkko Sakkinen | 2677ca9 | 2018-11-04 11:38:27 +0200 | [diff] [blame] | 280 | tpm_put_ops(chip); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 281 | return count; |
| 282 | } |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 283 | static DEVICE_ATTR_WO(cancel); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 284 | |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 285 | static ssize_t durations_show(struct device *dev, struct device_attribute *attr, |
| 286 | char *buf) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 287 | { |
Jason Gunthorpe | 062807f | 2016-04-18 13:26:13 -0400 | [diff] [blame] | 288 | struct tpm_chip *chip = to_tpm_chip(dev); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 289 | |
Christophe Ricard | af782f3 | 2016-03-31 22:56:59 +0200 | [diff] [blame] | 290 | if (chip->duration[TPM_LONG] == 0) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 291 | return 0; |
| 292 | |
| 293 | return sprintf(buf, "%d %d %d [%s]\n", |
Christophe Ricard | af782f3 | 2016-03-31 22:56:59 +0200 | [diff] [blame] | 294 | jiffies_to_usecs(chip->duration[TPM_SHORT]), |
| 295 | jiffies_to_usecs(chip->duration[TPM_MEDIUM]), |
| 296 | jiffies_to_usecs(chip->duration[TPM_LONG]), |
| 297 | chip->duration_adjusted |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 298 | ? "adjusted" : "original"); |
| 299 | } |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 300 | static DEVICE_ATTR_RO(durations); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 301 | |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 302 | static ssize_t timeouts_show(struct device *dev, struct device_attribute *attr, |
| 303 | char *buf) |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 304 | { |
Jason Gunthorpe | 062807f | 2016-04-18 13:26:13 -0400 | [diff] [blame] | 305 | struct tpm_chip *chip = to_tpm_chip(dev); |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 306 | |
| 307 | return sprintf(buf, "%d %d %d %d [%s]\n", |
Christophe Ricard | af782f3 | 2016-03-31 22:56:59 +0200 | [diff] [blame] | 308 | jiffies_to_usecs(chip->timeout_a), |
| 309 | jiffies_to_usecs(chip->timeout_b), |
| 310 | jiffies_to_usecs(chip->timeout_c), |
| 311 | jiffies_to_usecs(chip->timeout_d), |
| 312 | chip->timeout_adjusted |
Jason Gunthorpe | 000a07b | 2013-11-26 13:30:41 -0700 | [diff] [blame] | 313 | ? "adjusted" : "original"); |
| 314 | } |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 315 | static DEVICE_ATTR_RO(timeouts); |
| 316 | |
| 317 | static struct attribute *tpm_dev_attrs[] = { |
| 318 | &dev_attr_pubek.attr, |
| 319 | &dev_attr_pcrs.attr, |
| 320 | &dev_attr_enabled.attr, |
| 321 | &dev_attr_active.attr, |
| 322 | &dev_attr_owned.attr, |
| 323 | &dev_attr_temp_deactivated.attr, |
| 324 | &dev_attr_caps.attr, |
| 325 | &dev_attr_cancel.attr, |
| 326 | &dev_attr_durations.attr, |
| 327 | &dev_attr_timeouts.attr, |
| 328 | NULL, |
| 329 | }; |
| 330 | |
| 331 | static const struct attribute_group tpm_dev_group = { |
| 332 | .attrs = tpm_dev_attrs, |
| 333 | }; |
| 334 | |
Jason Gunthorpe | 062807f | 2016-04-18 13:26:13 -0400 | [diff] [blame] | 335 | void tpm_sysfs_add_device(struct tpm_chip *chip) |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 336 | { |
Josh Zimmerman | d1bd4a7 | 2017-06-25 14:53:24 -0700 | [diff] [blame] | 337 | /* XXX: If you wish to remove this restriction, you must first update |
| 338 | * tpm_sysfs to explicitly lock chip->ops. |
| 339 | */ |
Jarkko Sakkinen | 7518a21 | 2016-11-14 05:00:51 -0500 | [diff] [blame] | 340 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
| 341 | return; |
| 342 | |
Jason Gunthorpe | 062807f | 2016-04-18 13:26:13 -0400 | [diff] [blame] | 343 | /* The sysfs routines rely on an implicit tpm_try_get_ops, device_del |
| 344 | * is called before ops is null'd and the sysfs core synchronizes this |
| 345 | * removal so that no callbacks are running or can run again |
Jason Gunthorpe | 4e26195 | 2016-02-12 20:29:53 -0700 | [diff] [blame] | 346 | */ |
Jason Gunthorpe | 062807f | 2016-04-18 13:26:13 -0400 | [diff] [blame] | 347 | WARN_ON(chip->groups_cnt != 0); |
| 348 | chip->groups[chip->groups_cnt++] = &tpm_dev_group; |
Jason Gunthorpe | 1e3b73a | 2013-11-26 13:30:42 -0700 | [diff] [blame] | 349 | } |