diff options
author | Claudio Carvalho <cclaudio@linux.vnet.ibm.com> | 2017-12-09 02:52:30 -0200 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-12-18 21:30:57 -0600 |
commit | 7da364fd3646013166b90baf26fc55078a446a21 (patch) | |
tree | c188bfef58d9ea7c0885efb2fd9bfa6e0318dbb9 | |
parent | 48fd73cfc7073911a1ecdf0ff62e1800ef544d2a (diff) | |
download | skiboot-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.inc | 2 | ||||
-rw-r--r-- | hdata/hdata.h | 1 | ||||
-rw-r--r-- | hdata/spira.c | 4 | ||||
-rw-r--r-- | hdata/spira.h | 33 | ||||
-rw-r--r-- | hdata/test/hdata_to_dt.c | 1 | ||||
-rw-r--r-- | hdata/tpmrel.c | 116 |
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); +} |