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