xref: /aosp_15_r20/external/coreboot/src/drivers/intel/fsp2_0/fsp_timestamp.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <console/console.h>
4 #include <fsp/util.h>
5 
6 #define TIMESTAMP_TO_MICRO(x) ((x) / 1000ull)
7 
8 static const uint8_t fpdt_guid[16] = {
9 	0xfd, 0x7b, 0x38, 0x3b, 0xbc, 0x7a, 0xf2, 0x4c,
10 	0xa0, 0xca, 0xb6, 0xa1, 0x6c, 0x1b, 0x1b, 0x25,
11 };
12 
13 enum fpdt_record_type {
14 	FPDT_GUID_EVENT		= 0x1010,
15 	FPDT_STRING_EVENT	= 0x1011,
16 };
17 
18 struct perf_record_hdr {
19 	uint16_t	type;
20 	uint8_t		length;
21 	uint8_t		revision;
22 } __packed;
23 
24 struct generic_event_record {
25 	struct perf_record_hdr	header;
26 	uint16_t		progress_id;
27 	uint32_t		apic_id;
28 	uint64_t		timestamp;
29 	uint8_t			guid[16];
30 	uint8_t			string[];
31 } __packed;
32 
33 /*
34  * Performance HOB:
35  *   GUID - fpdt_guid;
36  *   Data - FPDT_PEI_EXT_PERF_HEADER one or more FPDT records
37 */
38 struct fpdt_pei_ext_perf_header {
39 	uint32_t	table_size;
40 	uint32_t	load_image_count;
41 	uint32_t	hob_is_full;
42 } __packed;
43 
print_guid_record(const struct generic_event_record * rec)44 static void print_guid_record(const struct generic_event_record *rec)
45 {
46 	printk(BIOS_INFO, "%5x\t%16llu\t\t", rec->progress_id, TIMESTAMP_TO_MICRO(rec->timestamp));
47 	fsp_print_guid(BIOS_INFO, rec->guid);
48 	printk(BIOS_INFO, "\n");
49 }
50 
print_string_record(const struct generic_event_record * rec)51 static void print_string_record(const struct generic_event_record *rec)
52 {
53 	size_t str_len = rec->header.length - offsetof(struct generic_event_record, string);
54 	printk(BIOS_INFO, "%5x\t%16llu\t\t%*s/",
55 	       rec->progress_id, TIMESTAMP_TO_MICRO(rec->timestamp), (int)str_len, rec->string);
56 	fsp_print_guid(BIOS_INFO, rec->guid);
57 	printk(BIOS_INFO, "\n");
58 }
59 
print_fsp_perf_timestamp(const struct generic_event_record * rec)60 static void print_fsp_perf_timestamp(const struct generic_event_record *rec)
61 {
62 	switch (rec->header.type) {
63 	case FPDT_GUID_EVENT:
64 		print_guid_record(rec);
65 		break;
66 	case FPDT_STRING_EVENT:
67 		print_string_record(rec);
68 		break;
69 	default:
70 		printk(BIOS_INFO, "Unhandled Event Type 0x%x\n", rec->header.type);
71 		break;
72 	}
73 }
74 
print_fsp_timestamp_header(void)75 static void print_fsp_timestamp_header(void)
76 {
77 	printk(BIOS_INFO, "+---------------------------------------------------+\n");
78 	printk(BIOS_INFO, "|------ FSP Performance Timestamp Table Dump -------|\n");
79 	printk(BIOS_INFO, "+---------------------------------------------------+\n");
80 	printk(BIOS_INFO, "| Perf-ID\tTimestamp(us)\t\tString/GUID |\n");
81 	printk(BIOS_INFO, "+---------------------------------------------------+\n");
82 }
83 
fsp_display_timestamp(void)84 void fsp_display_timestamp(void)
85 {
86 	size_t size;
87 	const struct fpdt_pei_ext_perf_header *hdr = fsp_find_extension_hob_by_guid(fpdt_guid,
88 							 &size);
89 
90 	if (!hdr || !size) {
91 		printk(BIOS_INFO, "FPDT Extended Firmware Performance HOB Not Found!\n"
92 		"Check if PcdFspPerformanceEnable is set to `TRUE` inside FSP package\n");
93 		return;
94 	}
95 
96 	const struct generic_event_record *rec = (const struct generic_event_record *)(
97 				(uint8_t *)hdr + sizeof(struct fpdt_pei_ext_perf_header));
98 
99 	print_fsp_timestamp_header();
100 	for (size_t i = 0; i < hdr->table_size;) {
101 		print_fsp_perf_timestamp(rec);
102 
103 		i += rec->header.length;
104 		rec = (const struct generic_event_record *)((uint8_t *)rec +
105 				 rec->header.length);
106 	}
107 }
108