diff options
-rw-r--r-- | src/arch/x86/boot/smbios.c | 4 | ||||
-rw-r--r-- | src/drivers/elog/elog.c | 29 | ||||
-rw-r--r-- | src/drivers/elog/elog_internal.h | 15 | ||||
-rw-r--r-- | src/include/elog.h | 1 | ||||
-rw-r--r-- | src/include/smbios.h | 31 |
5 files changed, 80 insertions, 0 deletions
diff --git a/src/arch/x86/boot/smbios.c b/src/arch/x86/boot/smbios.c index 3b9e5a1327..9c61e28dcc 100644 --- a/src/arch/x86/boot/smbios.c +++ b/src/arch/x86/boot/smbios.c @@ -29,6 +29,7 @@ #include <cpu/x86/name.h> #include <cbfs_core.h> #include <arch/byteorder.h> +#include <elog.h> #if CONFIG_CHROMEOS #include <vendorcode/google/chromeos/gnvs.h> #endif @@ -296,6 +297,9 @@ unsigned long smbios_write_tables(unsigned long current) len += smbios_write_type1(¤t, handle++); len += smbios_write_type3(¤t, handle++); len += smbios_write_type4(¤t, handle++); +#if CONFIG_ELOG + len += elog_smbios_write_type15(¤t, handle++); +#endif len += smbios_write_type32(¤t, handle++); len += smbios_walk_device_tree(all_devices, &handle, ¤t); diff --git a/src/drivers/elog/elog.c b/src/drivers/elog/elog.c index 8e56b85242..9c0fa930ad 100644 --- a/src/drivers/elog/elog.c +++ b/src/drivers/elog/elog.c @@ -20,6 +20,7 @@ #include <arch/acpi.h> #include <console/console.h> #include <pc80/mc146818rtc.h> +#include <smbios.h> #include <spi.h> #include <spi_flash.h> #include <stdint.h> @@ -677,6 +678,34 @@ static int elog_spi_init(void) } /* + * Fill out SMBIOS Type 15 table entry so the + * event log can be discovered at runtime. + */ +int elog_smbios_write_type15(unsigned long *current, int handle) +{ + struct smbios_type15 *t = (struct smbios_type15 *)*current; + int len = sizeof(struct smbios_type15); + + memset(t, 0, len); + t->type = SMBIOS_EVENT_LOG; + t->length = len - 2; + t->handle = handle; + t->area_length = elog_get_flash()->total_size - 1; + t->header_offset = 0; + t->data_offset = sizeof(struct elog_header); + t->access_method = SMBIOS_EVENTLOG_ACCESS_METHOD_MMIO32; + t->log_status = SMBIOS_EVENTLOG_STATUS_VALID; + t->change_token = 0; + t->address = (u32)elog_get_flash()->backing_store; + t->header_format = ELOG_HEADER_TYPE_OEM; + t->log_type_descriptors = 0; + t->log_type_descriptor_length = 2; + + *current += len; + return len; +} + +/* * Clear the entire event log */ int elog_clear(void) diff --git a/src/drivers/elog/elog_internal.h b/src/drivers/elog/elog_internal.h index 2a6a0b7fc4..6d9a0d4bb5 100644 --- a/src/drivers/elog/elog_internal.h +++ b/src/drivers/elog/elog_internal.h @@ -32,6 +32,21 @@ struct elog_header { #define ELOG_SIGNATURE 0x474f4c45 /* 'ELOG' */ #define ELOG_VERSION 1 +/* SMBIOS event log header */ +struct event_header { + u8 type; + u8 length; + u8 year; + u8 month; + u8 day; + u8 hour; + u8 minute; + u8 second; +} __attribute__ ((packed)); + +/* SMBIOS Type 15 related constants */ +#define ELOG_HEADER_TYPE_OEM 0x88 + typedef enum elog_descriptor_type { ELOG_DESCRIPTOR_UNKNOWN, ELOG_DESCRIPTOR_MEMORY, diff --git a/src/include/elog.h b/src/include/elog.h index c6599a249c..897a90bf41 100644 --- a/src/include/elog.h +++ b/src/include/elog.h @@ -113,6 +113,7 @@ extern void elog_add_event_byte(u8 event_type, u8 data); extern void elog_add_event_word(u8 event_type, u16 data); extern void elog_add_event_dword(u8 event_type, u32 data); extern void elog_add_event_wake(u8 source, u32 instance); +extern int elog_smbios_write_type15(unsigned long *current, int handle); #endif /* !CONFIG_ELOG */ diff --git a/src/include/smbios.h b/src/include/smbios.h index 7912ba151f..c65851550a 100644 --- a/src/include/smbios.h +++ b/src/include/smbios.h @@ -28,6 +28,7 @@ typedef enum { SMBIOS_PROCESSOR_INFORMATION=4, SMBIOS_CACHE_INFORMATION=7, SMBIOS_SYSTEM_SLOTS=9, + SMBIOS_EVENT_LOG=15, SMBIOS_PHYS_MEMORY_ARRAY=16, SMBIOS_MEMORY_DEVICE=17, SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS=19, @@ -138,6 +139,36 @@ struct smbios_type4 { char eos[2]; } __attribute__((packed)); +struct smbios_type15 { + u8 type; + u8 length; + u16 handle; + u16 area_length; + u16 header_offset; + u16 data_offset; + u8 access_method; + u8 log_status; + u32 change_token; + u32 address; + u8 header_format; + u8 log_type_descriptors; + u8 log_type_descriptor_length; + char eos[2]; +} __attribute__((packed)); + +enum { + SMBIOS_EVENTLOG_ACCESS_METHOD_IO8 = 0, + SMBIOS_EVENTLOG_ACCESS_METHOD_IO8X2, + SMBIOS_EVENTLOG_ACCESS_METHOD_IO16, + SMBIOS_EVENTLOG_ACCESS_METHOD_MMIO32, + SMBIOS_EVENTLOG_ACCESS_METHOD_GPNV, +}; + +enum { + SMBIOS_EVENTLOG_STATUS_VALID = 1, /* Bit 0 */ + SMBIOS_EVENTLOG_STATUS_FULL = 2, /* Bit 1 */ +}; + struct smbios_type16 { u8 type; u8 length; |