xref: /openbmc/linux/drivers/char/tpm/tpm.h (revision f2f5820e3ba6b7ce17dc7cc10a1e838378edcf75)
1b886d83cSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Copyright (C) 2004 IBM Corporation
4a74f8b36SJarkko Sakkinen  * Copyright (C) 2015 Intel Corporation
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:
71da177e4SLinus Torvalds  * Leendert van Doorn <leendert@watson.ibm.com>
81da177e4SLinus Torvalds  * Dave Safford <safford@watson.ibm.com>
91da177e4SLinus Torvalds  * Reiner Sailer <sailer@watson.ibm.com>
101da177e4SLinus Torvalds  * Kylene Hall <kjhall@us.ibm.com>
111da177e4SLinus Torvalds  *
128e81cc13SKent Yoder  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  * Device driver for TCG/TCPA TPM (trusted platform module).
151da177e4SLinus Torvalds  * Specifications at www.trustedcomputinggroup.org
161da177e4SLinus Torvalds  */
17d2efee6eSChristophe Ricard 
18d2efee6eSChristophe Ricard #ifndef __TPM_H__
19d2efee6eSChristophe Ricard #define __TPM_H__
20d2efee6eSChristophe Ricard 
211da177e4SLinus Torvalds #include <linux/module.h>
221da177e4SLinus Torvalds #include <linux/delay.h>
23d081d470SMatthias Kaehlcke #include <linux/mutex.h>
24914e2637SAl Viro #include <linux/sched.h>
25bbc5b212SAl Viro #include <linux/platform_device.h>
26276ad0c1SAndrew Morton #include <linux/io.h>
27659aaf2bSRajiv Andrade #include <linux/tpm.h>
28a74f8b36SJarkko Sakkinen #include <linux/highmem.h>
29fd3ec366SThiebaud Weksteen #include <linux/tpm_eventlog.h>
301da177e4SLinus Torvalds 
315e572cabSAzhar Shaikh #ifdef CONFIG_X86
325e572cabSAzhar Shaikh #include <asm/intel-family.h>
335e572cabSAzhar Shaikh #endif
345e572cabSAzhar Shaikh 
35901615cbSRoberto Sassu #define TPM_MINOR		224	/* officially assigned */
36901615cbSRoberto Sassu #define TPM_BUFSIZE		4096
37901615cbSRoberto Sassu #define TPM_NUM_DEVICES		65536
38901615cbSRoberto Sassu #define TPM_RETRY		50
3941ab999cSKent Yoder 
403122a88aSKylene Hall enum tpm_timeout {
413122a88aSKylene Hall 	TPM_TIMEOUT = 5,	/* msecs */
429f3fc7bcSHamza Attak 	TPM_TIMEOUT_RETRY = 100, /* msecs */
4359f5a6b0SNayna Jain 	TPM_TIMEOUT_RANGE_US = 300,	/* usecs */
44424eaf91SNayna Jain 	TPM_TIMEOUT_POLL = 1,	/* msecs */
45424eaf91SNayna Jain 	TPM_TIMEOUT_USECS_MIN = 100,      /* usecs */
46424eaf91SNayna Jain 	TPM_TIMEOUT_USECS_MAX = 500      /* usecs */
473122a88aSKylene Hall };
481da177e4SLinus Torvalds 
491da177e4SLinus Torvalds /* TPM addresses */
503122a88aSKylene Hall enum tpm_addr {
51daacdfa6SKylene Jo Hall 	TPM_SUPERIO_ADDR = 0x2E,
523122a88aSKylene Hall 	TPM_ADDR = 0x4E,
533122a88aSKylene Hall };
543122a88aSKylene Hall 
5532d33b29SDuncan Laurie #define TPM_WARN_RETRY          0x800
5668d6e671SStefan Berger #define TPM_WARN_DOING_SELFTEST 0x802
57be405411SStefan Berger #define TPM_ERR_DEACTIVATED     0x6
58be405411SStefan Berger #define TPM_ERR_DISABLED        0x7
59c584af19SJason Gunthorpe #define TPM_ERR_INVALID_POSTINIT 38
60be405411SStefan Berger 
61b9e3238aSRajiv Andrade #define TPM_HEADER_SIZE		10
627a1d7e6dSJarkko Sakkinen 
637a1d7e6dSJarkko Sakkinen enum tpm2_const {
647a1d7e6dSJarkko Sakkinen 	TPM2_PLATFORM_PCR       =     24,
657a1d7e6dSJarkko Sakkinen 	TPM2_PCR_SELECT_MIN     = ((TPM2_PLATFORM_PCR + 7) / 8),
66076d3564STomas Winkler };
67076d3564STomas Winkler 
68076d3564STomas Winkler enum tpm2_timeouts {
697a1d7e6dSJarkko Sakkinen 	TPM2_TIMEOUT_A          =    750,
707a1d7e6dSJarkko Sakkinen 	TPM2_TIMEOUT_B          =   2000,
717a1d7e6dSJarkko Sakkinen 	TPM2_TIMEOUT_C          =    200,
727a1d7e6dSJarkko Sakkinen 	TPM2_TIMEOUT_D          =     30,
737a1d7e6dSJarkko Sakkinen 	TPM2_DURATION_SHORT     =     20,
747a1d7e6dSJarkko Sakkinen 	TPM2_DURATION_MEDIUM    =    750,
757a1d7e6dSJarkko Sakkinen 	TPM2_DURATION_LONG      =   2000,
76076d3564STomas Winkler 	TPM2_DURATION_LONG_LONG = 300000,
77076d3564STomas Winkler 	TPM2_DURATION_DEFAULT   = 120000,
787a1d7e6dSJarkko Sakkinen };
797a1d7e6dSJarkko Sakkinen 
807a1d7e6dSJarkko Sakkinen enum tpm2_structures {
817a1d7e6dSJarkko Sakkinen 	TPM2_ST_NO_SESSIONS	= 0x8001,
827a1d7e6dSJarkko Sakkinen 	TPM2_ST_SESSIONS	= 0x8002,
837a1d7e6dSJarkko Sakkinen };
847a1d7e6dSJarkko Sakkinen 
85095531f8SJavier Martinez Canillas /* Indicates from what layer of the software stack the error comes from */
86095531f8SJavier Martinez Canillas #define TSS2_RC_LAYER_SHIFT	 16
87095531f8SJavier Martinez Canillas #define TSS2_RESMGR_TPM_RC_LAYER (11 << TSS2_RC_LAYER_SHIFT)
88095531f8SJavier Martinez Canillas 
897a1d7e6dSJarkko Sakkinen enum tpm2_return_codes {
90745b361eSJarkko Sakkinen 	TPM2_RC_SUCCESS		= 0x0000,
915ca4c20cSJarkko Sakkinen 	TPM2_RC_HASH		= 0x0083, /* RC_FMT1 */
92745b361eSJarkko Sakkinen 	TPM2_RC_HANDLE		= 0x008B,
935ca4c20cSJarkko Sakkinen 	TPM2_RC_INITIALIZE	= 0x0100, /* RC_VER1 */
942be8ffedSJames Bottomley 	TPM2_RC_FAILURE		= 0x0101,
957a1d7e6dSJarkko Sakkinen 	TPM2_RC_DISABLED	= 0x0120,
96095531f8SJavier Martinez Canillas 	TPM2_RC_COMMAND_CODE    = 0x0143,
975ca4c20cSJarkko Sakkinen 	TPM2_RC_TESTING		= 0x090A, /* RC_WARN */
98745b361eSJarkko Sakkinen 	TPM2_RC_REFERENCE_H0	= 0x0910,
99e2fb992dSJames Bottomley 	TPM2_RC_RETRY		= 0x0922,
1007a1d7e6dSJarkko Sakkinen };
1017a1d7e6dSJarkko Sakkinen 
1027a1d7e6dSJarkko Sakkinen enum tpm2_command_codes {
1037a1d7e6dSJarkko Sakkinen 	TPM2_CC_FIRST		        = 0x011F,
104899102bcSTomas Winkler 	TPM2_CC_HIERARCHY_CONTROL       = 0x0121,
105899102bcSTomas Winkler 	TPM2_CC_HIERARCHY_CHANGE_AUTH   = 0x0129,
106076d3564STomas Winkler 	TPM2_CC_CREATE_PRIMARY          = 0x0131,
107899102bcSTomas Winkler 	TPM2_CC_SEQUENCE_COMPLETE       = 0x013E,
1087a1d7e6dSJarkko Sakkinen 	TPM2_CC_SELF_TEST	        = 0x0143,
1097a1d7e6dSJarkko Sakkinen 	TPM2_CC_STARTUP		        = 0x0144,
1107a1d7e6dSJarkko Sakkinen 	TPM2_CC_SHUTDOWN	        = 0x0145,
111899102bcSTomas Winkler 	TPM2_CC_NV_READ                 = 0x014E,
112954650efSJarkko Sakkinen 	TPM2_CC_CREATE		        = 0x0153,
113954650efSJarkko Sakkinen 	TPM2_CC_LOAD		        = 0x0157,
114899102bcSTomas Winkler 	TPM2_CC_SEQUENCE_UPDATE         = 0x015C,
115954650efSJarkko Sakkinen 	TPM2_CC_UNSEAL		        = 0x015E,
116745b361eSJarkko Sakkinen 	TPM2_CC_CONTEXT_LOAD	        = 0x0161,
11758472f5cSJarkko Sakkinen 	TPM2_CC_CONTEXT_SAVE	        = 0x0162,
118954650efSJarkko Sakkinen 	TPM2_CC_FLUSH_CONTEXT	        = 0x0165,
119899102bcSTomas Winkler 	TPM2_CC_VERIFY_SIGNATURE        = 0x0177,
1207a1d7e6dSJarkko Sakkinen 	TPM2_CC_GET_CAPABILITY	        = 0x017A,
1217a1d7e6dSJarkko Sakkinen 	TPM2_CC_GET_RANDOM	        = 0x017B,
1227a1d7e6dSJarkko Sakkinen 	TPM2_CC_PCR_READ	        = 0x017E,
1237a1d7e6dSJarkko Sakkinen 	TPM2_CC_PCR_EXTEND	        = 0x0182,
124899102bcSTomas Winkler 	TPM2_CC_EVENT_SEQUENCE_COMPLETE = 0x0185,
125899102bcSTomas Winkler 	TPM2_CC_HASH_SEQUENCE_START     = 0x0186,
126899102bcSTomas Winkler 	TPM2_CC_CREATE_LOADED           = 0x0191,
127899102bcSTomas Winkler 	TPM2_CC_LAST		        = 0x0193, /* Spec 1.36 */
1287a1d7e6dSJarkko Sakkinen };
1297a1d7e6dSJarkko Sakkinen 
1307a1d7e6dSJarkko Sakkinen enum tpm2_permanent_handles {
1317a1d7e6dSJarkko Sakkinen 	TPM2_RS_PW		= 0x40000009,
1327a1d7e6dSJarkko Sakkinen };
1337a1d7e6dSJarkko Sakkinen 
1347a1d7e6dSJarkko Sakkinen enum tpm2_capabilities {
135745b361eSJarkko Sakkinen 	TPM2_CAP_HANDLES	= 1,
13658472f5cSJarkko Sakkinen 	TPM2_CAP_COMMANDS	= 2,
1371db15344SNayna Jain 	TPM2_CAP_PCRS		= 5,
1387a1d7e6dSJarkko Sakkinen 	TPM2_CAP_TPM_PROPERTIES = 6,
1397a1d7e6dSJarkko Sakkinen };
1407a1d7e6dSJarkko Sakkinen 
14158472f5cSJarkko Sakkinen enum tpm2_properties {
14258472f5cSJarkko Sakkinen 	TPM_PT_TOTAL_COMMANDS	= 0x0129,
14358472f5cSJarkko Sakkinen };
14458472f5cSJarkko Sakkinen 
1457a1d7e6dSJarkko Sakkinen enum tpm2_startup_types {
1467a1d7e6dSJarkko Sakkinen 	TPM2_SU_CLEAR	= 0x0000,
1477a1d7e6dSJarkko Sakkinen 	TPM2_SU_STATE	= 0x0001,
1487a1d7e6dSJarkko Sakkinen };
1497a1d7e6dSJarkko Sakkinen 
15058472f5cSJarkko Sakkinen enum tpm2_cc_attrs {
15158472f5cSJarkko Sakkinen 	TPM2_CC_ATTR_CHANDLES	= 25,
15258472f5cSJarkko Sakkinen 	TPM2_CC_ATTR_RHANDLE	= 28,
15358472f5cSJarkko Sakkinen };
15458472f5cSJarkko Sakkinen 
1554e401fb0SStefan Berger #define TPM_VID_INTEL    0x8086
1561f866057SStefan Berger #define TPM_VID_WINBOND  0x1050
1571f866057SStefan Berger #define TPM_VID_STM      0x104A
1584e401fb0SStefan Berger 
159afb5abc2SJarkko Sakkinen enum tpm_chip_flags {
1609b774d5cSJarkko Sakkinen 	TPM_CHIP_FLAG_TPM2		= BIT(1),
161570a3609SChristophe Ricard 	TPM_CHIP_FLAG_IRQ		= BIT(2),
1622f9f5377SStefan Berger 	TPM_CHIP_FLAG_VIRTUAL		= BIT(3),
163d1d253cfSJason Gunthorpe 	TPM_CHIP_FLAG_HAVE_TIMEOUTS	= BIT(4),
164b5d0ebc9SEnric Balletbo i Serra 	TPM_CHIP_FLAG_ALWAYS_POWERED	= BIT(5),
165afb5abc2SJarkko Sakkinen };
166afb5abc2SJarkko Sakkinen 
1679b774d5cSJarkko Sakkinen #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
16827084efeSLeendert van Doorn 
169b34b77a9SJarkko Sakkinen struct tpm_header {
17008837438SRajiv Andrade 	__be16 tag;
17108837438SRajiv Andrade 	__be32 length;
172b34b77a9SJarkko Sakkinen 	union {
17308837438SRajiv Andrade 		__be32 ordinal;
17408837438SRajiv Andrade 		__be32 return_code;
175b34b77a9SJarkko Sakkinen 	};
176348df8dbSJason Gunthorpe } __packed;
17708837438SRajiv Andrade 
17806e93279SRoberto Sassu #define TPM_TAG_RQU_COMMAND 193
179000a07b0SJason Gunthorpe 
18008837438SRajiv Andrade struct	stclear_flags_t {
18108837438SRajiv Andrade 	__be16	tag;
18208837438SRajiv Andrade 	u8	deactivated;
18308837438SRajiv Andrade 	u8	disableForceClear;
18408837438SRajiv Andrade 	u8	physicalPresence;
18508837438SRajiv Andrade 	u8	physicalPresenceLock;
18608837438SRajiv Andrade 	u8	bGlobalLock;
187348df8dbSJason Gunthorpe } __packed;
18808837438SRajiv Andrade 
189*f2f5820eSJarkko Sakkinen struct tpm1_version {
190*f2f5820eSJarkko Sakkinen 	u8 major;
191*f2f5820eSJarkko Sakkinen 	u8 minor;
192*f2f5820eSJarkko Sakkinen 	u8 rev_major;
193*f2f5820eSJarkko Sakkinen 	u8 rev_minor;
194348df8dbSJason Gunthorpe } __packed;
19508837438SRajiv Andrade 
196*f2f5820eSJarkko Sakkinen struct tpm1_version2 {
19708837438SRajiv Andrade 	__be16 tag;
198*f2f5820eSJarkko Sakkinen 	struct tpm1_version version;
199348df8dbSJason Gunthorpe } __packed;
20008837438SRajiv Andrade 
20108837438SRajiv Andrade struct	timeout_t {
20208837438SRajiv Andrade 	__be32	a;
20308837438SRajiv Andrade 	__be32	b;
20408837438SRajiv Andrade 	__be32	c;
20508837438SRajiv Andrade 	__be32	d;
206348df8dbSJason Gunthorpe } __packed;
20708837438SRajiv Andrade 
20808837438SRajiv Andrade struct duration_t {
20908837438SRajiv Andrade 	__be32	tpm_short;
21008837438SRajiv Andrade 	__be32	tpm_medium;
21108837438SRajiv Andrade 	__be32	tpm_long;
212348df8dbSJason Gunthorpe } __packed;
21308837438SRajiv Andrade 
21408837438SRajiv Andrade struct permanent_flags_t {
21508837438SRajiv Andrade 	__be16	tag;
21608837438SRajiv Andrade 	u8	disable;
21708837438SRajiv Andrade 	u8	ownership;
21808837438SRajiv Andrade 	u8	deactivated;
21908837438SRajiv Andrade 	u8	readPubek;
22008837438SRajiv Andrade 	u8	disableOwnerClear;
22108837438SRajiv Andrade 	u8	allowMaintenance;
22208837438SRajiv Andrade 	u8	physicalPresenceLifetimeLock;
22308837438SRajiv Andrade 	u8	physicalPresenceHWEnable;
22408837438SRajiv Andrade 	u8	physicalPresenceCMDEnable;
22508837438SRajiv Andrade 	u8	CEKPUsed;
22608837438SRajiv Andrade 	u8	TPMpost;
22708837438SRajiv Andrade 	u8	TPMpostLock;
22808837438SRajiv Andrade 	u8	FIPS;
22908837438SRajiv Andrade 	u8	operator;
23008837438SRajiv Andrade 	u8	enableRevokeEK;
23108837438SRajiv Andrade 	u8	nvLocked;
23208837438SRajiv Andrade 	u8	readSRKPub;
23308837438SRajiv Andrade 	u8	tpmEstablished;
23408837438SRajiv Andrade 	u8	maintenanceDone;
23508837438SRajiv Andrade 	u8	disableFullDALogicInfo;
236348df8dbSJason Gunthorpe } __packed;
23708837438SRajiv Andrade 
23808837438SRajiv Andrade typedef union {
23908837438SRajiv Andrade 	struct	permanent_flags_t perm_flags;
24008837438SRajiv Andrade 	struct	stclear_flags_t	stclear_flags;
241a118cf2aSStefan Berger 	__u8	owned;
24208837438SRajiv Andrade 	__be32	num_pcrs;
243*f2f5820eSJarkko Sakkinen 	struct tpm1_version version1;
244*f2f5820eSJarkko Sakkinen 	struct tpm1_version2 version2;
24508837438SRajiv Andrade 	__be32	manufacturer_id;
24608837438SRajiv Andrade 	struct timeout_t  timeout;
24708837438SRajiv Andrade 	struct duration_t duration;
24808837438SRajiv Andrade } cap_t;
24908837438SRajiv Andrade 
250000a07b0SJason Gunthorpe enum tpm_capabilities {
25184fda152SJarkko Sakkinen 	TPM_CAP_FLAG = 4,
25284fda152SJarkko Sakkinen 	TPM_CAP_PROP = 5,
25384fda152SJarkko Sakkinen 	TPM_CAP_VERSION_1_1 = 0x06,
25484fda152SJarkko Sakkinen 	TPM_CAP_VERSION_1_2 = 0x1A,
255000a07b0SJason Gunthorpe };
256000a07b0SJason Gunthorpe 
257000a07b0SJason Gunthorpe enum tpm_sub_capabilities {
25884fda152SJarkko Sakkinen 	TPM_CAP_PROP_PCR = 0x101,
25984fda152SJarkko Sakkinen 	TPM_CAP_PROP_MANUFACTURER = 0x103,
26084fda152SJarkko Sakkinen 	TPM_CAP_FLAG_PERM = 0x108,
26184fda152SJarkko Sakkinen 	TPM_CAP_FLAG_VOL = 0x109,
26284fda152SJarkko Sakkinen 	TPM_CAP_PROP_OWNER = 0x111,
26384fda152SJarkko Sakkinen 	TPM_CAP_PROP_TIS_TIMEOUT = 0x115,
26484fda152SJarkko Sakkinen 	TPM_CAP_PROP_TIS_DURATION = 0x120,
265000a07b0SJason Gunthorpe };
266000a07b0SJason Gunthorpe 
267659aaf2bSRajiv Andrade 
26841ab999cSKent Yoder /* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
26941ab999cSKent Yoder  * bytes, but 128 is still a relatively large number of random bytes and
27041ab999cSKent Yoder  * anything much bigger causes users of struct tpm_cmd_t to start getting
27141ab999cSKent Yoder  * compiler warnings about stack frame size. */
27241ab999cSKent Yoder #define TPM_MAX_RNG_DATA	128
27341ab999cSKent Yoder 
274a74f8b36SJarkko Sakkinen /* A string buffer type for constructing TPM commands. This is based on the
275a74f8b36SJarkko Sakkinen  * ideas of string buffer code in security/keys/trusted.h but is heap based
276a74f8b36SJarkko Sakkinen  * in order to keep the stack usage minimal.
277a74f8b36SJarkko Sakkinen  */
278a74f8b36SJarkko Sakkinen 
279a74f8b36SJarkko Sakkinen enum tpm_buf_flags {
280a74f8b36SJarkko Sakkinen 	TPM_BUF_OVERFLOW	= BIT(0),
281a74f8b36SJarkko Sakkinen };
282a74f8b36SJarkko Sakkinen 
283a74f8b36SJarkko Sakkinen struct tpm_buf {
284a74f8b36SJarkko Sakkinen 	struct page *data_page;
285a74f8b36SJarkko Sakkinen 	unsigned int flags;
286a74f8b36SJarkko Sakkinen 	u8 *data;
287a74f8b36SJarkko Sakkinen };
288a74f8b36SJarkko Sakkinen 
289ce63c05bSJarkko Sakkinen static inline void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal)
290a74f8b36SJarkko Sakkinen {
291b34b77a9SJarkko Sakkinen 	struct tpm_header *head = (struct tpm_header *)buf->data;
292b34b77a9SJarkko Sakkinen 
293ce63c05bSJarkko Sakkinen 	head->tag = cpu_to_be16(tag);
294ce63c05bSJarkko Sakkinen 	head->length = cpu_to_be32(sizeof(*head));
295ce63c05bSJarkko Sakkinen 	head->ordinal = cpu_to_be32(ordinal);
296ce63c05bSJarkko Sakkinen }
297a74f8b36SJarkko Sakkinen 
298ce63c05bSJarkko Sakkinen static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal)
299ce63c05bSJarkko Sakkinen {
300a74f8b36SJarkko Sakkinen 	buf->data_page = alloc_page(GFP_HIGHUSER);
301a74f8b36SJarkko Sakkinen 	if (!buf->data_page)
302a74f8b36SJarkko Sakkinen 		return -ENOMEM;
303a74f8b36SJarkko Sakkinen 
304a74f8b36SJarkko Sakkinen 	buf->flags = 0;
305a74f8b36SJarkko Sakkinen 	buf->data = kmap(buf->data_page);
306ce63c05bSJarkko Sakkinen 	tpm_buf_reset(buf, tag, ordinal);
307a74f8b36SJarkko Sakkinen 	return 0;
308a74f8b36SJarkko Sakkinen }
309a74f8b36SJarkko Sakkinen 
310a74f8b36SJarkko Sakkinen static inline void tpm_buf_destroy(struct tpm_buf *buf)
311a74f8b36SJarkko Sakkinen {
312a74f8b36SJarkko Sakkinen 	kunmap(buf->data_page);
313a74f8b36SJarkko Sakkinen 	__free_page(buf->data_page);
314a74f8b36SJarkko Sakkinen }
315a74f8b36SJarkko Sakkinen 
316a74f8b36SJarkko Sakkinen static inline u32 tpm_buf_length(struct tpm_buf *buf)
317a74f8b36SJarkko Sakkinen {
318b34b77a9SJarkko Sakkinen 	struct tpm_header *head = (struct tpm_header *)buf->data;
319a74f8b36SJarkko Sakkinen 
320a74f8b36SJarkko Sakkinen 	return be32_to_cpu(head->length);
321a74f8b36SJarkko Sakkinen }
322a74f8b36SJarkko Sakkinen 
323a74f8b36SJarkko Sakkinen static inline u16 tpm_buf_tag(struct tpm_buf *buf)
324a74f8b36SJarkko Sakkinen {
325b34b77a9SJarkko Sakkinen 	struct tpm_header *head = (struct tpm_header *)buf->data;
326a74f8b36SJarkko Sakkinen 
327a74f8b36SJarkko Sakkinen 	return be16_to_cpu(head->tag);
328a74f8b36SJarkko Sakkinen }
329a74f8b36SJarkko Sakkinen 
330a74f8b36SJarkko Sakkinen static inline void tpm_buf_append(struct tpm_buf *buf,
331a74f8b36SJarkko Sakkinen 				  const unsigned char *new_data,
332a74f8b36SJarkko Sakkinen 				  unsigned int new_len)
333a74f8b36SJarkko Sakkinen {
334b34b77a9SJarkko Sakkinen 	struct tpm_header *head = (struct tpm_header *)buf->data;
335a74f8b36SJarkko Sakkinen 	u32 len = tpm_buf_length(buf);
336a74f8b36SJarkko Sakkinen 
337a74f8b36SJarkko Sakkinen 	/* Return silently if overflow has already happened. */
338a74f8b36SJarkko Sakkinen 	if (buf->flags & TPM_BUF_OVERFLOW)
339a74f8b36SJarkko Sakkinen 		return;
340a74f8b36SJarkko Sakkinen 
341a74f8b36SJarkko Sakkinen 	if ((len + new_len) > PAGE_SIZE) {
342a74f8b36SJarkko Sakkinen 		WARN(1, "tpm_buf: overflow\n");
343a74f8b36SJarkko Sakkinen 		buf->flags |= TPM_BUF_OVERFLOW;
344a74f8b36SJarkko Sakkinen 		return;
345a74f8b36SJarkko Sakkinen 	}
346a74f8b36SJarkko Sakkinen 
347a74f8b36SJarkko Sakkinen 	memcpy(&buf->data[len], new_data, new_len);
348a74f8b36SJarkko Sakkinen 	head->length = cpu_to_be32(len + new_len);
349a74f8b36SJarkko Sakkinen }
350a74f8b36SJarkko Sakkinen 
351a74f8b36SJarkko Sakkinen static inline void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value)
352a74f8b36SJarkko Sakkinen {
353a74f8b36SJarkko Sakkinen 	tpm_buf_append(buf, &value, 1);
354a74f8b36SJarkko Sakkinen }
355a74f8b36SJarkko Sakkinen 
356a74f8b36SJarkko Sakkinen static inline void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value)
357a74f8b36SJarkko Sakkinen {
358a74f8b36SJarkko Sakkinen 	__be16 value2 = cpu_to_be16(value);
359a74f8b36SJarkko Sakkinen 
360a74f8b36SJarkko Sakkinen 	tpm_buf_append(buf, (u8 *) &value2, 2);
361a74f8b36SJarkko Sakkinen }
362a74f8b36SJarkko Sakkinen 
363a74f8b36SJarkko Sakkinen static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
364a74f8b36SJarkko Sakkinen {
365a74f8b36SJarkko Sakkinen 	__be32 value2 = cpu_to_be32(value);
366a74f8b36SJarkko Sakkinen 
367a74f8b36SJarkko Sakkinen 	tpm_buf_append(buf, (u8 *) &value2, 4);
368a74f8b36SJarkko Sakkinen }
369a74f8b36SJarkko Sakkinen 
370313d21eeSJarkko Sakkinen extern struct class *tpm_class;
371fdc915f7SJames Bottomley extern struct class *tpmrm_class;
372313d21eeSJarkko Sakkinen extern dev_t tpm_devt;
373313d21eeSJarkko Sakkinen extern const struct file_operations tpm_fops;
374fdc915f7SJames Bottomley extern const struct file_operations tpmrm_fops;
37515516788SStefan Berger extern struct idr dev_nums_idr;
376313d21eeSJarkko Sakkinen 
37747a6c28bSJarkko Sakkinen ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz);
3785faafbabSJarkko Sakkinen ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf,
37947a6c28bSJarkko Sakkinen 			 size_t min_rsp_body_length, const char *desc);
380d4abd956SJarkko Sakkinen int tpm_get_timeouts(struct tpm_chip *);
381b03c4370STomas Winkler int tpm_auto_startup(struct tpm_chip *chip);
382c82a330cSTomas Winkler 
38395adc6b4STomas Winkler int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr);
384cae8b441SJason Gunthorpe int tpm1_auto_startup(struct tpm_chip *chip);
385d4a31756STomas Winkler int tpm1_do_selftest(struct tpm_chip *chip);
38670a3199aSTomas Winkler int tpm1_get_timeouts(struct tpm_chip *chip);
387b2d6e6deSTomas Winkler unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
38895adc6b4STomas Winkler int tpm1_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash,
3891ad6640cSTomas Winkler 		    const char *log_msg);
39095adc6b4STomas Winkler int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf);
391f4d916b7STomas Winkler ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
392f4d916b7STomas Winkler 		    const char *desc, size_t min_cap_length);
393433d390fSTomas Winkler int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max);
394fa4f99c0SNayna Jain int tpm1_get_pcr_allocation(struct tpm_chip *chip);
395d856c00fSTomas Winkler unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
396d4abd956SJarkko Sakkinen int tpm_pm_suspend(struct device *dev);
397d4abd956SJarkko Sakkinen int tpm_pm_resume(struct device *dev);
398f84fdff0SXiaoyan Zhang 
3999f3fc7bcSHamza Attak static inline void tpm_msleep(unsigned int delay_msec)
4009f3fc7bcSHamza Attak {
4015ef924d9SNayna Jain 	usleep_range((delay_msec * 1000) - TPM_TIMEOUT_RANGE_US,
4025ef924d9SNayna Jain 		     delay_msec * 1000);
4039f3fc7bcSHamza Attak };
4049f3fc7bcSHamza Attak 
40547a6c28bSJarkko Sakkinen int tpm_chip_start(struct tpm_chip *chip);
40647a6c28bSJarkko Sakkinen void tpm_chip_stop(struct tpm_chip *chip);
407fc1d52b7SStefan Berger struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip);
4084e26195fSJason Gunthorpe __must_check int tpm_try_get_ops(struct tpm_chip *chip);
4094e26195fSJason Gunthorpe void tpm_put_ops(struct tpm_chip *chip);
4104e26195fSJason Gunthorpe 
411d4abd956SJarkko Sakkinen struct tpm_chip *tpm_chip_alloc(struct device *dev,
4123897cd9cSJason Gunthorpe 				const struct tpm_class_ops *ops);
413d4abd956SJarkko Sakkinen struct tpm_chip *tpmm_chip_alloc(struct device *pdev,
414afb5abc2SJarkko Sakkinen 				 const struct tpm_class_ops *ops);
415d4abd956SJarkko Sakkinen int tpm_chip_register(struct tpm_chip *chip);
416d4abd956SJarkko Sakkinen void tpm_chip_unregister(struct tpm_chip *chip);
417afb5abc2SJarkko Sakkinen 
418062807f2SJason Gunthorpe void tpm_sysfs_add_device(struct tpm_chip *chip);
419afdba32eSJason Gunthorpe 
420000a07b0SJason Gunthorpe 
421f84fdff0SXiaoyan Zhang #ifdef CONFIG_ACPI
4229b774d5cSJarkko Sakkinen extern void tpm_add_ppi(struct tpm_chip *chip);
423f84fdff0SXiaoyan Zhang #else
4249b774d5cSJarkko Sakkinen static inline void tpm_add_ppi(struct tpm_chip *chip)
4251631cfb7SGang Wei {
4261631cfb7SGang Wei }
427f84fdff0SXiaoyan Zhang #endif
4287a1d7e6dSJarkko Sakkinen 
4292d56c718SRuben Roy static inline u32 tpm2_rc_value(u32 rc)
4307d761119SJarkko Sakkinen {
4317d761119SJarkko Sakkinen 	return (rc & BIT(7)) ? rc & 0xff : rc;
4327d761119SJarkko Sakkinen }
4337d761119SJarkko Sakkinen 
43470a3199aSTomas Winkler int tpm2_get_timeouts(struct tpm_chip *chip);
435879b5892SRoberto Sassu int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
436879b5892SRoberto Sassu 		  struct tpm_digest *digest, u16 *digest_size_ptr);
4370b6cf6b9SRoberto Sassu int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
438aa042475SRoberto Sassu 		    struct tpm_digest *digests);
439ce63c05bSJarkko Sakkinen int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max);
44047a6c28bSJarkko Sakkinen void tpm2_flush_context(struct tpm_chip *chip, u32 handle);
441954650efSJarkko Sakkinen int tpm2_seal_trusted(struct tpm_chip *chip,
442954650efSJarkko Sakkinen 		      struct trusted_key_payload *payload,
443954650efSJarkko Sakkinen 		      struct trusted_key_options *options);
444954650efSJarkko Sakkinen int tpm2_unseal_trusted(struct tpm_chip *chip,
445954650efSJarkko Sakkinen 			struct trusted_key_payload *payload,
446954650efSJarkko Sakkinen 			struct trusted_key_options *options);
4477a1d7e6dSJarkko Sakkinen ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
4487a1d7e6dSJarkko Sakkinen 			u32 *value, const char *desc);
4497a1d7e6dSJarkko Sakkinen 
450fa4f99c0SNayna Jain ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip);
451cae8b441SJason Gunthorpe int tpm2_auto_startup(struct tpm_chip *chip);
452d4abd956SJarkko Sakkinen void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
453d4abd956SJarkko Sakkinen unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
454d4abd956SJarkko Sakkinen int tpm2_probe(struct tpm_chip *chip);
45558472f5cSJarkko Sakkinen int tpm2_find_cc(struct tpm_chip *chip, u32 cc);
456745b361eSJarkko Sakkinen int tpm2_init_space(struct tpm_space *space);
4574d57856aSJames Bottomley void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space);
458304ff672SJarkko Sakkinen void tpm2_flush_space(struct tpm_chip *chip);
459c3465a37SJarkko Sakkinen int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd,
460c3465a37SJarkko Sakkinen 		       size_t cmdsiz);
461c3465a37SJarkko Sakkinen int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, void *buf,
462c3465a37SJarkko Sakkinen 		      size_t *bufsiz);
463fd3ec366SThiebaud Weksteen 
464fd3ec366SThiebaud Weksteen int tpm_bios_log_setup(struct tpm_chip *chip);
465fd3ec366SThiebaud Weksteen void tpm_bios_log_teardown(struct tpm_chip *chip);
4669e1b74a6STadeusz Struk int tpm_dev_common_init(void);
4679e1b74a6STadeusz Struk void tpm_dev_common_exit(void);
468d2efee6eSChristophe Ricard #endif
469