1 /* SPDX-License-Identifier: BSD-3-Clause */
10 #include <commonlib/console/post_codes.h>
11 #include <commonlib/bsd/elog.h>
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
27 /* When true, then the separator is not printed */
28 static int eventlog_printf_ignore_separator_once
= 1;
30 static void eventlog_printf(const char *format
, ...)
34 // Separator for each field
35 if (eventlog_printf_ignore_separator_once
)
36 eventlog_printf_ignore_separator_once
= 0;
38 fprintf(stdout
, " | ");
40 va_start(args
, format
);
41 vfprintf(stdout
, format
, args
);
46 * eventlog_print_timestamp - forms the key-value pair for event timestamp
48 * @entry: the smbios log entry to get the data information
50 * Forms the key-value description pair for the event timestamp.
52 static void eventlog_print_timestamp(const struct event_header
*event
,
53 enum eventlog_timezone tz
)
55 const char *tm_format
= "%y-%m-%d%t%H:%M:%S";
61 memset(&tm
, 0, sizeof(tm
));
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
);
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
);
76 /* Set DST flag to -1 to indicate "not available" and let
77 * system determine if DST is on based on date */
81 time
+= tm
.tm_gmtoff
; /* force adjust for timezone */
83 if (tz
== EVENTLOG_TIMEZONE_UTC
)
84 tmptr
= gmtime(&time
);
86 tmptr
= localtime(&time
);
87 strftime(tm_string
, sizeof(tm_string
), "%Y-%m-%d %H:%M:%S%z", tmptr
);
89 eventlog_printf("%s", tm_string
);
94 * eventlog_print_type - print the type of the entry
96 * @entry: the smbios log entry to get type information
99 static void eventlog_print_type(const struct event_header
*event
)
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"},
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"},
150 {ELOG_DEPRECATED_TYPE_CROS_DEVELOPER_MODE
, "ChromeOS Developer Mode"},
151 {ELOG_DEPRECATED_TYPE_CROS_RECOVERY_MODE
, "ChromeOS Recovery Mode"},
152 {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"},
166 {ELOG_TYPE_CROS_DIAGNOSTICS
, "Diagnostics Mode"},
167 {ELOG_TYPE_FW_VBOOT_INFO
, "Firmware vboot info"},
168 {ELOG_TYPE_FW_EARLY_SOL
, "Early Sign of Life"},
169 {ELOG_TYPE_PSR_DATA_BACKUP
, "PSR data backup"},
170 {ELOG_TYPE_PSR_DATA_LOST
, "PSR data lost"},
171 {ELOG_TYPE_FW_SPLASH_SCREEN
, "Firmware Splash Screen"},
172 {ELOG_TYPE_EOL
, "End of log"},
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
);
179 /* Indicate unknown type in value pair */
180 eventlog_printf("Unknown");
181 eventlog_printf("0x%02x", event
->type
);
185 eventlog_printf("%s", type
);
189 * CMOS Extra log format:
190 * [31:24] = Extra Log Type
191 * [23:0] = Extra Log Data
193 * If Extra Log Type is 0x01 then Data is Device Path
194 * [23:16] = Device Type
195 * [15:0] = Encoded Device Path
197 static int eventlog_print_post_extra(uint32_t extra
)
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"},
213 const uint8_t type
= (extra
>> 16) & 0xff;
215 /* Currently only know how to print device path */
216 if ((extra
>> 24) != ELOG_TYPE_POST_EXTRA_PATH
) {
217 eventlog_printf("0x%08x", extra
);
221 eventlog_printf("%s", val2str(type
, path_type_values
));
223 /* Handle different device path types */
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
);
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
);
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);
251 * eventlog_print_data - print the data associated with the entry
253 * @event: the smbios log entry to get the data information
255 * Returns 0 on failure, 1 on success.
257 static int eventlog_print_data(const struct event_header
*event
)
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"},
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"},
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"},
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"},
365 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"},
374 static const struct valstr coreboot_post_codes
[] = {
375 {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"},
414 {POSTCODE_INVALID_ROM
, "Invalid ROM"},
415 {POSTCODE_INVALID_CBFS
, "Invalid CBFS"},
416 {POSTCODE_INVALID_VENDOR_BINARY
, "Invalid Vendor Binary"},
417 {POSTCODE_RAM_FAILURE
, "RAM Failure"},
418 {POSTCODE_HW_INIT_FAILURE
, "Hardware Init Failure"},
419 {POSTCODE_VIDEO_FAILURE
, "Video Failure"},
420 {POSTCODE_TPM_FAILURE
, "TPM Failure"},
421 {POSTCODE_DEAD_CODE
, "Dead Code"},
422 {POSTCODE_RESUME_FAILURE
, "Resume Failure"},
423 {POSTCODE_JUMPING_TO_PAYLOAD
, "Before Jump to Payload"},
424 {POSTCODE_ENTER_ELF_BOOT
, "Before ELF Boot"},
425 {POSTCODE_OS_RESUME
, "Before OS Resume"},
426 {POSTCODE_OS_BOOT
, "Before OS Boot"},
427 {POSTCODE_DIE
, "coreboot Dead"},
430 static const struct valstr mem_cache_slots
[] = {
431 {ELOG_MEM_CACHE_UPDATE_SLOT_NORMAL
, "Normal"},
432 {ELOG_MEM_CACHE_UPDATE_SLOT_RECOVERY
, "Recovery"},
433 {ELOG_MEM_CACHE_UPDATE_SLOT_VARIABLE
, "Variable"},
436 static const struct valstr mem_cache_statuses
[] = {
437 {ELOG_MEM_CACHE_UPDATE_STATUS_SUCCESS
, "Success"},
438 {ELOG_MEM_CACHE_UPDATE_STATUS_FAIL
, "Fail"},
442 static const struct valstr extended_event_subtypes
[] = {
443 {ELOG_SLEEP_PENDING_PM1_WAKE
, "S3 failed due to pending wake event, PM1"},
444 {ELOG_SLEEP_PENDING_GPE0_WAKE
, "S3 failed due to pending wake event, GPE0"},
448 static const struct valstr cros_diagnostics_types
[] = {
449 {ELOG_DEPRECATED_CROS_LAUNCH_DIAGNOSTICS
, "Launch Diagnostics"},
450 {ELOG_CROS_DIAGNOSTICS_LOGS
, "Diagnostics Logs"},
454 static const struct valstr cros_diagnostics_diag_types
[] = {
455 {ELOG_CROS_DIAG_TYPE_NONE
, "None"},
456 {ELOG_CROS_DIAG_TYPE_STORAGE_HEALTH
, "Storage health info"},
457 {ELOG_CROS_DIAG_TYPE_STORAGE_TEST_SHORT
, "Storage self-test (short)"},
458 {ELOG_CROS_DIAG_TYPE_STORAGE_TEST_EXTENDED
, "Storage self-test (extended)"},
459 {ELOG_CROS_DIAG_TYPE_MEMORY_QUICK
, "Memory check (quick)"},
460 {ELOG_CROS_DIAG_TYPE_MEMORY_FULL
, "Memory check (full)"},
464 static const struct valstr cros_diagnostics_diag_results
[] = {
465 {ELOG_CROS_DIAG_RESULT_PASSED
, "Passed"},
466 {ELOG_CROS_DIAG_RESULT_ERROR
, "Error"},
467 {ELOG_CROS_DIAG_RESULT_FAILED
, "Failed"},
468 {ELOG_CROS_DIAG_RESULT_ABORTED
, "Aborted"},
472 static const struct valstr early_sol_path_types
[] = {
473 {ELOG_FW_EARLY_SOL_CSE_SYNC
, "CSE Sync Early SOL Screen Shown"},
474 {ELOG_FW_EARLY_SOL_MRC
, "MRC Early SOL Screen Shown"},
478 static const struct valstr psr_data_backup_statuses
[] = {
479 {ELOG_PSR_DATA_BACKUP_SUCCESS
, "Success"},
480 {ELOG_PSR_DATA_BACKUP_FAILED
, "Fail"},
484 size_t elog_type_to_min_size
[] = {
485 [ELOG_TYPE_LOG_CLEAR
] = sizeof(uint16_t),
486 [ELOG_TYPE_BOOT
] = sizeof(uint32_t),
487 [ELOG_TYPE_LAST_POST_CODE
] = sizeof(uint16_t),
488 [ELOG_TYPE_POST_EXTRA
] = sizeof(uint32_t),
489 [ELOG_TYPE_OS_EVENT
] = sizeof(uint32_t),
490 [ELOG_TYPE_ACPI_ENTER
] = sizeof(uint8_t),
491 [ELOG_TYPE_ACPI_WAKE
] = sizeof(uint8_t),
492 [ELOG_TYPE_ACPI_DEEP_WAKE
] = sizeof(uint8_t),
493 [ELOG_TYPE_WAKE_SOURCE
] = sizeof(struct elog_event_data_wake
),
494 [ELOG_TYPE_EC_EVENT
] = sizeof(uint8_t),
495 [ELOG_TYPE_EC_DEVICE_EVENT
] = sizeof(uint8_t),
496 [ELOG_DEPRECATED_TYPE_CROS_RECOVERY_MODE
] = sizeof(uint8_t),
497 [ELOG_TYPE_MANAGEMENT_ENGINE
] = sizeof(uint8_t),
498 [ELOG_TYPE_MEM_CACHE_UPDATE
] = sizeof(struct elog_event_mem_cache_update
),
499 [ELOG_TYPE_EXTENDED_EVENT
] = sizeof(struct elog_event_extended_event
),
500 [ELOG_TYPE_CROS_DIAGNOSTICS
] = sizeof(uint8_t),
501 [ELOG_TYPE_FW_VBOOT_INFO
] = sizeof(uint16_t),
502 [ELOG_TYPE_FW_EARLY_SOL
] = sizeof(uint8_t),
503 [ELOG_TYPE_PSR_DATA_BACKUP
] = sizeof(uint8_t),
504 [ELOG_TYPE_FW_SPLASH_SCREEN
] = sizeof(uint8_t),
508 if (event
->length
<= sizeof(*event
) + elog_type_to_min_size
[event
->type
]) {
509 eventlog_printf("INVALID DATA (length = %u)", event
->length
- sizeof(*event
));
513 switch (event
->type
) {
514 case ELOG_TYPE_LOG_CLEAR
: {
515 const uint16_t *bytes
= event_get_data(event
);
516 eventlog_printf("%u", *bytes
);
520 case ELOG_TYPE_BOOT
: {
521 const uint32_t *count
= event_get_data(event
);
522 eventlog_printf("%u", *count
);
525 case ELOG_TYPE_LAST_POST_CODE
: {
526 const uint16_t *code
= event_get_data(event
);
527 eventlog_printf("0x%02x", *code
);
528 eventlog_printf("%s", val2str(*code
, coreboot_post_codes
));
531 case ELOG_TYPE_POST_EXTRA
: {
532 const uint32_t *extra
= event_get_data(event
);
533 eventlog_print_post_extra(*extra
);
536 case ELOG_TYPE_OS_EVENT
: {
537 const uint32_t *osevent
= event_get_data(event
);
538 eventlog_printf("%s", val2str(*osevent
, os_events
));
541 case ELOG_TYPE_ACPI_ENTER
:
542 case ELOG_TYPE_ACPI_WAKE
: {
543 const uint8_t *state
= event_get_data(event
);
544 eventlog_printf("S%u", *state
);
547 case ELOG_TYPE_ACPI_DEEP_WAKE
: {
548 const uint8_t *state
= event_get_data(event
);
549 eventlog_printf("Deep S%u", *state
);
552 case ELOG_TYPE_WAKE_SOURCE
: {
553 const struct elog_event_data_wake
*wake_source
;
554 wake_source
= event_get_data(event
);
555 eventlog_printf("%s", val2str(wake_source
->source
, wake_source_types
));
556 eventlog_printf("%u", wake_source
->instance
);
559 case ELOG_TYPE_EC_EVENT
: {
560 const uint8_t *ec_event
= event_get_data(event
);
561 eventlog_printf("%s", val2str(*ec_event
, ec_event_types
));
564 case ELOG_TYPE_EC_DEVICE_EVENT
: {
565 const uint8_t *dev_event
= event_get_data(event
);
566 eventlog_printf("%s", val2str(*dev_event
, ec_device_event_types
));
569 case ELOG_DEPRECATED_TYPE_CROS_RECOVERY_MODE
: {
570 const uint8_t *reason
= event_get_data(event
);
571 eventlog_printf("%s", vb2_get_recovery_reason_string(*reason
));
572 eventlog_printf("0x%02x", *reason
);
575 case ELOG_TYPE_MANAGEMENT_ENGINE
: {
576 const uint8_t *path
= event_get_data(event
);
577 eventlog_printf("%s", val2str(*path
, me_path_types
));
580 case ELOG_TYPE_MEM_CACHE_UPDATE
: {
581 const struct elog_event_mem_cache_update
*update
;
582 update
= event_get_data(event
);
583 eventlog_printf("%s", val2str(update
->slot
, mem_cache_slots
));
584 eventlog_printf("%s", val2str(update
->status
, mem_cache_statuses
));
587 case ELOG_TYPE_EXTENDED_EVENT
: {
588 const struct elog_event_extended_event
*ext_event
;
589 ext_event
= event_get_data(event
);
590 eventlog_printf("%s", val2str(ext_event
->event_type
, extended_event_subtypes
));
591 eventlog_printf("0x%X", ext_event
->event_complement
);
594 case ELOG_TYPE_CROS_DIAGNOSTICS
: {
595 const uint8_t *data
= event_get_data(event
);
596 const uint8_t subtype
= *data
;
597 eventlog_printf("%s", val2str(subtype
, cros_diagnostics_types
));
600 * If the subtype is diagnostics logs, there will be many
601 * elog_event_diag_log events after subtype:
603 * [event_header][(subtype)(log 1)(log 2)...(log n)][checksum]
605 * Parse them one by one.
607 if (subtype
== ELOG_CROS_DIAGNOSTICS_LOGS
) {
608 size_t i
, base_size
, log_size
, num_logs
;
609 const union elog_event_cros_diag_log
*log
;
612 * base_size = event header + checksum + subtype;
613 * log_size = event length - base_size.
615 base_size
= sizeof(*event
) + 1 + sizeof(subtype
);
616 /* Validity check to prevent log_size overflow */
617 if (event
->length
> base_size
) {
618 log_size
= event
->length
- base_size
;
619 num_logs
= log_size
/ sizeof(union elog_event_cros_diag_log
);
620 log
= (const union elog_event_cros_diag_log
*)(data
+ 1);
621 for (i
= 0; i
< num_logs
; i
++) {
622 eventlog_printf("type=%s, result=%s, time=%um%us",
624 cros_diagnostics_diag_types
),
626 cros_diagnostics_diag_results
),
627 log
->time_s
/ 60, log
->time_s
% 60);
634 case ELOG_TYPE_FW_VBOOT_INFO
: {
635 const union vb2_fw_boot_info
*info
= event_get_data(event
);
637 eventlog_printf("boot_mode=%s", vb2_boot_mode_string(info
->boot_mode
));
639 if (info
->boot_mode
== VB2_BOOT_MODE_BROKEN_SCREEN
||
640 info
->boot_mode
== VB2_BOOT_MODE_MANUAL_RECOVERY
) {
641 if (event
->length
<= sizeof(*event
) + sizeof(*info
))
642 eventlog_printf("INVALID DATA (length = %u)",
643 event
->length
- sizeof(*event
));
645 eventlog_printf("recovery_reason=%#x/%#x (%s)",
646 info
->recovery_reason
, info
->recovery_subcode
,
647 vb2_get_recovery_reason_string(info
->recovery_reason
));
650 eventlog_printf("fw_tried=%s", vb2_slot_string(info
->slot
));
651 eventlog_printf("fw_try_count=%d", info
->tries
);
652 eventlog_printf("fw_prev_tried=%s", vb2_slot_string(info
->prev_slot
));
653 eventlog_printf("fw_prev_result=%s", vb2_result_string(info
->prev_result
));
656 case ELOG_TYPE_FW_EARLY_SOL
: {
657 const uint8_t *sol_event
= event_get_data(event
);
658 eventlog_printf("%s", val2str(*sol_event
, early_sol_path_types
));
661 case ELOG_TYPE_PSR_DATA_BACKUP
: {
662 const uint8_t *psr_backup_event
= event_get_data(event
);
663 eventlog_printf("%s", val2str(*psr_backup_event
, psr_data_backup_statuses
));
666 case ELOG_TYPE_FW_SPLASH_SCREEN
: {
667 const uint8_t *fw_splash_screen_event
= event_get_data(event
);
668 eventlog_printf("%s", *fw_splash_screen_event
? "Enabled" : "Disabled");
678 void eventlog_print_event(const struct event_header
*event
, int count
,
679 enum eventlog_timezone tz
)
681 /* Ignore the printf separator at the beginning and end of each line */
682 eventlog_printf_ignore_separator_once
= 1;
684 eventlog_printf("%d", count
);
685 eventlog_print_timestamp(event
, tz
);
686 eventlog_print_type(event
);
687 eventlog_print_data(event
);
689 /* End of line, after printing each event */
690 eventlog_printf_ignore_separator_once
= 1;
691 eventlog_printf("\n");
695 * Initializes the eventlog header with the given type and data,
696 * and calculates the checksum.
697 * buffer_get() points to the event to be initialized.
698 * On success it returns 1, otherwise 0.
700 int eventlog_init_event(const struct buffer
*buf
, uint8_t type
,
701 const void *data
, int data_size
)
703 struct event_header
*event
;
704 time_t secs
= time(NULL
);
707 /* Must have at least size for data + checksum byte */
708 if (buffer_size(buf
) < (size_t)data_size
+ 1)
711 event
= buffer_get(buf
);
714 gmtime_r(&secs
, &tm
);
715 /* Month should be +1, since gmtime uses 0 as first month */
716 elog_fill_timestamp(event
, tm
.tm_sec
, tm
.tm_min
, tm
.tm_hour
,
717 tm
.tm_mday
, tm
.tm_mon
+ 1, tm
.tm_year
);
719 if (data
&& data_size
) {
720 uint32_t *ptr
= (uint32_t *)&event
[1];
721 memcpy(ptr
, data
, data_size
);
724 /* Header + data + checksum */
725 event
->length
= sizeof(*event
) + data_size
+ 1;
727 /* Zero the checksum byte and then compute checksum */
728 elog_update_checksum(event
, 0);
729 elog_update_checksum(event
, -(elog_checksum_event(event
)));