Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 68d6e671 authored by Stefan Berger's avatar Stefan Berger Committed by Rajiv Andrade
Browse files

tpm: Introduce function to poll for result of self test



This patch introduces a function that runs the TPM_ContinueSelfTest()
function and then polls the TPM to check whether it finished the selftest
and can receive new commands.

Signed-off-by: default avatarStefan Berger <stefanb@linux.vnet.ibm.com>
parent d97c6ade
Loading
Loading
Loading
Loading
+41 −3
Original line number Diff line number Diff line
@@ -627,7 +627,7 @@ static struct tpm_input_header continue_selftest_header = {
 * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
 * a TPM error code.
 */
int tpm_continue_selftest(struct tpm_chip *chip)
static int tpm_continue_selftest(struct tpm_chip *chip)
{
	int rc;
	struct tpm_cmd_t cmd;
@@ -637,7 +637,6 @@ int tpm_continue_selftest(struct tpm_chip *chip)
			  "continue selftest");
	return rc;
}
EXPORT_SYMBOL_GPL(tpm_continue_selftest);

ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
			char *buf)
@@ -732,7 +731,7 @@ static struct tpm_input_header pcrread_header = {
	.ordinal = TPM_ORDINAL_PCRREAD
};

int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
{
	int rc;
	struct tpm_cmd_t cmd;
@@ -812,6 +811,45 @@ int tpm_pcr_extend(u32 chip_num, 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;
	u8 digest[TPM_DIGEST_SIZE];
	unsigned int loops;
	unsigned int delay_msec = 1000;
	unsigned long duration;

	duration = tpm_calc_ordinal_duration(chip,
	                                     TPM_ORD_CONTINUE_SELFTEST);

	loops = jiffies_to_msecs(duration) / delay_msec;

	rc = tpm_continue_selftest(chip);
	/* 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 {
		rc = __tpm_pcr_read(chip, 0, digest);
		if (rc != TPM_WARN_DOING_SELFTEST)
			return rc;
		msleep(delay_msec);
	} while (--loops > 0);

	return rc;
}
EXPORT_SYMBOL_GPL(tpm_do_selftest);

int tpm_send(u32 chip_num, void *cmd, size_t buflen)
{
	struct tpm_chip *chip;
+3 −1
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ enum tpm_addr {
	TPM_ADDR = 0x4E,
};

#define TPM_WARN_DOING_SELFTEST 0x802

extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
				char *);
extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
@@ -281,7 +283,7 @@ ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *);

extern int tpm_get_timeouts(struct tpm_chip *);
extern void tpm_gen_interrupt(struct tpm_chip *);
extern int tpm_continue_selftest(struct tpm_chip *);
extern int tpm_do_selftest(struct tpm_chip *);
extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
extern struct tpm_chip* tpm_register_hardware(struct device *,
				 const struct tpm_vendor_specific *);
+7 −2
Original line number Diff line number Diff line
@@ -616,6 +616,12 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
	/* get the timeouts before testing for irqs */
	tpm_get_timeouts(chip);

	if (tpm_do_selftest(chip)) {
		dev_err(dev, "TPM self test failed\n");
		rc = -ENODEV;
		goto out_err;
	}

	/* INTERRUPT Setup */
	init_waitqueue_head(&chip->vendor.read_queue);
	init_waitqueue_head(&chip->vendor.int_queue);
@@ -722,7 +728,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
	list_add(&chip->vendor.list, &tis_chips);
	spin_unlock(&tis_lock);

	tpm_continue_selftest(chip);

	return 0;
out_err:
@@ -790,7 +795,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev)

	ret = tpm_pm_resume(&dev->dev);
	if (!ret)
		tpm_continue_selftest(chip);
		tpm_do_selftest(chip);

	return ret;
}