[SeaBIOS] [PATCH 4/4] WIP: add TPM CRB device support

2017-10-06 Thread marcandre . lureau
From: Marc-André Lureau 

The CRB device was introduced with TPM 2.0 to be physical-bus agnostic
and defined in TCG PC Client Platform TPM Profile (PTP) Specification
Family “2.0” Level 00 Revision 01.03 v22

It seems to be required with Windows 10. It is also a simpler device
than FIFO/TIS.

This WIP patch doesn't support locality other than 0. The BIOS doesn't
seem to require other localities, so that code seems a bit pointless.

In theory, the cmd/resp buffers could be located above 4G, but I
don't know how seabios could reach it in 32bit mode (my qemu WIP
allocates next to 0xfed4).

Signed-off-by: Marc-André Lureau 
---
 src/hw/tpm_drivers.c | 198 ++-
 src/hw/tpm_drivers.h |  26 +++
 2 files changed, 223 insertions(+), 1 deletion(-)

diff --git a/src/hw/tpm_drivers.c b/src/hw/tpm_drivers.c
index 5cee9d8..3b8f6e1 100644
--- a/src/hw/tpm_drivers.c
+++ b/src/hw/tpm_drivers.c
@@ -36,7 +36,8 @@ struct tpm_driver {
 extern struct tpm_driver tpm_drivers[];
 
 #define TIS_DRIVER_IDX   0
-#define TPM_NUM_DRIVERS  1
+#define CRB_DRIVER_IDX   1
+#define TPM_NUM_DRIVERS  2
 
 #define TPM_INVALID_DRIVER   0xf
 
@@ -57,6 +58,11 @@ static const u32 tpm_default_durations[3] = {
 static u32 tpm_default_dur[3];
 static u32 tpm_default_to[4];
 
+static u32 crb_cmd_size;
+static void *crb_cmd;
+static u32 crb_resp_size;
+static void *crb_resp;
+
 /* if device is not there, return '0', '1' otherwise */
 static u32 tis_probe(void)
 {
@@ -338,6 +344,181 @@ static u32 tis_waitrespready(enum tpmDurationType to_t)
 return rc;
 }
 
+/* if device is not there, return '0', '1' otherwise */
+static u32 crb_probe(void)
+{
+if (!CONFIG_TCGBIOS)
+return 0;
+
+u32 ifaceid = readl(CRB_REG(0, CRB_REG_INTF_ID));
+
+if ((ifaceid & 0xf) != 0xf) {
+if ((ifaceid & 0xf) == 1) {
+/* CRB is active */
+return 1;
+}
+if ((ifaceid & (1 << 14)) == 0) {
+/* CRB cannot be selected */
+return 0;
+}
+/* write of 1 to bits 17-18 selects CRB */
+writel(CRB_REG(0, CRB_REG_INTF_ID), (1 << 17));
+/* lock it */
+writel(CRB_REG(0, CRB_REG_INTF_ID), (1 << 19));
+}
+
+/* no support for 64 bit addressing yet */
+if (readl(CRB_REG(0, CRB_REG_CTRL_CMD_HADDR)))
+return 1;
+
+u64 addr = readq(CRB_REG(0, CRB_REG_CTRL_RSP_ADDR));
+if (addr > __UINT32_MAX__)
+return 1;
+
+return 0;
+}
+
+static TPMVersion crb_get_tpm_version(void)
+{
+/* CRB is supposed to be TPM 2.0 only */
+return TPM_VERSION_2;
+}
+
+static u32 crb_init(void)
+{
+if (!CONFIG_TCGBIOS)
+return 1;
+
+crb_cmd = (void*)readl(CRB_REG(0, CRB_REG_CTRL_CMD_LADDR));
+crb_cmd_size = readl(CRB_REG(0, CRB_REG_CTRL_CMD_SIZE));
+crb_resp = (void*)readl(CRB_REG(0, CRB_REG_CTRL_RSP_ADDR));
+crb_resp_size = readl(CRB_REG(0, CRB_REG_CTRL_RSP_SIZE));
+
+init_timeout(CRB_DRIVER_IDX);
+
+return 0;
+}
+
+static u32 crb_wait_reg(u8 locty, u8 reg, u32 time, u8 mask, u8 expect)
+{
+if (!CONFIG_TCGBIOS)
+return 0;
+
+u32 rc = 1;
+u32 end = timer_calc_usec(time);
+
+for (;;) {
+u8 sts = readl(CRB_REG(locty, reg));
+if ((sts & mask) == expect) {
+rc = 0;
+break;
+}
+if (timer_check(end)) {
+warn_timeout();
+break;
+}
+yield();
+}
+return rc;
+}
+
+static u32 crb_activate(u8 locty)
+{
+if (!CONFIG_TCGBIOS)
+return 0;
+
+/* TODO activate locty */
+
+return 0;
+}
+
+static u32 crb_find_active_locality(void)
+{
+if (!CONFIG_TCGBIOS)
+return 0;
+
+/* TODO return current locty */
+
+return 0;
+}
+
+#define CRB_CTRL_REQ_CMD_READY 0b1
+#define CRB_START_INVOKE 0b1
+#define CRB_CTRL_STS_ERROR 0b1
+
+static u32 crb_ready(void)
+{
+if (!CONFIG_TCGBIOS)
+return 0;
+
+u32 rc = 0;
+u8 locty = crb_find_active_locality();
+u32 timeout_c = tpm_drivers[CRB_DRIVER_IDX].timeouts[TIS_TIMEOUT_TYPE_C];
+
+writel(CRB_REG(locty, CRB_REG_CTRL_REQ), CRB_CTRL_REQ_CMD_READY);
+rc = crb_wait_reg(locty, CRB_REG_CTRL_REQ, timeout_c,
+  CRB_CTRL_REQ_CMD_READY, 0);
+
+return rc;
+}
+
+static u32 crb_senddata(const u8 *const data, u32 len)
+{
+if (!CONFIG_TCGBIOS)
+return 0;
+
+if (len > crb_cmd_size)
+return 1;
+
+u8 locty = tis_find_active_locality();
+memcpy(crb_cmd, data, len);
+writel(CRB_REG(locty, CRB_REG_CTRL_START), CRB_START_INVOKE);
+
+return 0;
+}
+
+static u32 crb_readresp(u8 *buffer, u32 *len)
+{
+if (!CONFIG_TCGBIOS)
+return 0;
+
+u8 locty = tis_find_active_locality();
+if (readl(CRB_REG(locty, CRB_REG_CTRL_STS)) & CRB_CTRL_STS_ERROR)
+return 1;
+
+if (*len < 6)
+return 1;
+
+memcpy(buffer, crb_resp, 

[SeaBIOS] [PATCH 0/4] RFC: add CRB TPM device

2017-10-06 Thread marcandre . lureau
From: Marc-André Lureau 

Hi,

The following series implements a limited TPM CRB driver. The TIS
device with a TPM 2.0 seems to be ignored by Windows 10, so I
implemented a simple CRB device that I will send shortly on the
qemu-devel. With the CRB device, Windows 10 correctly recognized and
exchange with a TPM 2.0.

As long as the device isn't in qemu, I suppose this series should
remain RFC.

Feedback welcome!

Marc-André Lureau (4):
  x86: add readq()
  tpm: generalize init_timeout()
  tpm: use get_tpm_version() callback
  WIP: add TPM CRB device support

 src/hw/tpm_drivers.c | 226 ---
 src/hw/tpm_drivers.h |  26 ++
 src/x86.h|   5 ++
 3 files changed, 245 insertions(+), 12 deletions(-)

-- 
2.14.1.146.gd35faa819


___
SeaBIOS mailing list
SeaBIOS@seabios.org
https://mail.coreboot.org/mailman/listinfo/seabios

[SeaBIOS] [PATCH 1/4] x86: add readq()

2017-10-06 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
---
 src/x86.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/src/x86.h b/src/x86.h
index 4aea65c..c7bb60d 100644
--- a/src/x86.h
+++ b/src/x86.h
@@ -211,6 +211,11 @@ static inline void writeb(void *addr, u8 val) {
 barrier();
 *(volatile u8 *)addr = val;
 }
+static inline u64 readq(const void *addr) {
+u64 val = *(volatile const u64 *)addr;
+barrier();
+return val;
+}
 static inline u32 readl(const void *addr) {
 u32 val = *(volatile const u32 *)addr;
 barrier();
-- 
2.14.1.146.gd35faa819


___
SeaBIOS mailing list
SeaBIOS@seabios.org
https://mail.coreboot.org/mailman/listinfo/seabios

[SeaBIOS] [PATCH 3/4] tpm: use get_tpm_version() callback

2017-10-06 Thread marcandre . lureau
From: Marc-André Lureau 

As originally intended, I guess.

Signed-off-by: Marc-André Lureau 
---
 src/hw/tpm_drivers.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/hw/tpm_drivers.c b/src/hw/tpm_drivers.c
index 0daaef2..5cee9d8 100644
--- a/src/hw/tpm_drivers.c
+++ b/src/hw/tpm_drivers.c
@@ -346,6 +346,7 @@ struct tpm_driver tpm_drivers[TPM_NUM_DRIVERS] = {
 .durations = NULL,
 .set_timeouts  = set_timeouts,
 .probe = tis_probe,
+.get_tpm_version = tis_get_tpm_version,
 .init  = tis_init,
 .activate  = tis_activate,
 .ready = tis_ready,
@@ -367,7 +368,7 @@ tpmhw_probe(void)
 if (td->probe() != 0) {
 td->init();
 TPMHW_driver_to_use = i;
-return tis_get_tpm_version();
+return td->get_tpm_version();
 }
 }
 return TPM_VERSION_NONE;
-- 
2.14.1.146.gd35faa819


___
SeaBIOS mailing list
SeaBIOS@seabios.org
https://mail.coreboot.org/mailman/listinfo/seabios

[SeaBIOS] [PATCH 2/4] tpm: generalize init_timeout()

2017-10-06 Thread marcandre . lureau
From: Marc-André Lureau 

It seems both TIS & CRB devices share the same timeout. Make
initialization function generic for now.

Signed-off-by: Marc-André Lureau 
---
 src/hw/tpm_drivers.c | 25 +++--
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/src/hw/tpm_drivers.c b/src/hw/tpm_drivers.c
index a137e62..0daaef2 100644
--- a/src/hw/tpm_drivers.c
+++ b/src/hw/tpm_drivers.c
@@ -102,26 +102,31 @@ static TPMVersion tis_get_tpm_version(void)
 return TPM_VERSION_1_2;
 }
 
-static u32 tis_init(void)
+static void init_timeout(int driver)
 {
-if (!CONFIG_TCGBIOS)
-return 1;
-
-writeb(TIS_REG(0, TIS_REG_INT_ENABLE), 0);
-
-if (tpm_drivers[TIS_DRIVER_IDX].durations == NULL) {
+if (tpm_drivers[driver].durations == NULL) {
 u32 *durations = tpm_default_dur;
 memcpy(durations, tpm_default_durations,
sizeof(tpm_default_durations));
-tpm_drivers[TIS_DRIVER_IDX].durations = durations;
+tpm_drivers[driver].durations = durations;
 }
 
-if (tpm_drivers[TIS_DRIVER_IDX].timeouts == NULL) {
+if (tpm_drivers[driver].timeouts == NULL) {
 u32 *timeouts = tpm_default_to;
 memcpy(timeouts, tis_default_timeouts,
sizeof(tis_default_timeouts));
-tpm_drivers[TIS_DRIVER_IDX].timeouts = timeouts;
+tpm_drivers[driver].timeouts = timeouts;
 }
+}
+
+static u32 tis_init(void)
+{
+if (!CONFIG_TCGBIOS)
+return 1;
+
+writeb(TIS_REG(0, TIS_REG_INT_ENABLE), 0);
+
+init_timeout(TIS_DRIVER_IDX);
 
 return 1;
 }
-- 
2.14.1.146.gd35faa819


___
SeaBIOS mailing list
SeaBIOS@seabios.org
https://mail.coreboot.org/mailman/listinfo/seabios