diff options
Diffstat (limited to 'roms/skiboot/libstb/secvar/storage/fakenv_ops.c')
-rw-r--r-- | roms/skiboot/libstb/secvar/storage/fakenv_ops.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/roms/skiboot/libstb/secvar/storage/fakenv_ops.c b/roms/skiboot/libstb/secvar/storage/fakenv_ops.c new file mode 100644 index 000000000..224ac2a5d --- /dev/null +++ b/roms/skiboot/libstb/secvar/storage/fakenv_ops.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* Copyright 2020 IBM Corp. */ +#include <skiboot.h> +#include "secboot_tpm.h" + +/* Offset into the SECBOOT PNOR partition to write "TPMNV" data */ +static size_t fakenv_offset = sizeof(struct secboot); + +struct fake_tpmnv { + struct { + struct secboot_header header; + char vars[2048]; // Hardcode the size to 2048 for now + } vars; + struct tpmnv_control control; + int defined[2]; +} __attribute__((packed)); + +static struct fake_tpmnv fakenv; +static int tpm_ready; + + +static inline void *nv_index_address(int index) +{ + switch (index) { + case SECBOOT_TPMNV_VARS_INDEX: + return &fakenv.vars; + case SECBOOT_TPMNV_CONTROL_INDEX: + return &fakenv.control; + default: + return 0; + } +} + + +static int tpm_init(void) +{ + int rc; + + if (tpm_ready) + return 0; + + rc = flash_secboot_read(&fakenv, fakenv_offset, sizeof(struct fake_tpmnv)); + if (rc) + return rc; + + tpm_ready = 1; + + return 0; +} + +static int fakenv_read(TPMI_RH_NV_INDEX nvIndex, void *buf, + size_t bufsize, uint16_t off) +{ + if (tpm_init()) + return OPAL_INTERNAL_ERROR; + + memcpy(buf, nv_index_address(nvIndex) + off, bufsize); + + return 0; +} + +static int fakenv_write(TPMI_RH_NV_INDEX nvIndex, void *buf, + size_t bufsize, uint16_t off) +{ + if (tpm_init()) + return OPAL_INTERNAL_ERROR; + + memcpy(nv_index_address(nvIndex) + off, buf, bufsize); + + /* Just write the whole NV struct for now */ + return flash_secboot_write(fakenv_offset, &fakenv, sizeof(struct fake_tpmnv)); +} + +static int fakenv_definespace(TPMI_RH_NV_INDEX nvIndex, uint16_t dataSize) +{ + if (tpm_init()) + return OPAL_INTERNAL_ERROR; + + (void) dataSize; + + switch (nvIndex) { + case SECBOOT_TPMNV_VARS_INDEX: + fakenv.defined[0] = 1; + return 0; + case SECBOOT_TPMNV_CONTROL_INDEX: + fakenv.defined[1] = 1; + return 0; + } + + return OPAL_INTERNAL_ERROR; +} + +static int fakenv_writelock(TPMI_RH_NV_INDEX nvIndex) +{ + if (tpm_init()) + return OPAL_INTERNAL_ERROR; + + (void) nvIndex; + + return 0; +} + +static int fakenv_get_defined_indices(TPMI_RH_NV_INDEX **indices, size_t *count) +{ + if (tpm_init()) + return OPAL_INTERNAL_ERROR; + + *indices = zalloc(sizeof(fakenv.defined)); + if (*indices == NULL) + return OPAL_NO_MEM; + + *count = 0; + + if (fakenv.defined[0]) { + *indices[0] = SECBOOT_TPMNV_VARS_INDEX; + (*count)++; + } + if (fakenv.defined[1]) { + *indices[1] = SECBOOT_TPMNV_CONTROL_INDEX; + (*count)++; + } + + return 0; +} + +static int fakenv_undefinespace(TPMI_RH_NV_INDEX index) +{ + if (tpm_init()) + return OPAL_INTERNAL_ERROR; + + switch (index) { + case SECBOOT_TPMNV_VARS_INDEX: + fakenv.defined[0] = 0; + memset(&fakenv.vars, 0, sizeof(fakenv.vars)); + return 0; + case SECBOOT_TPMNV_CONTROL_INDEX: + fakenv.defined[1] = 0; + memset(&fakenv.control, 0, sizeof(fakenv.control)); + return 0; + } + + return -1; +} + +static int fakenv_readpublic(TPMI_RH_NV_INDEX index, TPMS_NV_PUBLIC *nv_public, + TPM2B_NAME *nv_name) +{ + if (tpm_init()) + return OPAL_INTERNAL_ERROR; + + (void) nv_public; + + switch (index) { + case SECBOOT_TPMNV_VARS_INDEX: + memcpy(&nv_name->t.name, tpmnv_vars_name, sizeof(TPM2B_NAME)); + break; + case SECBOOT_TPMNV_CONTROL_INDEX: + memcpy(&nv_name->t.name, tpmnv_control_name, sizeof(TPM2B_NAME)); + break; + default: + return OPAL_INTERNAL_ERROR; + } + + return 0; +} + +struct tpmnv_ops_s tpmnv_ops = { + .read = fakenv_read, + .write = fakenv_write, + .writelock = fakenv_writelock, + .definespace = fakenv_definespace, + .getindices = fakenv_get_defined_indices, + .undefinespace = fakenv_undefinespace, + .readpublic = fakenv_readpublic, +}; |