[4/5] hdata/tpmrel.c: add the ibm, container-verification-code node

Message ID 1504165372-15971-5-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.
In the secureboot-v2, the container verification code is stored in a
hostboot reserved memory.

This walks through the ms_vpd hdat structure to identify what hostboot
reserved memory the container verification code is stored in and then
creates the 'ibm,container-verification-code' node, which has a cross
reference (memory-region property) to that hostboot reserved memory.

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

Patch

diff --git a/hdata/spira.h b/hdata/spira.h
index 0056887..d4c3023 100644
--- a/hdata/spira.h
+++ b/hdata/spira.h
@@ -529,6 +529,9 @@  struct msvpd_trace {
 /* Idata index 5: Hostboot reserved memory address range */
 #define MSVPD_IDATA_HB_RESERVED_MEM	5
 struct msvpd_hb_reserved_mem {
+#define MSVPD_HBRMEM_RANGE_TYPE	PPC_BITMASK32(0,7)
+#define HBRMEM_CVC_CONTAINER_V1 	0x3
+#define MSVPD_HBRMEM_INSTANCE_NUMBER	PPC_BITMASK32(8,31)
 	__be32		type_instance;
 	__be64		start_addr;
 	__be64		end_addr;
diff --git a/hdata/tpmrel.c b/hdata/tpmrel.c
index f2e2ec8..81e6443 100644
--- a/hdata/tpmrel.c
+++ b/hdata/tpmrel.c
@@ -20,6 +20,7 @@ 
 
 #include <skiboot.h>
 #include <device.h>
+#include <ccan/str/str.h>
 
 #include "spira.h"
 #include "hdata.h"
@@ -75,9 +76,121 @@  static void add_tpmrel_tpm_eventlog(const struct HDIF_common_hdr *hdif_hdr)
 	}
 }
 
+struct hdat_container_verification_code {
+	uint32_t container_version;
+	uint32_t hb_reserved_mem_type;
+	uint32_t num_offsets;
+	const char *compat;
+};
+
+static struct hdat_container_verification_code cvc[] = {
+	/* ibm,secure-crypt-algo-code */
+	{ 0x1, HBRMEM_CVC_CONTAINER_V1, 2, "ibm,container-v1-verification-code"}
+};
+
+static struct hdat_container_verification_code *map_cvc(uint32_t type)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cvc); i++) {
+		if (cvc[i].hb_reserved_mem_type == type)
+			return &cvc[i];
+	}
+	return NULL;
+}
+
+#define HRMOR_BIT (1ul << 63)
+
+static struct dt_node *get_reserved_memory(const struct msvpd_hb_reserved_mem *hb_resv_mem)
+{
+	struct dt_node *node;
+	uint64_t start_addr, end_addr;
+	const char *reserved = "/ibm,hostboot/reserved-memory/";
+	char *path;
+	size_t len;
+
+	start_addr = be64_to_cpu(hb_resv_mem->start_addr);
+	end_addr = be64_to_cpu(hb_resv_mem->end_addr);
+
+	start_addr &= ~HRMOR_BIT;
+	end_addr &= ~HRMOR_BIT;
+
+	len = strlen(reserved) + strlen(hb_resv_mem->label) +
+		STR_MAX_CHARS(start_addr) + 2;
+	path = malloc(len);
+	assert(path);
+	snprintf(path, len, "%s%s@%llx", reserved,
+		 hb_resv_mem->label, (long long) start_addr);
+	node = dt_find_by_path(dt_root, path);
+	free(path);
+
+	return node;
+}
+
+static void cvc_init(struct dt_node *parent)
+{
+	const struct msvpd_hb_reserved_mem *hb_resv_mem;
+	const struct HDIF_common_hdr *ms_vpd;
+	struct hdat_container_verification_code *cvc;
+	uint32_t type;
+	int count, i;
+
+	ms_vpd = get_hdif(&spira.ntuples.ms_vpd, MSVPD_HDIF_SIG);
+
+	if (!ms_vpd) {
+		prerror("TPMREL: MS VPD invalid\n");
+		return;
+	}
+
+	count = HDIF_get_iarray_size(ms_vpd, MSVPD_IDATA_HB_RESERVED_MEM);
+	if (count <= 0) {
+		prerror("TPMREL: No hostboot reserved memory found\n");
+		return;
+	}
+	/*
+	 * The secureboot container verification code is stored in a hosboot
+	 * reserved memory. We walk through the hostboot reserved memory nodes
+	 * to find it.
+	 *
+	 * Once we find the container verification code we create a new node
+	 * with a cross reference to its reserved memory.
+	 */
+	for (i = 0; i < count; i++) {
+		hb_resv_mem = HDIF_get_iarray_item(ms_vpd,
+						   MSVPD_IDATA_HB_RESERVED_MEM,
+						   i, NULL);
+		if (!CHECK_SPPTR(hb_resv_mem))
+			continue;
+
+		type = be32_to_cpu(hb_resv_mem->type_instance);
+		type = GETFIELD(MSVPD_HBRMEM_RANGE_TYPE, type);
+		cvc = map_cvc(type);
+		if (cvc) {
+			struct dt_node *reserved_mem, *node;
+
+			reserved_mem= get_reserved_memory(hb_resv_mem);
+			if (!reserved_mem) {
+				prlog(PR_INFO, "reserved memory for %s not found\n",
+				      cvc->compat);
+				return;
+			}
+
+			node = dt_new(parent, "ibm,container-verification-code");
+			assert(node);
+
+			dt_add_property_cells(node, "#address-cells", 1);
+			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);
+		}
+	}
+	return;
+}
+
 void node_stb_parse(void)
 {
 	struct HDIF_common_hdr *hdif_hdr;
+	struct dt_node *node;
 
 	hdif_hdr = get_hdif(&spira.ntuples.node_stb_data, "TPMREL");
 	if (!hdif_hdr) {
@@ -87,6 +200,11 @@  void node_stb_parse(void)
 
 	add_tpmrel_tpm_eventlog(hdif_hdr);
 
-	/* TODO: Idata 1: User Physical Interaction Mechanism Info */
-	/* TODO: Idata 2: Hash and Verification Function Offset Array */
+	node = dt_find_by_path(dt_root, "/ibm,secureboot");
+	if (!node) {
+		prlog(PR_INFO, "'ibm,secureboot' node not found\n");
+		return;
+	}
+
+	cvc_init(node);
 }