aboutsummaryrefslogtreecommitdiff
path: root/hdata
diff options
context:
space:
mode:
authorClaudio Carvalho <cclaudio@linux.vnet.ibm.com>2017-12-09 02:52:31 -0200
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-12-18 21:30:57 -0600
commitf56ff29ed6f97bf24b815f6781fdf072e624fea8 (patch)
tree910df9bec02c620c1917f541b89b09891a082cdd /hdata
parent7da364fd3646013166b90baf26fc55078a446a21 (diff)
downloadskiboot-f56ff29ed6f97bf24b815f6781fdf072e624fea8.zip
skiboot-f56ff29ed6f97bf24b815f6781fdf072e624fea8.tar.gz
skiboot-f56ff29ed6f97bf24b815f6781fdf072e624fea8.tar.bz2
hdata/tpmrel.c: add ibm, cvc device tree node
In P9, the Container Verification Code is stored in a hostboot reserved memory and the list of provided CVC services is stored in the TPMREL_IDATA_HASH_VERIF_OFFSETS idata array. Each CVC service has an offset and version. This adds the ibm,cvc device tree node and its documentation. Signed-off-by: Claudio Carvalho <cclaudio@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hdata')
-rw-r--r--hdata/spira.h14
-rw-r--r--hdata/tpmrel.c105
2 files changed, 119 insertions, 0 deletions
diff --git a/hdata/spira.h b/hdata/spira.h
index e2d45ab..2ef13f3 100644
--- a/hdata/spira.h
+++ b/hdata/spira.h
@@ -529,6 +529,8 @@ 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_CONTAINER_VERIFICATION_CODE 0x3
__be32 type_instance;
__be64 start_addr;
__be64 end_addr;
@@ -1259,6 +1261,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_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 5b6731f..9b09765 100644
--- a/hdata/tpmrel.c
+++ b/hdata/tpmrel.c
@@ -102,6 +102,110 @@ static void tpmrel_add_firmware_event_log(const struct HDIF_common_hdr *hdif_hdr
}
}
+static struct dt_node *get_hb_reserved_memory(const char *label)
+{
+ struct dt_node *node, *hb_reserved_mem;
+
+ hb_reserved_mem = dt_find_by_path(dt_root, "/ibm,hostboot/reserved-memory");
+ if (!hb_reserved_mem) {
+ prlog(PR_DEBUG, "/ibm,hostboot/reserved-memory node not found\n");
+ return NULL;
+ }
+
+ dt_for_each_node(hb_reserved_mem, node) {
+ const char *prd_label;
+ if (!dt_find_property(node, "ibm,prd-label"))
+ continue;
+ prd_label = dt_prop_get(node, "ibm,prd-label");
+ if (!strcmp(prd_label, label))
+ return node;
+ }
+ return NULL;
+}
+
+struct {
+ uint32_t type;
+ const char *compat;
+} cvc_services[] = {
+ { TPMREL_HV_SHA512, "ibm,cvc-sha512" },
+ { TPMREL_HV_VERIFY, "ibm,cvc-verify" },
+};
+
+static const char* cvc_service_map_compat(uint32_t type) {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(cvc_services); i++) {
+ if (cvc_services[i].type == type)
+ return cvc_services[i].compat;
+ }
+ return NULL;
+}
+
+static void tpmrel_cvc_init(struct HDIF_common_hdr *hdif_hdr)
+{
+ struct dt_node *cvc_reserved_mem, *node, *parent;
+ int count, i;
+ unsigned int asize;
+
+ /* Are the hdat values populated? */
+ if (!HDIF_get_idata(hdif_hdr, TPMREL_IDATA_HASH_VERIF_OFFSETS, &asize))
+ return;
+ if (asize < sizeof(struct HDIF_array_hdr)) {
+ prlog(PR_ERR, "hash_and_verification idata not populated\n");
+ return;
+ }
+
+ node = dt_find_by_path(dt_root, "/ibm,secureboot");
+ if (!node)
+ return;
+
+ cvc_reserved_mem = get_hb_reserved_memory("ibm,secure-crypt-algo-code");
+ if (!cvc_reserved_mem) {
+ prlog(PR_ERR, "CVC reserved memory not found\n");
+ return;
+ }
+
+ parent = dt_new(node, "ibm,cvc");
+ assert(parent);
+ dt_add_property_cells(parent, "#address-cells", 1);
+ dt_add_property_cells(parent, "#size-cells", 0);
+ dt_add_property_strings(parent, "compatible", "ibm,container-verification-code");
+ dt_add_property_cells(parent, "memory-region", cvc_reserved_mem->phandle);
+
+ /*
+ * Initialize each service provided by the container verification code
+ */
+ count = HDIF_get_iarray_size(hdif_hdr, TPMREL_IDATA_HASH_VERIF_OFFSETS);
+ if (count <= 0 ) {
+ prlog(PR_ERR, "no CVC service found\n");
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ const struct hash_and_verification *hv;
+ uint32_t type, offset, version;
+ const char *compat;
+
+ hv = HDIF_get_iarray_item(hdif_hdr,
+ TPMREL_IDATA_HASH_VERIF_OFFSETS,
+ i, NULL);
+ type = be32_to_cpu(hv->type);
+ offset = be32_to_cpu(hv->offset);
+ version = be32_to_cpu(hv->version);
+
+ compat = cvc_service_map_compat(type);
+
+ if (!compat) {
+ prlog(PR_WARNING, "CVC service type 0x%x unknown\n", type);
+ continue;
+ }
+
+ node = dt_new_addr(parent, "ibm,cvc-service", offset);
+ dt_add_property_strings(node, "compatible", compat);
+ dt_add_property_cells(node, "reg", offset);
+ dt_add_property_cells(node, "version", version);
+ }
+}
+
void node_stb_parse(void)
{
struct HDIF_common_hdr *hdif_hdr;
@@ -113,4 +217,5 @@ void node_stb_parse(void)
}
tpmrel_add_firmware_event_log(hdif_hdr);
+ tpmrel_cvc_init(hdif_hdr);
}