18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2004 IBM Corporation 48c2ecf20Sopenharmony_ci * Authors: 58c2ecf20Sopenharmony_ci * Leendert van Doorn <leendert@watson.ibm.com> 68c2ecf20Sopenharmony_ci * Dave Safford <safford@watson.ibm.com> 78c2ecf20Sopenharmony_ci * Reiner Sailer <sailer@watson.ibm.com> 88c2ecf20Sopenharmony_ci * Kylene Hall <kjhall@us.ibm.com> 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Copyright (C) 2013 Obsidian Research Corp 118c2ecf20Sopenharmony_ci * Jason Gunthorpe <jgunthorpe@obsidianresearch.com> 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * sysfs filesystem inspection interface to the TPM 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci#include <linux/device.h> 168c2ecf20Sopenharmony_ci#include "tpm.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistruct tpm_readpubek_out { 198c2ecf20Sopenharmony_ci u8 algorithm[4]; 208c2ecf20Sopenharmony_ci u8 encscheme[2]; 218c2ecf20Sopenharmony_ci u8 sigscheme[2]; 228c2ecf20Sopenharmony_ci __be32 paramsize; 238c2ecf20Sopenharmony_ci u8 parameters[12]; 248c2ecf20Sopenharmony_ci __be32 keysize; 258c2ecf20Sopenharmony_ci u8 modulus[256]; 268c2ecf20Sopenharmony_ci u8 checksum[20]; 278c2ecf20Sopenharmony_ci} __packed; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256) 308c2ecf20Sopenharmony_ci#define TPM_ORD_READPUBEK 124 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic ssize_t pubek_show(struct device *dev, struct device_attribute *attr, 338c2ecf20Sopenharmony_ci char *buf) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci struct tpm_buf tpm_buf; 368c2ecf20Sopenharmony_ci struct tpm_readpubek_out *out; 378c2ecf20Sopenharmony_ci int i; 388c2ecf20Sopenharmony_ci char *str = buf; 398c2ecf20Sopenharmony_ci struct tpm_chip *chip = to_tpm_chip(dev); 408c2ecf20Sopenharmony_ci char anti_replay[20]; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci memset(&anti_replay, 0, sizeof(anti_replay)); 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci if (tpm_try_get_ops(chip)) 458c2ecf20Sopenharmony_ci return 0; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK)) 488c2ecf20Sopenharmony_ci goto out_ops; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay)); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci if (tpm_transmit_cmd(chip, &tpm_buf, READ_PUBEK_RESULT_MIN_BODY_SIZE, 538c2ecf20Sopenharmony_ci "attempting to read the PUBEK")) 548c2ecf20Sopenharmony_ci goto out_buf; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci out = (struct tpm_readpubek_out *)&tpm_buf.data[10]; 578c2ecf20Sopenharmony_ci str += 588c2ecf20Sopenharmony_ci sprintf(str, 598c2ecf20Sopenharmony_ci "Algorithm: %4ph\n" 608c2ecf20Sopenharmony_ci "Encscheme: %2ph\n" 618c2ecf20Sopenharmony_ci "Sigscheme: %2ph\n" 628c2ecf20Sopenharmony_ci "Parameters: %12ph\n" 638c2ecf20Sopenharmony_ci "Modulus length: %d\n" 648c2ecf20Sopenharmony_ci "Modulus:\n", 658c2ecf20Sopenharmony_ci out->algorithm, 668c2ecf20Sopenharmony_ci out->encscheme, 678c2ecf20Sopenharmony_ci out->sigscheme, 688c2ecf20Sopenharmony_ci out->parameters, 698c2ecf20Sopenharmony_ci be32_to_cpu(out->keysize)); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci for (i = 0; i < 256; i += 16) 728c2ecf20Sopenharmony_ci str += sprintf(str, "%16ph\n", &out->modulus[i]); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ciout_buf: 758c2ecf20Sopenharmony_ci tpm_buf_destroy(&tpm_buf); 768c2ecf20Sopenharmony_ciout_ops: 778c2ecf20Sopenharmony_ci tpm_put_ops(chip); 788c2ecf20Sopenharmony_ci return str - buf; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(pubek); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic ssize_t pcrs_show(struct device *dev, struct device_attribute *attr, 838c2ecf20Sopenharmony_ci char *buf) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci cap_t cap; 868c2ecf20Sopenharmony_ci u8 digest[TPM_DIGEST_SIZE]; 878c2ecf20Sopenharmony_ci u32 i, j, num_pcrs; 888c2ecf20Sopenharmony_ci char *str = buf; 898c2ecf20Sopenharmony_ci struct tpm_chip *chip = to_tpm_chip(dev); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci if (tpm_try_get_ops(chip)) 928c2ecf20Sopenharmony_ci return 0; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (tpm1_getcap(chip, TPM_CAP_PROP_PCR, &cap, 958c2ecf20Sopenharmony_ci "attempting to determine the number of PCRS", 968c2ecf20Sopenharmony_ci sizeof(cap.num_pcrs))) { 978c2ecf20Sopenharmony_ci tpm_put_ops(chip); 988c2ecf20Sopenharmony_ci return 0; 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci num_pcrs = be32_to_cpu(cap.num_pcrs); 1028c2ecf20Sopenharmony_ci for (i = 0; i < num_pcrs; i++) { 1038c2ecf20Sopenharmony_ci if (tpm1_pcr_read(chip, i, digest)) { 1048c2ecf20Sopenharmony_ci str = buf; 1058c2ecf20Sopenharmony_ci break; 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci str += sprintf(str, "PCR-%02d: ", i); 1088c2ecf20Sopenharmony_ci for (j = 0; j < TPM_DIGEST_SIZE; j++) 1098c2ecf20Sopenharmony_ci str += sprintf(str, "%02X ", digest[j]); 1108c2ecf20Sopenharmony_ci str += sprintf(str, "\n"); 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci tpm_put_ops(chip); 1138c2ecf20Sopenharmony_ci return str - buf; 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(pcrs); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic ssize_t enabled_show(struct device *dev, struct device_attribute *attr, 1188c2ecf20Sopenharmony_ci char *buf) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci struct tpm_chip *chip = to_tpm_chip(dev); 1218c2ecf20Sopenharmony_ci ssize_t rc = 0; 1228c2ecf20Sopenharmony_ci cap_t cap; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (tpm_try_get_ops(chip)) 1258c2ecf20Sopenharmony_ci return 0; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci if (tpm1_getcap(chip, TPM_CAP_FLAG_PERM, &cap, 1288c2ecf20Sopenharmony_ci "attempting to determine the permanent enabled state", 1298c2ecf20Sopenharmony_ci sizeof(cap.perm_flags))) 1308c2ecf20Sopenharmony_ci goto out_ops; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci rc = sprintf(buf, "%d\n", !cap.perm_flags.disable); 1338c2ecf20Sopenharmony_ciout_ops: 1348c2ecf20Sopenharmony_ci tpm_put_ops(chip); 1358c2ecf20Sopenharmony_ci return rc; 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(enabled); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic ssize_t active_show(struct device *dev, struct device_attribute *attr, 1408c2ecf20Sopenharmony_ci char *buf) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci struct tpm_chip *chip = to_tpm_chip(dev); 1438c2ecf20Sopenharmony_ci ssize_t rc = 0; 1448c2ecf20Sopenharmony_ci cap_t cap; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci if (tpm_try_get_ops(chip)) 1478c2ecf20Sopenharmony_ci return 0; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci if (tpm1_getcap(chip, TPM_CAP_FLAG_PERM, &cap, 1508c2ecf20Sopenharmony_ci "attempting to determine the permanent active state", 1518c2ecf20Sopenharmony_ci sizeof(cap.perm_flags))) 1528c2ecf20Sopenharmony_ci goto out_ops; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated); 1558c2ecf20Sopenharmony_ciout_ops: 1568c2ecf20Sopenharmony_ci tpm_put_ops(chip); 1578c2ecf20Sopenharmony_ci return rc; 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(active); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic ssize_t owned_show(struct device *dev, struct device_attribute *attr, 1628c2ecf20Sopenharmony_ci char *buf) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci struct tpm_chip *chip = to_tpm_chip(dev); 1658c2ecf20Sopenharmony_ci ssize_t rc = 0; 1668c2ecf20Sopenharmony_ci cap_t cap; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci if (tpm_try_get_ops(chip)) 1698c2ecf20Sopenharmony_ci return 0; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci if (tpm1_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap, 1728c2ecf20Sopenharmony_ci "attempting to determine the owner state", 1738c2ecf20Sopenharmony_ci sizeof(cap.owned))) 1748c2ecf20Sopenharmony_ci goto out_ops; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci rc = sprintf(buf, "%d\n", cap.owned); 1778c2ecf20Sopenharmony_ciout_ops: 1788c2ecf20Sopenharmony_ci tpm_put_ops(chip); 1798c2ecf20Sopenharmony_ci return rc; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(owned); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic ssize_t temp_deactivated_show(struct device *dev, 1848c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci struct tpm_chip *chip = to_tpm_chip(dev); 1878c2ecf20Sopenharmony_ci ssize_t rc = 0; 1888c2ecf20Sopenharmony_ci cap_t cap; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci if (tpm_try_get_ops(chip)) 1918c2ecf20Sopenharmony_ci return 0; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci if (tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap, 1948c2ecf20Sopenharmony_ci "attempting to determine the temporary state", 1958c2ecf20Sopenharmony_ci sizeof(cap.stclear_flags))) 1968c2ecf20Sopenharmony_ci goto out_ops; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated); 1998c2ecf20Sopenharmony_ciout_ops: 2008c2ecf20Sopenharmony_ci tpm_put_ops(chip); 2018c2ecf20Sopenharmony_ci return rc; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(temp_deactivated); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic ssize_t caps_show(struct device *dev, struct device_attribute *attr, 2068c2ecf20Sopenharmony_ci char *buf) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci struct tpm_chip *chip = to_tpm_chip(dev); 2098c2ecf20Sopenharmony_ci struct tpm1_version *version; 2108c2ecf20Sopenharmony_ci ssize_t rc = 0; 2118c2ecf20Sopenharmony_ci char *str = buf; 2128c2ecf20Sopenharmony_ci cap_t cap; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci if (tpm_try_get_ops(chip)) 2158c2ecf20Sopenharmony_ci return 0; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (tpm1_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap, 2188c2ecf20Sopenharmony_ci "attempting to determine the manufacturer", 2198c2ecf20Sopenharmony_ci sizeof(cap.manufacturer_id))) 2208c2ecf20Sopenharmony_ci goto out_ops; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci str += sprintf(str, "Manufacturer: 0x%x\n", 2238c2ecf20Sopenharmony_ci be32_to_cpu(cap.manufacturer_id)); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci /* TPM 1.2 */ 2268c2ecf20Sopenharmony_ci if (!tpm1_getcap(chip, TPM_CAP_VERSION_1_2, &cap, 2278c2ecf20Sopenharmony_ci "attempting to determine the 1.2 version", 2288c2ecf20Sopenharmony_ci sizeof(cap.version2))) { 2298c2ecf20Sopenharmony_ci version = &cap.version2.version; 2308c2ecf20Sopenharmony_ci goto out_print; 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci /* TPM 1.1 */ 2348c2ecf20Sopenharmony_ci if (tpm1_getcap(chip, TPM_CAP_VERSION_1_1, &cap, 2358c2ecf20Sopenharmony_ci "attempting to determine the 1.1 version", 2368c2ecf20Sopenharmony_ci sizeof(cap.version1))) { 2378c2ecf20Sopenharmony_ci goto out_ops; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci version = &cap.version1; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ciout_print: 2438c2ecf20Sopenharmony_ci str += sprintf(str, 2448c2ecf20Sopenharmony_ci "TCG version: %d.%d\nFirmware version: %d.%d\n", 2458c2ecf20Sopenharmony_ci version->major, version->minor, 2468c2ecf20Sopenharmony_ci version->rev_major, version->rev_minor); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci rc = str - buf; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ciout_ops: 2518c2ecf20Sopenharmony_ci tpm_put_ops(chip); 2528c2ecf20Sopenharmony_ci return rc; 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(caps); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cistatic ssize_t cancel_store(struct device *dev, struct device_attribute *attr, 2578c2ecf20Sopenharmony_ci const char *buf, size_t count) 2588c2ecf20Sopenharmony_ci{ 2598c2ecf20Sopenharmony_ci struct tpm_chip *chip = to_tpm_chip(dev); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci if (tpm_try_get_ops(chip)) 2628c2ecf20Sopenharmony_ci return 0; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci chip->ops->cancel(chip); 2658c2ecf20Sopenharmony_ci tpm_put_ops(chip); 2668c2ecf20Sopenharmony_ci return count; 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_cistatic DEVICE_ATTR_WO(cancel); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic ssize_t durations_show(struct device *dev, struct device_attribute *attr, 2718c2ecf20Sopenharmony_ci char *buf) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci struct tpm_chip *chip = to_tpm_chip(dev); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci if (chip->duration[TPM_LONG] == 0) 2768c2ecf20Sopenharmony_ci return 0; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci return sprintf(buf, "%d %d %d [%s]\n", 2798c2ecf20Sopenharmony_ci jiffies_to_usecs(chip->duration[TPM_SHORT]), 2808c2ecf20Sopenharmony_ci jiffies_to_usecs(chip->duration[TPM_MEDIUM]), 2818c2ecf20Sopenharmony_ci jiffies_to_usecs(chip->duration[TPM_LONG]), 2828c2ecf20Sopenharmony_ci chip->duration_adjusted 2838c2ecf20Sopenharmony_ci ? "adjusted" : "original"); 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(durations); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistatic ssize_t timeouts_show(struct device *dev, struct device_attribute *attr, 2888c2ecf20Sopenharmony_ci char *buf) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci struct tpm_chip *chip = to_tpm_chip(dev); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci return sprintf(buf, "%d %d %d %d [%s]\n", 2938c2ecf20Sopenharmony_ci jiffies_to_usecs(chip->timeout_a), 2948c2ecf20Sopenharmony_ci jiffies_to_usecs(chip->timeout_b), 2958c2ecf20Sopenharmony_ci jiffies_to_usecs(chip->timeout_c), 2968c2ecf20Sopenharmony_ci jiffies_to_usecs(chip->timeout_d), 2978c2ecf20Sopenharmony_ci chip->timeout_adjusted 2988c2ecf20Sopenharmony_ci ? "adjusted" : "original"); 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(timeouts); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic ssize_t tpm_version_major_show(struct device *dev, 3038c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci struct tpm_chip *chip = to_tpm_chip(dev); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci return sprintf(buf, "%s\n", chip->flags & TPM_CHIP_FLAG_TPM2 3088c2ecf20Sopenharmony_ci ? "2" : "1"); 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(tpm_version_major); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic struct attribute *tpm1_dev_attrs[] = { 3138c2ecf20Sopenharmony_ci &dev_attr_pubek.attr, 3148c2ecf20Sopenharmony_ci &dev_attr_pcrs.attr, 3158c2ecf20Sopenharmony_ci &dev_attr_enabled.attr, 3168c2ecf20Sopenharmony_ci &dev_attr_active.attr, 3178c2ecf20Sopenharmony_ci &dev_attr_owned.attr, 3188c2ecf20Sopenharmony_ci &dev_attr_temp_deactivated.attr, 3198c2ecf20Sopenharmony_ci &dev_attr_caps.attr, 3208c2ecf20Sopenharmony_ci &dev_attr_cancel.attr, 3218c2ecf20Sopenharmony_ci &dev_attr_durations.attr, 3228c2ecf20Sopenharmony_ci &dev_attr_timeouts.attr, 3238c2ecf20Sopenharmony_ci &dev_attr_tpm_version_major.attr, 3248c2ecf20Sopenharmony_ci NULL, 3258c2ecf20Sopenharmony_ci}; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic struct attribute *tpm2_dev_attrs[] = { 3288c2ecf20Sopenharmony_ci &dev_attr_tpm_version_major.attr, 3298c2ecf20Sopenharmony_ci NULL 3308c2ecf20Sopenharmony_ci}; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic const struct attribute_group tpm1_dev_group = { 3338c2ecf20Sopenharmony_ci .attrs = tpm1_dev_attrs, 3348c2ecf20Sopenharmony_ci}; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic const struct attribute_group tpm2_dev_group = { 3378c2ecf20Sopenharmony_ci .attrs = tpm2_dev_attrs, 3388c2ecf20Sopenharmony_ci}; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_civoid tpm_sysfs_add_device(struct tpm_chip *chip) 3418c2ecf20Sopenharmony_ci{ 3428c2ecf20Sopenharmony_ci WARN_ON(chip->groups_cnt != 0); 3438c2ecf20Sopenharmony_ci if (chip->flags & TPM_CHIP_FLAG_TPM2) 3448c2ecf20Sopenharmony_ci chip->groups[chip->groups_cnt++] = &tpm2_dev_group; 3458c2ecf20Sopenharmony_ci else 3468c2ecf20Sopenharmony_ci chip->groups[chip->groups_cnt++] = &tpm1_dev_group; 3478c2ecf20Sopenharmony_ci} 348