tpm: crb: check the error bit only after taking locality

tpmcrb_transmit() read CRB_CTRL_STS before requesting locality 0.
An AMD Pluton fTPM (like FrameWork Desktop) using the plain CRB start method
reads the control area as all-ones until locality is assigned, so bit 0 looks
like a stuck tpmSts and every command failed with EIO.

With RANDOM_ENABLE_TPM the harvester retries every 10 seconds, so this printed
"Device has Error bit set" forever.

Reviewed by:	kbowling
Approved by:	kbowling
MFC after:	2 weeks
Sponsored by:	Netflix
Differential Revision:	https://reviews.freebsd.org/D59661
This commit is contained in:
Olivier Cochard committed 2026-09-14 16:25:47 +02:00
1 parent eaeb5f29bc
commit 7c375af72e
1 file changed
+13 -5
+13 -5
View File
@@ -514,17 +514,25 @@ tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t length)
return (E2BIG);
}
if (TPM_READ_4(dev, TPM_CRB_CTRL_STS) & TPM_CRB_CTRL_STS_ERR_BIT) {
device_printf(dev,
"Device has Error bit set\n");
return (EIO);
}
if (!tpmcrb_request_locality(sc, 0)) {
device_printf(dev,
"Failed to obtain locality\n");
return (EIO);
}
locality = true;
/*
* Only check for the error once we own the locality: some
* implementations do not return meaningful values in the control area
* before then. An AMD Pluton fTPM using the plain CRB start method
* reads all-ones, which looks like a permanently stuck tpmSts.
*/
if (TPM_READ_4(dev, TPM_CRB_CTRL_STS) & TPM_CRB_CTRL_STS_ERR_BIT) {
device_printf(dev,
"Device has Error bit set\n");
error = EIO;
goto out;
}
/* Clear cancellation bit */
TPM_WRITE_4(dev, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CLEAR);