diff options
Diffstat (limited to 'drivers/char/tpm/tpm-interface.c')
| -rw-r--r-- | drivers/char/tpm/tpm-interface.c | 832 | 
1 files changed, 58 insertions, 774 deletions
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 129f640424b7..d9439f9abe78 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -33,297 +33,32 @@  #include "tpm.h" -#define TPM_MAX_ORDINAL 243 -#define TSC_MAX_ORDINAL 12 -#define TPM_PROTECTED_COMMAND 0x00 -#define TPM_CONNECTION_COMMAND 0x40 -  /*   * Bug workaround - some TPM's don't flush the most   * recently changed pcr on suspend, so force the flush   * with an extend to the selected _unused_ non-volatile pcr.   */ -static int tpm_suspend_pcr; +static u32 tpm_suspend_pcr;  module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644);  MODULE_PARM_DESC(suspend_pcr,  		 "PCR to use for dummy writes to facilitate flush on suspend."); -/* - * Array with one entry per ordinal defining the maximum amount - * of time the chip could take to return the result.  The ordinal - * designation of short, medium or long is defined in a table in - * TCG Specification TPM Main Part 2 TPM Structures Section 17. The - * values of the SHORT, MEDIUM, and LONG durations are retrieved - * from the chip during initialization with a call to tpm_get_timeouts. - */ -static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { -	TPM_UNDEFINED,		/* 0 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 5 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 10 */ -	TPM_SHORT, -	TPM_MEDIUM, -	TPM_LONG, -	TPM_LONG, -	TPM_MEDIUM,		/* 15 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_MEDIUM, -	TPM_LONG, -	TPM_SHORT,		/* 20 */ -	TPM_SHORT, -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_SHORT,		/* 25 */ -	TPM_SHORT, -	TPM_MEDIUM, -	TPM_SHORT, -	TPM_SHORT, -	TPM_MEDIUM,		/* 30 */ -	TPM_LONG, -	TPM_MEDIUM, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT,		/* 35 */ -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_MEDIUM,		/* 40 */ -	TPM_LONG, -	TPM_MEDIUM, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT,		/* 45 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_LONG, -	TPM_MEDIUM,		/* 50 */ -	TPM_MEDIUM, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 55 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_MEDIUM,		/* 60 */ -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_SHORT, -	TPM_SHORT, -	TPM_MEDIUM,		/* 65 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 70 */ -	TPM_SHORT, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 75 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_LONG,		/* 80 */ -	TPM_UNDEFINED, -	TPM_MEDIUM, -	TPM_LONG, -	TPM_SHORT, -	TPM_UNDEFINED,		/* 85 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 90 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_UNDEFINED,		/* 95 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_MEDIUM,		/* 100 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 105 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 110 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT,		/* 115 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_LONG,		/* 120 */ -	TPM_LONG, -	TPM_MEDIUM, -	TPM_UNDEFINED, -	TPM_SHORT, -	TPM_SHORT,		/* 125 */ -	TPM_SHORT, -	TPM_LONG, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT,		/* 130 */ -	TPM_MEDIUM, -	TPM_UNDEFINED, -	TPM_SHORT, -	TPM_MEDIUM, -	TPM_UNDEFINED,		/* 135 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 140 */ -	TPM_SHORT, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 145 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 150 */ -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_SHORT, -	TPM_SHORT, -	TPM_UNDEFINED,		/* 155 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 160 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 165 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_LONG,		/* 170 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 175 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_MEDIUM,		/* 180 */ -	TPM_SHORT, -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_MEDIUM,		/* 185 */ -	TPM_SHORT, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 190 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 195 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 200 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT, -	TPM_SHORT,		/* 205 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_MEDIUM,		/* 210 */ -	TPM_UNDEFINED, -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_UNDEFINED,		/* 215 */ -	TPM_MEDIUM, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT, -	TPM_SHORT,		/* 220 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_UNDEFINED,		/* 225 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 230 */ -	TPM_LONG, -	TPM_MEDIUM, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 235 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 240 */ -	TPM_UNDEFINED, -	TPM_MEDIUM, -}; - -/* - * Returns max number of jiffies to wait +/** + * tpm_calc_ordinal_duration() - calculate the maximum command duration + * @chip:    TPM chip to use. + * @ordinal: TPM command ordinal. + * + * The function returns the maximum amount of time the chip could take + * to return the result for a particular ordinal in jiffies. + * + * Return: A maximal duration time for an ordinal in jiffies.   */ -unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, -					   u32 ordinal) +unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)  { -	int duration_idx = TPM_UNDEFINED; -	int duration = 0; - -	/* -	 * We only have a duration table for protected commands, where the upper -	 * 16 bits are 0. For the few other ordinals the fallback will be used. -	 */ -	if (ordinal < TPM_MAX_ORDINAL) -		duration_idx = tpm_ordinal_duration[ordinal]; - -	if (duration_idx != TPM_UNDEFINED) -		duration = chip->duration[duration_idx]; -	if (duration <= 0) -		return 2 * 60 * HZ; +	if (chip->flags & TPM_CHIP_FLAG_TPM2) +		return tpm2_calc_ordinal_duration(chip, ordinal);  	else -		return duration; +		return tpm1_calc_ordinal_duration(chip, ordinal);  }  EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); @@ -477,13 +212,15 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip,  	if (need_locality) {  		rc = tpm_request_locality(chip, flags); -		if (rc < 0) -			goto out_no_locality; +		if (rc < 0) { +			need_locality = false; +			goto out_locality; +		}  	}  	rc = tpm_cmd_ready(chip, flags);  	if (rc) -		goto out; +		goto out_locality;  	rc = tpm2_prepare_space(chip, space, ordinal, buf);  	if (rc) @@ -500,10 +237,7 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip,  	if (chip->flags & TPM_CHIP_FLAG_IRQ)  		goto out_recv; -	if (chip->flags & TPM_CHIP_FLAG_TPM2) -		stop = jiffies + tpm2_calc_ordinal_duration(chip, ordinal); -	else -		stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); +	stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);  	do {  		u8 status = chip->ops->status(chip);  		if ((status & chip->ops->req_complete_mask) == @@ -547,14 +281,13 @@ out_recv:  		dev_err(&chip->dev, "tpm2_commit_space: error %d\n", rc);  out: -	rc = tpm_go_idle(chip, flags); -	if (rc) -		goto out; +	/* may fail but do not override previous error value in rc */ +	tpm_go_idle(chip, flags); +out_locality:  	if (need_locality)  		tpm_relinquish_locality(chip, flags); -out_no_locality:  	if (chip->ops->clk_enable != NULL)  		chip->ops->clk_enable(chip, false); @@ -677,277 +410,18 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,  }  EXPORT_SYMBOL_GPL(tpm_transmit_cmd); -#define TPM_ORD_STARTUP 153 -#define TPM_ST_CLEAR 1 - -/** - * tpm_startup - turn on the TPM - * @chip: TPM chip to use - * - * Normally the firmware should start the TPM. This function is provided as a - * workaround if this does not happen. A legal case for this could be for - * example when a TPM emulator is used. - * - * Return: same as tpm_transmit_cmd() - */ -int tpm_startup(struct tpm_chip *chip) -{ -	struct tpm_buf buf; -	int rc; - -	dev_info(&chip->dev, "starting up the TPM manually\n"); - -	if (chip->flags & TPM_CHIP_FLAG_TPM2) { -		rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP); -		if (rc < 0) -			return rc; - -		tpm_buf_append_u16(&buf, TPM2_SU_CLEAR); -	} else { -		rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP); -		if (rc < 0) -			return rc; - -		tpm_buf_append_u16(&buf, TPM_ST_CLEAR); -	} - -	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, -			      "attempting to start the TPM"); - -	tpm_buf_destroy(&buf); -	return rc; -} - -#define TPM_DIGEST_SIZE 20 -#define TPM_RET_CODE_IDX 6 -#define TPM_INTERNAL_RESULT_SIZE 200 -#define TPM_ORD_GET_CAP 101 -#define TPM_ORD_GET_RANDOM 70 - -static const struct tpm_input_header tpm_getcap_header = { -	.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), -	.length = cpu_to_be32(22), -	.ordinal = cpu_to_be32(TPM_ORD_GET_CAP) -}; - -ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, -		   const char *desc, size_t min_cap_length) -{ -	struct tpm_buf buf; -	int rc; - -	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP); -	if (rc) -		return rc; - -	if (subcap_id == TPM_CAP_VERSION_1_1 || -	    subcap_id == TPM_CAP_VERSION_1_2) { -		tpm_buf_append_u32(&buf, subcap_id); -		tpm_buf_append_u32(&buf, 0); -	} else { -		if (subcap_id == TPM_CAP_FLAG_PERM || -		    subcap_id == TPM_CAP_FLAG_VOL) -			tpm_buf_append_u32(&buf, TPM_CAP_FLAG); -		else -			tpm_buf_append_u32(&buf, TPM_CAP_PROP); - -		tpm_buf_append_u32(&buf, 4); -		tpm_buf_append_u32(&buf, subcap_id); -	} -	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, -			      min_cap_length, 0, desc); -	if (!rc) -		*cap = *(cap_t *)&buf.data[TPM_HEADER_SIZE + 4]; - -	tpm_buf_destroy(&buf); -	return rc; -} -EXPORT_SYMBOL_GPL(tpm_getcap); -  int tpm_get_timeouts(struct tpm_chip *chip)  { -	cap_t cap; -	unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4]; -	ssize_t rc; -  	if (chip->flags & TPM_CHIP_FLAG_HAVE_TIMEOUTS)  		return 0; -	if (chip->flags & TPM_CHIP_FLAG_TPM2) { -		/* Fixed timeouts for TPM2 */ -		chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A); -		chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B); -		chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C); -		chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D); -		chip->duration[TPM_SHORT] = -		    msecs_to_jiffies(TPM2_DURATION_SHORT); -		chip->duration[TPM_MEDIUM] = -		    msecs_to_jiffies(TPM2_DURATION_MEDIUM); -		chip->duration[TPM_LONG] = -		    msecs_to_jiffies(TPM2_DURATION_LONG); -		chip->duration[TPM_LONG_LONG] = -		    msecs_to_jiffies(TPM2_DURATION_LONG_LONG); - -		chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; -		return 0; -	} - -	rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL, -			sizeof(cap.timeout)); -	if (rc == TPM_ERR_INVALID_POSTINIT) { -		if (tpm_startup(chip)) -			return rc; - -		rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, -				"attempting to determine the timeouts", -				sizeof(cap.timeout)); -	} - -	if (rc) { -		dev_err(&chip->dev, -			"A TPM error (%zd) occurred attempting to determine the timeouts\n", -			rc); -		return rc; -	} - -	timeout_old[0] = jiffies_to_usecs(chip->timeout_a); -	timeout_old[1] = jiffies_to_usecs(chip->timeout_b); -	timeout_old[2] = jiffies_to_usecs(chip->timeout_c); -	timeout_old[3] = jiffies_to_usecs(chip->timeout_d); -	timeout_chip[0] = be32_to_cpu(cap.timeout.a); -	timeout_chip[1] = be32_to_cpu(cap.timeout.b); -	timeout_chip[2] = be32_to_cpu(cap.timeout.c); -	timeout_chip[3] = be32_to_cpu(cap.timeout.d); -	memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff)); - -	/* -	 * Provide ability for vendor overrides of timeout values in case -	 * of misreporting. -	 */ -	if (chip->ops->update_timeouts != NULL) -		chip->timeout_adjusted = -			chip->ops->update_timeouts(chip, timeout_eff); - -	if (!chip->timeout_adjusted) { -		/* Restore default if chip reported 0 */ -		int i; - -		for (i = 0; i < ARRAY_SIZE(timeout_eff); i++) { -			if (timeout_eff[i]) -				continue; - -			timeout_eff[i] = timeout_old[i]; -			chip->timeout_adjusted = true; -		} - -		if (timeout_eff[0] != 0 && timeout_eff[0] < 1000) { -			/* timeouts in msec rather usec */ -			for (i = 0; i != ARRAY_SIZE(timeout_eff); i++) -				timeout_eff[i] *= 1000; -			chip->timeout_adjusted = true; -		} -	} - -	/* Report adjusted timeouts */ -	if (chip->timeout_adjusted) { -		dev_info(&chip->dev, -			 HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n", -			 timeout_chip[0], timeout_eff[0], -			 timeout_chip[1], timeout_eff[1], -			 timeout_chip[2], timeout_eff[2], -			 timeout_chip[3], timeout_eff[3]); -	} - -	chip->timeout_a = usecs_to_jiffies(timeout_eff[0]); -	chip->timeout_b = usecs_to_jiffies(timeout_eff[1]); -	chip->timeout_c = usecs_to_jiffies(timeout_eff[2]); -	chip->timeout_d = usecs_to_jiffies(timeout_eff[3]); - -	rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_DURATION, &cap, -			"attempting to determine the durations", -			sizeof(cap.duration)); -	if (rc) -		return rc; - -	chip->duration[TPM_SHORT] = -		usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_short)); -	chip->duration[TPM_MEDIUM] = -		usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_medium)); -	chip->duration[TPM_LONG] = -		usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_long)); -	chip->duration[TPM_LONG_LONG] = 0; /* not used under 1.2 */ - -	/* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above -	 * value wrong and apparently reports msecs rather than usecs. So we -	 * fix up the resulting too-small TPM_SHORT value to make things work. -	 * We also scale the TPM_MEDIUM and -_LONG values by 1000. -	 */ -	if (chip->duration[TPM_SHORT] < (HZ / 100)) { -		chip->duration[TPM_SHORT] = HZ; -		chip->duration[TPM_MEDIUM] *= 1000; -		chip->duration[TPM_LONG] *= 1000; -		chip->duration_adjusted = true; -		dev_info(&chip->dev, "Adjusting TPM timeout parameters."); -	} - -	chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; -	return 0; +	if (chip->flags & TPM_CHIP_FLAG_TPM2) +		return tpm2_get_timeouts(chip); +	else +		return tpm1_get_timeouts(chip);  }  EXPORT_SYMBOL_GPL(tpm_get_timeouts); -#define TPM_ORD_CONTINUE_SELFTEST 83 -#define CONTINUE_SELFTEST_RESULT_SIZE 10 - -static const struct tpm_input_header continue_selftest_header = { -	.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), -	.length = cpu_to_be32(10), -	.ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST), -}; - -/** - * tpm_continue_selftest -- run TPM's selftest - * @chip: TPM chip to use - * - * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing - * a TPM error code. - */ -static int tpm_continue_selftest(struct tpm_chip *chip) -{ -	int rc; -	struct tpm_cmd_t cmd; - -	cmd.header.in = continue_selftest_header; -	rc = tpm_transmit_cmd(chip, NULL, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, -			      0, 0, "continue selftest"); -	return rc; -} - -#define TPM_ORDINAL_PCRREAD 21 -#define READ_PCR_RESULT_SIZE 30 -#define READ_PCR_RESULT_BODY_SIZE 20 -static const struct tpm_input_header pcrread_header = { -	.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), -	.length = cpu_to_be32(14), -	.ordinal = cpu_to_be32(TPM_ORDINAL_PCRREAD) -}; - -int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) -{ -	int rc; -	struct tpm_cmd_t cmd; - -	cmd.header.in = pcrread_header; -	cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); -	rc = tpm_transmit_cmd(chip, NULL, &cmd, READ_PCR_RESULT_SIZE, -			      READ_PCR_RESULT_BODY_SIZE, 0, -			      "attempting to read a pcr value"); - -	if (rc == 0) -		memcpy(res_buf, cmd.params.pcrread_out.pcr_result, -		       TPM_DIGEST_SIZE); -	return rc; -} -  /**   * tpm_is_tpm2 - do we a have a TPM2 chip?   * @chip:	a &struct tpm_chip instance, %NULL for the default chip @@ -981,50 +455,24 @@ EXPORT_SYMBOL_GPL(tpm_is_tpm2);   *   * Return: same as with tpm_transmit_cmd()   */ -int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) +int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf)  {  	int rc;  	chip = tpm_find_get_ops(chip);  	if (!chip)  		return -ENODEV; +  	if (chip->flags & TPM_CHIP_FLAG_TPM2)  		rc = tpm2_pcr_read(chip, pcr_idx, res_buf);  	else -		rc = tpm_pcr_read_dev(chip, pcr_idx, res_buf); +		rc = tpm1_pcr_read(chip, pcr_idx, res_buf); +  	tpm_put_ops(chip);  	return rc;  }  EXPORT_SYMBOL_GPL(tpm_pcr_read); -#define TPM_ORD_PCR_EXTEND 20 -#define EXTEND_PCR_RESULT_SIZE 34 -#define EXTEND_PCR_RESULT_BODY_SIZE 20 -static const struct tpm_input_header pcrextend_header = { -	.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), -	.length = cpu_to_be32(34), -	.ordinal = cpu_to_be32(TPM_ORD_PCR_EXTEND) -}; - -static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash, -			   char *log_msg) -{ -	struct tpm_buf buf; -	int rc; - -	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND); -	if (rc) -		return rc; - -	tpm_buf_append_u32(&buf, pcr_idx); -	tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE); - -	rc = tpm_transmit_cmd(chip, NULL, buf.data, EXTEND_PCR_RESULT_SIZE, -			      EXTEND_PCR_RESULT_BODY_SIZE, 0, log_msg); -	tpm_buf_destroy(&buf); -	return rc; -} -  /**   * tpm_pcr_extend - extend a PCR value in SHA1 bank.   * @chip:	a &struct tpm_chip instance, %NULL for the default chip @@ -1037,7 +485,7 @@ static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,   *   * Return: same as with tpm_transmit_cmd()   */ -int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash) +int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash)  {  	int rc;  	struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)]; @@ -1071,97 +519,6 @@ int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)  EXPORT_SYMBOL_GPL(tpm_pcr_extend);  /** - * tpm_do_selftest - have the TPM continue its selftest and wait until it - *                   can receive further commands - * @chip: TPM chip to use - * - * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing - * a TPM error code. - */ -int tpm_do_selftest(struct tpm_chip *chip) -{ -	int rc; -	unsigned int loops; -	unsigned int delay_msec = 100; -	unsigned long duration; -	u8 dummy[TPM_DIGEST_SIZE]; - -	duration = tpm_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST); - -	loops = jiffies_to_msecs(duration) / delay_msec; - -	rc = tpm_continue_selftest(chip); -	if (rc == TPM_ERR_INVALID_POSTINIT) { -		chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; -		dev_info(&chip->dev, "TPM not ready (%d)\n", rc); -	} -	/* This may fail if there was no TPM driver during a suspend/resume -	 * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) -	 */ -	if (rc) -		return rc; - -	do { -		/* Attempt to read a PCR value */ -		rc = tpm_pcr_read_dev(chip, 0, dummy); - -		/* Some buggy TPMs will not respond to tpm_tis_ready() for -		 * around 300ms while the self test is ongoing, keep trying -		 * until the self test duration expires. */ -		if (rc == -ETIME) { -			dev_info( -			    &chip->dev, HW_ERR -			    "TPM command timed out during continue self test"); -			tpm_msleep(delay_msec); -			continue; -		} - -		if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { -			dev_info(&chip->dev, -				 "TPM is disabled/deactivated (0x%X)\n", rc); -			/* TPM is disabled and/or deactivated; driver can -			 * proceed and TPM does handle commands for -			 * suspend/resume correctly -			 */ -			return 0; -		} -		if (rc != TPM_WARN_DOING_SELFTEST) -			return rc; -		tpm_msleep(delay_msec); -	} while (--loops > 0); - -	return rc; -} -EXPORT_SYMBOL_GPL(tpm_do_selftest); - -/** - * tpm1_auto_startup - Perform the standard automatic TPM initialization - *                     sequence - * @chip: TPM chip to use - * - * Returns 0 on success, < 0 in case of fatal error. - */ -int tpm1_auto_startup(struct tpm_chip *chip) -{ -	int rc; - -	rc = tpm_get_timeouts(chip); -	if (rc) -		goto out; -	rc = tpm_do_selftest(chip); -	if (rc) { -		dev_err(&chip->dev, "TPM self test failed\n"); -		goto out; -	} - -	return rc; -out: -	if (rc > 0) -		rc = -ENODEV; -	return rc; -} - -/**   * tpm_send - send a TPM command   * @chip:	a &struct tpm_chip instance, %NULL for the default chip   * @cmd:	a TPM command buffer @@ -1184,14 +541,20 @@ int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)  }  EXPORT_SYMBOL_GPL(tpm_send); -#define TPM_ORD_SAVESTATE 152 -#define SAVESTATE_RESULT_SIZE 10 +int tpm_auto_startup(struct tpm_chip *chip) +{ +	int rc; + +	if (!(chip->ops->flags & TPM_OPS_AUTO_STARTUP)) +		return 0; -static const struct tpm_input_header savestate_header = { -	.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), -	.length = cpu_to_be32(10), -	.ordinal = cpu_to_be32(TPM_ORD_SAVESTATE) -}; +	if (chip->flags & TPM_CHIP_FLAG_TPM2) +		rc = tpm2_auto_startup(chip); +	else +		rc = tpm1_auto_startup(chip); + +	return rc; +}  /*   * We are about to suspend. Save the TPM state @@ -1200,54 +563,18 @@ static const struct tpm_input_header savestate_header = {  int tpm_pm_suspend(struct device *dev)  {  	struct tpm_chip *chip = dev_get_drvdata(dev); -	struct tpm_cmd_t cmd; -	int rc, try; +	int rc = 0; -	u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; - -	if (chip == NULL) +	if (!chip)  		return -ENODEV;  	if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)  		return 0; -	if (chip->flags & TPM_CHIP_FLAG_TPM2) { +	if (chip->flags & TPM_CHIP_FLAG_TPM2)  		tpm2_shutdown(chip, TPM2_SU_STATE); -		return 0; -	} - -	/* for buggy tpm, flush pcrs with extend to selected dummy */ -	if (tpm_suspend_pcr) -		rc = tpm1_pcr_extend(chip, tpm_suspend_pcr, dummy_hash, -				     "extending dummy pcr before suspend"); - -	/* now do the actual savestate */ -	for (try = 0; try < TPM_RETRY; try++) { -		cmd.header.in = savestate_header; -		rc = tpm_transmit_cmd(chip, NULL, &cmd, SAVESTATE_RESULT_SIZE, -				      0, 0, NULL); - -		/* -		 * If the TPM indicates that it is too busy to respond to -		 * this command then retry before giving up.  It can take -		 * several seconds for this TPM to be ready. -		 * -		 * This can happen if the TPM has already been sent the -		 * SaveState command before the driver has loaded.  TCG 1.2 -		 * specification states that any communication after SaveState -		 * may cause the TPM to invalidate previously saved state. -		 */ -		if (rc != TPM_WARN_RETRY) -			break; -		tpm_msleep(TPM_TIMEOUT_RETRY); -	} - -	if (rc) -		dev_err(&chip->dev, -			"Error (%d) sending savestate before suspend\n", rc); -	else if (try > 0) -		dev_warn(&chip->dev, "TPM savestate took %dms\n", -			 try * TPM_TIMEOUT_RETRY); +	else +		rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);  	return rc;  } @@ -1268,75 +595,32 @@ int tpm_pm_resume(struct device *dev)  }  EXPORT_SYMBOL_GPL(tpm_pm_resume); -#define TPM_GETRANDOM_RESULT_SIZE	18 -static const struct tpm_input_header tpm_getrandom_header = { -	.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), -	.length = cpu_to_be32(14), -	.ordinal = cpu_to_be32(TPM_ORD_GET_RANDOM) -}; -  /**   * tpm_get_random() - get random bytes from the TPM's RNG   * @chip:	a &struct tpm_chip instance, %NULL for the default chip   * @out:	destination buffer for the random bytes   * @max:	the max number of bytes to write to @out   * - * Return: same as with tpm_transmit_cmd() + * Return: number of random bytes read or a negative error value.   */  int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)  { -	struct tpm_cmd_t tpm_cmd; -	u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA), rlength; -	int err, total = 0, retries = 5; -	u8 *dest = out; +	int rc; -	if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) +	if (!out || max > TPM_MAX_RNG_DATA)  		return -EINVAL;  	chip = tpm_find_get_ops(chip);  	if (!chip)  		return -ENODEV; -	if (chip->flags & TPM_CHIP_FLAG_TPM2) { -		err = tpm2_get_random(chip, out, max); -		tpm_put_ops(chip); -		return err; -	} - -	do { -		tpm_cmd.header.in = tpm_getrandom_header; -		tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); - -		err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, -				       TPM_GETRANDOM_RESULT_SIZE + num_bytes, -				       offsetof(struct tpm_getrandom_out, -						rng_data), -				       0, "attempting get random"); -		if (err) -			break; - -		recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len); -		if (recd > num_bytes) { -			total = -EFAULT; -			break; -		} - -		rlength = be32_to_cpu(tpm_cmd.header.out.length); -		if (rlength < TPM_HEADER_SIZE + -			      offsetof(struct tpm_getrandom_out, rng_data) + -			      recd) { -			total = -EFAULT; -			break; -		} -		memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd); - -		dest += recd; -		total += recd; -		num_bytes -= recd; -	} while (retries-- && total < max); +	if (chip->flags & TPM_CHIP_FLAG_TPM2) +		rc = tpm2_get_random(chip, out, max); +	else +		rc = tpm1_get_random(chip, out, max);  	tpm_put_ops(chip); -	return total ? total : -EIO; +	return rc;  }  EXPORT_SYMBOL_GPL(tpm_get_random);  | 
