From nobody Fri Sep 18 00:07:40 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hmCcX6Jjgz6sHTH for ; Fri, 18 Sep 2026 00:07:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hmCcX5qbRz4Z2N for ; Fri, 18 Sep 2026 00:07:40 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789690060; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Lfq5BOpeyF6HVSvJGPQiTB7kQ6o58wF2FmEpMMYbNEA=; b=P0g+hM7VAmfMWWc0/sCztV0O08YUESR1rEqzmknyrNoI2iszOd6Td+87CZ8t+y9srjaIGI roVz/9fF86KeJATFLGwBsiSUUQ6QfbYLXy5gFY9LH7WWiDTM/ZvlI3w4hTGNv/6F+Mt+u5 a3FqxeLlLvsv33uG8mKOx8m1DoDPbf9yFDvfqgqhz1M4tw2nsUIdaw+OF8ttGXmI6fgsgh 3dozJ3NTzg2AK/JOZ3Kk7zbUjoglN/769w2F6GQAVXWZdg90cfyLHuiIAg5ZETjgidecMK q4kow1LKPVTTeNDfWtoen0uU6Hx4CSRtDoVWAH8MAxomf/hnVLPRXiErIzb91Q== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1789690060; b=mjhkvZBEd9qu0oPjXnKIGh2kAEStukVVSwrQmy0dtTIzd5o0T2oaCfnnoKVtGC4E4K61pf b24VofofkDpQ8xQvEZRw2gP8dSazufh9ddRrbsSaYYjwttJkoqCzL/oH3Y/ERqai9B+W9R DWJ/SOdlwDAlHnE3CUWi8TjZWfUFnRmfK7sBEt6pjV+Zo43HzRKQiAD8iuEWY0FP3Wm+/i aXKyQxdtY9XDkeDcypd6ukFICwzhhYn3uPT6bsNPRlWvoSR2hu2ooq7WGIb1qQcZ5qO8/t jLab1FAAd853YR8b2ZO8aKcAn3NmZxtVLR6/oWVKesdXUcteb6jp2ggjd0GlcQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789690060; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Lfq5BOpeyF6HVSvJGPQiTB7kQ6o58wF2FmEpMMYbNEA=; b=RXIfNO7td2tRIS6hMODjMFoYO1lAMbjicwP4BuCvHhk4IEtWp8JwY6q9qt1fZYCm0/mCxJ DLdq9Rmn6+mM75Jcz0/uu8ET/YIvD2+F4EBKxInr9aO9nT/3H8xjYzgf0X/NDSCaV0NmbG wGxNdkpeP7k0fVYjLJsiiY4/h8uFGYii5LrML9jez34KIh8gBR2j1scVmeu1xmPTSnnjNZ ZiP/w/UYWdLTNNaFZi+SKeAdk8GJ4MkeN3wW2nA5RvfVMq3xr41hl+EA1GL9XR/bFbKgnY 5quB/r+l2TEDguwZEzqTEdJKLCyMkCuGFz1nHCFaun8+aegEFxXuexYy+fQA6w== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hmCcX4Zplzw6Z for ; Fri, 18 Sep 2026 00:07:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 31682 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 18 Sep 2026 00:07:40 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kevin Bowling Subject: git: 63c33b5f1192 - stable/15 - tpm: Correct the TPM 1.2 suspend transaction List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kbowling X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: 63c33b5f1192e2869e33d139ac3d583ec4f966cf Auto-Submitted: auto-generated Date: Fri, 18 Sep 2026 00:07:40 +0000 Message-Id: <6aac80cc.31682.56e7912e@gitrepo.freebsd.org> The branch stable/15 has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=63c33b5f1192e2869e33d139ac3d583ec4f966cf commit 63c33b5f1192e2869e33d139ac3d583ec4f966cf Author: Kevin Bowling AuthorDate: 2026-08-26 10:32:34 +0000 Commit: Kevin Bowling CommitDate: 2026-09-18 00:07:28 +0000 tpm: Correct the TPM 1.2 suspend transaction The legacy driver wrote TPM_ORD_SaveState directly to the command FIFO, but used ordinal 156 instead of the TPM 1.2 ordinal 152 and never completed the transaction through the transport start and end methods. On a TIS device this omitted TPM_STS_GO, and the response read used the header length as flags instead of requesting the complete parameter size. The legacy Atmel reader would also dereference the null byte-count pointer. Send the header-only command through the normal transport lifecycle, validate the response header and TPM result, and retry TPM_WARN_RETRY for a bounded five seconds. Fail suspend rather than enter S3 after an unsuccessful state save. This follows the TPM 1.2 SaveState command definition and the bounded retry policy used by other TPM 1.2 implementations. The stock driver failed to resume a ThinkPad T440p with its STMicro TPM 1.2 Security Chip enabled; disabling the chip made S3 reliable. With this change and the following TIS resume restoration, the enabled TPM completed two consecutive S3 cycles. PCR 0 was readable with the same value before and after each cycle, and no TPM errors were logged. PR: 291067 Reviewed by: kevans Sponsored by: BBOX.io Differential Revision: https://reviews.freebsd.org/D59192 (cherry picked from commit c0356f4cd02255419a4d4309f393998185c8de2d) --- sys/dev/tpm/tpm.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 13 deletions(-) diff --git a/sys/dev/tpm/tpm.c b/sys/dev/tpm/tpm.c index da2541907952..855dad8eee85 100644 --- a/sys/dev/tpm/tpm.c +++ b/sys/dev/tpm/tpm.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -46,6 +47,14 @@ #define TPM_PARAM_SIZE 0x0001 +#define TPM_TAG_RQU_COMMAND 0x00c1 +#define TPM_TAG_RSP_COMMAND 0x00c4 +#define TPM_ORD_SAVESTATE 0x00000098 +#define TPM_WARN_RETRY 0x00000800 + +#define TPM_SAVESTATE_RETRIES 50 +#define TPM_SAVESTATE_RETRY_MS 100 + #define IRQUNK -1 #define TPM_ACCESS 0x0000 /* access register */ @@ -185,6 +194,8 @@ int tpm_legacy_read(struct tpm_softc *, void *, int, size_t *, int); int tpm_legacy_write(struct tpm_softc *, void *, int); int tpm_legacy_end(struct tpm_softc *, int, int); +static int tpm_transmit_header(struct tpm_softc *, uint32_t, uint32_t *); + /* * FreeBSD specific code for probing and attaching TPM to device tree. @@ -492,29 +503,85 @@ tpm_tmotohz(int tmo) return tvtohz(&tv); } +/* + * Transmit a command with no parameters and consume its header-only reply. + */ +static int +tpm_transmit_header(struct tpm_softc *sc, uint32_t ordinal, uint32_t *tpm_rc) +{ + uint8_t buf[TPM_HDRSIZE]; + size_t count; + int end_error, error; + + be16enc(buf, TPM_TAG_RQU_COMMAND); + be32enc(buf + 2, sizeof(buf)); + be32enc(buf + 6, ordinal); + + error = sc->sc_start(sc, UIO_WRITE); + if (error != 0) + return (error); + error = sc->sc_write(sc, buf, sizeof(buf)); + end_error = sc->sc_end(sc, UIO_WRITE, error); + if (error == 0) + error = end_error; + if (error != 0) + return (error); + + error = sc->sc_start(sc, UIO_READ); + if (error != 0) + return (error); + count = 0; + error = sc->sc_read(sc, buf, sizeof(buf), &count, TPM_PARAM_SIZE); + end_error = sc->sc_end(sc, UIO_READ, error); + if (error == 0) + error = end_error; + if (error != 0) + return (error); + + if (count != sizeof(buf) || be16dec(buf) != TPM_TAG_RSP_COMMAND || + be32dec(buf + 2) != sizeof(buf)) + return (EPROTO); + *tpm_rc = be32dec(buf + 6); + return (0); +} + /* Save TPM state on suspend. */ int tpm_suspend(device_t dev) { - struct tpm_softc *sc = device_get_softc(dev); - int why = 1; - u_int8_t command[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 10, /* Length in bytes */ - 0, 0, 0, 156 /* TPM_ORD_SaveStates */ - }; + struct tpm_softc *sc; + uint32_t tpm_rc; + int error, tries; /* - * Power down: We have to issue the SaveStates command. + * A TPM may report RETRY for several seconds when firmware issued + * SaveState before the driver loaded. Any subsequent command can + * invalidate that saved state, so retry SaveState before entering S3. */ - sc->sc_write(sc, &command, sizeof(command)); - sc->sc_read(sc, &command, sizeof(command), NULL, TPM_HDRSIZE); + sc = device_get_softc(dev); + for (tries = 0; tries < TPM_SAVESTATE_RETRIES; tries++) { + error = tpm_transmit_header(sc, TPM_ORD_SAVESTATE, &tpm_rc); + if (error != 0 || tpm_rc != TPM_WARN_RETRY) + break; + pause("tpmsave", MAX(hz * TPM_SAVESTATE_RETRY_MS / 1000, 1)); + } + if (error != 0) { + device_printf(dev, "failed to save state: %d\n", error); + return (error); + } + if (tpm_rc != 0) { + device_printf(dev, "SaveState failed: TPM error 0x%x\n", + tpm_rc); + return (EIO); + } + if (tries != 0) + device_printf(dev, "SaveState required %d retries\n", tries); #ifdef TPM_DEBUG - printf("tpm_suspend: power down: %d -> %d\n", sc->sc_suspend, why); + device_printf(dev, "suspend: %d -> 1\n", sc->sc_suspend); #endif - sc->sc_suspend = why; + sc->sc_suspend = 1; - return 0; + return (0); } /*