feat(handoff): add event log test

Adds a new TFTF test to validate presence and correctness of the TPM
event log in the transfer list received from EL3. Uses event_log_dump to
parse and output log data.

Change-Id: I0b1f782429e4bfe3d1760fce52d40a9836dc27a2
Signed-off-by: Harrison Mutai <harrison.mutai@arm.com>
diff --git a/include/lib/transfer_list.h b/include/lib/transfer_list.h
index f1e4181..eee2b82 100644
--- a/include/lib/transfer_list.h
+++ b/include/lib/transfer_list.h
@@ -48,6 +48,7 @@
 	TL_TAG_HOB_BLOCK = 2,
 	TL_TAG_HOB_LIST = 3,
 	TL_TAG_ACPI_TABLE_AGGREGATE = 4,
+	TL_TAG_TPM_EVLOG = 5,
 };
 
 enum transfer_list_ops {
@@ -91,6 +92,10 @@
 	 */
 };
 
+struct transfer_list_entry *
+transfer_list_next(struct transfer_list_header *tl,
+		   struct transfer_list_entry *last);
+
 bool transfer_list_verify_checksum(const struct transfer_list_header *tl);
 
 void *transfer_list_entry_data(struct transfer_list_entry *entry);
diff --git a/lib/transfer_list/transfer_list.c b/lib/transfer_list/transfer_list.c
index c83b0b3..13ff6ff 100644
--- a/lib/transfer_list/transfer_list.c
+++ b/lib/transfer_list/transfer_list.c
@@ -8,13 +8,63 @@
 
 #include <transfer_list.h>
 
+/*******************************************************************************
+ * Search for an existing transfer entry with the specified tag id from a
+ * transfer list
+ * Return pointer to the found transfer entry or NULL on error
+ ******************************************************************************/
 struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
 					       uint16_t tag_id)
 {
-	struct transfer_list_entry *te = (void *)tl + tl->hdr_size;
+	struct transfer_list_entry *te = NULL;
 
-	while (te->tag_id != tag_id) {
-		te += round_up(te->hdr_size + te->data_size, tl->alignment);
+	do {
+		te = transfer_list_next(tl, te);
+	} while (te && (te->tag_id != tag_id));
+
+	return te;
+}
+
+/*******************************************************************************
+ * Enumerate the next transfer entry
+ * Return pointer to the next transfer entry or NULL on error
+ ******************************************************************************/
+struct transfer_list_entry *transfer_list_next(struct transfer_list_header *tl,
+					       struct transfer_list_entry *last)
+{
+	struct transfer_list_entry *te = NULL;
+	uintptr_t tl_ev = 0;
+	uintptr_t va = 0;
+	uintptr_t ev = 0;
+	size_t sz = 0;
+
+	if (!tl) {
+		return NULL;
+	}
+
+	tl_ev = (uintptr_t)tl + tl->size;
+
+	if (last) {
+		va = (uintptr_t)last;
+		/* check if the total size overflow */
+		if (add_overflow(last->hdr_size, last->data_size, &sz)) {
+			return NULL;
+		}
+		/* roundup to the next entry */
+		if (add_with_round_up_overflow(va, sz, TRANSFER_LIST_GRANULE,
+					       &va)) {
+			return NULL;
+		}
+	} else {
+		va = (uintptr_t)tl + tl->hdr_size;
+	}
+
+	te = (struct transfer_list_entry *)va;
+
+	if (va + sizeof(*te) > tl_ev || te->hdr_size < sizeof(*te) ||
+	    add_overflow(te->hdr_size, te->data_size, &sz) ||
+	    add_overflow(va, sz, &ev) || ev > tl_ev) {
+		return NULL;
 	}
 
 	return te;
diff --git a/tftf/framework/framework.mk b/tftf/framework/framework.mk
index d5d3300..098f2b8 100644
--- a/tftf/framework/framework.mk
+++ b/tftf/framework/framework.mk
@@ -55,6 +55,7 @@
 	lib/${ARCH}/misc_helpers.S					\
 	lib/delay/delay.c						\
 	lib/events/events.c						\
+	${EVENT_LOG_SOURCES}						\
 	lib/extensions/amu/${ARCH}/amu.c				\
 	lib/extensions/amu/${ARCH}/amu_helpers.S			\
 	lib/exceptions/irq.c						\
diff --git a/tftf/tests/misc_tests/test_firmware_handoff.c b/tftf/tests/misc_tests/test_firmware_handoff.c
index 61091ae..026f057 100644
--- a/tftf/tests/misc_tests/test_firmware_handoff.c
+++ b/tftf/tests/misc_tests/test_firmware_handoff.c
@@ -6,10 +6,13 @@
 
 #include <assert.h>
 
+#include <drivers/measured_boot/event_log/tcg.h>
 #include <test_helpers.h>
 #include <tftf_lib.h>
 #include <transfer_list.h>
 
+#include "event_log.h"
+
 extern u_register_t hw_config_base;
 extern u_register_t ns_tl;
 extern u_register_t tl_signature;
@@ -61,3 +64,31 @@
 
 	return TEST_RESULT_SUCCESS;
 }
+
+test_result_t test_handoff_event_payload(void)
+{
+
+	struct transfer_list_header *tl = (struct transfer_list_header *)ns_tl;
+	struct transfer_list_entry *te;
+	uint8_t *log_addr;
+	size_t log_size;
+
+	tftf_testcase_printf(
+		"Validate that a TPM event log can be successfully dumped when "
+		"present in the transfer list.");
+
+	te = transfer_list_find(tl, TL_TAG_TPM_EVLOG);
+	if (te == NULL) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/* 4-bytes are reserved in TE data section. */
+	log_addr = (uint8_t *)transfer_list_entry_data(te) + U(4);
+	log_size = te->data_size - U(4);
+
+	if (event_log_dump(log_addr, log_size) != 0) {
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/tests-firmware-handoff.mk b/tftf/tests/tests-firmware-handoff.mk
index 515188a..65dfc4b 100644
--- a/tftf/tests/tests-firmware-handoff.mk
+++ b/tftf/tests/tests-firmware-handoff.mk
@@ -6,8 +6,12 @@
 
 ifeq (${TRANSFER_LIST}, 1)
 
+include lib/event_log/event_log.mk
+
 TESTS_SOURCES	+=	$(addprefix tftf/tests/misc_tests/,		\
 	test_firmware_handoff.c						\
 )
 
+TESTS_SOURCES	+=	${EVENT_LOG_SOURCES}
+
 endif
diff --git a/tftf/tests/tests-firmware-handoff.xml b/tftf/tests/tests-firmware-handoff.xml
index 4b4b2a4..9b456cc 100644
--- a/tftf/tests/tests-firmware-handoff.xml
+++ b/tftf/tests/tests-firmware-handoff.xml
@@ -10,5 +10,6 @@
   <testsuite name="Firmware Handoff" description="Validate transfer list managed by firmware handoff framework">
      <testcase name="Validate transfer list header" function="test_handoff_header" />
      <testcase name="Validate HW_CONFIG in transfer list" function="test_handoff_dtb_payload" />
+     <testcase name="Validate event log in transfer list" function="test_handoff_event_payload" />
   </testsuite>
 </testsuites>