summaryrefslogtreecommitdiffstats
path: root/fs/pstore/platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/pstore/platform.c')
-rw-r--r--fs/pstore/platform.c109
1 files changed, 89 insertions, 20 deletions
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 963ecafef8..755363c309 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -25,6 +25,7 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
+#include <console.h>
#include <malloc.h>
#include <printk.h>
#include <module.h>
@@ -43,14 +44,83 @@ void pstore_set_kmsg_bytes(int bytes)
kmsg_bytes = bytes;
}
-static int pstore_write_compat(enum pstore_type_id type,
- enum kmsg_dump_reason reason,
- u64 *id, unsigned int part, int count,
- bool compressed, size_t size,
- struct pstore_info *psi)
+#ifdef CONFIG_FS_PSTORE_CONSOLE
+static void pstore_console_write(const char *s, unsigned c)
{
- return psi->write_buf(type, reason, id, part, psinfo->buf, compressed,
- size, psi);
+ const char *e = s + c;
+
+ while (s < e) {
+ struct pstore_record record = {
+ .type = PSTORE_TYPE_CONSOLE,
+ .psi = psinfo,
+ };
+
+ if (c > psinfo->bufsize)
+ c = psinfo->bufsize;
+
+ record.buf = (char *)s;
+ record.size = c;
+ psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &record.id, 0,
+ record.buf, 0, record.size, psinfo);
+ s += c;
+ c = e - s;
+ }
+}
+
+static int pstore_console_puts(struct console_device *cdev, const char *s)
+{
+ pstore_console_write(s, strlen(s));
+ return strlen(s);
+}
+
+static void pstore_console_putc(struct console_device *cdev, char c)
+{
+ const char s[1] = { c };
+
+ pstore_console_write(s, 1);
+}
+
+static void pstore_console_capture_log(void)
+{
+ struct log_entry *log;
+
+ list_for_each_entry(log, &barebox_logbuf, list)
+ pstore_console_write(log->msg, strlen(log->msg));
+}
+
+static struct console_device *pstore_cdev;
+
+static void pstore_register_console(void)
+{
+ struct console_device *cdev;
+ int ret;
+
+ cdev = xzalloc(sizeof(struct console_device));
+ pstore_cdev = cdev;
+
+ cdev->puts = pstore_console_puts;
+ cdev->putc = pstore_console_putc;
+ cdev->devname = "pstore";
+ cdev->devid = DEVICE_ID_SINGLE;
+
+ ret = console_register(cdev);
+ if (ret)
+ pr_err("registering failed with %s\n", strerror(-ret));
+
+ pstore_console_capture_log();
+
+ console_set_active(pstore_cdev, CONSOLE_STDOUT);
+}
+#else
+static void pstore_register_console(void) {}
+#endif
+
+static int pstore_write_compat(struct pstore_record *record)
+{
+ return record->psi->write_buf(record->type, record->reason,
+ &record->id, record->part,
+ psinfo->buf, record->compressed,
+ record->size, record->psi);
}
/*
@@ -81,6 +151,8 @@ int pstore_register(struct pstore_info *psi)
pstore_get_records(0);
+ pstore_register_console();
+
pr_info("Registered %s as persistent store backend\n", psi->name);
return 0;
@@ -96,13 +168,8 @@ EXPORT_SYMBOL_GPL(pstore_register);
void pstore_get_records(int quiet)
{
struct pstore_info *psi = psinfo;
- char *buf = NULL;
- ssize_t size;
- u64 id;
- int count;
- enum pstore_type_id type;
+ struct pstore_record record = { .psi = psi, };
int failed = 0, rc;
- bool compressed;
int unzipped_len = -1;
if (!psi)
@@ -112,22 +179,24 @@ void pstore_get_records(int quiet)
if (psi->open && psi->open(psi))
goto out;
- while ((size = psi->read(&id, &type, &count, &buf, &compressed,
- psi)) > 0) {
- if (compressed && (type == PSTORE_TYPE_DMESG)) {
+ while ((record.size = psi->read(&record)) > 0) {
+ if (record.compressed &&
+ record.type == PSTORE_TYPE_DMESG) {
pr_err("barebox does not have ramoops compression support\n");
continue;
}
- rc = pstore_mkfile(type, psi->name, id, count, buf,
- compressed, (size_t)size, psi);
+ rc = pstore_mkfile(&record);
if (unzipped_len < 0) {
/* Free buffer other than big oops */
- kfree(buf);
- buf = NULL;
+ kfree(record.buf);
+ record.buf = NULL;
} else
unzipped_len = -1;
if (rc && (rc != -EEXIST || !quiet))
failed++;
+
+ memset(&record, 0, sizeof(record));
+ record.psi = psi;
}
if (psi->close)
psi->close(psi);