summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/x86/boot/smbios.c4
-rw-r--r--src/drivers/elog/elog.c29
-rw-r--r--src/drivers/elog/elog_internal.h15
-rw-r--r--src/include/elog.h1
-rw-r--r--src/include/smbios.h31
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(&current, handle++);
len += smbios_write_type3(&current, handle++);
len += smbios_write_type4(&current, handle++);
+#if CONFIG_ELOG
+ len += elog_smbios_write_type15(&current, handle++);
+#endif
len += smbios_write_type32(&current, handle++);
len += smbios_walk_device_tree(all_devices, &handle, &current);
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;