[Skiboot] [RFC PATCH 10/10] console: add log scraping OPAL call

Oliver O'Halloran oohall at gmail.com
Wed Dec 21 16:35:44 AEDT 2016


Adds an OPAL call that parses the OPAL log, finds important messages
(log_level below PR_WARN) and copies them up to the OS. This is intended
to make firmware error messages more visible to system administrators
since it allows the OS the report them in the usual places rather than
a OPAL specific log file (e.g. /sys/firmware/opal/msglog under linux).

Signed-off-by: Oliver O'Halloran <oohall at gmail.com>
---
 core/console-log.c |  5 +++++
 core/console.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/opal-api.h |  4 +++-
 3 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/core/console-log.c b/core/console-log.c
index 7173199135fd..5092a69e3b2c 100644
--- a/core/console-log.c
+++ b/core/console-log.c
@@ -27,6 +27,8 @@
 #include "console.h"
 #include "timebase.h"
 #include "ctype.h"
+#include "opal-api.h"
+#include "opal-internal.h"
 
 static int vprlog(int log_level, const char *fmt, va_list ap)
 {
@@ -51,6 +53,9 @@ static int vprlog(int log_level, const char *fmt, va_list ap)
 
 	console_write(buffer, count);
 
+	if (log_level <= PR_ERR)
+		opal_set_pending_evt(OPAL_EVENT_LOG_PENDING);
+
 	return count;
 }
 
diff --git a/core/console.c b/core/console.c
index 4a46f6ebaaa5..050d08903ffd 100644
--- a/core/console.c
+++ b/core/console.c
@@ -154,6 +154,12 @@ static int find_eol(int start)
 	return len;
 }
 
+/* this is a bit ugly, but eh... */
+#define foreach_logline(offset, start, len, log_lvl) \
+for (start = offset; \
+	log_lvl = parse_loghdr(start), len = find_eol(start), start != con_in; \
+	start = (start + len) % memcons.obuf_size)
+
 /*
  * Flush the console buffer into the driver. Returns true
  * if there is more to go, but that only happens when the
@@ -237,6 +243,55 @@ bail:
 	return con_out != con_in;
 }
 
+static int64_t opal_scrape_log(int64_t *offset, char *buffer,
+			       int64_t len, int64_t *lvl)
+{
+	int start, req, log_lvl, i = 0;
+	int64_t rc = OPAL_EMPTY;
+
+	if (*offset > memcons.obuf_size)
+		return OPAL_PARAMETER;
+
+	/* if we aren't provided a real offset then scan from the offset */
+	if (*offset < 0)
+		*offset = 0;// = last_err;
+
+	lock(&con_lock);
+
+	foreach_logline(*offset, start, req, log_lvl) {
+		if (log_lvl > PR_ERR)
+			continue;
+
+		if (log_lvl < 0)
+			continue;
+
+		*lvl = log_lvl;
+
+		/* strip the log header bits and the \r\n */
+		req -= loghdr_size + 2;
+		start += loghdr_size;
+
+		rc = OPAL_SUCCESS;
+		for (i = 0; i < req && i < len - 1; i++)
+			buffer[i] = conbuf_get(start + i);
+		buffer[i] = '\0';
+
+		/* buffer to small? */
+		if (i == len - 1)
+			rc = OPAL_PARTIAL;
+
+		break;
+	}
+
+	if (rc == OPAL_EMPTY)
+		opal_clr_pending_evt(OPAL_EVENT_LOG_PENDING);
+
+	*offset = start + i;
+	unlock(&con_lock);
+	return rc;
+}
+opal_call(OPAL_SCRAPE_LOG, opal_scrape_log, 4);
+
 bool flush_console(void)
 {
 	bool ret;
diff --git a/include/opal-api.h b/include/opal-api.h
index 05ff51dd549d..37b58229a15a 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -181,7 +181,8 @@
 #define OPAL_INT_SET_MFRR			125
 #define OPAL_PCI_TCE_KILL			126
 #define OPAL_NMMU_SET_PTCR			127
-#define OPAL_LAST				127
+#define OPAL_SCRAPE_LOG				128
+#define OPAL_LAST				128
 
 /* Device tree flags */
 
@@ -346,6 +347,7 @@ enum OpalPendingState {
 	OPAL_EVENT_PCI_ERROR	   = 0x200,
 	OPAL_EVENT_DUMP_AVAIL	   = 0x400,
 	OPAL_EVENT_MSG_PENDING	   = 0x800,
+	OPAL_EVENT_LOG_PENDING	   = 0x1000,
 };
 
 enum OpalThreadStatus {
-- 
2.7.4



More information about the Skiboot mailing list