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