aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/drivers/intel/fsp2_0/Kconfig10
-rw-r--r--src/drivers/intel/fsp2_0/Makefile.inc1
-rw-r--r--src/drivers/intel/fsp2_0/fsp_timestamp.c109
-rw-r--r--src/drivers/intel/fsp2_0/include/fsp/util.h2
-rw-r--r--src/drivers/intel/fsp2_0/silicon_init.c3
5 files changed, 125 insertions, 0 deletions
diff --git a/src/drivers/intel/fsp2_0/Kconfig b/src/drivers/intel/fsp2_0/Kconfig
index 0823aa3020..1eccd61400 100644
--- a/src/drivers/intel/fsp2_0/Kconfig
+++ b/src/drivers/intel/fsp2_0/Kconfig
@@ -359,4 +359,14 @@ config FSP_USES_CB_DEBUG_EVENT_HANDLER
This option allows to create `Debug Event Handler` to print FSP debug messages
to output device using coreboot native implementation.
+config DISPLAY_FSP_TIMESTAMPS
+ bool "Display FSP Timestamps"
+ default n
+ help
+ Select this config to retrieve FSP timestamps from Firmware Performance Data Table
+ (FPDT) and display from ramstage after FSP-S is executed.
+
+ To be able to use this, FSP has to be compiled with `PcdFspPerformanceEnable` set to
+ `TRUE`.
+
endif
diff --git a/src/drivers/intel/fsp2_0/Makefile.inc b/src/drivers/intel/fsp2_0/Makefile.inc
index 076ab2d84b..f5641ac182 100644
--- a/src/drivers/intel/fsp2_0/Makefile.inc
+++ b/src/drivers/intel/fsp2_0/Makefile.inc
@@ -19,6 +19,7 @@ romstage-y += cbmem.c
ramstage-y += debug.c
ramstage-$(CONFIG_FSP_USES_CB_DEBUG_EVENT_HANDLER) += fsp_debug_event.c
ramstage-$(CONFIG_USE_INTEL_FSP_MP_INIT) += fsp_mpinit.c
+ramstage-$(CONFIG_DISPLAY_FSP_TIMESTAMPS) += fsp_timestamp.c
ramstage-$(CONFIG_RUN_FSP_GOP) += graphics.c
ramstage-y += hand_off_block.c
ramstage-$(CONFIG_DISPLAY_FSP_HEADER) += header_display.c
diff --git a/src/drivers/intel/fsp2_0/fsp_timestamp.c b/src/drivers/intel/fsp2_0/fsp_timestamp.c
new file mode 100644
index 0000000000..da14db91c0
--- /dev/null
+++ b/src/drivers/intel/fsp2_0/fsp_timestamp.c
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <commonlib/bsd/compiler.h>
+#include <console/console.h>
+#include <fsp/util.h>
+#include <lib.h>
+
+#define TIMESTAMP_MS(x) ((x) / 1000ull)
+
+static const uint8_t fpdt_guid[16] = {
+ 0xfd, 0x7b, 0x38, 0x3b, 0xbc, 0x7a, 0xf2, 0x4c,
+ 0xa0, 0xca, 0xb6, 0xa1, 0x6c, 0x1b, 0x1b, 0x25,
+};
+
+enum fpdt_record_type {
+ FPDT_GUID_EVENT = 0x1010,
+ FPDT_STRING_EVENT = 0x1011,
+};
+
+struct perf_record_hdr {
+ uint16_t type;
+ uint8_t length;
+ uint8_t revision;
+} __packed;
+
+struct generic_event_record {
+ struct perf_record_hdr header;
+ uint16_t progress_id;
+ uint32_t apic_id;
+ uint64_t timestamp;
+ uint8_t guid[16];
+ uint8_t string[0];
+} __packed;
+
+/*
+ * Performance Hob:
+ * GUID - fpdt_guid;
+ * Data - FPDT_PEI_EXT_PERF_HEADER one or more FPDT records
+*/
+struct fpdt_pei_ext_perf_header {
+ uint32_t table_size;
+ uint32_t load_image_count;
+ uint32_t hob_is_full;
+} __packed;
+
+static void print_guid_record(const struct generic_event_record *rec)
+{
+ printk(BIOS_INFO, "%5x\t%16llu\t\t", rec->progress_id, TIMESTAMP_MS(rec->timestamp));
+ fsp_print_guid(rec->guid);
+ printk(BIOS_INFO, "\n");
+}
+
+static void print_string_record(const struct generic_event_record *rec)
+{
+ size_t str_len = rec->header.length - offsetof(struct generic_event_record, string);
+ printk(BIOS_INFO, "%5x\t%16llu\t\t%*s/",
+ rec->progress_id, TIMESTAMP_MS(rec->timestamp), (int)str_len, rec->string);
+ fsp_print_guid(rec->guid);
+ printk(BIOS_INFO, "\n");
+}
+
+static void print_fsp_perf_timestamp(const struct generic_event_record *rec)
+{
+ switch (rec->header.type) {
+ case FPDT_GUID_EVENT:
+ print_guid_record(rec);
+ break;
+ case FPDT_STRING_EVENT:
+ print_string_record(rec);
+ break;
+ default:
+ printk(BIOS_INFO, "Unhandled Event Type 0x%x\n", rec->header.type);
+ break;
+ }
+}
+
+static void print_fsp_timestamp_header(void)
+{
+ printk(BIOS_INFO, "+---------------------------------------------------+\n");
+ printk(BIOS_INFO, "|------ FSP Performance Timestamp Table Dump -------|\n");
+ printk(BIOS_INFO, "+---------------------------------------------------+\n");
+ printk(BIOS_INFO, "| Perf-ID\tTimestamp(ms)\t\tString/GUID |\n");
+ printk(BIOS_INFO, "+---------------------------------------------------+\n");
+}
+
+void fsp_display_timestamp(void)
+{
+ size_t size;
+ const struct fpdt_pei_ext_perf_header *hdr = fsp_find_extension_hob_by_guid(fpdt_guid,
+ &size);
+
+ if (!hdr || !size) {
+ printk(BIOS_INFO, "FPDT Extended Firmware Performance HOB Not Found!\n"
+ "Check if PcdFspPerformanceEnable is set to `TRUE` inside FSP package\n");
+ return;
+ }
+
+ const struct generic_event_record *rec = (const struct generic_event_record *)(
+ (uint8_t *)hdr + sizeof(struct fpdt_pei_ext_perf_header));
+
+ print_fsp_timestamp_header();
+ for (size_t i = 0; i < hdr->table_size;) {
+ print_fsp_perf_timestamp(rec);
+
+ i += rec->header.length;
+ rec = (const struct generic_event_record *)((uint8_t *)rec +
+ rec->header.length);
+ }
+}
diff --git a/src/drivers/intel/fsp2_0/include/fsp/util.h b/src/drivers/intel/fsp2_0/include/fsp/util.h
index 2687d0dc98..96dc472361 100644
--- a/src/drivers/intel/fsp2_0/include/fsp/util.h
+++ b/src/drivers/intel/fsp2_0/include/fsp/util.h
@@ -106,6 +106,8 @@ extern const uint8_t fsp_bootloader_tolum_guid[16];
extern const uint8_t fsp_nv_storage_guid[16];
extern const uint8_t fsp_reserved_memory_guid[16];
+/* Function to extract the FSP timestamp from FPDT Hob and display */
+void fsp_display_timestamp(void);
const void *fsp_get_hob_list(void);
void *fsp_get_hob_list_ptr(void);
const void *fsp_find_extension_hob_by_guid(const uint8_t *guid, size_t *size);
diff --git a/src/drivers/intel/fsp2_0/silicon_init.c b/src/drivers/intel/fsp2_0/silicon_init.c
index 05cea11d55..263ea3b46d 100644
--- a/src/drivers/intel/fsp2_0/silicon_init.c
+++ b/src/drivers/intel/fsp2_0/silicon_init.c
@@ -244,6 +244,9 @@ void fsp_silicon_init(void)
timestamp_add_now(TS_FSP_SILICON_INIT_LOAD);
fsps_load();
do_silicon_init(&fsps_hdr);
+
+ if (CONFIG(DISPLAY_FSP_TIMESTAMPS))
+ fsp_display_timestamp();
}
__weak void soc_load_logo(FSPS_UPD *supd) { }