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

Commit cae8b441 authored by Jason Gunthorpe's avatar Jason Gunthorpe Committed by Jarkko Sakkinen
Browse files

tpm: Factor out common startup code



The TCG standard startup sequence (get timeouts, tpm startup, etc) for
TPM and TPM2 chips is being open coded in many drivers, move it into
the core code.

tpm_tis and tpm_crb are used as the basis for the core code
implementation and the easy drivers are converted. In the process
several small drivers bugs relating to error handling this flow
are fixed.

For now the flag TPM_OPS_AUTO_STARTUP is optional to allow a staged
driver roll out, but ultimately all drivers should use this flow and
the flag removed. Some drivers still do not implement the startup
sequence at all and will need to be tested with it enabled.

Signed-off-by: default avatarJason Gunthorpe <jgunthorpe@obsidianresearch.com>
Tested-by: default avatarAndrew Zamansky <andrew.zamansky@nuvoton.com>
Reviewed-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
parent 2b88cd96
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -505,6 +505,7 @@ static bool st33zp24_req_canceled(struct tpm_chip *chip, u8 status)
}

static const struct tpm_class_ops st33zp24_tpm = {
	.flags = TPM_OPS_AUTO_STARTUP,
	.send = st33zp24_send,
	.recv = st33zp24_recv,
	.cancel = st33zp24_cancel,
@@ -592,9 +593,6 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
		tpm_gen_interrupt(chip);
	}

	tpm_get_timeouts(chip);
	tpm_do_selftest(chip);

	return tpm_chip_register(chip);
_tpm_clean_answer:
	dev_info(&chip->dev, "TPM initialization fail\n");
+9 −0
Original line number Diff line number Diff line
@@ -354,6 +354,15 @@ int tpm_chip_register(struct tpm_chip *chip)
{
	int rc;

	if (chip->ops->flags & TPM_OPS_AUTO_STARTUP) {
		if (chip->flags & TPM_CHIP_FLAG_TPM2)
			rc = tpm2_auto_startup(chip);
		else
			rc = tpm1_auto_startup(chip);
		if (rc)
			return rc;
	}

	rc = tpm1_chip_register(chip);
	if (rc)
		return rc;
+27 −0
Original line number Diff line number Diff line
@@ -843,6 +843,33 @@ int tpm_do_selftest(struct tpm_chip *chip)
}
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;
}

int tpm_send(u32 chip_num, void *cmd, size_t buflen)
{
	struct tpm_chip *chip;
+2 −2
Original line number Diff line number Diff line
@@ -484,6 +484,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, int len,
			 const char *desc);
extern int tpm_get_timeouts(struct tpm_chip *);
extern void tpm_gen_interrupt(struct tpm_chip *);
int tpm1_auto_startup(struct tpm_chip *chip);
extern int tpm_do_selftest(struct tpm_chip *);
extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
extern int tpm_pm_suspend(struct device *);
@@ -526,10 +527,9 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
			u32 *value, const char *desc);

extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type);
int tpm2_auto_startup(struct tpm_chip *chip);
extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32);
extern int tpm2_do_selftest(struct tpm_chip *chip);
extern int tpm2_gen_interrupt(struct tpm_chip *chip);
extern int tpm2_probe(struct tpm_chip *chip);
#endif
+42 −4
Original line number Diff line number Diff line
@@ -728,7 +728,7 @@ static const struct tpm_input_header tpm2_startup_header = {
 * returned it remarks a POSIX error code. If a positive number is returned
 * it remarks a TPM error.
 */
int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
static int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
{
	struct tpm2_cmd cmd;

@@ -738,7 +738,6 @@ int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
	return tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
				"attempting to start the TPM");
}
EXPORT_SYMBOL_GPL(tpm2_startup);

#define TPM2_SHUTDOWN_IN_SIZE \
	(sizeof(struct tpm_input_header) + \
@@ -854,7 +853,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
 * returned it remarks a POSIX error code. If a positive number is returned
 * it remarks a TPM error.
 */
int tpm2_do_selftest(struct tpm_chip *chip)
static int tpm2_do_selftest(struct tpm_chip *chip)
{
	int rc;
	unsigned int loops;
@@ -894,7 +893,6 @@ int tpm2_do_selftest(struct tpm_chip *chip)

	return rc;
}
EXPORT_SYMBOL_GPL(tpm2_do_selftest);

/**
 * tpm2_gen_interrupt() - generate an interrupt
@@ -942,3 +940,43 @@ int tpm2_probe(struct tpm_chip *chip)
	return 0;
}
EXPORT_SYMBOL_GPL(tpm2_probe);

/**
 * tpm2_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 tpm2_auto_startup(struct tpm_chip *chip)
{
	int rc;

	rc = tpm_get_timeouts(chip);
	if (rc)
		goto out;

	rc = tpm2_do_selftest(chip);
	if (rc != TPM2_RC_INITIALIZE) {
		dev_err(&chip->dev, "TPM self test failed\n");
		goto out;
	}

	if (rc == TPM2_RC_INITIALIZE) {
		rc = tpm2_startup(chip, TPM2_SU_CLEAR);
		if (rc)
			goto out;

		rc = tpm2_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;
}
Loading