[Skiboot] [PATCH 11/15] libstb/drivers: Add I2C nuvoton driver for TPM 2.0
Claudio Carvalho
cclaudio at linux.vnet.ibm.com
Thu Aug 11 15:23:53 AEST 2016
This adds a driver for the 'nuvoton,npct650' TPM 2.0. The driver was
ported and adapted from hostboot tpmdd.C.
Signed-off-by: Claudio Carvalho <cclaudio at linux.vnet.ibm.com>
---
libstb/Makefile.inc | 3 +-
libstb/drivers/Makefile.inc | 11 +
libstb/drivers/tpm_i2c_nuvoton.c | 653 +++++++++++++++++++++++++++++++++++++++
libstb/drivers/tpm_i2c_nuvoton.h | 22 ++
libstb/status_codes.h | 6 +
libstb/tpm.c | 2 +
6 files changed, 696 insertions(+), 1 deletion(-)
create mode 100644 libstb/drivers/Makefile.inc
create mode 100644 libstb/drivers/tpm_i2c_nuvoton.c
create mode 100644 libstb/drivers/tpm_i2c_nuvoton.h
diff --git a/libstb/Makefile.inc b/libstb/Makefile.inc
index 4cffd54..693e888 100644
--- a/libstb/Makefile.inc
+++ b/libstb/Makefile.inc
@@ -8,6 +8,7 @@ LIBSTB_SRCS = container.c tpm.c
LIBSTB_OBJS = $(LIBSTB_SRCS:%.c=%.o)
LIBSTB = $(LIBSTB_DIR)/built-in.o
+include $(SRC)/$(LIBSTB_DIR)/drivers/Makefile.inc
include $(SRC)/$(LIBSTB_DIR)/tss/Makefile.inc
-$(LIBSTB): $(LIBSTB_OBJS:%=$(LIBSTB_DIR)/%) $(TSS)
+$(LIBSTB): $(LIBSTB_OBJS:%=$(LIBSTB_DIR)/%) $(DRIVERS) $(TSS)
diff --git a/libstb/drivers/Makefile.inc b/libstb/drivers/Makefile.inc
new file mode 100644
index 0000000..12d8e82
--- /dev/null
+++ b/libstb/drivers/Makefile.inc
@@ -0,0 +1,11 @@
+# -*-Makefile-*-
+
+DRIVERS_DIR = libstb/drivers
+
+SUBDIRS += $(DRIVERS_DIR)
+
+DRIVERS_SRCS = tpm_i2c_nuvoton.c
+DRIVERS_OBJS = $(DRIVERS_SRCS:%.c=%.o)
+DRIVERS = $(DRIVERS_DIR)/built-in.o
+
+$(DRIVERS): $(DRIVERS_OBJS:%=$(DRIVERS_DIR)/%)
diff --git a/libstb/drivers/tpm_i2c_nuvoton.c b/libstb/drivers/tpm_i2c_nuvoton.c
new file mode 100644
index 0000000..b615347
--- /dev/null
+++ b/libstb/drivers/tpm_i2c_nuvoton.c
@@ -0,0 +1,653 @@
+/* Copyright 2013-2016 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/****************************************************************************
+ * THIS DRIVER WAS PORTED AND ADAPTED FROM:
+ * https://github.com/open-power/hostboot/blob/master-p8/src/usr/i2c/tpmdd.C
+ ****************************************************************************/
+
+#include <string.h>
+#include <timebase.h>
+#include <timer.h>
+#include <i2c.h>
+#include <skiboot.h>
+#include <opal-api.h>
+#include <device.h>
+
+#include "../status_codes.h"
+#include "../tpm.h"
+#include "tpm_i2c_nuvoton.h"
+
+//#define DBG(fmt, ...) prlog(PR_DEBUG, fmt, ##__VA_ARGS__)
+#define DBG(fmt, ...)
+
+#define DRIVER_NAME "i2c_tpm_nuvoton"
+
+/**
+ * Timings between various states or transitions within
+ * the interface protocol. See PTP spec for details.
+ */
+#define TCG_PTP_TIMEOUT_A 750
+#define TCG_PTP_TIMEOUT_B 2000
+#define TCG_PTP_TIMEOUT_C 200
+#define TCG_PTP_TIMEOUT_D 30
+
+/* I2C interface offsets */
+#define NUVOTON_TPM_STS 0x00
+#define NUVOTON_TPM_BURST_COUNT 0x01
+#define NUVOTON_TPM_DATA_FIFO_W 0x20
+#define NUVOTON_TPM_DATA_FIFO_R 0x40
+#define NUVOTON_TPM_VID_DID_RID 0x60
+
+/* Bit masks for the TPM STATUS register */
+#define TCG_PTP_STS_VALID 0x80
+#define TCG_PTP_STS_COMMAND_READY 0x40
+#define TCG_PTP_STS_GO 0x20
+#define TCG_PTP_STS_DATA_AVAIL 0x10
+#define TCG_PTP_STS_EXPECT 0x08
+#define TCG_PTP_STS_RESPONSE_RETRY 0x02
+#define TCG_PTP_STS_ERR_VAL 0x07
+
+/* from hw/p8-i2c.c */
+#define I2C_TIMEOUT_POLL_MS 4000 /* 4s/byte timeout */
+
+/* TPM Driver values */
+#define MAX_STSVALID_POLLS 5 /* Max poll of 50ms (5*10ms) */
+#define TPM_TIMEOUT_INTERVAL 10
+#define TPM_MAX_NACK_RETRIES 2
+
+static struct tpm_dev *tpm_device = NULL;
+static const char* compat = "nuvoton,npct650";
+
+static void i2c_request_complete(int rc, struct i2c_request *req)
+{
+ *(int*)req->user_data = rc;
+}
+
+/**
+ * tpm_i2c_request_send - send request to i2c bus
+ * @read_write: SMBUS_READ or SMBUS_WRITE
+ * @offset: any of the I2C interface offset defined
+ * @offset_bytes: offset size in bytes
+ * @buf: data to be read or written
+ * @buflen: buf length
+ *
+ * This interacts with skiboot i2c API to send an I2C request to the tpm
+ * device
+ *
+ * Returns: Zero on success otherwise a negative error code
+ */
+static int tpm_i2c_request_send(int read_write, uint32_t offset,
+ uint32_t offset_bytes, void* buf, size_t buflen)
+{
+ int rc, waited, retries, timeout;
+ struct i2c_request *req;
+ struct i2c_bus *bus;
+
+ bus = i2c_find_bus_by_id(tpm_device->bus_id);
+
+ if (!bus) {
+ /**
+ * @fwts-label TPMI2CInvalidBusID
+ * @fwts-advice tpm_i2c_request_send was passed an invalid bus
+ * ID. This indicates a tb_init() bug.
+ */
+ prlog(PR_ERR, "TPM: Invalid bus_id=%x\n", tpm_device->bus_id);
+ rc = STB_ARG_ERROR;
+ goto out;
+ }
+
+ req = i2c_alloc_req(bus);
+
+ if (!req) {
+ /**
+ * @fwts-label TPMI2CAllocationFailed
+ * @fwts-advice OPAL failed to allocate memory for an
+ * i2c_request. This points to an OPAL bug as OPAL run out of
+ * memory and this should never happen.
+ */
+ prlog(PR_ERR, "TPM: i2c_alloc_req failed\n");
+ rc = STB_DRIVER_ERROR;
+ goto out;
+ }
+
+ req->dev_addr = tpm_device->xscom_base;
+ req->op = read_write;
+ req->offset = offset;
+ req->offset_bytes = offset_bytes;
+ req->rw_buf = (void*) buf;
+ req->rw_len = buflen;
+ req->completion = i2c_request_complete;
+ req->user_data = &rc;
+
+ timeout = (buflen + offset_bytes + 2) * I2C_TIMEOUT_POLL_MS;
+
+ for (retries = 0; retries <= TPM_MAX_NACK_RETRIES; retries++)
+ {
+ rc = 1;
+ waited = 0;
+ i2c_queue_req(req);
+
+ do {
+ time_wait_ms(5);
+ waited += 5;
+ } while (waited < timeout && rc == 1);
+
+ if (rc == OPAL_I2C_NACK_RCVD)
+ continue;
+ else
+ /* error or success */
+ break;
+ }
+
+ DBG("%s tpm req op=%x offset=%x buf=%016llx buflen=%d delay=%d/%d,"
+ "rc=%d\n",
+ (rc) ? "!!!!" : "----", req->op, req->offset,
+ *(uint64_t*) buf, req->rw_len, waited, timeout, rc);
+
+ i2c_free_req(req);
+
+ /* error */
+ if (rc)
+ rc = STB_DRIVER_ERROR;
+
+out:
+ return rc;
+}
+
+static int tpm_status_write_byte(uint8_t byte)
+{
+ uint8_t value = byte;
+ return tpm_i2c_request_send(SMBUS_WRITE, NUVOTON_TPM_STS, 1, &value,
+ sizeof(value));
+}
+
+static int tpm_read_sts_reg_valid(uint8_t* value)
+{
+ int polls, rc;
+
+ for(polls=0; polls<=MAX_STSVALID_POLLS; polls++)
+ {
+ rc = tpm_i2c_request_send(SMBUS_READ, NUVOTON_TPM_STS, 1, value,
+ sizeof(uint8_t));
+
+ if (rc < 0)
+ return rc;
+
+ if (rc == 0 && ((*value &
+ TCG_PTP_STS_VALID) == TCG_PTP_STS_VALID))
+ return STB_SUCCESS;
+
+ // wait tpm sts reg be settled
+ time_wait_ms(5);
+ }
+
+ value = 0;
+ /**
+ * @fwts-label TPMValidBitTimeout
+ * @fwts-advice The valid bit of the tpm status register is taking
+ * longer to be settled. The wait time need to be increased or the TPM
+ * device is not functional.
+ */
+ prlog(PR_ERR, "TPM: valid bit not settled. Timeout.\n");
+
+ return STB_TPM_TIMEOUT;
+}
+
+static bool tpm_is_command_ready(int* rc)
+{
+ uint8_t value = 0;
+
+ *rc = tpm_i2c_request_send(SMBUS_READ, NUVOTON_TPM_STS, 1, &value,
+ sizeof(value));
+
+ if (*rc == 0 &&
+ ((value & TCG_PTP_STS_COMMAND_READY) == TCG_PTP_STS_COMMAND_READY)){
+ DBG("---- TPM is command ready\n");
+ return true;
+ }
+
+ return false;
+}
+
+static int tpm_poll_for_command_ready(void)
+{
+ int rc, polls, delay;
+
+ /**
+ * The first write to command ready may just abort an
+ * outstanding command, so we poll twice
+ */
+ for (polls=0; polls<2; polls++)
+ {
+ rc = tpm_status_write_byte(TCG_PTP_STS_COMMAND_READY);
+ if (rc < 0) {
+ return rc;
+ }
+
+ for (delay = 0;
+ delay < TCG_PTP_TIMEOUT_B;
+ delay += TPM_TIMEOUT_INTERVAL)
+ {
+ if (tpm_is_command_ready(&rc))
+ return rc;
+
+ time_wait_ms(TPM_TIMEOUT_INTERVAL);
+ }
+ DBG("--- Command ready polling, delay %d/%d\n",
+ delay, TCG_PTP_TIMEOUT_B);
+ }
+
+ /**
+ * @fwts-label TPMCommandReadyBitTimeout
+ * @fwts-advice The command ready bit of the tpm status register is
+ * taking longer to be settled. The wait time need to be increased or
+ * the TPM device is not functional.
+ */
+ prlog(PR_ERR, "TPM: command ready polling timeout\n");
+ return STB_TPM_TIMEOUT;
+}
+
+static bool tpm_is_expecting(int* rc)
+{
+ uint8_t value = 0;
+
+ *rc = tpm_read_sts_reg_valid(&value);
+
+ if (*rc == 0 && (( value &
+ TCG_PTP_STS_EXPECT) == TCG_PTP_STS_EXPECT))
+ return true;
+
+ return false;
+}
+
+static bool tpm_is_data_avail(int* rc)
+{
+ uint8_t value = 0;
+
+ *rc = tpm_read_sts_reg_valid(&value);
+
+ if (*rc == 0 && (( value &
+ TCG_PTP_STS_DATA_AVAIL) == TCG_PTP_STS_DATA_AVAIL))
+ return true;
+
+ return false;
+}
+
+static int tpm_poll_for_data_avail(void)
+{
+ int delay, rc;
+
+ /* Operation TIMEOUT_A defined by TCG spec for data available */
+ for (delay = 0;
+ delay < TCG_PTP_TIMEOUT_A;
+ delay += TPM_TIMEOUT_INTERVAL)
+ {
+ if (tpm_is_data_avail(&rc)) {
+ DBG("---- read FIFO. Data available. delay=%d/%d\n",
+ delay, TCG_PTP_TIMEOUT_A);
+ return rc;
+ }
+
+ time_wait_ms(TPM_TIMEOUT_INTERVAL);
+ }
+ /**
+ * @fwts-label TPMDataAvailBitTimeout
+ * @fwts-advice The data avail bit of the tpm status register is taking
+ * longer to be settled. The wait time need to be increased or the TPM
+ * device is not functional.
+ */
+ prlog(PR_ERR, "TPM: read FIFO. Polling timeout, delay=%d/%d\n",
+ delay, TCG_PTP_TIMEOUT_A);
+
+ return STB_TPM_TIMEOUT;
+}
+
+static int tpm_read_burst_count(uint8_t* burst_count)
+{
+ int rc = 0;
+
+ /* In i2C, burstCount is 1 byte */
+ rc = tpm_i2c_request_send(SMBUS_READ, NUVOTON_TPM_BURST_COUNT, 1,
+ burst_count, sizeof(uint8_t));
+
+ DBG("---- burst_count=%d rc=%d\n", *burst_count, rc);
+
+ if (rc < 0)
+ *burst_count = 0;
+
+ return rc;
+}
+
+static int tpm_write_fifo(uint8_t* buf, size_t buflen)
+{
+ uint8_t burst_count = 0;
+ int delay = 0;
+ int rc;
+
+ size_t curByte = 0;
+ uint8_t* bytePtr = buf;
+ uint8_t* curBytePtr = NULL;
+
+ /**
+ * We will transfer the command except for the last byte
+ * that will be transfered separately to allow for
+ * overflow checking
+ */
+ size_t length = buflen - 1;
+ size_t tx_len = 0;
+
+ do
+ {
+ rc = tpm_read_burst_count(&burst_count);
+
+ if (rc < 0)
+ return rc;
+ else if (burst_count == 0)
+ {
+ /* Need to delay to allow the TPM time */
+ time_wait_ms(TPM_TIMEOUT_INTERVAL);
+ delay += TPM_TIMEOUT_INTERVAL;
+ continue;
+ }
+
+ /* Send in some data */
+ curBytePtr = &(bytePtr[curByte]);
+ tx_len = (curByte + burst_count > length ?
+ (length - curByte) :
+ burst_count);
+
+ rc = tpm_i2c_request_send(SMBUS_WRITE, NUVOTON_TPM_DATA_FIFO_W,
+ 1, curBytePtr, tx_len);
+
+ curByte += tx_len;
+ DBG("%s write FIFO sent %zd bytes."
+ " burstcount polling delay=%d/%d, rc=%d\n",
+ (rc) ? "!!!!" : "----", curByte, delay,
+ TCG_PTP_TIMEOUT_D, rc);
+ delay = 0;
+
+ if (rc < 0)
+ return rc;
+
+ if (!tpm_is_expecting(&rc)) {
+ /**
+ * @fwts-label TPMWriteFifoOverflow1
+ * @fwts-advice We overflow to write to the TPM FIFO,
+ * the TPM is not expecting more data. This indicates a bug
+ * in the TPM device driver.
+ */
+ prlog(PR_ERR, "TPM: write FIFO overflow1\n");
+ return STB_TPM_OVERFLOW;
+ }
+
+ /* Everything but the last byte sent? */
+ if (curByte >= length)
+ break;
+
+ /* Operation TIMEOUT_D defined by TCG spec for FIFO availability */
+ } while (delay < TCG_PTP_TIMEOUT_D);
+
+ if (delay < TCG_PTP_TIMEOUT_D)
+ {
+ delay = 0;
+
+ /* Send the final byte */
+ do
+ {
+ rc = tpm_read_burst_count(&burst_count);
+
+ if (rc < 0)
+ return rc;
+ else if (burst_count == 0)
+ {
+ /* Need to delay to allow the TPM time */
+ time_wait_ms(TPM_TIMEOUT_INTERVAL);
+ delay += TPM_TIMEOUT_INTERVAL;
+ continue;
+ }
+
+ /* Send in some data */
+ curBytePtr = &(bytePtr[curByte]);
+ rc = tpm_i2c_request_send(SMBUS_WRITE,
+ NUVOTON_TPM_DATA_FIFO_W, 1,
+ curBytePtr, 1);
+
+ DBG("%s write FIFO sent last byte, delay=%d/%d,"
+ " rc=%d\n",
+ (rc) ? "!!!!" : "----", delay,
+ TCG_PTP_TIMEOUT_D, rc);
+
+ /* done */
+ break;
+
+ /**
+ * Operation TIMEOUT_D defined by TCG spec for
+ * FIFO availability
+ */
+ } while (delay < TCG_PTP_TIMEOUT_D);
+
+ }
+
+ if (delay >= TCG_PTP_TIMEOUT_D) {
+ /**
+ * @fwts-label TPMWriteBurstcountBitTimeout
+ * @fwts-advice The burstcount bit of the tpm status register is
+ * taking longer to be settled. The wait time need to be increased or
+ * the TPM device is not functional.
+ */
+ prlog(PR_ERR, "TPM: write FIFO, burstcount polling timeout."
+ " delay=%d/%d\n", delay, TCG_PTP_TIMEOUT_D);
+ return STB_TPM_TIMEOUT;
+ }
+
+ if (rc == 0)
+ {
+ if (tpm_is_expecting(&rc)) {
+ /**
+ * @fwts-label TPMWriteFifoOverflow2
+ * @fwts-advice We overflow to write to the TPM FIFO.
+ * It is expecting more data even though we think we
+ * are done. This indicates a bug in the TPM device
+ * driver.
+ */
+ prlog(PR_ERR, "TPM: write FIFO overflow2\n");
+ return STB_TPM_OVERFLOW;
+ }
+ }
+
+ return rc;
+}
+
+static int tpm_read_fifo(uint8_t* buf, size_t* buflen)
+{
+ int rc;
+ uint8_t burst_count;
+
+ int delay = 0;
+ size_t curByte = 0;
+ uint8_t* bytePtr = (uint8_t*)buf;
+ uint8_t* curBytePtr = NULL;
+
+ /* Verify whether the TPM has data waiting for us */
+ rc = tpm_poll_for_data_avail();
+
+ if (rc == 0)
+ {
+ do
+ {
+ rc = tpm_read_burst_count(&burst_count);
+
+ if (rc < 0)
+ break;
+ else if (burst_count == 0) {
+ /* Need to delay to allow the TPM time */
+ time_wait_ms(TPM_TIMEOUT_INTERVAL);
+ delay += TPM_TIMEOUT_INTERVAL;
+ continue;
+ }
+
+ /* Check for a buffer overflow */
+ if (curByte + burst_count > *buflen)
+ {
+ /**
+ * @fwts-label TPMReadFifoOverflow1
+ * @fwts-advice We overflow to read the TPM FIFO. It is
+ * expecting more data even though we think we are done.
+ * This indicates a bug in the TPM device driver.
+ */
+ prlog(PR_ERR, "TPM: read FIFO overflow1. delay %d/%d\n",
+ delay, TCG_PTP_TIMEOUT_D);
+ rc = STB_TPM_OVERFLOW;
+ }
+
+ /* Read some data */
+ curBytePtr = &(bytePtr[curByte]);
+ rc = tpm_i2c_request_send(SMBUS_READ,
+ NUVOTON_TPM_DATA_FIFO_R, 1,
+ curBytePtr, burst_count);
+
+ curByte += burst_count;
+ DBG("%s read FIFO. received %zd bytes. burstcount"
+ " polling delay=%d/%d, rc=%d\n",
+ (rc) ? "!!!!" : "----", curByte, delay,
+ TCG_PTP_TIMEOUT_D, rc);
+ delay = 0;
+
+ if (rc < 0)
+ break;
+
+ if (!tpm_is_data_avail(&rc))
+ break;
+
+ /* Operation TIMEOUT_D defined by TCG spec for
+ * FIFO availability */
+ } while (delay < TCG_PTP_TIMEOUT_D);
+ }
+
+ if (rc == 0 && delay >= TCG_PTP_TIMEOUT_D) {
+ /**
+ * @fwts-label TPMReadBurstcountBitTimeout
+ * @fwts-advice The burstcount bit of the tpm status register is
+ * taking longer to be settled. The wait time need to be increased or
+ * the TPM device is not functional.
+ */
+ prlog(PR_ERR, "TPM: read FIFO, burstcount polling timeout."
+ " delay=%d/%d\n",
+ delay, TCG_PTP_TIMEOUT_D);
+ return STB_TPM_TIMEOUT;
+ }
+
+ if (rc == 0) {
+ /* We read it properly tell the caller the result length */
+ *buflen = curByte;
+ }
+ else {
+ *buflen = 0;
+ }
+
+ return rc;
+}
+
+static int tpm_transmit(struct tpm_dev *dev, uint8_t* buf, size_t cmdlen,
+ size_t* buflen)
+{
+ int rc = STB_SUCCESS;
+
+ if (!dev) {
+ /**
+ * @fwts-label TPMDeviceNotInitialized
+ * @fwts-advice TPM device is not initialized. This indicates a
+ * bug in the tpm_transmit() caller
+ */
+ prlog(PR_ERR, "TPM: tpm device not initialized\n");
+ return STB_ARG_ERROR;
+ }
+
+ tpm_device = dev;
+
+ DBG("**** %s: dev %#x/%#x buf %016llx cmdlen %zu"
+ " buflen %zu ****\n",
+ __func__, dev->bus_id, dev->xscom_base, *(uint64_t*) buf,
+ cmdlen, *buflen);
+
+ DBG("step 1/5: check command ready\n");
+ if (!tpm_is_command_ready(&rc)) {
+ if (rc < 0)
+ goto out;
+ rc = tpm_poll_for_command_ready();
+ if (rc < 0)
+ goto out;
+ }
+
+ DBG("step 2/5: write FIFO\n");
+ rc = tpm_write_fifo(buf, cmdlen);
+ if (rc < 0)
+ goto out;
+
+ DBG("step 3/5: write tpmgo\n");
+ rc = tpm_status_write_byte(TCG_PTP_STS_GO);
+ if (rc < 0)
+ goto out;
+
+ DBG("step 4/5: read FIFO\n");
+ rc = tpm_read_fifo(buf, buflen);
+ if (rc < 0)
+ goto out;
+
+ DBG("step 5/5: write command ready\n");
+ rc = tpm_status_write_byte(TCG_PTP_STS_COMMAND_READY);
+
+out:
+ DBG("**** tpm_transmit %s, rc=%d ****\n",
+ (rc) ? "ERROR" : "SUCCESS", rc);
+ return rc;
+}
+
+static struct tpm_driver i2c_tpm_nuvoton_driver = {
+ .name = DRIVER_NAME,
+ .transmit = tpm_transmit,
+};
+
+void i2c_nuvoton_probe(void)
+{
+ struct tpm_chip *tpm = NULL;
+ struct tpm_dev *tpm_device = NULL;
+ struct dt_node *node = NULL;
+
+ dt_for_each_compatible(dt_root, node, compat) {
+
+ tpm = tpm_allocate_chip(node);
+
+ if (!tpm)
+ continue;
+
+ /* TPM device */
+ tpm_device = (struct tpm_dev*) malloc(sizeof(struct tpm_dev));
+ assert(tpm_device);
+
+ tpm_device->xscom_base = dt_prop_get_u32(node, "reg");
+ tpm_device->bus_id = dt_prop_get_u32(node->parent,
+ "ibm,opal-id");
+ tpm->dev = tpm_device;
+
+ /* TPM driver */
+ tpm->driver = &i2c_tpm_nuvoton_driver;
+
+ tpm_register_chip(tpm);
+ }
+}
+
diff --git a/libstb/drivers/tpm_i2c_nuvoton.h b/libstb/drivers/tpm_i2c_nuvoton.h
new file mode 100644
index 0000000..e05f53b
--- /dev/null
+++ b/libstb/drivers/tpm_i2c_nuvoton.h
@@ -0,0 +1,22 @@
+/* Copyright 2013-2016 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TPM_I2C_NUVOTON_H
+#define __TPM_I2C_NUVOTON_H
+
+extern void i2c_nuvoton_probe(void);
+
+#endif /* __TPM_I2C_NUVOTON_H */
diff --git a/libstb/status_codes.h b/libstb/status_codes.h
index 3a742c3..a1a71da 100644
--- a/libstb/status_codes.h
+++ b/libstb/status_codes.h
@@ -19,9 +19,15 @@
/* general return codes */
#define STB_SUCCESS 0
+#define STB_ARG_ERROR -1
+#define STB_DRIVER_ERROR -2
/* trusted boot */
#define STB_EVENTLOG_FAILED -200
#define STB_PCR_EXTEND_FAILED -201
+/* TPM */
+#define STB_TPM_OVERFLOW -300
+#define STB_TPM_TIMEOUT -301
+
#endif /* __STB_STATUS_CODES_H */
diff --git a/libstb/tpm.c b/libstb/tpm.c
index 26b411b..577341a 100644
--- a/libstb/tpm.c
+++ b/libstb/tpm.c
@@ -20,6 +20,7 @@
#include "status_codes.h"
#include "container.h"
+#include "drivers/tpm_i2c_nuvoton.h"
#include "tss/trustedbootCmds.H"
#include "tpm.h"
@@ -176,6 +177,7 @@ void tpm_init(void)
list_head_init(&tpm_list);
/* tpm drivers supported */
+ i2c_nuvoton_probe();
if (list_empty(&tpm_list)) {
/**
--
1.9.1
More information about the Skiboot
mailing list