d9e469
From 624d8a1d99a2f3bd06cbc537aff3cc30201ba7c2 Mon Sep 17 00:00:00 2001
d9e469
From: Tyler Baicar <tbaicar@codeaurora.org>
d9e469
Date: Mon, 12 Jun 2017 16:16:04 -0600
d9e469
Subject: [PATCH 1/2] rasdaemon: add support for non standard CPER section
d9e469
 events
d9e469
d9e469
Add support to handle the non standard CPER section kernel trace
d9e469
events which cover RAS errors who's section type is unknown.
d9e469
d9e469
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
d9e469
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
d9e469
---
d9e469
 Makefile.am                |   3 +
d9e469
 configure.ac               |   9 +++
d9e469
 ras-events.c               |  15 +++++
d9e469
 ras-events.h               |   8 +++
d9e469
 ras-non-standard-handler.c | 147 +++++++++++++++++++++++++++++++++++++++++++++
d9e469
 ras-non-standard-handler.h |  26 ++++++++
d9e469
 ras-record.c               |  59 ++++++++++++++++++
d9e469
 ras-record.h               |  15 +++++
d9e469
 ras-report.c               |  80 ++++++++++++++++++++++++
d9e469
 ras-report.h               |  18 +++++-
d9e469
 10 files changed, 379 insertions(+), 1 deletion(-)
d9e469
 create mode 100644 ras-non-standard-handler.c
d9e469
 create mode 100644 ras-non-standard-handler.h
d9e469
d9e469
diff --git a/Makefile.am b/Makefile.am
d9e469
index a10e4b3..c5811e8 100644
d9e469
--- a/Makefile.am
d9e469
+++ b/Makefile.am
d9e469
@@ -24,6 +24,9 @@ endif
d9e469
 if WITH_AER
d9e469
    rasdaemon_SOURCES += ras-aer-handler.c
d9e469
 endif
d9e469
+if WITH_NON_STANDARD
d9e469
+   rasdaemon_SOURCES += ras-non-standard-handler.c
d9e469
+endif
d9e469
 if WITH_MCE
d9e469
    rasdaemon_SOURCES += ras-mce-handler.c mce-intel.c mce-amd-k8.c \
d9e469
 			mce-intel-p4-p6.c mce-intel-nehalem.c \
d9e469
diff --git a/configure.ac b/configure.ac
d9e469
index 5af5227..31bf6bd 100644
d9e469
--- a/configure.ac
d9e469
+++ b/configure.ac
d9e469
@@ -44,6 +44,15 @@ AS_IF([test "x$enable_aer" = "xyes"], [
d9e469
 ])
d9e469
 AM_CONDITIONAL([WITH_AER], [test x$enable_aer = xyes])
d9e469
 
d9e469
+AC_ARG_ENABLE([non_standard],
d9e469
+    AS_HELP_STRING([--enable-non-standard], [enable NON_STANDARD events (currently experimental)]))
d9e469
+
d9e469
+AS_IF([test "x$enable_non_standard" = "xyes"], [
d9e469
+  AC_DEFINE(HAVE_NON_STANDARD,1,"have UNKNOWN_SEC events collect")
d9e469
+  AC_SUBST([WITH_NON_STANDARD])
d9e469
+])
d9e469
+AM_CONDITIONAL([WITH_NON_STANDARD], [test x$enable_non_standard = xyes])
d9e469
+
d9e469
 AC_ARG_ENABLE([mce],
d9e469
     AS_HELP_STRING([--enable-mce], [enable MCE events (currently experimental)]))
d9e469
 
d9e469
diff --git a/ras-events.c b/ras-events.c
d9e469
index 0be7c3f..96aa6f1 100644
d9e469
--- a/ras-events.c
d9e469
+++ b/ras-events.c
d9e469
@@ -29,6 +29,7 @@
d9e469
 #include "libtrace/event-parse.h"
d9e469
 #include "ras-mc-handler.h"
d9e469
 #include "ras-aer-handler.h"
d9e469
+#include "ras-non-standard-handler.h"
d9e469
 #include "ras-mce-handler.h"
d9e469
 #include "ras-extlog-handler.h"
d9e469
 #include "ras-record.h"
d9e469
@@ -208,6 +209,10 @@ int toggle_ras_mc_event(int enable)
d9e469
 	rc |= __toggle_ras_mc_event(ras, "ras", "extlog_mem_event", enable);
d9e469
 #endif
d9e469
 
d9e469
+#ifdef HAVE_NON_STANDARD
d9e469
+	rc |= __toggle_ras_mc_event(ras, "ras", "non_standard_event", enable);
d9e469
+#endif
d9e469
+
d9e469
 free_ras:
d9e469
 	free(ras);
d9e469
 	return rc;
d9e469
@@ -676,6 +681,16 @@ int handle_ras_events(int record_events)
d9e469
 		    "ras", "aer_event");
d9e469
 #endif
d9e469
 
d9e469
+#ifdef HAVE_NON_STANDARD
d9e469
+        rc = add_event_handler(ras, pevent, page_size, "ras", "non_standard_event",
d9e469
+                               ras_non_standard_event_handler);
d9e469
+        if (!rc)
d9e469
+                num_events++;
d9e469
+        else
d9e469
+                log(ALL, LOG_ERR, "Can't get traces from %s:%s\n",
d9e469
+                    "ras", "non_standard_event");
d9e469
+#endif
d9e469
+
d9e469
 	cpus = get_num_cpus(ras);
d9e469
 
d9e469
 #ifdef HAVE_MCE
d9e469
diff --git a/ras-events.h b/ras-events.h
d9e469
index 64e045a..3e1008f 100644
d9e469
--- a/ras-events.h
d9e469
+++ b/ras-events.h
d9e469
@@ -68,6 +68,14 @@ enum hw_event_mc_err_type {
d9e469
 	HW_EVENT_ERR_INFO,
d9e469
 };
d9e469
 
d9e469
+/* Should match the code at Kernel's include/acpi/ghes.h */
d9e469
+enum ghes_severity {
d9e469
+	GHES_SEV_NO,
d9e469
+	GHES_SEV_CORRECTED,
d9e469
+	GHES_SEV_RECOVERABLE,
d9e469
+	GHES_SEV_PANIC,
d9e469
+};
d9e469
+
d9e469
 /* Function prototypes */
d9e469
 int toggle_ras_mc_event(int enable);
d9e469
 int handle_ras_events(int record_events);
d9e469
diff --git a/ras-non-standard-handler.c b/ras-non-standard-handler.c
d9e469
new file mode 100644
d9e469
index 0000000..4c154e5
d9e469
--- /dev/null
d9e469
+++ b/ras-non-standard-handler.c
d9e469
@@ -0,0 +1,147 @@
d9e469
+/*
d9e469
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
d9e469
+ *
d9e469
+ * This program is free software; you can redistribute it and/or modify
d9e469
+ * it under the terms of the GNU General Public License version 2 and
d9e469
+ * only version 2 as published by the Free Software Foundation.
d9e469
+
d9e469
+ * This program is distributed in the hope that it will be useful,
d9e469
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
d9e469
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
d9e469
+ * GNU General Public License for more details.
d9e469
+ */
d9e469
+
d9e469
+#include <stdio.h>
d9e469
+#include <stdlib.h>
d9e469
+#include <string.h>
d9e469
+#include <unistd.h>
d9e469
+#include "libtrace/kbuffer.h"
d9e469
+#include "ras-non-standard-handler.h"
d9e469
+#include "ras-record.h"
d9e469
+#include "ras-logger.h"
d9e469
+#include "ras-report.h"
d9e469
+
d9e469
+void print_le_hex(struct trace_seq *s, const uint8_t *buf, int index) {
d9e469
+	trace_seq_printf(s, "%02x%02x%02x%02x", buf[index+3], buf[index+2], buf[index+1], buf[index]);
d9e469
+}
d9e469
+
d9e469
+static char *uuid_le(const char *uu)
d9e469
+{
d9e469
+	static char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
d9e469
+	char *p = uuid;
d9e469
+	int i;
d9e469
+	static const unsigned char le[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15};
d9e469
+
d9e469
+	for (i = 0; i < 16; i++) {
d9e469
+		p += sprintf(p, "%.2x", uu[le[i]]);
d9e469
+		switch (i) {
d9e469
+		case 3:
d9e469
+		case 5:
d9e469
+		case 7:
d9e469
+		case 9:
d9e469
+			*p++ = '-';
d9e469
+			break;
d9e469
+		}
d9e469
+	}
d9e469
+
d9e469
+	*p = 0;
d9e469
+
d9e469
+	return uuid;
d9e469
+}
d9e469
+
d9e469
+int ras_non_standard_event_handler(struct trace_seq *s,
d9e469
+			 struct pevent_record *record,
d9e469
+			 struct event_format *event, void *context)
d9e469
+{
d9e469
+	int len, i, line_count;
d9e469
+	unsigned long long val;
d9e469
+	struct ras_events *ras = context;
d9e469
+	time_t now;
d9e469
+	struct tm *tm;
d9e469
+	struct ras_non_standard_event ev;
d9e469
+
d9e469
+	/*
d9e469
+	 * Newer kernels (3.10-rc1 or upper) provide an uptime clock.
d9e469
+	 * On previous kernels, the way to properly generate an event would
d9e469
+	 * be to inject a fake one, measure its timestamp and diff it against
d9e469
+	 * gettimeofday. We won't do it here. Instead, let's use uptime,
d9e469
+	 * falling-back to the event report's time, if "uptime" clock is
d9e469
+	 * not available (legacy kernels).
d9e469
+	 */
d9e469
+
d9e469
+	if (ras->use_uptime)
d9e469
+		now = record->ts/user_hz + ras->uptime_diff;
d9e469
+	else
d9e469
+		now = time(NULL);
d9e469
+
d9e469
+	tm = localtime(&now;;
d9e469
+	if (tm)
d9e469
+		strftime(ev.timestamp, sizeof(ev.timestamp),
d9e469
+			 "%Y-%m-%d %H:%M:%S %z", tm);
d9e469
+	trace_seq_printf(s, "%s ", ev.timestamp);
d9e469
+
d9e469
+	if (pevent_get_field_val(s, event, "sev", record, &val, 1) < 0)
d9e469
+		return -1;
d9e469
+	switch (val) {
d9e469
+	case GHES_SEV_NO:
d9e469
+		ev.severity = "Informational";
d9e469
+		break;
d9e469
+	case GHES_SEV_CORRECTED:
d9e469
+		ev.severity = "Corrected";
d9e469
+		break;
d9e469
+	case GHES_SEV_RECOVERABLE:
d9e469
+		ev.severity = "Recoverable";
d9e469
+		break;
d9e469
+	default:
d9e469
+	case GHES_SEV_PANIC:
d9e469
+		ev.severity = "Fatal";
d9e469
+	}
d9e469
+	trace_seq_printf(s, "\n %s", ev.severity);
d9e469
+
d9e469
+	ev.sec_type = pevent_get_field_raw(s, event, "sec_type", record, &len, 1);
d9e469
+	if(!ev.sec_type)
d9e469
+		return -1;
d9e469
+	trace_seq_printf(s, "\n section type: %s", uuid_le(ev.sec_type));
d9e469
+	ev.fru_text = pevent_get_field_raw(s, event, "fru_text",
d9e469
+						record, &len, 1);
d9e469
+	ev.fru_id = pevent_get_field_raw(s, event, "fru_id",
d9e469
+						record, &len, 1);
d9e469
+	trace_seq_printf(s, " fru text: %s fru id: %s ",
d9e469
+				ev.fru_text,
d9e469
+				uuid_le(ev.fru_id));
d9e469
+
d9e469
+	if (pevent_get_field_val(s, event, "len", record, &val, 1) < 0)
d9e469
+		return -1;
d9e469
+	ev.length = val;
d9e469
+	trace_seq_printf(s, "\n length: %d\n", ev.length);
d9e469
+
d9e469
+	ev.error = pevent_get_field_raw(s, event, "buf", record, &len, 1);
d9e469
+	if(!ev.error)
d9e469
+		return -1;
d9e469
+	len = ev.length;
d9e469
+	i = 0;
d9e469
+	line_count = 0;
d9e469
+	trace_seq_printf(s, " error:\n  %08x: ", i);
d9e469
+	while(len >= 4) {
d9e469
+		print_le_hex(s, ev.error, i);
d9e469
+		i+=4;
d9e469
+		len-=4;
d9e469
+		if(++line_count == 4) {
d9e469
+			trace_seq_printf(s, "\n  %08x: ", i);
d9e469
+			line_count = 0;
d9e469
+		} else
d9e469
+			trace_seq_printf(s, " ");
d9e469
+	}
d9e469
+
d9e469
+	/* Insert data into the SGBD */
d9e469
+#ifdef HAVE_SQLITE3
d9e469
+	ras_store_non_standard_record(ras, &ev;;
d9e469
+#endif
d9e469
+
d9e469
+#ifdef HAVE_ABRT_REPORT
d9e469
+	/* Report event to ABRT */
d9e469
+	ras_report_non_standard_event(ras, &ev;;
d9e469
+#endif
d9e469
+
d9e469
+	return 0;
d9e469
+}
d9e469
diff --git a/ras-non-standard-handler.h b/ras-non-standard-handler.h
d9e469
new file mode 100644
d9e469
index 0000000..2b5ac35
d9e469
--- /dev/null
d9e469
+++ b/ras-non-standard-handler.h
d9e469
@@ -0,0 +1,26 @@
d9e469
+/*
d9e469
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
d9e469
+ *
d9e469
+ * This program is free software; you can redistribute it and/or modify
d9e469
+ * it under the terms of the GNU General Public License version 2 and
d9e469
+ * only version 2 as published by the Free Software Foundation.
d9e469
+
d9e469
+ * This program is distributed in the hope that it will be useful,
d9e469
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
d9e469
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
d9e469
+ * GNU General Public License for more details.
d9e469
+ */
d9e469
+
d9e469
+#ifndef __RAS_NON_STANDARD_HANDLER_H
d9e469
+#define __RAS_NON_STANDARD_HANDLER_H
d9e469
+
d9e469
+#include "ras-events.h"
d9e469
+#include "libtrace/event-parse.h"
d9e469
+
d9e469
+int ras_non_standard_event_handler(struct trace_seq *s,
d9e469
+			 struct pevent_record *record,
d9e469
+			 struct event_format *event, void *context);
d9e469
+
d9e469
+void print_le_hex(struct trace_seq *s, const uint8_t *buf, int index);
d9e469
+
d9e469
+#endif
d9e469
diff --git a/ras-record.c b/ras-record.c
d9e469
index 3dc4493..357ab61 100644
d9e469
--- a/ras-record.c
d9e469
+++ b/ras-record.c
d9e469
@@ -1,5 +1,6 @@
d9e469
 /*
d9e469
  * Copyright (C) 2013 Mauro Carvalho Chehab <mchehab@redhat.com>
d9e469
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
d9e469
  *
d9e469
  * This program is free software; you can redistribute it and/or modify
d9e469
  * it under the terms of the GNU General Public License as published by
d9e469
@@ -157,6 +158,57 @@ int ras_store_aer_event(struct ras_events *ras, struct ras_aer_event *ev)
d9e469
 }
d9e469
 #endif
d9e469
 
d9e469
+/*
d9e469
+ * Table and functions to handle ras:non standard
d9e469
+ */
d9e469
+
d9e469
+#ifdef HAVE_NON_STANDARD
d9e469
+static const struct db_fields non_standard_event_fields[] = {
d9e469
+		{ .name="id",			.type="INTEGER PRIMARY KEY" },
d9e469
+		{ .name="timestamp",		.type="TEXT" },
d9e469
+		{ .name="sec_type",		.type="BLOB" },
d9e469
+		{ .name="fru_id",		.type="BLOB" },
d9e469
+		{ .name="fru_text",		.type="TEXT" },
d9e469
+		{ .name="severity",		.type="TEXT" },
d9e469
+		{ .name="error",		.type="BLOB" },
d9e469
+};
d9e469
+
d9e469
+static const struct db_table_descriptor non_standard_event_tab = {
d9e469
+	.name = "non_standard_event",
d9e469
+	.fields = non_standard_event_fields,
d9e469
+	.num_fields = ARRAY_SIZE(non_standard_event_fields),
d9e469
+};
d9e469
+
d9e469
+int ras_store_non_standard_record(struct ras_events *ras, struct ras_non_standard_event *ev)
d9e469
+{
d9e469
+	int rc;
d9e469
+	struct sqlite3_priv *priv = ras->db_priv;
d9e469
+
d9e469
+	if (!priv || !priv->stmt_non_standard_record)
d9e469
+		return 0;
d9e469
+	log(TERM, LOG_INFO, "non_standard_event store: %p\n", priv->stmt_non_standard_record);
d9e469
+
d9e469
+	sqlite3_bind_text (priv->stmt_non_standard_record,  1, ev->timestamp, -1, NULL);
d9e469
+	sqlite3_bind_blob (priv->stmt_non_standard_record,  2, ev->sec_type, -1, NULL);
d9e469
+	sqlite3_bind_blob (priv->stmt_non_standard_record,  3, ev->fru_id, 16, NULL);
d9e469
+	sqlite3_bind_text (priv->stmt_non_standard_record,  4, ev->fru_text, -1, NULL);
d9e469
+	sqlite3_bind_text (priv->stmt_non_standard_record,  5, ev->severity, -1, NULL);
d9e469
+	sqlite3_bind_blob (priv->stmt_non_standard_record,  6, ev->error, ev->length, NULL);
d9e469
+
d9e469
+	rc = sqlite3_step(priv->stmt_non_standard_record);
d9e469
+	if (rc != SQLITE_OK && rc != SQLITE_DONE)
d9e469
+		log(TERM, LOG_ERR,
d9e469
+		    "Failed to do non_standard_event step on sqlite: error = %d\n", rc);
d9e469
+	rc = sqlite3_reset(priv->stmt_non_standard_record);
d9e469
+	if (rc != SQLITE_OK && rc != SQLITE_DONE)
d9e469
+		log(TERM, LOG_ERR,
d9e469
+		    "Failed reset non_standard_event on sqlite: error = %d\n", rc);
d9e469
+	log(TERM, LOG_INFO, "register inserted at db\n");
d9e469
+
d9e469
+	return rc;
d9e469
+}
d9e469
+#endif
d9e469
+
d9e469
 #ifdef HAVE_EXTLOG
d9e469
 static const struct db_fields extlog_event_fields[] = {
d9e469
 		{ .name="id",			.type="INTEGER PRIMARY KEY" },
d9e469
@@ -450,6 +502,13 @@ int ras_mc_event_opendb(unsigned cpu, struct ras_events *ras)
d9e469
 					 &mce_record_tab);
d9e469
 #endif
d9e469
 
d9e469
+#ifdef HAVE_NON_STANDARD
d9e469
+	rc = ras_mc_create_table(priv, &non_standard_event_tab);
d9e469
+	if (rc == SQLITE_OK)
d9e469
+		rc = ras_mc_prepare_stmt(priv, &priv->stmt_non_standard_record,
d9e469
+					&non_standard_event_tab);
d9e469
+#endif
d9e469
+
d9e469
 		ras->db_priv = priv;
d9e469
 	return 0;
d9e469
 }
d9e469
diff --git a/ras-record.h b/ras-record.h
d9e469
index 5d84297..473ae40 100644
d9e469
--- a/ras-record.h
d9e469
+++ b/ras-record.h
d9e469
@@ -1,5 +1,6 @@
d9e469
 /*
d9e469
  * Copyright (C) 2013 Mauro Carvalho Chehab <mchehab@redhat.com>
d9e469
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
d9e469
  *
d9e469
  * This program is free software; you can redistribute it and/or modify
d9e469
  * it under the terms of the GNU General Public License as published by
d9e469
@@ -56,9 +57,18 @@ struct ras_extlog_event {
d9e469
 	unsigned short cper_data_length;
d9e469
 };
d9e469
 
d9e469
+struct ras_non_standard_event {
d9e469
+	char timestamp[64];
d9e469
+	const char *sec_type, *fru_id, *fru_text;
d9e469
+	const char *severity;
d9e469
+	const uint8_t *error;
d9e469
+	uint32_t length;
d9e469
+};
d9e469
+
d9e469
 struct ras_mc_event;
d9e469
 struct ras_aer_event;
d9e469
 struct ras_extlog_event;
d9e469
+struct ras_non_standard_event;
d9e469
 struct mce_event;
d9e469
 
d9e469
 #ifdef HAVE_SQLITE3
d9e469
@@ -77,6 +87,9 @@ struct sqlite3_priv {
d9e469
 #ifdef HAVE_EXTLOG
d9e469
 	sqlite3_stmt	*stmt_extlog_record;
d9e469
 #endif
d9e469
+#ifdef HAVE_NON_STANDARD
d9e469
+	sqlite3_stmt	*stmt_non_standard_record;
d9e469
+#endif
d9e469
 };
d9e469
 
d9e469
 int ras_mc_event_opendb(unsigned cpu, struct ras_events *ras);
d9e469
@@ -84,6 +97,7 @@ int ras_store_mc_event(struct ras_events *ras, struct ras_mc_event *ev);
d9e469
 int ras_store_aer_event(struct ras_events *ras, struct ras_aer_event *ev);
d9e469
 int ras_store_mce_record(struct ras_events *ras, struct mce_event *ev);
d9e469
 int ras_store_extlog_mem_record(struct ras_events *ras, struct ras_extlog_event *ev);
d9e469
+int ras_store_non_standard_record(struct ras_events *ras, struct ras_non_standard_event *ev);
d9e469
 
d9e469
 #else
d9e469
 static inline int ras_mc_event_opendb(unsigned cpu, struct ras_events *ras) { return 0; };
d9e469
@@ -91,6 +105,7 @@ static inline int ras_store_mc_event(struct ras_events *ras, struct ras_mc_event
d9e469
 static inline int ras_store_aer_event(struct ras_events *ras, struct ras_aer_event *ev) { return 0; };
d9e469
 static inline int ras_store_mce_record(struct ras_events *ras, struct mce_event *ev) { return 0; };
d9e469
 static inline int ras_store_extlog_mem_record(struct ras_events *ras, struct ras_extlog_event *ev) { return 0; };
d9e469
+static inline int ras_store_non_standard_record(struct ras_events *ras, struct ras_non_standard_event *ev) { return 0; };
d9e469
 
d9e469
 #endif
d9e469
 
d9e469
diff --git a/ras-report.c b/ras-report.c
d9e469
index 0a05732..1eb9f79 100644
d9e469
--- a/ras-report.c
d9e469
+++ b/ras-report.c
d9e469
@@ -1,3 +1,16 @@
d9e469
+/*
d9e469
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
d9e469
+ *
d9e469
+ * This program is free software; you can redistribute it and/or modify
d9e469
+ * it under the terms of the GNU General Public License version 2 and
d9e469
+ * only version 2 as published by the Free Software Foundation.
d9e469
+
d9e469
+ * This program is distributed in the hope that it will be useful,
d9e469
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
d9e469
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
d9e469
+ * GNU General Public License for more details.
d9e469
+ */
d9e469
+
d9e469
 #include <stdio.h>
d9e469
 #include <string.h>
d9e469
 #include <unistd.h>
d9e469
@@ -196,6 +209,25 @@ static int set_aer_event_backtrace(char *buf, struct ras_aer_event *ev){
d9e469
 	return 0;
d9e469
 }
d9e469
 
d9e469
+static int set_non_standard_event_backtrace(char *buf, struct ras_non_standard_event *ev){
d9e469
+	char bt_buf[MAX_BACKTRACE_SIZE];
d9e469
+
d9e469
+	if(!buf || !ev)
d9e469
+		return -1;
d9e469
+
d9e469
+	sprintf(bt_buf, "BACKTRACE="	\
d9e469
+						"timestamp=%s\n"	\
d9e469
+						"severity=%s\n"	\
d9e469
+						"length=%d\n",	\
d9e469
+						ev->timestamp,	\
d9e469
+						ev->severity,	\
d9e469
+						ev->length);
d9e469
+
d9e469
+	strcat(buf, bt_buf);
d9e469
+
d9e469
+	return 0;
d9e469
+}
d9e469
+
d9e469
 static int commit_report_backtrace(int sockfd, int type, void *ev){
d9e469
 	char buf[MAX_BACKTRACE_SIZE];
d9e469
 	char *pbuf = buf;
d9e469
@@ -218,6 +250,9 @@ static int commit_report_backtrace(int sockfd, int type, void *ev){
d9e469
 	case MCE_EVENT:
d9e469
 		rc = set_mce_event_backtrace(buf, (struct mce_event *)ev);
d9e469
 		break;
d9e469
+	case NON_STANDARD_EVENT:
d9e469
+		rc = set_non_standard_event_backtrace(buf, (struct ras_non_standard_event *)ev);
d9e469
+		break;
d9e469
 	default:
d9e469
 		return -1;
d9e469
 	}
d9e469
@@ -345,6 +380,51 @@ aer_fail:
d9e469
 	}
d9e469
 }
d9e469
 
d9e469
+int ras_report_non_standard_event(struct ras_events *ras, struct ras_non_standard_event *ev){
d9e469
+	char buf[MAX_MESSAGE_SIZE];
d9e469
+	int sockfd = 0;
d9e469
+	int rc = -1;
d9e469
+
d9e469
+	memset(buf, 0, sizeof(buf));
d9e469
+
d9e469
+	sockfd = setup_report_socket();
d9e469
+	if(sockfd < 0){
d9e469
+		return rc;
d9e469
+	}
d9e469
+
d9e469
+	rc = commit_report_basic(sockfd);
d9e469
+	if(rc < 0){
d9e469
+		goto non_standard_fail;
d9e469
+	}
d9e469
+
d9e469
+	rc = commit_report_backtrace(sockfd, NON_STANDARD_EVENT, ev);
d9e469
+	if(rc < 0){
d9e469
+		goto non_standard_fail;
d9e469
+	}
d9e469
+
d9e469
+	sprintf(buf, "ANALYZER=%s", "rasdaemon-non-standard");
d9e469
+	rc = write(sockfd, buf, strlen(buf) + 1);
d9e469
+	if(rc < strlen(buf) + 1){
d9e469
+		goto non_standard_fail;
d9e469
+	}
d9e469
+
d9e469
+	sprintf(buf, "REASON=%s", "Unknown CPER section problem");
d9e469
+	rc = write(sockfd, buf, strlen(buf) + 1);
d9e469
+	if(rc < strlen(buf) + 1){
d9e469
+		goto non_standard_fail;
d9e469
+	}
d9e469
+
d9e469
+	rc = 0;
d9e469
+
d9e469
+non_standard_fail:
d9e469
+
d9e469
+	if(sockfd > 0){
d9e469
+		close(sockfd);
d9e469
+	}
d9e469
+
d9e469
+	return rc;
d9e469
+}
d9e469
+
d9e469
 int ras_report_mce_event(struct ras_events *ras, struct mce_event *ev){
d9e469
 	char buf[MAX_MESSAGE_SIZE];
d9e469
 	int sockfd = 0;
d9e469
diff --git a/ras-report.h b/ras-report.h
d9e469
index 7920cdf..c2fcf42 100644
d9e469
--- a/ras-report.h
d9e469
+++ b/ras-report.h
d9e469
@@ -1,3 +1,16 @@
d9e469
+/*
d9e469
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
d9e469
+ *
d9e469
+ * This program is free software; you can redistribute it and/or modify
d9e469
+ * it under the terms of the GNU General Public License version 2 and
d9e469
+ * only version 2 as published by the Free Software Foundation.
d9e469
+
d9e469
+ * This program is distributed in the hope that it will be useful,
d9e469
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
d9e469
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
d9e469
+ * GNU General Public License for more details.
d9e469
+ */
d9e469
+
d9e469
 #ifndef __RAS_REPORT_H
d9e469
 #define __RAS_REPORT_H
d9e469
 
d9e469
@@ -19,7 +32,8 @@
d9e469
 enum {
d9e469
 	MC_EVENT,
d9e469
 	MCE_EVENT,
d9e469
-	AER_EVENT
d9e469
+	AER_EVENT,
d9e469
+	NON_STANDARD_EVENT
d9e469
 };
d9e469
 
d9e469
 #ifdef HAVE_ABRT_REPORT
d9e469
@@ -27,12 +41,14 @@ enum {
d9e469
 int ras_report_mc_event(struct ras_events *ras, struct ras_mc_event *ev);
d9e469
 int ras_report_aer_event(struct ras_events *ras, struct ras_aer_event *ev);
d9e469
 int ras_report_mce_event(struct ras_events *ras, struct mce_event *ev);
d9e469
+int ras_report_non_standard_event(struct ras_events *ras, struct ras_non_standard_event *ev);
d9e469
 
d9e469
 #else
d9e469
 
d9e469
 static inline int ras_report_mc_event(struct ras_events *ras, struct ras_mc_event *ev) { return 0; };
d9e469
 static inline int ras_report_aer_event(struct ras_events *ras, struct ras_aer_event *ev) { return 0; };
d9e469
 static inline int ras_report_mce_event(struct ras_events *ras, struct mce_event *ev) { return 0; };
d9e469
+static inline int ras_report_non_standard_event(struct ras_events *ras, struct ras_non_standard_event *ev) { return 0; };
d9e469
 
d9e469
 #endif
d9e469
 
d9e469
-- 
d9e469
1.8.3.1
d9e469