blob: e090ebee013e18f97c77d2e49ae49263cf7aeab6 [file] [log] [blame]
Ricardo Quesadac2cf3942021-07-16 16:49:04 -07001/* SPDX-License-Identifier: BSD-3-Clause */
2
3#include "eventlog.h"
4
5#include <inttypes.h>
6#include <stdarg.h>
7#include <stdlib.h>
8#include <time.h>
9
10#include <commonlib/console/post_codes.h>
11#include <commonlib/bsd/elog.h>
12#include <vb2_api.h>
13
Ricardo Quesada49a96a92021-08-16 11:25:52 -070014#include "common.h"
Ricardo Quesadac2cf3942021-07-16 16:49:04 -070015#include "valstr.h"
16
17#define PATH_PCI_BUS_SHIFT 8
18#define PATH_PCI_BUS_MASK 0xff
19#define PATH_PCI_DEV_SHIFT 3
20#define PATH_PCI_DEV_MASK 0x1f
21#define PATH_PCI_FN_SHIFT 0
22#define PATH_PCI_FN_MASK 0x03
23#define PATH_I2C_MODE10BIT_SHIFT 8
24#define PATH_I2C_MODE10BIT_MASK 0xff
25#define PATH_I2C_ADDRESS_MASK 0xff
26
27/* When true, then the separator is not printed */
28static int eventlog_printf_ignore_separator_once = 1;
29
30static void eventlog_printf(const char *format, ...)
31{
32 va_list args;
33
34 // Separator for each field
35 if (eventlog_printf_ignore_separator_once)
36 eventlog_printf_ignore_separator_once = 0;
37 else
38 fprintf(stdout, " | ");
39
40 va_start(args, format);
41 vfprintf(stdout, format, args);
42 va_end(args);
43}
44
45/*
46 * eventlog_print_timestamp - forms the key-value pair for event timestamp
47 *
48 * @entry: the smbios log entry to get the data information
49 *
50 * Forms the key-value description pair for the event timestamp.
51 */
Wojciech Macek9edaccd2023-02-23 09:33:06 +010052static void eventlog_print_timestamp(const struct event_header *event,
53 enum eventlog_timezone tz)
Ricardo Quesadac2cf3942021-07-16 16:49:04 -070054{
55 const char *tm_format = "%y-%m-%d%t%H:%M:%S";
56 char tm_string[40];
Wojciech Macek9edaccd2023-02-23 09:33:06 +010057 struct tm *tmptr;
Ricardo Quesadac2cf3942021-07-16 16:49:04 -070058 struct tm tm;
59 time_t time;
60
61 memset(&tm, 0, sizeof(tm));
62
63 /* Time is in "hexa". Convert it to decimal, and then convert it to "tm" struct */
64 snprintf(tm_string, sizeof(tm_string), "%02x-%02x-%02x %02x:%02x:%02x", event->year,
65 event->month, event->day, event->hour, event->minute, event->second);
66
67 if (strptime(tm_string, tm_format, &tm) == NULL) {
68 /* Backup in case string could not be parsed. Timezone not included */
69 eventlog_printf("%02d%02x-%02x-%02x %02x:%02x:%02x",
70 (event->year > 0x80 && event->year < 0x99) ? 19 : 20,
71 event->year, event->month, event->day, event->hour,
72 event->minute, event->second);
73 return;
74 }
75
76 /* Set DST flag to -1 to indicate "not available" and let
77 * system determine if DST is on based on date */
78 tm.tm_isdst = -1;
79
80 time = mktime(&tm);
81 time += tm.tm_gmtoff; /* force adjust for timezone */
82
Wojciech Macek9edaccd2023-02-23 09:33:06 +010083 if (tz == EVENTLOG_TIMEZONE_UTC)
84 tmptr = gmtime(&time);
85 else
86 tmptr = localtime(&time);
87 strftime(tm_string, sizeof(tm_string), "%Y-%m-%d %H:%M:%S%z", tmptr);
Ricardo Quesadac2cf3942021-07-16 16:49:04 -070088
89 eventlog_printf("%s", tm_string);
90}
91
92
93/*
94 * eventlog_print_type - print the type of the entry
95 *
96 * @entry: the smbios log entry to get type information
97 *
98 */
99static void eventlog_print_type(const struct event_header *event)
100{
101 const char *type;
102 static const struct valstr elog_event_types[] = {
103 /* SMBIOS Event Log types, SMBIOSv2.4 section 3.3.16.1 */
104 {ELOG_TYPE_UNDEFINED_EVENT, "Reserved"},
105 {ELOG_TYPE_SINGLE_BIT_ECC_MEM_ERR, "Single-bit ECC memory error"},
106 {ELOG_TYPE_MULTI_BIT_ECC_MEM_ERR, "Multi-bit ECC memory error"},
107 {ELOG_TYPE_MEM_PARITY_ERR, "Parity memory error"},
108 {ELOG_TYPE_BUS_TIMEOUT, "Bus timeout"},
109 {ELOG_TYPE_IO_CHECK, "I/O channel check"},
110 {ELOG_TYPE_SW_NMI, "Software NMI"},
111 {ELOG_TYPE_POST_MEM_RESIZE, "POST memory resize"},
112 {ELOG_TYPE_POST_ERR, "POST error"},
113 {ELOG_TYPE_PCI_PERR, "PCI parity error"},
114 {ELOG_TYPE_PCI_SERR, "PCI system error"},
115 {ELOG_TYPE_CPU_FAIL, "CPU failure"},
116 {ELOG_TYPE_EISA_TIMEOUT, "EISA failsafe timer timeout"},
117 {ELOG_TYPE_CORRECTABLE_MEMLOG_DIS, "Correctable memory log disabled"},
118 {ELOG_TYPE_LOG_DISABLED, "Logging disabled, too many errors"},
119 {ELOG_TYPE_UNDEFINED_EVENT2, "Reserved"},
120 {ELOG_TYPE_SYS_LIMIT_EXCEED, "System limit exceeded"},
121 {ELOG_TYPE_ASYNC_HW_TIMER_EXPIRED, "Hardware watchdog reset"},
122 {ELOG_TYPE_SYS_CONFIG_INFO, "System configuration information"},
123 {ELOG_TYPE_HDD_INFO, "Hard-disk information"},
124 {ELOG_TYPE_SYS_RECONFIG, "System reconfigured"},
125 {ELOG_TYPE_CPU_ERROR, "Uncorrectable CPU-complex error"},
126 {ELOG_TYPE_LOG_CLEAR, "Log area cleared"},
127 {ELOG_TYPE_BOOT, "System boot"},
128
129 /* Extended events defined by OEMs */
130 {ELOG_TYPE_OS_EVENT, "Kernel Event"},
131 {ELOG_TYPE_OS_BOOT, "OS Boot"},
132 {ELOG_TYPE_EC_EVENT, "EC Event"},
133 {ELOG_TYPE_POWER_FAIL, "Power Fail"},
134 {ELOG_TYPE_SUS_POWER_FAIL, "SUS Power Fail"},
135 {ELOG_TYPE_PWROK_FAIL, "PWROK Fail"},
136 {ELOG_TYPE_SYS_PWROK_FAIL, "SYS PWROK Fail"},
137 {ELOG_TYPE_POWER_ON, "Power On"},
138 {ELOG_TYPE_POWER_BUTTON, "Power Button"},
139 {ELOG_TYPE_POWER_BUTTON_OVERRIDE, "Power Button Override"},
140 {ELOG_TYPE_RESET_BUTTON, "Reset Button"},
141 {ELOG_TYPE_SYSTEM_RESET, "System Reset"},
142 {ELOG_TYPE_RTC_RESET, "RTC Reset"},
143 {ELOG_TYPE_TCO_RESET, "TCO Reset"},
144 {ELOG_TYPE_ACPI_ENTER, "ACPI Enter"},
145 {ELOG_TYPE_ACPI_WAKE, "ACPI Wake"},
146 {ELOG_TYPE_ACPI_DEEP_WAKE, "ACPI Wake"},
147 {ELOG_TYPE_S0IX_ENTER, "S0ix Enter"},
148 {ELOG_TYPE_S0IX_EXIT, "S0ix Exit"},
149 {ELOG_TYPE_WAKE_SOURCE, "Wake Source"},
Subrata Banik151dcf42022-08-02 11:42:49 +0000150 {ELOG_DEPRECATED_TYPE_CROS_DEVELOPER_MODE, "ChromeOS Developer Mode"},
151 {ELOG_DEPRECATED_TYPE_CROS_RECOVERY_MODE, "ChromeOS Recovery Mode"},
Ricardo Quesadac2cf3942021-07-16 16:49:04 -0700152 {ELOG_TYPE_MANAGEMENT_ENGINE, "Management Engine"},
153 {ELOG_TYPE_MANAGEMENT_ENGINE_EXT, "Management Engine Extra"},
154 {ELOG_TYPE_LAST_POST_CODE, "Last post code in previous boot"},
155 {ELOG_TYPE_POST_EXTRA, "Extra info from previous boot"},
156 {ELOG_TYPE_EC_SHUTDOWN, "EC Shutdown"},
157 {ELOG_TYPE_SLEEP, "Sleep"},
158 {ELOG_TYPE_WAKE, "Wake"},
159 {ELOG_TYPE_FW_WAKE, "FW Wake"},
160 {ELOG_TYPE_MEM_CACHE_UPDATE, "Memory Cache Update"},
161 {ELOG_TYPE_THERM_TRIP, "CPU Thermal Trip"},
162 {ELOG_TYPE_CR50_UPDATE, "cr50 Update Reset"},
163 {ELOG_TYPE_CR50_NEED_RESET, "cr50 Reset Required"},
164 {ELOG_TYPE_EC_DEVICE_EVENT, "EC Device"},
165 {ELOG_TYPE_EXTENDED_EVENT, "Extended Event"},
Hsuan Ting Chenfec16a32022-09-26 19:37:11 +0800166 {ELOG_TYPE_CROS_DIAGNOSTICS, "Diagnostics Mode"},
Subrata Banik8b468402022-07-17 18:20:24 +0530167 {ELOG_TYPE_FW_VBOOT_INFO, "Firmware vboot info"},
Tarun Tuli5044dc42023-01-31 18:24:38 +0000168 {ELOG_TYPE_FW_EARLY_SOL, "Early Sign of Life"},
Krishna Prasad Bhat93be5d5d2023-08-07 10:24:37 +0530169 {ELOG_TYPE_PSR_DATA_BACKUP, "PSR data backup"},
170 {ELOG_TYPE_PSR_DATA_LOST, "PSR data lost"},
Subrata Banik1cfb2862023-08-27 21:03:43 +0000171 {ELOG_TYPE_FW_SPLASH_SCREEN, "Firmware Splash Screen"},
Ricardo Quesadac2cf3942021-07-16 16:49:04 -0700172 {ELOG_TYPE_EOL, "End of log"},
173 };
174
175 /* Passing NULL as default, because we want to print the event->type if it fails */
176 type = val2str_default(event->type, elog_event_types, NULL);
177
178 if (type == NULL) {
179 /* Indicate unknown type in value pair */
180 eventlog_printf("Unknown");
181 eventlog_printf("0x%02x", event->type);
182 return;
183 }
184
185 eventlog_printf("%s", type);
186}
187
188/*
189 * CMOS Extra log format:
190 * [31:24] = Extra Log Type
191 * [23:0] = Extra Log Data
192 *
193 * If Extra Log Type is 0x01 then Data is Device Path
194 * [23:16] = Device Type
195 * [15:0] = Encoded Device Path
196 */
197static int eventlog_print_post_extra(uint32_t extra)
198{
199 static const struct valstr path_type_values[] = {
200 {ELOG_DEV_PATH_TYPE_NONE, "None"},
201 {ELOG_DEV_PATH_TYPE_ROOT, "Root"},
202 {ELOG_DEV_PATH_TYPE_PCI, "PCI"},
203 {ELOG_DEV_PATH_TYPE_PNP, "PNP"},
204 {ELOG_DEV_PATH_TYPE_I2C, "I2C"},
205 {ELOG_DEV_PATH_TYPE_APIC, "APIC"},
206 {ELOG_DEV_PATH_TYPE_DOMAIN, "DOMAIN"},
207 {ELOG_DEV_PATH_TYPE_CPU_CLUSTER, "CPU Cluster"},
208 {ELOG_DEV_PATH_TYPE_CPU, "CPU"},
209 {ELOG_DEV_PATH_TYPE_CPU_BUS, "CPU Bus"},
210 {ELOG_DEV_PATH_TYPE_IOAPIC, "IO-APIC"},
211 {0, NULL},
212 };
213 const uint8_t type = (extra >> 16) & 0xff;
214
215 /* Currently only know how to print device path */
216 if ((extra >> 24) != ELOG_TYPE_POST_EXTRA_PATH) {
217 eventlog_printf("0x%08x", extra);
218 return 0;
219 }
220
221 eventlog_printf("%s", val2str(type, path_type_values));
222
223 /* Handle different device path types */
224 switch (type) {
225 case ELOG_DEV_PATH_TYPE_PCI:
226 eventlog_printf("%02x:%02x.%1x",
227 (extra >> PATH_PCI_BUS_SHIFT) & PATH_PCI_BUS_MASK,
228 (extra >> PATH_PCI_DEV_SHIFT) & PATH_PCI_DEV_MASK,
229 (extra >> PATH_PCI_FN_SHIFT) & PATH_PCI_FN_MASK);
230 break;
231 case ELOG_DEV_PATH_TYPE_PNP:
232 case ELOG_DEV_PATH_TYPE_I2C:
233 eventlog_printf("%02x:%02x",
234 (extra >> PATH_I2C_MODE10BIT_SHIFT) & PATH_I2C_MODE10BIT_MASK,
235 extra & PATH_I2C_ADDRESS_MASK);
236 break;
237 case ELOG_DEV_PATH_TYPE_APIC:
238 case ELOG_DEV_PATH_TYPE_DOMAIN:
239 case ELOG_DEV_PATH_TYPE_CPU_CLUSTER:
240 case ELOG_DEV_PATH_TYPE_CPU:
241 case ELOG_DEV_PATH_TYPE_CPU_BUS:
242 case ELOG_DEV_PATH_TYPE_IOAPIC:
243 eventlog_printf("0x%04x", extra & 0xffff);
244 break;
245 }
246
247 return 0;
248}
249
250/*
251 * eventlog_print_data - print the data associated with the entry
252 *
253 * @event: the smbios log entry to get the data information
254 *
255 * Returns 0 on failure, 1 on success.
256 */
257static int eventlog_print_data(const struct event_header *event)
258{
259 static const struct valstr os_events[] = {
260 {ELOG_OS_EVENT_CLEAN, "Clean Shutdown"},
261 {ELOG_OS_EVENT_NMIWDT, "NMI Watchdog"},
262 {ELOG_OS_EVENT_PANIC, "Panic"},
263 {ELOG_OS_EVENT_OOPS, "Oops"},
264 {ELOG_OS_EVENT_DIE, "Die"},
265 {ELOG_OS_EVENT_MCE, "MCE"},
266 {ELOG_OS_EVENT_SOFTWDT, "Software Watchdog"},
267 {ELOG_OS_EVENT_MBE, "Multi-bit Error"},
268 {ELOG_OS_EVENT_TRIPLE, "Triple Fault"},
269 {ELOG_OS_EVENT_THERMAL, "Critical Thermal Threshold"},
270 {0, NULL},
271 };
272 static const struct valstr wake_source_types[] = {
273 {ELOG_WAKE_SOURCE_PCIE, "PCI Express"},
274 {ELOG_WAKE_SOURCE_PME, "PCI PME"},
275 {ELOG_WAKE_SOURCE_PME_INTERNAL, "Internal PME"},
276 {ELOG_WAKE_SOURCE_RTC, "RTC Alarm"},
277 {ELOG_WAKE_SOURCE_GPE, "GPE #"},
278 {ELOG_WAKE_SOURCE_SMBUS, "SMBALERT"},
279 {ELOG_WAKE_SOURCE_PWRBTN, "Power Button"},
280 {ELOG_WAKE_SOURCE_PME_HDA, "PME - HDA"},
281 {ELOG_WAKE_SOURCE_PME_GBE, "PME - GBE"},
282 {ELOG_WAKE_SOURCE_PME_EMMC, "PME - EMMC"},
283 {ELOG_WAKE_SOURCE_PME_SDCARD, "PME - SDCARD"},
284 {ELOG_WAKE_SOURCE_PME_PCIE1, "PME - PCIE1"},
285 {ELOG_WAKE_SOURCE_PME_PCIE2, "PME - PCIE2"},
286 {ELOG_WAKE_SOURCE_PME_PCIE3, "PME - PCIE3"},
287 {ELOG_WAKE_SOURCE_PME_PCIE4, "PME - PCIE4"},
288 {ELOG_WAKE_SOURCE_PME_PCIE5, "PME - PCIE5"},
289 {ELOG_WAKE_SOURCE_PME_PCIE6, "PME - PCIE6"},
290 {ELOG_WAKE_SOURCE_PME_PCIE7, "PME - PCIE7"},
291 {ELOG_WAKE_SOURCE_PME_PCIE8, "PME - PCIE8"},
292 {ELOG_WAKE_SOURCE_PME_PCIE9, "PME - PCIE9"},
293 {ELOG_WAKE_SOURCE_PME_PCIE10, "PME - PCIE10"},
294 {ELOG_WAKE_SOURCE_PME_PCIE11, "PME - PCIE11"},
295 {ELOG_WAKE_SOURCE_PME_PCIE12, "PME - PCIE12"},
296 {ELOG_WAKE_SOURCE_PME_SATA, "PME - SATA"},
297 {ELOG_WAKE_SOURCE_PME_CSE, "PME - CSE"},
298 {ELOG_WAKE_SOURCE_PME_CSE2, "PME - CSE2"},
299 {ELOG_WAKE_SOURCE_PME_CSE3, "PME - CSE"},
300 {ELOG_WAKE_SOURCE_PME_XHCI, "PME - XHCI"},
301 {ELOG_WAKE_SOURCE_PME_XDCI, "PME - XDCI"},
302 {ELOG_WAKE_SOURCE_PME_XHCI_USB_2, "PME - XHCI (USB 2.0 port)"},
303 {ELOG_WAKE_SOURCE_PME_XHCI_USB_3, "PME - XHCI (USB 3.0 port)"},
304 {ELOG_WAKE_SOURCE_PME_WIFI, "PME - WIFI"},
305 {ELOG_WAKE_SOURCE_PME_PCIE13, "PME - PCIE13"},
306 {ELOG_WAKE_SOURCE_PME_PCIE14, "PME - PCIE14"},
307 {ELOG_WAKE_SOURCE_PME_PCIE15, "PME - PCIE15"},
308 {ELOG_WAKE_SOURCE_PME_PCIE16, "PME - PCIE16"},
309 {ELOG_WAKE_SOURCE_PME_PCIE17, "PME - PCIE17"},
310 {ELOG_WAKE_SOURCE_PME_PCIE18, "PME - PCIE18"},
311 {ELOG_WAKE_SOURCE_PME_PCIE19, "PME - PCIE19"},
312 {ELOG_WAKE_SOURCE_PME_PCIE20, "PME - PCIE20"},
313 {ELOG_WAKE_SOURCE_PME_PCIE21, "PME - PCIE21"},
314 {ELOG_WAKE_SOURCE_PME_PCIE22, "PME - PCIE22"},
315 {ELOG_WAKE_SOURCE_PME_PCIE23, "PME - PCIE23"},
316 {ELOG_WAKE_SOURCE_PME_PCIE24, "PME - PCIE24"},
317 {ELOG_WAKE_SOURCE_GPIO, " GPIO #"},
318 {ELOG_WAKE_SOURCE_PME_TBT, "PME - Thunderbolt"},
319 {ELOG_WAKE_SOURCE_PME_TCSS_XHCI, "PME - TCSS XHCI"},
320 {ELOG_WAKE_SOURCE_PME_TCSS_XHCI, "PME - TCSS XDCI"},
321 {ELOG_WAKE_SOURCE_PME_TCSS_XHCI, "PME - TCSS DMA"},
322 {0, NULL},
323 };
324 static const struct valstr ec_event_types[] = {
325 {EC_EVENT_LID_CLOSED, "Lid Closed"},
326 {EC_EVENT_LID_OPEN, "Lid Open"},
327 {EC_EVENT_POWER_BUTTON, "Power Button"},
328 {EC_EVENT_AC_CONNECTED, "AC Connected"},
329 {EC_EVENT_AC_DISCONNECTED, "AC Disconnected"},
330 {EC_EVENT_BATTERY_LOW, "Battery Low"},
331 {EC_EVENT_BATTERY_CRITICAL, "Battery Critical"},
332 {EC_EVENT_BATTERY, "Battery"},
333 {EC_EVENT_THERMAL_THRESHOLD, "Thermal Threshold"},
334 {EC_EVENT_DEVICE_EVENT, "Device Event"},
335 {EC_EVENT_THERMAL, "Thermal"},
336 {EC_EVENT_USB_CHARGER, "USB Charger"},
337 {EC_EVENT_KEY_PRESSED, "Key Pressed"},
338 {EC_EVENT_INTERFACE_READY, "Host Interface Ready"},
339 {EC_EVENT_KEYBOARD_RECOVERY, "Keyboard Recovery"},
340 {EC_EVENT_THERMAL_SHUTDOWN, "Thermal Shutdown in previous boot"},
341 {EC_EVENT_BATTERY_SHUTDOWN, "Battery Shutdown in previous boot"},
342 {EC_EVENT_THROTTLE_START, "Throttle Requested"},
343 {EC_EVENT_THROTTLE_STOP, "Throttle Request Removed"},
344 {EC_EVENT_HANG_DETECT, "Host Event Hang"},
345 {EC_EVENT_HANG_REBOOT, "Host Event Hang Reboot"},
346 {EC_EVENT_PD_MCU, "PD MCU Request"},
347 {EC_EVENT_BATTERY_STATUS, "Battery Status Request"},
348 {EC_EVENT_PANIC, "Panic Reset in previous boot"},
349 {EC_EVENT_KEYBOARD_FASTBOOT, "Keyboard Fastboot Recovery"},
350 {EC_EVENT_RTC, "RTC"},
351 {EC_EVENT_MKBP, "MKBP"},
352 {EC_EVENT_USB_MUX, "USB MUX change"},
353 {EC_EVENT_MODE_CHANGE, "Mode change"},
354 {EC_EVENT_KEYBOARD_RECOVERY_HWREINIT,
355 "Keyboard Recovery Forced Hardware Reinit"},
356 {EC_EVENT_EXTENDED, "Extended EC events"},
357 {0, NULL},
358 };
359 static const struct valstr ec_device_event_types[] = {
360 {ELOG_EC_DEVICE_EVENT_TRACKPAD, "Trackpad"},
361 {ELOG_EC_DEVICE_EVENT_DSP, "DSP"},
362 {ELOG_EC_DEVICE_EVENT_WIFI, "WiFi"},
363 {0, NULL},
364 };
Ricardo Quesadac2cf3942021-07-16 16:49:04 -0700365 static const struct valstr me_path_types[] = {
366 {ELOG_ME_PATH_NORMAL, "Normal"},
367 {ELOG_ME_PATH_NORMAL, "S3 Wake"},
368 {ELOG_ME_PATH_ERROR, "Error"},
369 {ELOG_ME_PATH_RECOVERY, "Recovery"},
370 {ELOG_ME_PATH_DISABLED, "Disabled"},
371 {ELOG_ME_PATH_FW_UPDATE, "Firmware Update"},
372 {0, NULL},
373 };
374 static const struct valstr coreboot_post_codes[] = {
lilacious40cb3fe2023-06-21 23:24:14 +0200375 {POSTCODE_RESET_VECTOR_CORRECT, "Reset Vector Correct"},
376 {POSTCODE_ENTER_PROTECTED_MODE, "Enter Protected Mode"},
377 {POSTCODE_PREPARE_RAMSTAGE, "Prepare RAM stage"},
378 {POSTCODE_ENTRY_C_START, "RAM stage Start"},
379 {POSTCODE_MEM_PREINIT_PREP_START, "Preparing memory init params"},
380 {POSTCODE_MEM_PREINIT_PREP_END, "Memory init param preparation complete"},
381 {POSTCODE_CONSOLE_READY, "Console is ready"},
382 {POSTCODE_CONSOLE_BOOT_MSG, "Console Boot Message"},
383 {POSTCODE_ENABLING_CACHE, "Before Enabling Cache"},
384 {POSTCODE_PRE_HARDWAREMAIN, "Before Hardware Main"},
385 {POSTCODE_ENTRY_HARDWAREMAIN, "First call in Hardware Main"},
386 {POSTCODE_BS_PRE_DEVICE, "Before Device Probe"},
387 {POSTCODE_BS_DEV_INIT_CHIPS, "Initialize Chips"},
388 {POSTCODE_BS_DEV_ENUMERATE, "Device Enumerate"},
389 {POSTCODE_BS_DEV_RESOURCES, "Device Resource Allocation"},
390 {POSTCODE_BS_DEV_ENABLE, "Device Enable"},
391 {POSTCODE_BS_DEV_INIT, "Device Initialize"},
392 {POSTCODE_BS_POST_DEVICE, "After Device Probe"},
393 {POSTCODE_BS_OS_RESUME_CHECK, "OS Resume Check"},
394 {POSTCODE_BS_OS_RESUME, "OS Resume"},
395 {POSTCODE_BS_WRITE_TABLES, "Write Tables"},
396 {POSTCODE_BS_PAYLOAD_LOAD, "Load Payload"},
397 {POSTCODE_BS_PAYLOAD_BOOT, "Boot Payload"},
398 {POSTCODE_FSP_NOTIFY_BEFORE_END_OF_FIRMWARE, "FSP Notify Before End of Firmware"},
399 {POSTCODE_FSP_NOTIFY_AFTER_END_OF_FIRMWARE, "FSP Notify After End of Firmware"},
400 {POSTCODE_FSP_TEMP_RAM_INIT, "FSP-T Enter"},
401 {POSTCODE_FSP_TEMP_RAM_EXIT, "FSP-T Exit"},
402 {POSTCODE_FSP_MEMORY_INIT, "FSP-M Enter"},
403 {POSTCODE_FSP_SILICON_INIT, "FSP-S Enter"},
404 {POSTCODE_FSP_NOTIFY_BEFORE_ENUMERATE, "FSP Notify Before Enumerate"},
405 {POSTCODE_FSP_NOTIFY_BEFORE_FINALIZE, "FSP Notify Before Finalize"},
406 {POSTCODE_OS_ENTER_PTS, "ACPI _PTS Method"},
407 {POSTCODE_OS_ENTER_WAKE, "ACPI _WAK Method"},
408 {POSTCODE_FSP_MEMORY_EXIT, "FSP-M Exit"},
409 {POSTCODE_FSP_SILICON_EXIT, "FSP-S Exit"},
410 {POSTCODE_FSP_MULTI_PHASE_SI_INIT_ENTRY, "FSP-S Init Enter"},
411 {POSTCODE_FSP_MULTI_PHASE_SI_INIT_EXIT, "FPS-S Init Exit"},
412 {POSTCODE_FSP_NOTIFY_AFTER_ENUMERATE, "FSP Notify After Enumerate"},
413 {POSTCODE_FSP_NOTIFY_AFTER_FINALIZE, "FSP Notify After Finalize"},
Jeremy Compostella1879b6a2024-01-30 12:44:54 -0800414 {POSTCODE_FSP_MULTI_PHASE_MEM_INIT_ENTRY, "FSP-M Init Enter"},
415 {POSTCODE_FSP_MULTI_PHASE_MEM_INIT_EXIT, "FPS-M Init Exit"},
lilacious40cb3fe2023-06-21 23:24:14 +0200416 {POSTCODE_INVALID_ROM, "Invalid ROM"},
417 {POSTCODE_INVALID_CBFS, "Invalid CBFS"},
418 {POSTCODE_INVALID_VENDOR_BINARY, "Invalid Vendor Binary"},
419 {POSTCODE_RAM_FAILURE, "RAM Failure"},
420 {POSTCODE_HW_INIT_FAILURE, "Hardware Init Failure"},
421 {POSTCODE_VIDEO_FAILURE, "Video Failure"},
422 {POSTCODE_TPM_FAILURE, "TPM Failure"},
423 {POSTCODE_DEAD_CODE, "Dead Code"},
424 {POSTCODE_RESUME_FAILURE, "Resume Failure"},
425 {POSTCODE_JUMPING_TO_PAYLOAD, "Before Jump to Payload"},
426 {POSTCODE_ENTER_ELF_BOOT, "Before ELF Boot"},
427 {POSTCODE_OS_RESUME, "Before OS Resume"},
428 {POSTCODE_OS_BOOT, "Before OS Boot"},
429 {POSTCODE_DIE, "coreboot Dead"},
Ricardo Quesadac2cf3942021-07-16 16:49:04 -0700430 {0, NULL},
431 };
432 static const struct valstr mem_cache_slots[] = {
433 {ELOG_MEM_CACHE_UPDATE_SLOT_NORMAL, "Normal"},
434 {ELOG_MEM_CACHE_UPDATE_SLOT_RECOVERY, "Recovery"},
435 {ELOG_MEM_CACHE_UPDATE_SLOT_VARIABLE, "Variable"},
436 {0, NULL},
437 };
438 static const struct valstr mem_cache_statuses[] = {
439 {ELOG_MEM_CACHE_UPDATE_STATUS_SUCCESS, "Success"},
440 {ELOG_MEM_CACHE_UPDATE_STATUS_FAIL, "Fail"},
441 {0, NULL},
442 };
443
444 static const struct valstr extended_event_subtypes[] = {
445 {ELOG_SLEEP_PENDING_PM1_WAKE, "S3 failed due to pending wake event, PM1"},
446 {ELOG_SLEEP_PENDING_GPE0_WAKE, "S3 failed due to pending wake event, GPE0"},
447 {0, NULL},
448 };
449
Hsuan Ting Chenfec16a32022-09-26 19:37:11 +0800450 static const struct valstr cros_diagnostics_types[] = {
Subrata Banik151dcf42022-08-02 11:42:49 +0000451 {ELOG_DEPRECATED_CROS_LAUNCH_DIAGNOSTICS, "Launch Diagnostics"},
Hsuan Ting Chenfec16a32022-09-26 19:37:11 +0800452 {ELOG_CROS_DIAGNOSTICS_LOGS, "Diagnostics Logs"},
453 {0, NULL},
454 };
455
456 static const struct valstr cros_diagnostics_diag_types[] = {
457 {ELOG_CROS_DIAG_TYPE_NONE, "None"},
Hsuan Ting Chen5faaca02022-10-31 17:41:32 +0800458 {ELOG_CROS_DIAG_TYPE_STORAGE_HEALTH, "Storage health info"},
Hsuan Ting Chenfec16a32022-09-26 19:37:11 +0800459 {ELOG_CROS_DIAG_TYPE_STORAGE_TEST_SHORT, "Storage self-test (short)"},
460 {ELOG_CROS_DIAG_TYPE_STORAGE_TEST_EXTENDED, "Storage self-test (extended)"},
461 {ELOG_CROS_DIAG_TYPE_MEMORY_QUICK, "Memory check (quick)"},
462 {ELOG_CROS_DIAG_TYPE_MEMORY_FULL, "Memory check (full)"},
463 {0, NULL},
464 };
465
466 static const struct valstr cros_diagnostics_diag_results[] = {
467 {ELOG_CROS_DIAG_RESULT_PASSED, "Passed"},
468 {ELOG_CROS_DIAG_RESULT_ERROR, "Error"},
469 {ELOG_CROS_DIAG_RESULT_FAILED, "Failed"},
470 {ELOG_CROS_DIAG_RESULT_ABORTED, "Aborted"},
Hsuan Ting Chena5cbe272021-11-01 19:14:01 +0800471 {0, NULL},
472 };
473
Tarun Tuli5044dc42023-01-31 18:24:38 +0000474 static const struct valstr early_sol_path_types[] = {
475 {ELOG_FW_EARLY_SOL_CSE_SYNC, "CSE Sync Early SOL Screen Shown"},
476 {ELOG_FW_EARLY_SOL_MRC, "MRC Early SOL Screen Shown"},
477 {0, NULL},
478 };
479
Krishna Prasad Bhat93be5d5d2023-08-07 10:24:37 +0530480 static const struct valstr psr_data_backup_statuses[] = {
481 {ELOG_PSR_DATA_BACKUP_SUCCESS, "Success"},
482 {ELOG_PSR_DATA_BACKUP_FAILED, "Fail"},
483 {0, NULL},
484 };
485
Kapil Porwal0b6954b2023-01-20 01:00:42 +0530486 size_t elog_type_to_min_size[] = {
487 [ELOG_TYPE_LOG_CLEAR] = sizeof(uint16_t),
488 [ELOG_TYPE_BOOT] = sizeof(uint32_t),
489 [ELOG_TYPE_LAST_POST_CODE] = sizeof(uint16_t),
490 [ELOG_TYPE_POST_EXTRA] = sizeof(uint32_t),
491 [ELOG_TYPE_OS_EVENT] = sizeof(uint32_t),
492 [ELOG_TYPE_ACPI_ENTER] = sizeof(uint8_t),
493 [ELOG_TYPE_ACPI_WAKE] = sizeof(uint8_t),
494 [ELOG_TYPE_ACPI_DEEP_WAKE] = sizeof(uint8_t),
495 [ELOG_TYPE_WAKE_SOURCE] = sizeof(struct elog_event_data_wake),
496 [ELOG_TYPE_EC_EVENT] = sizeof(uint8_t),
497 [ELOG_TYPE_EC_DEVICE_EVENT] = sizeof(uint8_t),
498 [ELOG_DEPRECATED_TYPE_CROS_RECOVERY_MODE] = sizeof(uint8_t),
499 [ELOG_TYPE_MANAGEMENT_ENGINE] = sizeof(uint8_t),
500 [ELOG_TYPE_MEM_CACHE_UPDATE] = sizeof(struct elog_event_mem_cache_update),
501 [ELOG_TYPE_EXTENDED_EVENT] = sizeof(struct elog_event_extended_event),
502 [ELOG_TYPE_CROS_DIAGNOSTICS] = sizeof(uint8_t),
503 [ELOG_TYPE_FW_VBOOT_INFO] = sizeof(uint16_t),
Tarun Tuli5044dc42023-01-31 18:24:38 +0000504 [ELOG_TYPE_FW_EARLY_SOL] = sizeof(uint8_t),
Krishna Prasad Bhat93be5d5d2023-08-07 10:24:37 +0530505 [ELOG_TYPE_PSR_DATA_BACKUP] = sizeof(uint8_t),
Subrata Banik1cfb2862023-08-27 21:03:43 +0000506 [ELOG_TYPE_FW_SPLASH_SCREEN] = sizeof(uint8_t),
Kapil Porwal0b6954b2023-01-20 01:00:42 +0530507 [0xff] = 0,
508 };
509
510 if (event->length <= sizeof(*event) + elog_type_to_min_size[event->type]) {
511 eventlog_printf("INVALID DATA (length = %u)", event->length - sizeof(*event));
512 return 0;
513 }
514
Ricardo Quesadac2cf3942021-07-16 16:49:04 -0700515 switch (event->type) {
516 case ELOG_TYPE_LOG_CLEAR: {
517 const uint16_t *bytes = event_get_data(event);
518 eventlog_printf("%u", *bytes);
519 break;
520 }
521
522 case ELOG_TYPE_BOOT: {
523 const uint32_t *count = event_get_data(event);
524 eventlog_printf("%u", *count);
525 break;
526 }
527 case ELOG_TYPE_LAST_POST_CODE: {
528 const uint16_t *code = event_get_data(event);
529 eventlog_printf("0x%02x", *code);
530 eventlog_printf("%s", val2str(*code, coreboot_post_codes));
531 break;
532 }
533 case ELOG_TYPE_POST_EXTRA: {
534 const uint32_t *extra = event_get_data(event);
535 eventlog_print_post_extra(*extra);
536 break;
537 }
538 case ELOG_TYPE_OS_EVENT: {
539 const uint32_t *osevent = event_get_data(event);
540 eventlog_printf("%s", val2str(*osevent, os_events));
541 break;
542 }
543 case ELOG_TYPE_ACPI_ENTER:
544 case ELOG_TYPE_ACPI_WAKE: {
545 const uint8_t *state = event_get_data(event);
546 eventlog_printf("S%u", *state);
547 break;
548 }
549 case ELOG_TYPE_ACPI_DEEP_WAKE: {
550 const uint8_t *state = event_get_data(event);
551 eventlog_printf("Deep S%u", *state);
552 break;
553 }
554 case ELOG_TYPE_WAKE_SOURCE: {
555 const struct elog_event_data_wake *wake_source;
556 wake_source = event_get_data(event);
557 eventlog_printf("%s", val2str(wake_source->source, wake_source_types));
558 eventlog_printf("%u", wake_source->instance);
559 break;
560 }
561 case ELOG_TYPE_EC_EVENT: {
562 const uint8_t *ec_event = event_get_data(event);
563 eventlog_printf("%s", val2str(*ec_event, ec_event_types));
564 break;
565 }
566 case ELOG_TYPE_EC_DEVICE_EVENT: {
567 const uint8_t *dev_event = event_get_data(event);
568 eventlog_printf("%s", val2str(*dev_event, ec_device_event_types));
569 break;
570 }
Subrata Banik151dcf42022-08-02 11:42:49 +0000571 case ELOG_DEPRECATED_TYPE_CROS_RECOVERY_MODE: {
Ricardo Quesadac2cf3942021-07-16 16:49:04 -0700572 const uint8_t *reason = event_get_data(event);
Subrata Banik151dcf42022-08-02 11:42:49 +0000573 eventlog_printf("%s", vb2_get_recovery_reason_string(*reason));
Ricardo Quesadac2cf3942021-07-16 16:49:04 -0700574 eventlog_printf("0x%02x", *reason);
575 break;
576 }
577 case ELOG_TYPE_MANAGEMENT_ENGINE: {
578 const uint8_t *path = event_get_data(event);
579 eventlog_printf("%s", val2str(*path, me_path_types));
580 break;
581 }
582 case ELOG_TYPE_MEM_CACHE_UPDATE: {
583 const struct elog_event_mem_cache_update *update;
584 update = event_get_data(event);
585 eventlog_printf("%s", val2str(update->slot, mem_cache_slots));
586 eventlog_printf("%s", val2str(update->status, mem_cache_statuses));
587 break;
588 }
589 case ELOG_TYPE_EXTENDED_EVENT: {
590 const struct elog_event_extended_event *ext_event;
591 ext_event = event_get_data(event);
592 eventlog_printf("%s", val2str(ext_event->event_type, extended_event_subtypes));
593 eventlog_printf("0x%X", ext_event->event_complement);
594 break;
595 }
Hsuan Ting Chenfec16a32022-09-26 19:37:11 +0800596 case ELOG_TYPE_CROS_DIAGNOSTICS: {
597 const uint8_t *data = event_get_data(event);
598 const uint8_t subtype = *data;
599 eventlog_printf("%s", val2str(subtype, cros_diagnostics_types));
600
601 /*
602 * If the subtype is diagnostics logs, there will be many
603 * elog_event_diag_log events after subtype:
604 *
605 * [event_header][(subtype)(log 1)(log 2)...(log n)][checksum]
606 *
607 * Parse them one by one.
608 */
609 if (subtype == ELOG_CROS_DIAGNOSTICS_LOGS) {
610 size_t i, base_size, log_size, num_logs;
611 const union elog_event_cros_diag_log *log;
612
613 /*
614 * base_size = event header + checksum + subtype;
615 * log_size = event length - base_size.
616 */
617 base_size = sizeof(*event) + 1 + sizeof(subtype);
618 /* Validity check to prevent log_size overflow */
619 if (event->length > base_size) {
620 log_size = event->length - base_size;
621 num_logs = log_size / sizeof(union elog_event_cros_diag_log);
622 log = (const union elog_event_cros_diag_log *)(data + 1);
623 for (i = 0; i < num_logs; i++) {
624 eventlog_printf("type=%s, result=%s, time=%um%us",
625 val2str(log->type,
626 cros_diagnostics_diag_types),
627 val2str(log->result,
628 cros_diagnostics_diag_results),
629 log->time_s / 60, log->time_s % 60);
630 log++;
631 }
632 }
633 }
Subrata Banik8b468402022-07-17 18:20:24 +0530634 break;
635 }
636 case ELOG_TYPE_FW_VBOOT_INFO: {
637 const union vb2_fw_boot_info *info = event_get_data(event);
638
639 eventlog_printf("boot_mode=%s", vb2_boot_mode_string(info->boot_mode));
640
641 if (info->boot_mode == VB2_BOOT_MODE_BROKEN_SCREEN ||
Kapil Porwal0b6954b2023-01-20 01:00:42 +0530642 info->boot_mode == VB2_BOOT_MODE_MANUAL_RECOVERY) {
643 if (event->length <= sizeof(*event) + sizeof(*info))
644 eventlog_printf("INVALID DATA (length = %u)",
645 event->length - sizeof(*event));
646 else
647 eventlog_printf("recovery_reason=%#x/%#x (%s)",
Subrata Banik8b468402022-07-17 18:20:24 +0530648 info->recovery_reason, info->recovery_subcode,
649 vb2_get_recovery_reason_string(info->recovery_reason));
Kapil Porwal0b6954b2023-01-20 01:00:42 +0530650 }
Subrata Banik8b468402022-07-17 18:20:24 +0530651
652 eventlog_printf("fw_tried=%s", vb2_slot_string(info->slot));
653 eventlog_printf("fw_try_count=%d", info->tries);
654 eventlog_printf("fw_prev_tried=%s", vb2_slot_string(info->prev_slot));
655 eventlog_printf("fw_prev_result=%s", vb2_result_string(info->prev_result));
656 break;
Hsuan Ting Chena5cbe272021-11-01 19:14:01 +0800657 }
Tarun Tuli5044dc42023-01-31 18:24:38 +0000658 case ELOG_TYPE_FW_EARLY_SOL: {
659 const uint8_t *sol_event = event_get_data(event);
660 eventlog_printf("%s", val2str(*sol_event, early_sol_path_types));
661 break;
662 }
Krishna Prasad Bhat93be5d5d2023-08-07 10:24:37 +0530663 case ELOG_TYPE_PSR_DATA_BACKUP: {
664 const uint8_t *psr_backup_event = event_get_data(event);
665 eventlog_printf("%s", val2str(*psr_backup_event, psr_data_backup_statuses));
666 break;
667 }
Subrata Banik1cfb2862023-08-27 21:03:43 +0000668 case ELOG_TYPE_FW_SPLASH_SCREEN: {
669 const uint8_t *fw_splash_screen_event = event_get_data(event);
670 eventlog_printf("%s", *fw_splash_screen_event ? "Enabled" : "Disabled");
671 break;
672 }
Ricardo Quesadac2cf3942021-07-16 16:49:04 -0700673 default:
674 break;
675 }
676
677 return 0;
678}
679
Wojciech Macek9edaccd2023-02-23 09:33:06 +0100680void eventlog_print_event(const struct event_header *event, int count,
681 enum eventlog_timezone tz)
Ricardo Quesadac2cf3942021-07-16 16:49:04 -0700682{
683 /* Ignore the printf separator at the beginning and end of each line */
684 eventlog_printf_ignore_separator_once = 1;
685
686 eventlog_printf("%d", count);
Wojciech Macek9edaccd2023-02-23 09:33:06 +0100687 eventlog_print_timestamp(event, tz);
Ricardo Quesadac2cf3942021-07-16 16:49:04 -0700688 eventlog_print_type(event);
689 eventlog_print_data(event);
690
691 /* End of line, after printing each event */
692 eventlog_printf_ignore_separator_once = 1;
693 eventlog_printf("\n");
694}
Ricardo Quesada49a96a92021-08-16 11:25:52 -0700695
696/*
697 * Initializes the eventlog header with the given type and data,
698 * and calculates the checksum.
699 * buffer_get() points to the event to be initialized.
700 * On success it returns 1, otherwise 0.
701 */
702int eventlog_init_event(const struct buffer *buf, uint8_t type,
703 const void *data, int data_size)
704{
705 struct event_header *event;
706 time_t secs = time(NULL);
707 struct tm tm;
708
709 /* Must have at least size for data + checksum byte */
710 if (buffer_size(buf) < (size_t)data_size + 1)
711 return 0;
712
713 event = buffer_get(buf);
714
715 event->type = type;
716 gmtime_r(&secs, &tm);
Ricardo Quesada1427f122021-09-22 20:08:35 -0700717 /* Month should be +1, since gmtime uses 0 as first month */
Ricardo Quesada49a96a92021-08-16 11:25:52 -0700718 elog_fill_timestamp(event, tm.tm_sec, tm.tm_min, tm.tm_hour,
Ricardo Quesada1427f122021-09-22 20:08:35 -0700719 tm.tm_mday, tm.tm_mon + 1, tm.tm_year);
Ricardo Quesada49a96a92021-08-16 11:25:52 -0700720
721 if (data && data_size) {
722 uint32_t *ptr = (uint32_t *)&event[1];
723 memcpy(ptr, data, data_size);
724 }
725
726 /* Header + data + checksum */
727 event->length = sizeof(*event) + data_size + 1;
728
729 /* Zero the checksum byte and then compute checksum */
730 elog_update_checksum(event, 0);
731 elog_update_checksum(event, -(elog_checksum_event(event)));
732
733 return 1;
734}