[5/5] hdata/tpmrel.c: add cvc offset nodes

Message ID 1504165372-15971-6-git-send-email-cclaudio@linux.vnet.ibm.com
State Under Review
Headers show
Series
  • hdata: add and parse the tpmrel structure
Related show

Commit Message

Claudio Carvalho Aug. 31, 2017, 7:42 a.m.
This parses the hdat tpmrel structure to get the offsets of the
functions provided by the container verification code and then creates
one 'ibm,container-verification-code' child node for each offset found.

Signed-off-by: Claudio Carvalho <cclaudio@linux.vnet.ibm.com>
---
 hdata/spira.h  | 12 +++++++++
 hdata/tpmrel.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 87 insertions(+), 3 deletions(-)

Patch

diff --git a/hdata/spira.h b/hdata/spira.h
index d4c3023..799f0d7 100644
--- a/hdata/spira.h
+++ b/hdata/spira.h
@@ -1132,6 +1132,18 @@  struct secureboot_tpm_info {
 	__be32 drtm_log_size;
 } __packed;
 
+/* Idata index 2: Hash and Verification Function Offsets Array */
+#define TPMREL_IDATA_HASH_VERIF_OFFSETS 	2
+
+struct hash_and_verification {
+#define TPMREL_HV_SHA512			0x00
+#define TPMREL_HV_CONTAINER_VERIFY		0x01
+	__be32 type;
+	__be32 version;
+	__be32 dbob_id;
+	__be32 offset;
+} __packed;
+
 static inline const char *cpu_state(u32 flags)
 {
 	switch ((flags & CPU_ID_VERIFY_MASK) >> CPU_ID_VERIFY_SHIFT) {
diff --git a/hdata/tpmrel.c b/hdata/tpmrel.c
index 81e6443..cc80f3f 100644
--- a/hdata/tpmrel.c
+++ b/hdata/tpmrel.c
@@ -99,6 +99,75 @@  static struct hdat_container_verification_code *map_cvc(uint32_t type)
 	return NULL;
 }
 
+struct {
+	uint32_t container_version;
+	uint32_t type;
+	uint32_t version;
+	const char *compat;
+} cvc_offsets[] = {
+	{0x1, TPMREL_HV_SHA512, 0x1, "ibm,sha512-hash"},
+	{0x1, TPMREL_HV_CONTAINER_VERIFY, 0x1, "ibm,container-verify"}
+};
+
+static const char *map_offset_compat(uint32_t container_version, uint32_t type,
+				   uint32_t version)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cvc_offsets); i++) {
+		if (cvc_offsets[i].container_version == container_version &&
+		    cvc_offsets[i].type == type &&
+		    cvc_offsets[i].version == version)
+			return cvc_offsets[i].compat;
+	}
+	return NULL;
+}
+
+static int cvc_add_code_offset_nodes(struct dt_node *parent,
+				      struct HDIF_common_hdr *hdif_hdr,
+				      struct hdat_container_verification_code *cvc)
+{
+	const struct hash_and_verification *hv;
+	const char *compat;
+	uint32_t type, version;
+	int count, i;
+
+	count = HDIF_get_iarray_size(hdif_hdr, TPMREL_IDATA_HASH_VERIF_OFFSETS);
+
+	if (count > cvc->num_offsets) {
+		prlog(PR_ALERT, "found %d cvc offsets for %s. (expected=%d) "
+		      "HOSTBOOT BUG?", count, cvc->compat, cvc->num_offsets);
+		return -1;
+	}
+
+	for (i = 0; i < count; i++) {
+
+		hv = HDIF_get_iarray_item(hdif_hdr,
+					  TPMREL_IDATA_HASH_VERIF_OFFSETS,
+					  i, NULL);
+
+		type = be32_to_cpu(hv->type);
+		version = be32_to_cpu(hv->version);
+
+		compat = map_offset_compat(cvc->container_version, type, version);
+		if (compat) {
+			uint32_t reg;
+			struct dt_node *code;
+
+			reg = be32_to_cpu(hv->offset);
+
+			code = dt_new_addr(parent, "ibm,code-offset", reg);
+			dt_add_property_strings(code, "compatible", compat);
+			dt_add_property_cells(code, "reg", reg);
+		} else {
+			prlog(PR_INFO, "cvc offset not added. UNKNOWN:"
+			      "cv=%d, type=%d, version=%d\n",
+			      cvc->container_version, type, version);
+		}
+	}
+	return 0;
+}
+
 #define HRMOR_BIT (1ul << 63)
 
 static struct dt_node *get_reserved_memory(const struct msvpd_hb_reserved_mem *hb_resv_mem)
@@ -127,7 +196,7 @@  static struct dt_node *get_reserved_memory(const struct msvpd_hb_reserved_mem *h
 	return node;
 }
 
-static void cvc_init(struct dt_node *parent)
+static void cvc_init(struct dt_node *parent, struct HDIF_common_hdr *hdif_hdr)
 {
 	const struct msvpd_hb_reserved_mem *hb_resv_mem;
 	const struct HDIF_common_hdr *ms_vpd;
@@ -153,7 +222,8 @@  static void cvc_init(struct dt_node *parent)
 	 * to find it.
 	 *
 	 * Once we find the container verification code we create a new node
-	 * with a cross reference to its reserved memory.
+	 * with a cross reference to its reserved memory and also create inner
+	 * nodes (one for each code offset provided).
 	 */
 	for (i = 0; i < count; i++) {
 		hb_resv_mem = HDIF_get_iarray_item(ms_vpd,
@@ -182,6 +252,8 @@  static void cvc_init(struct dt_node *parent)
 			dt_add_property_cells(node, "#size-cells", 0);
 			dt_add_property_strings(node, "compatible", cvc->compat);
 			dt_add_property_cells(node, "memory-region", reserved_mem->phandle);
+
+			cvc_add_code_offset_nodes(node, hdif_hdr, cvc);
 		}
 	}
 	return;
@@ -206,5 +278,5 @@  void node_stb_parse(void)
 		return;
 	}
 
-	cvc_init(node);
+	cvc_init(node, hdif_hdr);
 }