summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNamyoon Woo <namyoon@chromium.org>2019-12-06 13:40:18 -0800
committerCommit Bot <commit-bot@chromium.org>2020-02-22 01:46:37 +0000
commitc5322ba116003017deab926f5d1e9bdd16f649b8 (patch)
tree029288582014d5a5d8be0ca87643e0e1fe707328
parentcfc689dcb00f3b81e857c8fbd21e4599443ceeff (diff)
downloadchrome-ec-c5322ba116003017deab926f5d1e9bdd16f649b8.tar.gz
read EC Firmware hash from kernel secdata during board init
Cr50 reads EC Firmware hash from kernel secdata. This data shall be used for EC-EFS (Early Firmware Selection) procedure. BUG=chromium:1020578, b:148489182 BRANCH=cr50 TEST=none Change-Id: Id8942b5b49dd5b0412d198a12ee0bf87fd59d47f Signed-off-by: Namyoon Woo <namyoon@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1956159 Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
-rw-r--r--board/cr50/ec_comm.h4
-rw-r--r--board/cr50/ec_efs.c61
-rw-r--r--board/cr50/tpm2/NVMem.c9
-rw-r--r--include/common.h2
-rw-r--r--include/tpm_nvmem.h3
-rw-r--r--include/vboot.h18
6 files changed, 95 insertions, 2 deletions
diff --git a/board/cr50/ec_comm.h b/board/cr50/ec_comm.h
index 9e84a715e1..bec2deb57b 100644
--- a/board/cr50/ec_comm.h
+++ b/board/cr50/ec_comm.h
@@ -36,4 +36,8 @@ void ec_efs_reset(void);
uint16_t ec_efs_set_boot_mode(const char *data, const uint8_t size);
/* Verify the given hash data against the EC-FW hash from kernel secdata */
uint16_t ec_efs_verify_hash(const char *hash_data, const uint8_t size);
+
+/* Re-load EC Hash code from TPM Kernel Secdata */
+void ec_efs_refresh(void);
+
#endif /* __CROS_EC_COMM_H */
diff --git a/board/cr50/ec_efs.c b/board/cr50/ec_efs.c
index da5a31f019..677fb7d7f9 100644
--- a/board/cr50/ec_efs.c
+++ b/board/cr50/ec_efs.c
@@ -7,10 +7,13 @@
#include "common.h"
#include "console.h"
#include "ec_comm.h"
+#include "crc8.h"
#include "ec_commands.h"
#include "hooks.h"
#include "registers.h"
#include "system.h"
+#include "tpm_nvmem.h"
+#include "tpm_nvmem_ops.h"
#include "vboot.h"
#ifdef CR50_DEV
@@ -48,6 +51,44 @@ static void set_boot_mode_(uint8_t mode_val)
GREG32(PMU, PWRDN_SCRATCH20) |= mode_val;
}
+static int load_ec_hash_(uint8_t * const ec_hash)
+{
+ struct vb2_secdata_kernel secdata;
+ const uint8_t secdata_size = sizeof(struct vb2_secdata_kernel);
+ uint8_t size_to_crc;
+ uint8_t struct_size;
+ uint8_t crc;
+
+ if (read_tpm_nvmem(KERNEL_NV_INDEX, secdata_size,
+ (void *)&secdata) != tpm_read_success)
+ return EC_ERROR_VBOOT_DATA_UNDERSIZED;
+
+ /*
+ * Check struct version. CRC offset may be different with old struct
+ * version
+ */
+ if (secdata.struct_version < VB2_SECDATA_KERNEL_STRUCT_VERSION_MIN)
+ return EC_ERROR_VBOOT_DATA_INCOMPATIBLE;
+
+ /* Check struct size. */
+ struct_size = secdata.struct_size;
+ if (struct_size != secdata_size)
+ return EC_ERROR_VBOOT_DATA;
+
+ /* Check CRC */
+ size_to_crc = struct_size -
+ offsetof(struct vb2_secdata_kernel, crc8) -
+ sizeof(secdata.crc8);
+ crc = crc8((uint8_t *)&secdata.reserved0, size_to_crc);
+ if (crc != secdata.crc8)
+ return EC_ERROR_CRC;
+
+ /* Read hash and copy to hash */
+ memcpy(ec_hash, secdata.ec_hash, sizeof(secdata.ec_hash));
+
+ return EC_SUCCESS;
+}
+
/*
* Initialize EC-EFS context.
*/
@@ -66,7 +107,11 @@ static void ec_efs_init_(void)
else
ec_efs_reset();
- /* TODO(crbug/1020578): Read Hash from Kernel NV Index */
+ /* Read an EC hash in kernel secdata (TPM kernel NV index). */
+ if (ec_efs_ctx.hash_is_loaded)
+ return;
+
+ ec_efs_refresh();
}
DECLARE_HOOK(HOOK_INIT, ec_efs_init_, HOOK_PRIO_DEFAULT);
@@ -74,3 +119,17 @@ void ec_efs_reset(void)
{
set_boot_mode_(EC_EFS_BOOT_MODE_NORMAL);
}
+
+void ec_efs_refresh(void)
+{
+ int rv;
+
+ rv = load_ec_hash_(ec_efs_ctx.hash);
+ if (rv == EC_SUCCESS) {
+ ec_efs_ctx.hash_is_loaded = 1;
+ } else {
+ ec_efs_ctx.hash_is_loaded = 0;
+ cprints(CC_SYSTEM, "load_ec_hash error: 0x%x\n", rv);
+ }
+ ec_efs_ctx.secdata_error_code = rv;
+}
diff --git a/board/cr50/tpm2/NVMem.c b/board/cr50/tpm2/NVMem.c
index e1a14b4536..052165d5b6 100644
--- a/board/cr50/tpm2/NVMem.c
+++ b/board/cr50/tpm2/NVMem.c
@@ -14,9 +14,12 @@
#include "Platform.h"
#include "PlatformData.h"
+#include "TPM_Types.h"
#include "TpmError.h"
#include "assert.h"
+#include "ec_comm.h"
#include "nvmem.h"
+#include "tpm_nvmem.h"
/* Local state */
static struct {
@@ -188,3 +191,9 @@ void _plat__ClearNvAvail(void)
local_state.s_NvIsAvailable = FALSE;
return;
}
+
+void _plat__NvInformIndexDataChanged(unsigned int handle)
+{
+ if (handle == (HR_NV_INDEX + KERNEL_NV_INDEX))
+ ec_efs_refresh();
+}
diff --git a/include/common.h b/include/common.h
index 99e9ad91c9..62f7d438d0 100644
--- a/include/common.h
+++ b/include/common.h
@@ -239,6 +239,8 @@ enum ec_error_list {
/* Verified boot data errors */
EC_ERROR_VBOOT_DATA = 0x1200,
EC_ERROR_VBOOT_DATA_VERIFY = 0x1201,
+ EC_ERROR_VBOOT_DATA_INCOMPATIBLE = 0x1202,
+ EC_ERROR_VBOOT_DATA_UNDERSIZED = 0x1203,
/* Module-internal error codes may use this range. */
EC_ERROR_INTERNAL_FIRST = 0x10000,
diff --git a/include/tpm_nvmem.h b/include/tpm_nvmem.h
index 2508c9ae65..3315148323 100644
--- a/include/tpm_nvmem.h
+++ b/include/tpm_nvmem.h
@@ -8,6 +8,7 @@
#define __CROS_EC_TPM_NVMEM_H
#define FIRMWARE_NV_INDEX 0x1007
-#define FWMP_NV_INDEX 0x100a
+#define KERNEL_NV_INDEX 0x1008
+#define FWMP_NV_INDEX 0x100a
#endif /* __CROS_EC_TPM_NVMEM_H */
diff --git a/include/vboot.h b/include/vboot.h
index 195db31a54..ba924508c7 100644
--- a/include/vboot.h
+++ b/include/vboot.h
@@ -72,6 +72,24 @@ enum ec_efs_boot_mode {
EC_EFS_BOOT_MODE_LIMIT = 255,
};
+/****************************************************************************
+ * This is quoted from 2secdata_struct.h in the directory,
+ * src/platform/vboot_reference/firmware/2lib/include/.
+ ****************************************************************************/
+
+/* Kernel secure storage space */
+#define VB2_SECDATA_KERNEL_STRUCT_VERSION_MIN 0x10
+#define VB2_SECDATA_KERNEL_UID 0x4752574c /* 'LWRG' */
+struct vb2_secdata_kernel {
+ uint8_t struct_version; /* top-half:major. bottom-half:minor. */
+ uint8_t struct_size; /* Whole structure size */
+ uint8_t crc8; /* CRC for everything below */
+ uint8_t reserved0;
+
+ uint32_t kernel_versions; /* Kernel versions */
+ uint8_t ec_hash[SHA256_DIGEST_SIZE];
+} __packed;
+
/**
* Validate key contents.
*