aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Carvalho <cclaudio@linux.vnet.ibm.com>2017-12-09 02:52:30 -0200
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-12-18 21:30:57 -0600
commit7da364fd3646013166b90baf26fc55078a446a21 (patch)
treec188bfef58d9ea7c0885efb2fd9bfa6e0318dbb9
parent48fd73cfc7073911a1ecdf0ff62e1800ef544d2a (diff)
downloadskiboot-7da364fd3646013166b90baf26fc55078a446a21.zip
skiboot-7da364fd3646013166b90baf26fc55078a446a21.tar.gz
skiboot-7da364fd3646013166b90baf26fc55078a446a21.tar.bz2
hdata/tpmrel.c: add firmware event log info to the tpm node
This parses the firmware event log information from the secureboot_tpm_info HDAT structure and add it to the tpm device tree node. There can be multiple secureboot_tpm_info entries with each entry corresponding to a master processor that has a tpm device, however, multiple tpm is not supported. Signed-off-by: Claudio Carvalho <cclaudio@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--hdata/Makefile.inc2
-rw-r--r--hdata/hdata.h1
-rw-r--r--hdata/spira.c4
-rw-r--r--hdata/spira.h33
-rw-r--r--hdata/test/hdata_to_dt.c1
-rw-r--r--hdata/tpmrel.c116
6 files changed, 156 insertions, 1 deletions
diff --git a/hdata/Makefile.inc b/hdata/Makefile.inc
index 5b79dfe..c17b04f 100644
--- a/hdata/Makefile.inc
+++ b/hdata/Makefile.inc
@@ -2,7 +2,7 @@
SUBDIRS += hdata
HDATA_OBJS = spira.o paca.o pcia.o hdif.o memory.o fsp.o iohub.o vpd.o slca.o
-HDATA_OBJS += cpu-common.o vpd-common.o hostservices.o i2c.o
+HDATA_OBJS += cpu-common.o vpd-common.o hostservices.o i2c.o tpmrel.o
DEVSRC_OBJ = hdata/built-in.o
$(DEVSRC_OBJ): $(HDATA_OBJS:%=hdata/%)
diff --git a/hdata/hdata.h b/hdata/hdata.h
index ce3719a..981affd 100644
--- a/hdata/hdata.h
+++ b/hdata/hdata.h
@@ -54,6 +54,7 @@ extern void slca_dt_add_sai_node(void);
extern bool hservices_from_hdat(const void *fdt, size_t size);
int parse_i2c_devs(const struct HDIF_common_hdr *hdr, int idata_index,
struct dt_node *xscom);
+extern void node_stb_parse(void);
/* used to look up the device-tree node representing a slot */
struct dt_node *find_slot_entry_node(struct dt_node *root, u32 entry_id);
diff --git a/hdata/spira.c b/hdata/spira.c
index edb140d..dc6370c 100644
--- a/hdata/spira.c
+++ b/hdata/spira.c
@@ -1669,6 +1669,10 @@ int parse_hdat(bool is_opal)
add_stop_levels();
+ /* Parse node secure and trusted boot data */
+ if (proc_gen >= proc_gen_p9)
+ node_stb_parse();
+
prlog(PR_DEBUG, "Parsing HDAT...done\n");
return 0;
diff --git a/hdata/spira.h b/hdata/spira.h
index 17c6a2a..e2d45ab 100644
--- a/hdata/spira.h
+++ b/hdata/spira.h
@@ -1226,6 +1226,39 @@ struct ipmi_sensors {
/* Idata index 1 : LED - sensors ID mapping data */
#define IPMI_SENSORS_IDATA_LED 1
+/*
+ * Node Secure and Trusted Boot Related Data
+ */
+#define STB_HDIF_SIG "TPMREL"
+
+/*
+ * Idata index 0 : Secure Boot and TPM Instance Info
+ *
+ * There can be multiple entries with each entry corresponding to
+ * a master processor that has a TPM device
+ */
+#define TPMREL_IDATA_SECUREBOOT_TPM_INFO 0
+
+struct secureboot_tpm_info {
+ __be32 chip_id;
+ __be32 dbob_id;
+ uint8_t locality1;
+ uint8_t locality2;
+ uint8_t locality3;
+ uint8_t locality4;
+#define TPM_PRESENT_AND_FUNCTIONAL 0x01
+#define TPM_PRESENT_AND_NOT_FUNCTIONAL 0x02
+#define TPM_NOT_PRESENT 0x03
+ uint8_t tpm_status;
+ uint8_t reserved[3];
+ /* zero indicates no tpm log data */
+ __be32 srtm_log_offset;
+ __be32 srtm_log_size;
+ /* zero indicates no tpm log data */
+ __be32 drtm_log_offset;
+ __be32 drtm_log_size;
+} __packed;
+
static inline const char *cpu_state(u32 flags)
{
switch ((flags & CPU_ID_VERIFY_MASK) >> CPU_ID_VERIFY_SHIFT) {
diff --git a/hdata/test/hdata_to_dt.c b/hdata/test/hdata_to_dt.c
index 634d7a7..f7ed65e 100644
--- a/hdata/test/hdata_to_dt.c
+++ b/hdata/test/hdata_to_dt.c
@@ -139,6 +139,7 @@ static bool spira_check_ptr(const void *ptr, const char *file, unsigned int line
#include "../slca.c"
#include "../hostservices.c"
#include "../i2c.c"
+#include "../tpmrel.c"
#include "../../core/vpd.c"
#include "../../core/device.c"
#include "../../core/chip.c"
diff --git a/hdata/tpmrel.c b/hdata/tpmrel.c
new file mode 100644
index 0000000..5b6731f
--- /dev/null
+++ b/hdata/tpmrel.c
@@ -0,0 +1,116 @@
+/* Copyright 2013-2017 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 pr_fmt
+#define pr_fmt(fmt) "TPMREL: " fmt
+#endif
+
+#include <skiboot.h>
+#include <device.h>
+
+#include "spira.h"
+#include "hdata.h"
+#include "hdif.h"
+
+static void tpmrel_add_firmware_event_log(const struct HDIF_common_hdr *hdif_hdr)
+{
+ const struct secureboot_tpm_info *stinfo;
+ struct dt_node *xscom, *node;
+ uint64_t addr;
+ int count, i;
+ unsigned int asize;
+
+ /* Are the hdat values populated? */
+ if (!HDIF_get_idata(hdif_hdr, TPMREL_IDATA_SECUREBOOT_TPM_INFO, &asize))
+ return;
+ if (asize < sizeof(struct HDIF_array_hdr)) {
+ prlog(PR_ERR, "secureboot_tpm_info idata not populated\n");
+ return;
+ }
+
+ count = HDIF_get_iarray_size(hdif_hdr, TPMREL_IDATA_SECUREBOOT_TPM_INFO);
+ if (count > 1) {
+ prlog(PR_ERR, "multiple TPM not supported, count=%d\n", count);
+ return;
+ }
+
+ /*
+ * There can be multiple secureboot_tpm_info entries with each entry
+ * corresponding to a master processor that has a tpm device.
+ * This looks for the tpm node that supposedly exists under the xscom
+ * node associated with the respective chip_id.
+ */
+ for (i = 0; i < count; i++) {
+
+ stinfo = HDIF_get_iarray_item(hdif_hdr,
+ TPMREL_IDATA_SECUREBOOT_TPM_INFO,
+ i, NULL);
+
+ xscom = find_xscom_for_chip(be32_to_cpu(stinfo->chip_id));
+ if (xscom) {
+ dt_for_each_node(xscom, node) {
+ if (dt_has_node_property(node, "label", "tpm"))
+ break;
+ }
+
+ if (node) {
+ addr = (uint64_t) stinfo +
+ be32_to_cpu(stinfo->srtm_log_offset);
+ dt_add_property_u64s(node, "linux,sml-base", addr);
+ dt_add_property_cells(node, "linux,sml-size",
+ be32_to_cpu(stinfo->srtm_log_size));
+
+ if (stinfo->tpm_status == TPM_PRESENT_AND_NOT_FUNCTIONAL)
+ dt_add_property_string(node, "status", "disabled");
+ } else {
+ /**
+ * @fwts-label HDATNoTpmForChipId
+ * @fwts-advice HDAT secureboot_tpm_info
+ * structure described a chip id, but no tpm
+ * node was found under that xscom chip id.
+ * This is most certainly a hostboot bug.
+ */
+ prlog(PR_ERR, "TPM node not found for "
+ "chip_id=%d (HB bug)\n", stinfo->chip_id);
+ continue;
+ }
+ } else {
+ /**
+ * @fwts-label HDATBadChipIdForTPM
+ * @fwts-advice HDAT secureboot_tpm_info structure
+ * described a chip id, but the xscom node for the
+ * chip_id was not found.
+ * This is most certainly a firmware bug.
+ */
+ prlog(PR_ERR, "xscom node not found for chip_id=%d\n",
+ stinfo->chip_id);
+ continue;
+ }
+ }
+}
+
+void node_stb_parse(void)
+{
+ struct HDIF_common_hdr *hdif_hdr;
+
+ hdif_hdr = get_hdif(&spira.ntuples.node_stb_data, "TPMREL");
+ if (!hdif_hdr) {
+ prlog(PR_DEBUG, "TPMREL data not found\n");
+ return;
+ }
+
+ tpmrel_add_firmware_event_log(hdif_hdr);
+}