Commit c82a330c authored by Tomas Winkler's avatar Tomas Winkler Committed by Jarkko Sakkinen

tpm: factor out tpm 1.x pm suspend flow into tpm1-cmd.c

Factor out TPM 1.x suspend flow from tpm-interface.c into a new function
tpm1_pm_suspend() in tpm1-cmd.c
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Reviewed-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
parent d4a31756
...@@ -585,15 +585,6 @@ int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen) ...@@ -585,15 +585,6 @@ int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)
} }
EXPORT_SYMBOL_GPL(tpm_send); EXPORT_SYMBOL_GPL(tpm_send);
#define TPM_ORD_SAVESTATE 152
#define SAVESTATE_RESULT_SIZE 10
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)
};
/* /*
* We are about to suspend. Save the TPM state * We are about to suspend. Save the TPM state
* so that it can be restored. * so that it can be restored.
...@@ -601,54 +592,18 @@ static const struct tpm_input_header savestate_header = { ...@@ -601,54 +592,18 @@ static const struct tpm_input_header savestate_header = {
int tpm_pm_suspend(struct device *dev) int tpm_pm_suspend(struct device *dev)
{ {
struct tpm_chip *chip = dev_get_drvdata(dev); struct tpm_chip *chip = dev_get_drvdata(dev);
struct tpm_cmd_t cmd; int rc = 0;
int rc, try;
u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
if (chip == NULL) if (!chip)
return -ENODEV; return -ENODEV;
if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED) if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
return 0; return 0;
if (chip->flags & TPM_CHIP_FLAG_TPM2) { if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_shutdown(chip, TPM2_SU_STATE); tpm2_shutdown(chip, TPM2_SU_STATE);
return 0; else
} rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
/* 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);
return rc; return rc;
} }
......
...@@ -542,6 +542,8 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, ...@@ -542,6 +542,8 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
const char *desc); const char *desc);
int tpm_startup(struct tpm_chip *chip); int tpm_startup(struct tpm_chip *chip);
int tpm_get_timeouts(struct tpm_chip *); int tpm_get_timeouts(struct tpm_chip *);
int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr);
int tpm1_auto_startup(struct tpm_chip *chip); int tpm1_auto_startup(struct tpm_chip *chip);
int tpm1_do_selftest(struct tpm_chip *chip); int tpm1_do_selftest(struct tpm_chip *chip);
int tpm1_get_timeouts(struct tpm_chip *chip); int tpm1_get_timeouts(struct tpm_chip *chip);
......
...@@ -666,3 +666,64 @@ int tpm1_auto_startup(struct tpm_chip *chip) ...@@ -666,3 +666,64 @@ int tpm1_auto_startup(struct tpm_chip *chip)
rc = -ENODEV; rc = -ENODEV;
return rc; return rc;
} }
#define TPM_ORD_SAVESTATE 152
#define SAVESTATE_RESULT_SIZE 10
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)
};
/**
* tpm1_pm_suspend() - pm suspend handler
* @chip: TPM chip to use.
* @tpm_suspend_pcr: flush pcr for buggy TPM chips.
*
* The functions saves the TPM state to be restored on resume.
*
* Return:
* * 0 on success,
* * < 0 on error.
*/
int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr)
{
u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
struct tpm_cmd_t cmd;
int rc, try;
/* 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);
return rc;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment