In order to support logging events for when we show early signs of life to the user during CSE FW syncs add support for the ELOG_TYPE_FW_LATE_SOL type. BUG=b:305898363 TEST=verify event shows in eventlog CSE sync. Change-Id: I862db946f6ff622ac83072e6bf27832732c0c318 Signed-off-by: Subrata Banik <subratabanik@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/83462 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Dinesh Gehlot <digehlot@google.com>
		
			
				
	
	
		
			747 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			747 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* SPDX-License-Identifier: BSD-3-Clause */
 | |
| 
 | |
| #include "eventlog.h"
 | |
| 
 | |
| #include <inttypes.h>
 | |
| #include <stdarg.h>
 | |
| #include <stdlib.h>
 | |
| #include <time.h>
 | |
| 
 | |
| #include <commonlib/console/post_codes.h>
 | |
| #include <commonlib/bsd/elog.h>
 | |
| #include <vb2_api.h>
 | |
| 
 | |
| #include "common.h"
 | |
| #include "valstr.h"
 | |
| 
 | |
| #define PATH_PCI_BUS_SHIFT		8
 | |
| #define PATH_PCI_BUS_MASK		0xff
 | |
| #define PATH_PCI_DEV_SHIFT		3
 | |
| #define PATH_PCI_DEV_MASK		0x1f
 | |
| #define PATH_PCI_FN_SHIFT		0
 | |
| #define PATH_PCI_FN_MASK		0x03
 | |
| #define PATH_I2C_MODE10BIT_SHIFT	8
 | |
| #define PATH_I2C_MODE10BIT_MASK		0xff
 | |
| #define PATH_I2C_ADDRESS_MASK		0xff
 | |
| 
 | |
| /* When true, then the separator is not printed */
 | |
| static int eventlog_printf_ignore_separator_once = 1;
 | |
| 
 | |
| static void eventlog_printf(const char *format, ...)
 | |
| {
 | |
| 	va_list args;
 | |
| 
 | |
| 	// Separator for each field
 | |
| 	if (eventlog_printf_ignore_separator_once)
 | |
| 		eventlog_printf_ignore_separator_once = 0;
 | |
| 	else
 | |
| 		fprintf(stdout, " | ");
 | |
| 
 | |
| 	va_start(args, format);
 | |
| 	vfprintf(stdout, format, args);
 | |
| 	va_end(args);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * eventlog_print_timestamp - forms the key-value pair for event timestamp
 | |
|  *
 | |
|  * @entry:  the smbios log entry to get the data information
 | |
|  *
 | |
|  * Forms the key-value description pair for the event timestamp.
 | |
|  */
 | |
| static void eventlog_print_timestamp(const struct event_header *event,
 | |
| 				     enum eventlog_timezone tz)
 | |
| {
 | |
| 	const char *tm_format = "%y-%m-%d%t%H:%M:%S";
 | |
| 	char tm_string[40];
 | |
| 	struct tm *tmptr;
 | |
| 	struct tm tm;
 | |
| 	time_t time;
 | |
| 
 | |
| 	memset(&tm, 0, sizeof(tm));
 | |
| 
 | |
| 	/* Time is in "hexa". Convert it to decimal, and then convert it to "tm" struct */
 | |
| 	snprintf(tm_string, sizeof(tm_string), "%02x-%02x-%02x %02x:%02x:%02x", event->year,
 | |
| 		 event->month, event->day, event->hour, event->minute, event->second);
 | |
| 
 | |
| 	if (strptime(tm_string, tm_format, &tm) == NULL) {
 | |
| 		/* Backup in case string could not be parsed. Timezone not included */
 | |
| 		eventlog_printf("%02d%02x-%02x-%02x %02x:%02x:%02x",
 | |
| 				(event->year > 0x80 && event->year < 0x99) ? 19 : 20,
 | |
| 				event->year, event->month, event->day, event->hour,
 | |
| 				event->minute, event->second);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	/* Set DST flag to -1 to indicate "not available" and let
 | |
| 	 * system determine if DST is on based on date */
 | |
| 	tm.tm_isdst = -1;
 | |
| 
 | |
| 	time = mktime(&tm);
 | |
| 	time += tm.tm_gmtoff; /* force adjust for timezone */
 | |
| 
 | |
| 	if (tz == EVENTLOG_TIMEZONE_UTC)
 | |
| 		tmptr = gmtime(&time);
 | |
| 	else
 | |
| 		tmptr = localtime(&time);
 | |
| 	strftime(tm_string, sizeof(tm_string), "%Y-%m-%d %H:%M:%S%z", tmptr);
 | |
| 
 | |
| 	eventlog_printf("%s", tm_string);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * eventlog_print_type - print the type of the entry
 | |
|  *
 | |
|  * @entry:  the smbios log entry to get type information
 | |
|  *
 | |
|  */
 | |
| static void eventlog_print_type(const struct event_header *event)
 | |
| {
 | |
| 	const char *type;
 | |
| 	static const struct valstr elog_event_types[] = {
 | |
| 		/* SMBIOS Event Log types, SMBIOSv2.4 section 3.3.16.1 */
 | |
| 		{ELOG_TYPE_UNDEFINED_EVENT, "Reserved"},
 | |
| 		{ELOG_TYPE_SINGLE_BIT_ECC_MEM_ERR, "Single-bit ECC memory error"},
 | |
| 		{ELOG_TYPE_MULTI_BIT_ECC_MEM_ERR, "Multi-bit ECC memory error"},
 | |
| 		{ELOG_TYPE_MEM_PARITY_ERR, "Parity memory error"},
 | |
| 		{ELOG_TYPE_BUS_TIMEOUT, "Bus timeout"},
 | |
| 		{ELOG_TYPE_IO_CHECK, "I/O channel check"},
 | |
| 		{ELOG_TYPE_SW_NMI, "Software NMI"},
 | |
| 		{ELOG_TYPE_POST_MEM_RESIZE, "POST memory resize"},
 | |
| 		{ELOG_TYPE_POST_ERR, "POST error"},
 | |
| 		{ELOG_TYPE_PCI_PERR, "PCI parity error"},
 | |
| 		{ELOG_TYPE_PCI_SERR, "PCI system error"},
 | |
| 		{ELOG_TYPE_CPU_FAIL, "CPU failure"},
 | |
| 		{ELOG_TYPE_EISA_TIMEOUT, "EISA failsafe timer timeout"},
 | |
| 		{ELOG_TYPE_CORRECTABLE_MEMLOG_DIS, "Correctable memory log disabled"},
 | |
| 		{ELOG_TYPE_LOG_DISABLED, "Logging disabled, too many errors"},
 | |
| 		{ELOG_TYPE_UNDEFINED_EVENT2, "Reserved"},
 | |
| 		{ELOG_TYPE_SYS_LIMIT_EXCEED, "System limit exceeded"},
 | |
| 		{ELOG_TYPE_ASYNC_HW_TIMER_EXPIRED, "Hardware watchdog reset"},
 | |
| 		{ELOG_TYPE_SYS_CONFIG_INFO, "System configuration information"},
 | |
| 		{ELOG_TYPE_HDD_INFO, "Hard-disk information"},
 | |
| 		{ELOG_TYPE_SYS_RECONFIG, "System reconfigured"},
 | |
| 		{ELOG_TYPE_CPU_ERROR, "Uncorrectable CPU-complex error"},
 | |
| 		{ELOG_TYPE_LOG_CLEAR, "Log area cleared"},
 | |
| 		{ELOG_TYPE_BOOT, "System boot"},
 | |
| 
 | |
| 		/* Extended events defined by OEMs */
 | |
| 		{ELOG_TYPE_OS_EVENT, "Kernel Event"},
 | |
| 		{ELOG_TYPE_OS_BOOT, "OS Boot"},
 | |
| 		{ELOG_TYPE_EC_EVENT, "EC Event"},
 | |
| 		{ELOG_TYPE_POWER_FAIL, "Power Fail"},
 | |
| 		{ELOG_TYPE_SUS_POWER_FAIL, "SUS Power Fail"},
 | |
| 		{ELOG_TYPE_PWROK_FAIL, "PWROK Fail"},
 | |
| 		{ELOG_TYPE_SYS_PWROK_FAIL, "SYS PWROK Fail"},
 | |
| 		{ELOG_TYPE_POWER_ON, "Power On"},
 | |
| 		{ELOG_TYPE_POWER_BUTTON, "Power Button"},
 | |
| 		{ELOG_TYPE_POWER_BUTTON_OVERRIDE, "Power Button Override"},
 | |
| 		{ELOG_TYPE_RESET_BUTTON, "Reset Button"},
 | |
| 		{ELOG_TYPE_SYSTEM_RESET, "System Reset"},
 | |
| 		{ELOG_TYPE_RTC_RESET, "RTC Reset"},
 | |
| 		{ELOG_TYPE_TCO_RESET, "TCO Reset"},
 | |
| 		{ELOG_TYPE_ACPI_ENTER, "ACPI Enter"},
 | |
| 		{ELOG_TYPE_ACPI_WAKE, "ACPI Wake"},
 | |
| 		{ELOG_TYPE_ACPI_DEEP_WAKE, "ACPI Wake"},
 | |
| 		{ELOG_TYPE_S0IX_ENTER, "S0ix Enter"},
 | |
| 		{ELOG_TYPE_S0IX_EXIT, "S0ix Exit"},
 | |
| 		{ELOG_TYPE_WAKE_SOURCE, "Wake Source"},
 | |
| 		{ELOG_DEPRECATED_TYPE_CROS_DEVELOPER_MODE, "ChromeOS Developer Mode"},
 | |
| 		{ELOG_DEPRECATED_TYPE_CROS_RECOVERY_MODE, "ChromeOS Recovery Mode"},
 | |
| 		{ELOG_TYPE_MANAGEMENT_ENGINE, "Management Engine"},
 | |
| 		{ELOG_TYPE_MANAGEMENT_ENGINE_EXT, "Management Engine Extra"},
 | |
| 		{ELOG_TYPE_LAST_POST_CODE, "Last post code in previous boot"},
 | |
| 		{ELOG_TYPE_POST_EXTRA, "Extra info from previous boot"},
 | |
| 		{ELOG_TYPE_EC_SHUTDOWN, "EC Shutdown"},
 | |
| 		{ELOG_TYPE_SLEEP, "Sleep"},
 | |
| 		{ELOG_TYPE_WAKE, "Wake"},
 | |
| 		{ELOG_TYPE_FW_WAKE, "FW Wake"},
 | |
| 		{ELOG_TYPE_MEM_CACHE_UPDATE, "Memory Cache Update"},
 | |
| 		{ELOG_TYPE_THERM_TRIP, "CPU Thermal Trip"},
 | |
| 		{ELOG_TYPE_CR50_UPDATE, "cr50 Update Reset"},
 | |
| 		{ELOG_TYPE_CR50_NEED_RESET, "cr50 Reset Required"},
 | |
| 		{ELOG_TYPE_EC_DEVICE_EVENT, "EC Device"},
 | |
| 		{ELOG_TYPE_EXTENDED_EVENT, "Extended Event"},
 | |
| 		{ELOG_TYPE_CROS_DIAGNOSTICS, "Diagnostics Mode"},
 | |
| 		{ELOG_TYPE_FW_VBOOT_INFO, "Firmware vboot info"},
 | |
| 		{ELOG_TYPE_FW_EARLY_SOL, "Early Sign of Life"},
 | |
| 		{ELOG_TYPE_PSR_DATA_BACKUP, "PSR data backup"},
 | |
| 		{ELOG_TYPE_PSR_DATA_LOST, "PSR data lost"},
 | |
| 		{ELOG_TYPE_FW_SPLASH_SCREEN, "Firmware Splash Screen"},
 | |
| 		{ELOG_TYPE_FW_LATE_SOL, "Late Sign of Life "},
 | |
| 		{ELOG_TYPE_EOL, "End of log"},
 | |
| 	};
 | |
| 
 | |
| 	/* Passing NULL as default, because we want to print the event->type if it fails */
 | |
| 	type = val2str_default(event->type, elog_event_types, NULL);
 | |
| 
 | |
| 	if (type == NULL) {
 | |
| 		/* Indicate unknown type in value pair */
 | |
| 		eventlog_printf("Unknown");
 | |
| 		eventlog_printf("0x%02x", event->type);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	eventlog_printf("%s", type);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * CMOS Extra log format:
 | |
|  * [31:24] = Extra Log Type
 | |
|  * [23:0]  = Extra Log Data
 | |
|  *
 | |
|  * If Extra Log Type is 0x01 then Data is Device Path
 | |
|  * [23:16] = Device Type
 | |
|  * [15:0]  = Encoded Device Path
 | |
|  */
 | |
| static int eventlog_print_post_extra(uint32_t extra)
 | |
| {
 | |
| 	static const struct valstr path_type_values[] = {
 | |
| 		{ELOG_DEV_PATH_TYPE_NONE, "None"},
 | |
| 		{ELOG_DEV_PATH_TYPE_ROOT, "Root"},
 | |
| 		{ELOG_DEV_PATH_TYPE_PCI, "PCI"},
 | |
| 		{ELOG_DEV_PATH_TYPE_PNP, "PNP"},
 | |
| 		{ELOG_DEV_PATH_TYPE_I2C, "I2C"},
 | |
| 		{ELOG_DEV_PATH_TYPE_APIC, "APIC"},
 | |
| 		{ELOG_DEV_PATH_TYPE_DOMAIN, "DOMAIN"},
 | |
| 		{ELOG_DEV_PATH_TYPE_CPU_CLUSTER, "CPU Cluster"},
 | |
| 		{ELOG_DEV_PATH_TYPE_CPU, "CPU"},
 | |
| 		{ELOG_DEV_PATH_TYPE_CPU_BUS, "CPU Bus"},
 | |
| 		{ELOG_DEV_PATH_TYPE_IOAPIC, "IO-APIC"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 	const uint8_t type = (extra >> 16) & 0xff;
 | |
| 
 | |
| 	/* Currently only know how to print device path */
 | |
| 	if ((extra >> 24) != ELOG_TYPE_POST_EXTRA_PATH) {
 | |
| 		eventlog_printf("0x%08x", extra);
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	eventlog_printf("%s", val2str(type, path_type_values));
 | |
| 
 | |
| 	/* Handle different device path types */
 | |
| 	switch (type) {
 | |
| 	case ELOG_DEV_PATH_TYPE_PCI:
 | |
| 		eventlog_printf("%02x:%02x.%1x",
 | |
| 				(extra >> PATH_PCI_BUS_SHIFT) & PATH_PCI_BUS_MASK,
 | |
| 				(extra >> PATH_PCI_DEV_SHIFT) & PATH_PCI_DEV_MASK,
 | |
| 				(extra >> PATH_PCI_FN_SHIFT) & PATH_PCI_FN_MASK);
 | |
| 		break;
 | |
| 	case ELOG_DEV_PATH_TYPE_PNP:
 | |
| 	case ELOG_DEV_PATH_TYPE_I2C:
 | |
| 		eventlog_printf("%02x:%02x",
 | |
| 				(extra >> PATH_I2C_MODE10BIT_SHIFT) & PATH_I2C_MODE10BIT_MASK,
 | |
| 				extra & PATH_I2C_ADDRESS_MASK);
 | |
| 		break;
 | |
| 	case ELOG_DEV_PATH_TYPE_APIC:
 | |
| 	case ELOG_DEV_PATH_TYPE_DOMAIN:
 | |
| 	case ELOG_DEV_PATH_TYPE_CPU_CLUSTER:
 | |
| 	case ELOG_DEV_PATH_TYPE_CPU:
 | |
| 	case ELOG_DEV_PATH_TYPE_CPU_BUS:
 | |
| 	case ELOG_DEV_PATH_TYPE_IOAPIC:
 | |
| 		eventlog_printf("0x%04x", extra & 0xffff);
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * eventlog_print_data - print the data associated with the entry
 | |
|  *
 | |
|  * @event:  the smbios log entry to get the data information
 | |
|  *
 | |
|  * Returns 0 on failure, 1 on success.
 | |
|  */
 | |
| static int eventlog_print_data(const struct event_header *event)
 | |
| {
 | |
| 	static const struct valstr os_events[] = {
 | |
| 		{ELOG_OS_EVENT_CLEAN, "Clean Shutdown"},
 | |
| 		{ELOG_OS_EVENT_NMIWDT, "NMI Watchdog"},
 | |
| 		{ELOG_OS_EVENT_PANIC, "Panic"},
 | |
| 		{ELOG_OS_EVENT_OOPS, "Oops"},
 | |
| 		{ELOG_OS_EVENT_DIE, "Die"},
 | |
| 		{ELOG_OS_EVENT_MCE, "MCE"},
 | |
| 		{ELOG_OS_EVENT_SOFTWDT, "Software Watchdog"},
 | |
| 		{ELOG_OS_EVENT_MBE, "Multi-bit Error"},
 | |
| 		{ELOG_OS_EVENT_TRIPLE, "Triple Fault"},
 | |
| 		{ELOG_OS_EVENT_THERMAL, "Critical Thermal Threshold"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 	static const struct valstr wake_source_types[] = {
 | |
| 		{ELOG_WAKE_SOURCE_PCIE, "PCI Express"},
 | |
| 		{ELOG_WAKE_SOURCE_PME, "PCI PME"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_INTERNAL, "Internal PME"},
 | |
| 		{ELOG_WAKE_SOURCE_RTC, "RTC Alarm"},
 | |
| 		{ELOG_WAKE_SOURCE_GPE, "GPE #"},
 | |
| 		{ELOG_WAKE_SOURCE_SMBUS, "SMBALERT"},
 | |
| 		{ELOG_WAKE_SOURCE_PWRBTN, "Power Button"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_HDA, "PME - HDA"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_GBE, "PME - GBE"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_EMMC, "PME - EMMC"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_SDCARD, "PME - SDCARD"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE1, "PME - PCIE1"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE2, "PME - PCIE2"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE3, "PME - PCIE3"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE4, "PME - PCIE4"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE5, "PME - PCIE5"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE6, "PME - PCIE6"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE7, "PME - PCIE7"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE8, "PME - PCIE8"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE9, "PME - PCIE9"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE10, "PME - PCIE10"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE11, "PME - PCIE11"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE12, "PME - PCIE12"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_SATA, "PME - SATA"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_CSE, "PME - CSE"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_CSE2, "PME - CSE2"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_CSE3, "PME - CSE"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_XHCI, "PME - XHCI"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_XDCI, "PME - XDCI"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_XHCI_USB_2, "PME - XHCI (USB 2.0 port)"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_XHCI_USB_3, "PME - XHCI (USB 3.0 port)"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_WIFI, "PME - WIFI"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE13, "PME - PCIE13"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE14, "PME - PCIE14"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE15, "PME - PCIE15"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE16, "PME - PCIE16"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE17, "PME - PCIE17"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE18, "PME - PCIE18"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE19, "PME - PCIE19"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE20, "PME - PCIE20"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE21, "PME - PCIE21"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE22, "PME - PCIE22"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE23, "PME - PCIE23"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_PCIE24, "PME - PCIE24"},
 | |
| 		{ELOG_WAKE_SOURCE_GPIO, " GPIO #"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_TBT, "PME - Thunderbolt"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_TCSS_XHCI, "PME - TCSS XHCI"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_TCSS_XHCI, "PME - TCSS XDCI"},
 | |
| 		{ELOG_WAKE_SOURCE_PME_TCSS_XHCI, "PME - TCSS DMA"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 	static const struct valstr ec_event_types[] = {
 | |
| 		{EC_EVENT_LID_CLOSED, "Lid Closed"},
 | |
| 		{EC_EVENT_LID_OPEN, "Lid Open"},
 | |
| 		{EC_EVENT_POWER_BUTTON, "Power Button"},
 | |
| 		{EC_EVENT_AC_CONNECTED, "AC Connected"},
 | |
| 		{EC_EVENT_AC_DISCONNECTED, "AC Disconnected"},
 | |
| 		{EC_EVENT_BATTERY_LOW, "Battery Low"},
 | |
| 		{EC_EVENT_BATTERY_CRITICAL, "Battery Critical"},
 | |
| 		{EC_EVENT_BATTERY, "Battery"},
 | |
| 		{EC_EVENT_THERMAL_THRESHOLD, "Thermal Threshold"},
 | |
| 		{EC_EVENT_DEVICE_EVENT, "Device Event"},
 | |
| 		{EC_EVENT_THERMAL, "Thermal"},
 | |
| 		{EC_EVENT_USB_CHARGER, "USB Charger"},
 | |
| 		{EC_EVENT_KEY_PRESSED, "Key Pressed"},
 | |
| 		{EC_EVENT_INTERFACE_READY, "Host Interface Ready"},
 | |
| 		{EC_EVENT_KEYBOARD_RECOVERY, "Keyboard Recovery"},
 | |
| 		{EC_EVENT_THERMAL_SHUTDOWN, "Thermal Shutdown in previous boot"},
 | |
| 		{EC_EVENT_BATTERY_SHUTDOWN, "Battery Shutdown in previous boot"},
 | |
| 		{EC_EVENT_THROTTLE_START, "Throttle Requested"},
 | |
| 		{EC_EVENT_THROTTLE_STOP, "Throttle Request Removed"},
 | |
| 		{EC_EVENT_HANG_DETECT, "Host Event Hang"},
 | |
| 		{EC_EVENT_HANG_REBOOT, "Host Event Hang Reboot"},
 | |
| 		{EC_EVENT_PD_MCU, "PD MCU Request"},
 | |
| 		{EC_EVENT_BATTERY_STATUS, "Battery Status Request"},
 | |
| 		{EC_EVENT_PANIC, "Panic Reset in previous boot"},
 | |
| 		{EC_EVENT_KEYBOARD_FASTBOOT, "Keyboard Fastboot Recovery"},
 | |
| 		{EC_EVENT_RTC, "RTC"},
 | |
| 		{EC_EVENT_MKBP, "MKBP"},
 | |
| 		{EC_EVENT_USB_MUX, "USB MUX change"},
 | |
| 		{EC_EVENT_MODE_CHANGE, "Mode change"},
 | |
| 		{EC_EVENT_KEYBOARD_RECOVERY_HWREINIT,
 | |
| 		 "Keyboard Recovery Forced Hardware Reinit"},
 | |
| 		{EC_EVENT_EXTENDED, "Extended EC events"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 	static const struct valstr ec_device_event_types[] = {
 | |
| 		{ELOG_EC_DEVICE_EVENT_TRACKPAD, "Trackpad"},
 | |
| 		{ELOG_EC_DEVICE_EVENT_DSP, "DSP"},
 | |
| 		{ELOG_EC_DEVICE_EVENT_WIFI, "WiFi"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 	static const struct valstr me_path_types[] = {
 | |
| 		{ELOG_ME_PATH_NORMAL, "Normal"},
 | |
| 		{ELOG_ME_PATH_NORMAL, "S3 Wake"},
 | |
| 		{ELOG_ME_PATH_ERROR, "Error"},
 | |
| 		{ELOG_ME_PATH_RECOVERY, "Recovery"},
 | |
| 		{ELOG_ME_PATH_DISABLED, "Disabled"},
 | |
| 		{ELOG_ME_PATH_FW_UPDATE, "Firmware Update"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 	static const struct valstr coreboot_post_codes[] = {
 | |
| 		{POSTCODE_RESET_VECTOR_CORRECT, "Reset Vector Correct"},
 | |
| 		{POSTCODE_ENTER_PROTECTED_MODE, "Enter Protected Mode"},
 | |
| 		{POSTCODE_PREPARE_RAMSTAGE, "Prepare RAM stage"},
 | |
| 		{POSTCODE_ENTRY_C_START, "RAM stage Start"},
 | |
| 		{POSTCODE_MEM_PREINIT_PREP_START, "Preparing memory init params"},
 | |
| 		{POSTCODE_MEM_PREINIT_PREP_END, "Memory init param preparation complete"},
 | |
| 		{POSTCODE_CONSOLE_READY, "Console is ready"},
 | |
| 		{POSTCODE_CONSOLE_BOOT_MSG, "Console Boot Message"},
 | |
| 		{POSTCODE_ENABLING_CACHE, "Before Enabling Cache"},
 | |
| 		{POSTCODE_PRE_HARDWAREMAIN, "Before Hardware Main"},
 | |
| 		{POSTCODE_ENTRY_HARDWAREMAIN, "First call in Hardware Main"},
 | |
| 		{POSTCODE_BS_PRE_DEVICE, "Before Device Probe"},
 | |
| 		{POSTCODE_BS_DEV_INIT_CHIPS, "Initialize Chips"},
 | |
| 		{POSTCODE_BS_DEV_ENUMERATE, "Device Enumerate"},
 | |
| 		{POSTCODE_BS_DEV_RESOURCES, "Device Resource Allocation"},
 | |
| 		{POSTCODE_BS_DEV_ENABLE, "Device Enable"},
 | |
| 		{POSTCODE_BS_DEV_INIT, "Device Initialize"},
 | |
| 		{POSTCODE_BS_POST_DEVICE, "After Device Probe"},
 | |
| 		{POSTCODE_BS_OS_RESUME_CHECK, "OS Resume Check"},
 | |
| 		{POSTCODE_BS_OS_RESUME, "OS Resume"},
 | |
| 		{POSTCODE_BS_WRITE_TABLES, "Write Tables"},
 | |
| 		{POSTCODE_BS_PAYLOAD_LOAD, "Load Payload"},
 | |
| 		{POSTCODE_BS_PAYLOAD_BOOT, "Boot Payload"},
 | |
| 		{POSTCODE_FSP_NOTIFY_BEFORE_END_OF_FIRMWARE, "FSP Notify Before End of Firmware"},
 | |
| 		{POSTCODE_FSP_NOTIFY_AFTER_END_OF_FIRMWARE, "FSP Notify After End of Firmware"},
 | |
| 		{POSTCODE_FSP_TEMP_RAM_INIT, "FSP-T Enter"},
 | |
| 		{POSTCODE_FSP_TEMP_RAM_EXIT, "FSP-T Exit"},
 | |
| 		{POSTCODE_FSP_MEMORY_INIT, "FSP-M Enter"},
 | |
| 		{POSTCODE_FSP_SILICON_INIT, "FSP-S Enter"},
 | |
| 		{POSTCODE_FSP_NOTIFY_BEFORE_ENUMERATE, "FSP Notify Before Enumerate"},
 | |
| 		{POSTCODE_FSP_NOTIFY_BEFORE_FINALIZE, "FSP Notify Before Finalize"},
 | |
| 		{POSTCODE_OS_ENTER_PTS, "ACPI _PTS Method"},
 | |
| 		{POSTCODE_OS_ENTER_WAKE, "ACPI _WAK Method"},
 | |
| 		{POSTCODE_FSP_MEMORY_EXIT, "FSP-M Exit"},
 | |
| 		{POSTCODE_FSP_SILICON_EXIT, "FSP-S Exit"},
 | |
| 		{POSTCODE_FSP_MULTI_PHASE_SI_INIT_ENTRY, "FSP-S Init Enter"},
 | |
| 		{POSTCODE_FSP_MULTI_PHASE_SI_INIT_EXIT, "FPS-S Init Exit"},
 | |
| 		{POSTCODE_FSP_NOTIFY_AFTER_ENUMERATE, "FSP Notify After Enumerate"},
 | |
| 		{POSTCODE_FSP_NOTIFY_AFTER_FINALIZE, "FSP Notify After Finalize"},
 | |
| 		{POSTCODE_FSP_MULTI_PHASE_MEM_INIT_ENTRY, "FSP-M Init Enter"},
 | |
| 		{POSTCODE_FSP_MULTI_PHASE_MEM_INIT_EXIT, "FPS-M Init Exit"},
 | |
| 		{POSTCODE_INVALID_ROM, "Invalid ROM"},
 | |
| 		{POSTCODE_INVALID_CBFS, "Invalid CBFS"},
 | |
| 		{POSTCODE_INVALID_VENDOR_BINARY, "Invalid Vendor Binary"},
 | |
| 		{POSTCODE_RAM_FAILURE, "RAM Failure"},
 | |
| 		{POSTCODE_HW_INIT_FAILURE, "Hardware Init Failure"},
 | |
| 		{POSTCODE_VIDEO_FAILURE, "Video Failure"},
 | |
| 		{POSTCODE_TPM_FAILURE, "TPM Failure"},
 | |
| 		{POSTCODE_DEAD_CODE, "Dead Code"},
 | |
| 		{POSTCODE_RESUME_FAILURE, "Resume Failure"},
 | |
| 		{POSTCODE_JUMPING_TO_PAYLOAD, "Before Jump to Payload"},
 | |
| 		{POSTCODE_ENTER_ELF_BOOT, "Before ELF Boot"},
 | |
| 		{POSTCODE_OS_RESUME, "Before OS Resume"},
 | |
| 		{POSTCODE_OS_BOOT, "Before OS Boot"},
 | |
| 		{POSTCODE_DIE, "coreboot Dead"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 	static const struct valstr mem_cache_slots[] = {
 | |
| 		{ELOG_MEM_CACHE_UPDATE_SLOT_NORMAL, "Normal"},
 | |
| 		{ELOG_MEM_CACHE_UPDATE_SLOT_RECOVERY, "Recovery"},
 | |
| 		{ELOG_MEM_CACHE_UPDATE_SLOT_VARIABLE, "Variable"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 	static const struct valstr mem_cache_statuses[] = {
 | |
| 		{ELOG_MEM_CACHE_UPDATE_STATUS_SUCCESS, "Success"},
 | |
| 		{ELOG_MEM_CACHE_UPDATE_STATUS_FAIL, "Fail"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 
 | |
| 	static const struct valstr extended_event_subtypes[] = {
 | |
| 		{ELOG_SLEEP_PENDING_PM1_WAKE, "S3 failed due to pending wake event, PM1"},
 | |
| 		{ELOG_SLEEP_PENDING_GPE0_WAKE, "S3 failed due to pending wake event, GPE0"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 
 | |
| 	static const struct valstr cros_diagnostics_types[] = {
 | |
| 		{ELOG_DEPRECATED_CROS_LAUNCH_DIAGNOSTICS, "Launch Diagnostics"},
 | |
| 		{ELOG_CROS_DIAGNOSTICS_LOGS, "Diagnostics Logs"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 
 | |
| 	static const struct valstr cros_diagnostics_diag_types[] = {
 | |
| 		{ELOG_CROS_DIAG_TYPE_NONE, "None"},
 | |
| 		{ELOG_CROS_DIAG_TYPE_STORAGE_HEALTH, "Storage health info"},
 | |
| 		{ELOG_CROS_DIAG_TYPE_STORAGE_TEST_SHORT, "Storage self-test (short)"},
 | |
| 		{ELOG_CROS_DIAG_TYPE_STORAGE_TEST_EXTENDED, "Storage self-test (extended)"},
 | |
| 		{ELOG_CROS_DIAG_TYPE_MEMORY_QUICK, "Memory check (quick)"},
 | |
| 		{ELOG_CROS_DIAG_TYPE_MEMORY_FULL, "Memory check (full)"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 
 | |
| 	static const struct valstr cros_diagnostics_diag_results[] = {
 | |
| 		{ELOG_CROS_DIAG_RESULT_PASSED, "Passed"},
 | |
| 		{ELOG_CROS_DIAG_RESULT_ERROR, "Error"},
 | |
| 		{ELOG_CROS_DIAG_RESULT_FAILED, "Failed"},
 | |
| 		{ELOG_CROS_DIAG_RESULT_ABORTED, "Aborted"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 
 | |
| 	static const struct valstr early_sol_path_types[] = {
 | |
| 		{ELOG_FW_EARLY_SOL_CSE_SYNC, "CSE Sync Early SOL Screen Shown"},
 | |
| 		{ELOG_FW_EARLY_SOL_MRC, "MRC Early SOL Screen Shown"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 
 | |
| 	static const struct valstr psr_data_backup_statuses[] = {
 | |
| 		{ELOG_PSR_DATA_BACKUP_SUCCESS, "Success"},
 | |
| 		{ELOG_PSR_DATA_BACKUP_FAILED, "Fail"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 
 | |
| 	static const struct valstr late_sol_path_types[] = {
 | |
| 		{ELOG_FW_LATE_SOL_CSE_SYNC, "CSE Sync Late SOL Screen Shown"},
 | |
| 		{0, NULL},
 | |
| 	};
 | |
| 
 | |
| 	size_t elog_type_to_min_size[] = {
 | |
| 		[ELOG_TYPE_LOG_CLEAR]		= sizeof(uint16_t),
 | |
| 		[ELOG_TYPE_BOOT]		= sizeof(uint32_t),
 | |
| 		[ELOG_TYPE_LAST_POST_CODE]	= sizeof(uint16_t),
 | |
| 		[ELOG_TYPE_POST_EXTRA]		= sizeof(uint32_t),
 | |
| 		[ELOG_TYPE_OS_EVENT]		= sizeof(uint32_t),
 | |
| 		[ELOG_TYPE_ACPI_ENTER]		= sizeof(uint8_t),
 | |
| 		[ELOG_TYPE_ACPI_WAKE]		= sizeof(uint8_t),
 | |
| 		[ELOG_TYPE_ACPI_DEEP_WAKE]	= sizeof(uint8_t),
 | |
| 		[ELOG_TYPE_WAKE_SOURCE]		= sizeof(struct elog_event_data_wake),
 | |
| 		[ELOG_TYPE_EC_EVENT]		= sizeof(uint8_t),
 | |
| 		[ELOG_TYPE_EC_DEVICE_EVENT]	= sizeof(uint8_t),
 | |
| 		[ELOG_DEPRECATED_TYPE_CROS_RECOVERY_MODE] = sizeof(uint8_t),
 | |
| 		[ELOG_TYPE_MANAGEMENT_ENGINE]	= sizeof(uint8_t),
 | |
| 		[ELOG_TYPE_MEM_CACHE_UPDATE]	= sizeof(struct elog_event_mem_cache_update),
 | |
| 		[ELOG_TYPE_EXTENDED_EVENT]	= sizeof(struct elog_event_extended_event),
 | |
| 		[ELOG_TYPE_CROS_DIAGNOSTICS]	= sizeof(uint8_t),
 | |
| 		[ELOG_TYPE_FW_VBOOT_INFO]	= sizeof(uint16_t),
 | |
| 		[ELOG_TYPE_FW_EARLY_SOL]	= sizeof(uint8_t),
 | |
| 		[ELOG_TYPE_PSR_DATA_BACKUP]	= sizeof(uint8_t),
 | |
| 		[ELOG_TYPE_FW_SPLASH_SCREEN]	= sizeof(uint8_t),
 | |
| 		[ELOG_TYPE_FW_LATE_SOL]	= sizeof(uint8_t),
 | |
| 		[0xff]				= 0,
 | |
| 	};
 | |
| 
 | |
| 	if (event->length <= sizeof(*event) + elog_type_to_min_size[event->type]) {
 | |
| 		eventlog_printf("INVALID DATA (length = %u)", event->length - sizeof(*event));
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	switch (event->type) {
 | |
| 	case ELOG_TYPE_LOG_CLEAR: {
 | |
| 		const uint16_t *bytes = event_get_data(event);
 | |
| 		eventlog_printf("%u", *bytes);
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	case ELOG_TYPE_BOOT: {
 | |
| 		const uint32_t *count = event_get_data(event);
 | |
| 		eventlog_printf("%u", *count);
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_LAST_POST_CODE: {
 | |
| 		const uint16_t *code = event_get_data(event);
 | |
| 		eventlog_printf("0x%02x", *code);
 | |
| 		eventlog_printf("%s", val2str(*code, coreboot_post_codes));
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_POST_EXTRA: {
 | |
| 		const uint32_t *extra = event_get_data(event);
 | |
| 		eventlog_print_post_extra(*extra);
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_OS_EVENT: {
 | |
| 		const uint32_t *osevent = event_get_data(event);
 | |
| 		eventlog_printf("%s", val2str(*osevent, os_events));
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_ACPI_ENTER:
 | |
| 	case ELOG_TYPE_ACPI_WAKE: {
 | |
| 		const uint8_t *state = event_get_data(event);
 | |
| 		eventlog_printf("S%u", *state);
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_ACPI_DEEP_WAKE: {
 | |
| 		const uint8_t *state = event_get_data(event);
 | |
| 		eventlog_printf("Deep S%u", *state);
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_WAKE_SOURCE: {
 | |
| 		const struct elog_event_data_wake *wake_source;
 | |
| 		wake_source = event_get_data(event);
 | |
| 		eventlog_printf("%s", val2str(wake_source->source, wake_source_types));
 | |
| 		eventlog_printf("%u", wake_source->instance);
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_EC_EVENT: {
 | |
| 		const uint8_t *ec_event = event_get_data(event);
 | |
| 		eventlog_printf("%s", val2str(*ec_event, ec_event_types));
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_EC_DEVICE_EVENT: {
 | |
| 		const uint8_t *dev_event = event_get_data(event);
 | |
| 		eventlog_printf("%s", val2str(*dev_event, ec_device_event_types));
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_DEPRECATED_TYPE_CROS_RECOVERY_MODE: {
 | |
| 		const uint8_t *reason = event_get_data(event);
 | |
| 		eventlog_printf("%s", vb2_get_recovery_reason_string(*reason));
 | |
| 		eventlog_printf("0x%02x", *reason);
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_MANAGEMENT_ENGINE: {
 | |
| 		const uint8_t *path = event_get_data(event);
 | |
| 		eventlog_printf("%s", val2str(*path, me_path_types));
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_MEM_CACHE_UPDATE: {
 | |
| 		const struct elog_event_mem_cache_update *update;
 | |
| 		update = event_get_data(event);
 | |
| 		eventlog_printf("%s", val2str(update->slot, mem_cache_slots));
 | |
| 		eventlog_printf("%s", val2str(update->status, mem_cache_statuses));
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_EXTENDED_EVENT: {
 | |
| 		const struct elog_event_extended_event *ext_event;
 | |
| 		ext_event = event_get_data(event);
 | |
| 		eventlog_printf("%s", val2str(ext_event->event_type, extended_event_subtypes));
 | |
| 		eventlog_printf("0x%X", ext_event->event_complement);
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_CROS_DIAGNOSTICS: {
 | |
| 		const uint8_t *data = event_get_data(event);
 | |
| 		const uint8_t subtype = *data;
 | |
| 		eventlog_printf("%s", val2str(subtype, cros_diagnostics_types));
 | |
| 
 | |
| 		/*
 | |
| 		 * If the subtype is diagnostics logs, there will be many
 | |
| 		 * elog_event_diag_log events after subtype:
 | |
| 		 *
 | |
| 		 * [event_header][(subtype)(log 1)(log 2)...(log n)][checksum]
 | |
| 		 *
 | |
| 		 * Parse them one by one.
 | |
| 		 */
 | |
| 		if (subtype == ELOG_CROS_DIAGNOSTICS_LOGS) {
 | |
| 			size_t i, base_size, log_size, num_logs;
 | |
| 			const union elog_event_cros_diag_log *log;
 | |
| 
 | |
| 			/*
 | |
| 			 * base_size = event header + checksum + subtype;
 | |
| 			 * log_size = event length - base_size.
 | |
| 			 */
 | |
| 			base_size = sizeof(*event) + 1 + sizeof(subtype);
 | |
| 			/* Validity check to prevent log_size overflow */
 | |
| 			if (event->length > base_size) {
 | |
| 				log_size = event->length - base_size;
 | |
| 				num_logs = log_size / sizeof(union elog_event_cros_diag_log);
 | |
| 				log = (const union elog_event_cros_diag_log *)(data + 1);
 | |
| 				for (i = 0; i < num_logs; i++) {
 | |
| 					eventlog_printf("type=%s, result=%s, time=%um%us",
 | |
| 						val2str(log->type,
 | |
| 							cros_diagnostics_diag_types),
 | |
| 						val2str(log->result,
 | |
| 							cros_diagnostics_diag_results),
 | |
| 						log->time_s / 60, log->time_s % 60);
 | |
| 					log++;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_FW_VBOOT_INFO: {
 | |
| 		const union vb2_fw_boot_info *info = event_get_data(event);
 | |
| 
 | |
| 		eventlog_printf("boot_mode=%s", vb2_boot_mode_string(info->boot_mode));
 | |
| 
 | |
| 		if (info->boot_mode == VB2_BOOT_MODE_BROKEN_SCREEN ||
 | |
| 		    info->boot_mode == VB2_BOOT_MODE_MANUAL_RECOVERY) {
 | |
| 			if (event->length <= sizeof(*event) + sizeof(*info))
 | |
| 				eventlog_printf("INVALID DATA (length = %u)",
 | |
| 				  event->length - sizeof(*event));
 | |
| 			else
 | |
| 				eventlog_printf("recovery_reason=%#x/%#x (%s)",
 | |
| 				  info->recovery_reason, info->recovery_subcode,
 | |
| 				  vb2_get_recovery_reason_string(info->recovery_reason));
 | |
| 		}
 | |
| 
 | |
| 		eventlog_printf("fw_tried=%s", vb2_slot_string(info->slot));
 | |
| 		eventlog_printf("fw_try_count=%d", info->tries);
 | |
| 		eventlog_printf("fw_prev_tried=%s", vb2_slot_string(info->prev_slot));
 | |
| 		eventlog_printf("fw_prev_result=%s", vb2_result_string(info->prev_result));
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_FW_EARLY_SOL: {
 | |
| 		const uint8_t *sol_event = event_get_data(event);
 | |
| 		eventlog_printf("%s", val2str(*sol_event, early_sol_path_types));
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_PSR_DATA_BACKUP: {
 | |
| 		const uint8_t *psr_backup_event = event_get_data(event);
 | |
| 		eventlog_printf("%s", val2str(*psr_backup_event, psr_data_backup_statuses));
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_FW_SPLASH_SCREEN: {
 | |
| 		const uint8_t *fw_splash_screen_event = event_get_data(event);
 | |
| 		eventlog_printf("%s", *fw_splash_screen_event ? "Enabled" : "Disabled");
 | |
| 		break;
 | |
| 	}
 | |
| 	case ELOG_TYPE_FW_LATE_SOL: {
 | |
| 		const uint8_t *sol_event = event_get_data(event);
 | |
| 		eventlog_printf("%s", val2str(*sol_event, late_sol_path_types));
 | |
| 		break;
 | |
| 	}
 | |
| 	default:
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| void eventlog_print_event(const struct event_header *event, int count,
 | |
| 			  enum eventlog_timezone tz)
 | |
| {
 | |
| 	/* Ignore the printf separator at the beginning and end of each line */
 | |
| 	eventlog_printf_ignore_separator_once = 1;
 | |
| 
 | |
| 	eventlog_printf("%d", count);
 | |
| 	eventlog_print_timestamp(event, tz);
 | |
| 	eventlog_print_type(event);
 | |
| 	eventlog_print_data(event);
 | |
| 
 | |
| 	/* End of line, after printing each event */
 | |
| 	eventlog_printf_ignore_separator_once = 1;
 | |
| 	eventlog_printf("\n");
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Initializes the eventlog header with the given type and data,
 | |
|  * and calculates the checksum.
 | |
|  * buffer_get() points to the event to be initialized.
 | |
|  * On success it returns 1, otherwise 0.
 | |
|  */
 | |
| int eventlog_init_event(const struct buffer *buf, uint8_t type,
 | |
| 			const void *data, int data_size)
 | |
| {
 | |
| 	struct event_header *event;
 | |
| 	time_t secs = time(NULL);
 | |
| 	struct tm tm;
 | |
| 
 | |
| 	/* Must have at least size for data + checksum byte */
 | |
| 	if (buffer_size(buf) < (size_t)data_size + 1)
 | |
| 		return 0;
 | |
| 
 | |
| 	event = buffer_get(buf);
 | |
| 
 | |
| 	event->type = type;
 | |
| 	gmtime_r(&secs, &tm);
 | |
| 	/* Month should be +1, since gmtime uses 0 as first month */
 | |
| 	elog_fill_timestamp(event, tm.tm_sec, tm.tm_min, tm.tm_hour,
 | |
| 			    tm.tm_mday, tm.tm_mon + 1, tm.tm_year);
 | |
| 
 | |
| 	if (data && data_size) {
 | |
| 		uint32_t *ptr = (uint32_t *)&event[1];
 | |
| 		memcpy(ptr, data, data_size);
 | |
| 	}
 | |
| 
 | |
| 	/* Header + data + checksum */
 | |
| 	event->length = sizeof(*event) + data_size + 1;
 | |
| 
 | |
| 	/* Zero the checksum byte and then compute checksum */
 | |
| 	elog_update_checksum(event, 0);
 | |
| 	elog_update_checksum(event, -(elog_checksum_event(event)));
 | |
| 
 | |
| 	return 1;
 | |
| }
 |