plat/arm/board/fvp: Add support for Measured Boot

This patch adds support for Measured Boot functionality
to FVP platform code. It also defines new properties
in 'tpm_event_log' node to store Event Log address and
it size
'tpm_event_log_sm_addr'
'tpm_event_log_addr'
'tpm_event_log_size'
in 'event_log.dtsi' included in 'fvp_tsp_fw_config.dts'
and 'fvp_nt_fw_config.dts'. The node and its properties
are described in binding document
'docs\components\measured_boot\event_log.rst'.

Change-Id: I087e1423afcb269d6cfe79c1af9c348931991292
Signed-off-by: Alexei Fedorov <Alexei.Fedorov@arm.com>
diff --git a/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c b/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c
new file mode 100644
index 0000000..e258015
--- /dev/null
+++ b/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+
+#include <libfdt.h>
+#include <fconf_nt_config_getter.h>
+
+#include <plat/common/platform.h>
+
+struct event_log_config_t event_log_config;
+
+int fconf_populate_event_log_config(uintptr_t config)
+{
+	int err;
+	int node;
+
+	/* Necessary to work with libfdt APIs */
+	const void *dtb = (const void *)config;
+
+	/*
+	 * Find the offset of the node containing "arm,tpm_event_log"
+	 * compatible property
+	 */
+	const char *compatible_str = "arm,tpm_event_log";
+
+	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+	if (node < 0) {
+		ERROR("FCONF: Can't find '%s' compatible in dtb\n",
+			compatible_str);
+		return node;
+	}
+
+	/* Retrieve Event Log details from the DTB */
+#ifdef SPD_opteed
+	err = fdtw_read_cells(dtb, node, "tpm_event_log_sm_addr", 2,
+				&event_log_config.tpm_event_log_sm_addr);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for 'tpm_event_log_sm_addr'\n");
+		return err;
+	}
+#endif
+	err = fdtw_read_cells(dtb, node,
+		"tpm_event_log_addr", 2, &event_log_config.tpm_event_log_addr);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for 'tpm_event_log_addr'\n");
+		return err;
+	}
+
+	err = fdtw_read_cells(dtb, node,
+		"tpm_event_log_size", 1, &event_log_config.tpm_event_log_size);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for 'tpm_event_log_size'\n");
+	}
+
+	return err;
+}
+
+FCONF_REGISTER_POPULATOR(NT_CONFIG, event_log_config,
+				fconf_populate_event_log_config);
diff --git a/plat/arm/board/fvp/fdts/event_log.dtsi b/plat/arm/board/fvp/fdts/event_log.dtsi
new file mode 100644
index 0000000..47af672
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/event_log.dtsi
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* TPM Event Log Config */
+event_log: tpm_event_log {
+	compatible = "arm,tpm_event_log";
+	tpm_event_log_addr = <0x0 0x0>;
+	tpm_event_log_size = <0x0>;
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
index 7ab980b..8f32b98 100644
--- a/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,5 +7,13 @@
 /dts-v1/;
 
 / {
+#if MEASURED_BOOT
+#include "event_log.dtsi"
+#endif
+};
 
+#if MEASURED_BOOT && defined(SPD_opteed)
+&event_log {
+	tpm_event_log_sm_addr = <0x0 0x0>;
 };
+#endif
diff --git a/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
index 7ab980b..7bed6cb 100644
--- a/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,5 +7,7 @@
 /dts-v1/;
 
 / {
-
+#if MEASURED_BOOT
+#include "event_log.dtsi"
+#endif
 };
diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c
index d13cc81..0e77c4d 100644
--- a/plat/arm/board/fvp/fvp_bl1_setup.c
+++ b/plat/arm/board/fvp/fvp_bl1_setup.c
@@ -70,6 +70,14 @@
 
 #if MEASURED_BOOT
 /*
+ * Calculates and writes BL2 hash data to TB_FW_CONFIG DTB.
+ */
+void bl1_plat_set_bl2_hash(const image_desc_t *image_desc)
+{
+	arm_bl1_set_bl2_hash(image_desc);
+}
+
+/*
  * Implementation for bl1_plat_handle_post_image_load(). This function
  * populates the default arguments to BL2. The BL2 memory layout structure
  * is allocated and the calculated layout is populated in arg1 to BL2.
@@ -90,7 +98,7 @@
 	assert(image_desc != NULL);
 
 	/* Calculate BL2 hash and set it in TB_FW_CONFIG */
-	arm_bl1_set_bl2_hash(image_desc);
+	bl1_plat_set_bl2_hash(image_desc);
 
 	/* Get the entry point info */
 	ep_info = &image_desc->ep_info;
diff --git a/plat/arm/board/fvp/fvp_bl2_setup.c b/plat/arm/board/fvp/fvp_bl2_setup.c
index d5618d9..f2f2143 100644
--- a/plat/arm/board/fvp/fvp_bl2_setup.c
+++ b/plat/arm/board/fvp/fvp_bl2_setup.c
@@ -6,8 +6,12 @@
 
 #include <assert.h>
 
+#include <common/debug.h>
 #include <common/desc_image_load.h>
 #include <drivers/arm/sp804_delay_timer.h>
+#if MEASURED_BOOT
+#include <drivers/measured_boot/measured_boot.h>
+#endif
 #include <lib/fconf/fconf.h>
 #include <lib/fconf/fconf_dyn_cfg_getter.h>
 
@@ -69,3 +73,45 @@
 
 	return arm_bl_params;
 }
+#if MEASURED_BOOT
+static int fvp_bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	const bl_mem_params_node_t *bl_mem_params =
+				get_bl_mem_params_node(image_id);
+
+	assert(bl_mem_params != NULL);
+
+	image_info_t info = bl_mem_params->image_info;
+	int err;
+
+	if ((info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U) {
+		/* Calculate image hash and record data in Event Log */
+		err = tpm_record_measurement(info.image_base,
+					     info.image_size, image_id);
+		if (err != 0) {
+			ERROR("%s%s image id %u (%i)\n",
+				"BL2: Failed to ", "record", image_id, err);
+			return err;
+		}
+	}
+
+	err = arm_bl2_handle_post_image_load(image_id);
+	if (err != 0) {
+		ERROR("%s%s image id %u (%i)\n",
+			"BL2: Failed to ", "handle", image_id, err);
+	}
+
+	return err;
+}
+
+int arm_bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	int err = fvp_bl2_plat_handle_post_image_load(image_id);
+
+	if (err != 0) {
+		ERROR("%s() returns %i\n", __func__, err);
+	}
+
+	return err;
+}
+#endif	/* MEASURED_BOOT */
diff --git a/plat/arm/board/fvp/fvp_measured_boot.c b/plat/arm/board/fvp/fvp_measured_boot.c
new file mode 100644
index 0000000..b145aae
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_measured_boot.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/measured_boot/event_log.h>
+#include <plat/arm/common/plat_arm.h>
+
+/* FVP table with platform specific image IDs, names and PCRs */
+static const image_data_t fvp_images_data[] = {
+	{ BL2_IMAGE_ID, BL2_STRING, PCR_0 },		/* Reserved for BL2 */
+	{ BL31_IMAGE_ID, BL31_STRING, PCR_0 },
+	{ BL32_IMAGE_ID, BL32_STRING, PCR_0 },
+	{ BL32_EXTRA1_IMAGE_ID, BL32_EXTRA1_IMAGE_STRING, PCR_0 },
+	{ BL32_EXTRA2_IMAGE_ID, BL32_EXTRA2_IMAGE_STRING, PCR_0 },
+	{ BL33_IMAGE_ID, BL33_STRING, PCR_0 },
+	{ GPT_IMAGE_ID, GPT_IMAGE_STRING, PCR_0 },
+	{ HW_CONFIG_ID, HW_CONFIG_STRING, PCR_0 },
+	{ NT_FW_CONFIG_ID, NT_FW_CONFIG_STRING, PCR_0 },
+	{ SCP_BL2_IMAGE_ID, SCP_BL2_IMAGE_STRING, PCR_0 },
+	{ SOC_FW_CONFIG_ID, SOC_FW_CONFIG_STRING, PCR_0 },
+	{ STM32_IMAGE_ID, STM32_IMAGE_STRING, PCR_0 },
+	{ TOS_FW_CONFIG_ID, TOS_FW_CONFIG_STRING, PCR_0 },
+	{ INVALID_ID, NULL, (unsigned int)(-1) }	/* Terminator */
+};
+
+static const measured_boot_data_t fvp_measured_boot_data = {
+	fvp_images_data,
+	arm_set_nt_fw_info,
+	arm_set_tos_fw_info
+};
+
+/*
+ * Function retuns pointer to FVP plat_measured_boot_data_t structure
+ */
+const measured_boot_data_t *plat_get_measured_boot_data(void)
+{
+	return &fvp_measured_boot_data;
+}
diff --git a/plat/arm/board/fvp/include/fconf_nt_config_getter.h b/plat/arm/board/fvp/include/fconf_nt_config_getter.h
new file mode 100644
index 0000000..0824c35
--- /dev/null
+++ b/plat/arm/board/fvp/include/fconf_nt_config_getter.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_NT_CONFIG_GETTER_H
+#define FCONF_NT_CONFIG_GETTER_H
+
+#include <lib/fconf/fconf.h>
+
+/* NT Firmware Config related getter */
+#define nt_config__event_log_config_getter(prop) event_log.prop
+
+struct event_log_config_t {
+#ifdef SPD_opteed
+	void *tpm_event_log_sm_addr;
+#endif
+	void *tpm_event_log_addr;
+	size_t tpm_event_log_size;
+};
+
+int fconf_populate_event_log_config(uintptr_t config);
+
+extern struct event_log_config_t event_log_config;
+
+#endif /* FCONF_NT_CONFIG_GETTER_H */
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index f8fb821..a986017 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -243,8 +243,8 @@
 
 /*
  * GIC related constants to cater for both GICv2 and GICv3 instances of an
- * FVP. They could be overriden at runtime in case the FVP implements the legacy
- * VE memory map.
+ * FVP. They could be overridden at runtime in case the FVP implements the
+ * legacy VE memory map.
  */
 #define PLAT_ARM_GICD_BASE		BASE_GICD_BASE
 #define PLAT_ARM_GICR_BASE		BASE_GICR_BASE
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 9b8fccc..98c70c9 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -354,6 +354,11 @@
 ifeq (${TRUSTED_BOARD_BOOT}, 1)
 BL1_SOURCES		+=	plat/arm/board/fvp/fvp_trusted_boot.c
 BL2_SOURCES		+=	plat/arm/board/fvp/fvp_trusted_boot.c
+
+ifeq (${MEASURED_BOOT},1)
+BL2_SOURCES		+=	plat/arm/board/fvp/fvp_measured_boot.c
+endif
+
 # FVP being a development platform, enable capability to disable Authentication
 # dynamically if TRUSTED_BOARD_BOOT is set.
 DYN_DISABLE_AUTH	:=	1