Module Name: src
Committed By: maxv
Date: Wed Oct 9 07:30:58 UTC 2019
Modified Files:
src/sys/dev/acpi: tpm_acpi.c
src/sys/dev/ic: tpm.c tpmreg.h tpmvar.h
src/sys/dev/isa: tpm_isa.c
Log Message:
Add suspend support for TPM 2.0 chips. Check the TPM response also for 1.2
chips. Unfortunately I cannot really test this change since ACPI suspend
does not work on any of my laptops.
To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 src/sys/dev/acpi/tpm_acpi.c
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/ic/tpm.c
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/ic/tpmreg.h src/sys/dev/ic/tpmvar.h
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/isa/tpm_isa.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/acpi/tpm_acpi.c
diff -u src/sys/dev/acpi/tpm_acpi.c:1.9 src/sys/dev/acpi/tpm_acpi.c:1.10
--- src/sys/dev/acpi/tpm_acpi.c:1.9 Tue Oct 8 18:43:02 2019
+++ src/sys/dev/acpi/tpm_acpi.c Wed Oct 9 07:30:58 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: tpm_acpi.c,v 1.9 2019/10/08 18:43:02 maxv Exp $ */
+/* $NetBSD: tpm_acpi.c,v 1.10 2019/10/09 07:30:58 maxv Exp $ */
/*
* Copyright (c) 2012, 2019 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.9 2019/10/08 18:43:02 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.10 2019/10/09 07:30:58 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -148,6 +148,8 @@ tpm_acpi_attach(device_t parent, device_
goto out1;
}
+ if (!pmf_device_register(self, tpm_suspend, tpm_resume))
+ aprint_error_dev(self, "couldn't establish power handler\n");
acpi_resource_cleanup(&res);
return;
Index: src/sys/dev/ic/tpm.c
diff -u src/sys/dev/ic/tpm.c:1.14 src/sys/dev/ic/tpm.c:1.15
--- src/sys/dev/ic/tpm.c:1.14 Tue Oct 8 18:43:02 2019
+++ src/sys/dev/ic/tpm.c Wed Oct 9 07:30:58 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: tpm.c,v 1.14 2019/10/08 18:43:02 maxv Exp $ */
+/* $NetBSD: tpm.c,v 1.15 2019/10/09 07:30:58 maxv Exp $ */
/*
* Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -48,7 +48,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.14 2019/10/08 18:43:02 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.15 2019/10/09 07:30:58 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -65,8 +65,9 @@ __KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.14
#include "ioconf.h"
+CTASSERT(sizeof(struct tpm_header) == 10);
+
#define TPM_BUFSIZ 1024
-#define TPM_HDRSIZE 10
#define TPM_PARAM_SIZE 0x0001 /* that's a flag */
@@ -163,31 +164,69 @@ tpm_status(struct tpm_softc *sc)
/* -------------------------------------------------------------------------- */
-/*
- * Save TPM state on suspend. On resume we don't do anything, since the BIOS
- * is supposed to restore the previously saved state.
- */
+static bool
+tpm12_suspend(struct tpm_softc *sc)
+{
+ static const uint8_t command[10] = {
+ 0x00, 0xC1, /* TPM_TAG_RQU_COMMAND */
+ 0x00, 0x00, 0x00, 10, /* Length in bytes */
+ 0x00, 0x00, 0x00, 0x98 /* TPM_ORD_SaveState */
+ };
+ struct tpm_header response;
-bool
-tpm12_suspend(device_t dev, const pmf_qual_t *qual)
+ if ((*sc->sc_write)(sc, &command, sizeof(command)) != 0)
+ return false;
+ if ((*sc->sc_read)(sc, &response, sizeof(response), NULL, 0) != 0)
+ return false;
+ if (TPM_BE32(response.code) != 0)
+ return false;
+
+ return true;
+}
+
+static bool
+tpm20_suspend(struct tpm_softc *sc)
{
- struct tpm_softc *sc = device_private(dev);
- static const uint8_t command[] = {
- 0, 0xC1, /* TPM_TAG_RQU_COMMAND */
- 0, 0, 0, 10, /* Length in bytes */
- 0, 0, 0, 0x98 /* TPM_ORD_SaveState */
+ static const uint8_t command[12] = {
+ 0x80, 0x01, /* TPM_ST_NO_SESSIONS */
+ 0x00, 0x00, 0x00, 12, /* Length in bytes */
+ 0x00, 0x00, 0x01, 0x45, /* TPM_CC_Shutdown */
+ 0x00, 0x01 /* TPM_SU_STATE */
};
- uint8_t scratch[sizeof(command)];
+ struct tpm_header response;
- (*sc->sc_write)(sc, &command, sizeof(command));
- (*sc->sc_read)(sc, &scratch, sizeof(scratch), NULL, 0);
+ if ((*sc->sc_write)(sc, &command, sizeof(command)) != 0)
+ return false;
+ if ((*sc->sc_read)(sc, &response, sizeof(response), NULL, 0) != 0)
+ return false;
+ if (TPM_BE32(response.code) != 0)
+ return false;
return true;
}
bool
-tpm12_resume(device_t dev, const pmf_qual_t *qual)
+tpm_suspend(device_t dev, const pmf_qual_t *qual)
{
+ struct tpm_softc *sc = device_private(dev);
+
+ switch (sc->sc_ver) {
+ case TPM_1_2:
+ return tpm12_suspend(sc);
+ case TPM_2_0:
+ return tpm20_suspend(sc);
+ default:
+ panic("%s: impossible", __func__);
+ }
+}
+
+bool
+tpm_resume(device_t dev, const pmf_qual_t *qual)
+{
+ /*
+ * Don't do anything, the BIOS is supposed to restore the previously
+ * saved state.
+ */
return true;
}
@@ -508,6 +547,7 @@ static int
tpmread(dev_t dev, struct uio *uio, int flags)
{
struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
+ struct tpm_header hdr;
uint8_t buf[TPM_BUFSIZ];
size_t cnt, len, n;
int rv;
@@ -519,11 +559,11 @@ tpmread(dev_t dev, struct uio *uio, int
goto out;
/* Get the header. */
- if ((rv = (*sc->sc_read)(sc, buf, TPM_HDRSIZE, &cnt, 0))) {
+ if ((rv = (*sc->sc_read)(sc, &hdr, sizeof(hdr), &cnt, 0))) {
(*sc->sc_end)(sc, UIO_READ, rv);
goto out;
}
- len = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8) | buf[5];
+ len = TPM_BE32(hdr.length);
if (len > uio->uio_resid || len < cnt) {
rv = EIO;
(*sc->sc_end)(sc, UIO_READ, rv);
@@ -531,7 +571,7 @@ tpmread(dev_t dev, struct uio *uio, int
}
/* Copy out the header. */
- if ((rv = uiomove(buf, cnt, uio))) {
+ if ((rv = uiomove(&hdr, cnt, uio))) {
(*sc->sc_end)(sc, UIO_READ, rv);
goto out;
}
Index: src/sys/dev/ic/tpmreg.h
diff -u src/sys/dev/ic/tpmreg.h:1.5 src/sys/dev/ic/tpmreg.h:1.6
--- src/sys/dev/ic/tpmreg.h:1.5 Tue Oct 8 18:43:02 2019
+++ src/sys/dev/ic/tpmreg.h Wed Oct 9 07:30:58 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: tpmreg.h,v 1.5 2019/10/08 18:43:02 maxv Exp $ */
+/* $NetBSD: tpmreg.h,v 1.6 2019/10/09 07:30:58 maxv Exp $ */
/*
* Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -29,6 +29,22 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+#define TPM_BE16(a) bswap16(a)
+#define TPM_BE32(a) bswap32(a)
+#else
+#define TPM_BE16(a) (a)
+#define TPM_BE32(a) (a)
+#endif
+
+struct tpm_header {
+ uint16_t tag;
+ uint32_t length;
+ uint32_t code;
+} __packed;
+
+/* -------------------------------------------------------------------------- */
+
/*
* TPM Interface Specification 1.2 (TIS12).
*/
Index: src/sys/dev/ic/tpmvar.h
diff -u src/sys/dev/ic/tpmvar.h:1.5 src/sys/dev/ic/tpmvar.h:1.6
--- src/sys/dev/ic/tpmvar.h:1.5 Tue Oct 8 18:43:02 2019
+++ src/sys/dev/ic/tpmvar.h Wed Oct 9 07:30:58 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: tpmvar.h,v 1.5 2019/10/08 18:43:02 maxv Exp $ */
+/* $NetBSD: tpmvar.h,v 1.6 2019/10/09 07:30:58 maxv Exp $ */
/*
* Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -69,8 +69,8 @@ struct tpm_softc {
uint32_t sc_caps;
};
-bool tpm12_suspend(device_t, const pmf_qual_t *);
-bool tpm12_resume(device_t, const pmf_qual_t *);
+bool tpm_suspend(device_t, const pmf_qual_t *);
+bool tpm_resume(device_t, const pmf_qual_t *);
int tpm_tis12_probe(bus_space_tag_t, bus_space_handle_t);
int tpm_tis12_init(struct tpm_softc *);
Index: src/sys/dev/isa/tpm_isa.c
diff -u src/sys/dev/isa/tpm_isa.c:1.5 src/sys/dev/isa/tpm_isa.c:1.6
--- src/sys/dev/isa/tpm_isa.c:1.5 Tue Oct 8 18:43:03 2019
+++ src/sys/dev/isa/tpm_isa.c Wed Oct 9 07:30:58 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: tpm_isa.c,v 1.5 2019/10/08 18:43:03 maxv Exp $ */
+/* $NetBSD: tpm_isa.c,v 1.6 2019/10/09 07:30:58 maxv Exp $ */
/*
* Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -48,7 +48,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.5 2019/10/08 18:43:03 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.6 2019/10/09 07:30:58 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -133,6 +133,6 @@ tpm_isa_attach(device_t parent, device_t
return;
}
- if (!pmf_device_register(sc->sc_dev, tpm12_suspend, tpm12_resume))
- aprint_error_dev(sc->sc_dev, "couldn't establish power handler\n");
+ if (!pmf_device_register(self, tpm_suspend, tpm_resume))
+ aprint_error_dev(self, "couldn't establish power handler\n");
}