[Skiboot] [PATCH 04/19] hdata/tpmrel.c: register CVC services during HDAT parsing
Claudio Carvalho
cclaudio at linux.vnet.ibm.com
Wed Nov 29 13:37:15 AEDT 2017
On 28/11/2017 04:54, Vasant Hegde wrote:
> On 11/11/2017 10:58 PM, Claudio Carvalho wrote:
>> This registers the address range of the Container-Verification-Code
>> (CVC) and then registers each CVC service provided. The offset of
>> each service is checked to make sure that it is not out of the CVC
>> address range.
>>
>> The hostboot reserved memory that stores the CVC is identified by
>> parsing the msvpd_hb_reserved_mem HDAT structure. In order to register
>> its address range, we call the cvc_register() libstb function.
>>
>> The CVC services provided are identified by parsing the hash_and_verify
>> HDAT structure. In order to register them, we call the
>> cvc_service_register() libstb function.
>>
>> This also updates the hdat_to_dt unit test adding one stub for each
>> libstb function called.
>>
>> Since skiboot is the only consumer for the CVC services, this patch
>> doesn't add them to the device tree.
>>
>> Signed-off-by: Claudio Carvalho <cclaudio at linux.vnet.ibm.com>
>> ---
>> hdata/spira.h | 12 ++++++
>> hdata/test/stubs.c | 2 +
>> hdata/tpmrel.c | 90 +++++++++++++++++++++++++++++++++++++++++
>> libstb/Makefile.inc | 2 +-
>> libstb/cvc.c | 114
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>> libstb/cvc.h | 29 +++++++++++++
>> 6 files changed, 248 insertions(+), 1 deletion(-)
>> create mode 100644 libstb/cvc.c
>> create mode 100644 libstb/cvc.h
>>
>
>
> .../...
>
>>
>> diff --git a/hdata/tpmrel.c b/hdata/tpmrel.c
>> index 0aaa70b..11ed3ce 100644
>> --- a/hdata/tpmrel.c
>> +++ b/hdata/tpmrel.c
>> @@ -20,6 +20,8 @@
>>
>> #include <skiboot.h>
>> #include <device.h>
>> +#include <inttypes.h>
>> +#include <libstb/cvc.h>
>>
>> #include "spira.h"
>> #include "hdata.h"
>> @@ -72,6 +74,93 @@ static void tpmrel_add_firmware_event_log(const
>> struct HDIF_common_hdr *hdif_hdr
>> }
>> }
>>
>> +static const struct msvpd_hb_reserved_mem
>> *get_cvc_reserved_memory(void)
>> +{
>> +
>
> May be we should add another property inside reserved-memory to
> identify reserved-memory type and use it here. Because today its just
> secureboot. Tomorrow someone else may want to use type field.
hmm ... maybe we don't need to add another property. Double checking the
HDAT spec, it defines that the label for the CVC reserved memory is
"ibm,secure-crypt-algo-code" and skiboot uses the label for the
reserved-memory node name and its "ibm,prd-label", see below. If it is
OK, I can iterate on the /ibm,hostboot/reserved-memory children looking
for ibm,prd-label="ibm,secure-crypt-algo-code".
ibm,secure-crypt-algo-code at ffd330000 {
ibm,prd-label = "ibm,secure-crypt-algo-code";
ibm,prd-instance = <0x0>;
phandle = <0x545>;
reg = <0xf 0xfd330000 0x0 0x10000>;
};
If we can't rely on ibm,prd-label, then I think we would need to tweak
hdata/memory.c to add the memory region type whenever it is
provided/exists. Roughly speaking, it would be something like this:
@@ -496,9 +501,9 @@ static void get_hb_reserved_mem(struct
HDIF_common_hdr *ms_vpd)
}
prlog(PR_DEBUG, "MEM: Reserve '%s' %#" PRIx64 "-%#"
PRIx64 " (type/inst=0x%08x)\n",
label, start_addr, end_addr,
be32_to_cpu(hb_resv_mem->type_instance));
- node = add_hb_reserve_node(label, start_addr, end_addr);
+ node = add_hb_reserve_node(label, start_addr, end_addr,
&type);
if (!node) {
prerror("unable to add node?\n");
continue;
@@ -554,7 +559,7 @@ static void parse_trace_reservations(struct
HDIF_common_hdr *ms_vpd)
"MS VPD: Trace area:
0x%.16"PRIx64"-0x%.16"PRIx64"\n",
start, end);
- node = add_hb_reserve_node("trace-area", start, end);
+ node = add_hb_reserve_node("trace-area", start, end, NULL);
if (!node) {
prerror("MEM: Unable to reserve trace area
%p-%p\n",
(void *) start, (void *) end);
@@ -401,7 +401,8 @@ static void get_msareas(struct dt_node *root,
static struct dt_node *dt_hb_reserves;
-static struct dt_node *add_hb_reserve_node(const char *name, u64 start,
u64 end)
+static struct dt_node *add_hb_reserve_node(const char *name, u64 start,
u64 end,
+ u32 *type)
{
struct dt_node *node, *hb;
@@ -424,6 +425,8 @@ static struct dt_node *add_hb_reserve_node(const
char *name, u64 start, u64 end)
}
dt_add_property_u64s(node, "reg", start, end - start + 1);
+ if (type)
+ dt_add_property_cells(node, "type", *type);
return node;
}
>
>
>> + const struct msvpd_hb_reserved_mem *hb_resv_mem;
>> + const struct HDIF_common_hdr *ms_vpd;
>> + uint32_t type;
>> + int count, i;
>> +
>> + ms_vpd = get_hdif(&spira.ntuples.ms_vpd, MSVPD_HDIF_SIG);
>> +
>> + if (!ms_vpd) {
>> + prlog(PR_ERR, "MS VPD invalid\n");
>> + return NULL;
>> + }
>> +
>> + count = HDIF_get_iarray_size(ms_vpd, MSVPD_IDATA_HB_RESERVED_MEM);
>> + if (count <= 0) {
>> + prlog(PR_ERR, "no hostboot reserved memory found\n");
>> + return NULL;
>> + }
>> +
>> + 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);
>> +
>> + /* Reserved memory for the Container Verification Code? */
>> + if (type == HBRMEM_CONTAINER_VERIFICATION_CODE)
>> + return hb_resv_mem;
>> + }
>> +
>> + return NULL;
>> +}
>> +
>> +#define HRMOR_BIT (1ul << 63)
>> +
>> +static void tpmrel_cvc_init(struct HDIF_common_hdr *hdif_hdr)
>> +{
>> + const struct hash_and_verification *hv;
>> + const struct msvpd_hb_reserved_mem *cvc_resv_mem;
>> + uint32_t type, version, offset;
>> + uint64_t start_addr, end_addr;
>> + int count, i;
>> +
>> + cvc_resv_mem = get_cvc_reserved_memory();
>> +
>> + if (!cvc_resv_mem) {
>> + prlog(PR_ERR, "CVC reserved memory not found\n");
>> + return;
>> + }
>> +
>> + start_addr = be64_to_cpu(cvc_resv_mem->start_addr);
>> + start_addr &= ~HRMOR_BIT;
>> + end_addr = be64_to_cpu(cvc_resv_mem->end_addr);
>> + end_addr &= ~HRMOR_BIT;
>> + prlog(PR_DEBUG, "Found CVC at 0x%"PRIx64"...0x%"PRIx64"\n",
>> + start_addr, end_addr);
>> + cvc_register(start_addr, end_addr);
>> + /*
>> + * 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++) {
>> +
>> + 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);
>> + offset = be32_to_cpu(hv->offset);
>
> Like Oliver mentioned you can add these properties to DT, and then
> call cvc_service_register outside hdata parsing.
>
Right. I will add the /ibm,secureboot/ibm,cvc node as DT_PRIVATE and
then call cvc_service_register outside of hdat parsing.
ibm,cvc {
phandle = <0xd9>;
#address-cells = <0x1>;
#size-cells = <0x0>;
compatible = "ibm,container-verification-code";
memory-region = <0x81>; ;; This points to
the /ibm,hostboot/reserved-memory/ibm,secure-crypt-algo-code/phandle
ibm,cvc-offset at 40 {
phandle = <0xda>;
compatible = "ibm,cvc-sha512";
reg = <0x40>;
version = 1;
};
ibm,cvc-offset at 50 {
phandle = <0xdb>;
compatible = "ibm,cvc-verify";
reg = <0x50>;
version = 1;
};
}
Claudio
More information about the Skiboot
mailing list