* [PATCH 0/9] RAMOOPS read support for Barebox
@ 2015-12-02 13:48 Markus Pargmann
2015-12-02 13:48 ` [PATCH 1/9] arm: boards: karo-tx6x remove definition of DIV_ROUND_UP Markus Pargmann
` (8 more replies)
0 siblings, 9 replies; 18+ messages in thread
From: Markus Pargmann @ 2015-12-02 13:48 UTC (permalink / raw)
To: barebox
Hi,
These patches add support to read RAMOOPS files that were written by the last
booted kernel.
The first patches 1-4 add minor functions to barebox from the linux kernel.
Patch 5 adds reed solomon codes as library routines.
Patch 6-7 cleanup the current memory offset calculations for arm. There are a
lot of hardcoded sizes in the current code. I tried to centralize these sizes.
Patch 8 adds a memory region right after the barebox image before the stack for
RAMOOPS. This avoids any ramoops dependencies between different barebox
versions (unless the stack size is changed).
Patch 9 adds the actual implementation of pstore and RAMOOPS as filesystem. It
is based on the kernel implementation but lots of code was removed and the
filesystem layer rewritten for barebox. The files are available in the
automounted filesystem /pstore.
Best Regards,
Markus
Markus Pargmann (9):
arm: boards: karo-tx6x remove definition of DIV_ROUND_UP
log2: Add missing __rounddown_pow_of_two()
printk: Add missing include/declaration
vsprintf: Add scnprintf from kernel
lib: Import reed solomon code from kernel
arm: Clarify memory layout calculation
arm: start: Add visible sdram region for barebox board data
arm: Add RAMOOPS memory area
fs: Add pstore filesystem
arch/arm/boards/karo-tx6x/board.c | 2 +-
arch/arm/cpu/start-pbl.c | 14 +-
arch/arm/cpu/start.c | 71 ++++--
arch/arm/cpu/uncompress.c | 31 +--
arch/arm/include/asm/barebox-arm.h | 65 +++--
common/startup.c | 5 +
fs/Kconfig | 2 +
fs/Makefile | 1 +
fs/pstore/Kconfig | 88 +++++++
fs/pstore/Makefile | 10 +
fs/pstore/fs.c | 280 ++++++++++++++++++++
fs/pstore/internal.h | 19 ++
fs/pstore/platform.c | 138 ++++++++++
fs/pstore/ram.c | 507 +++++++++++++++++++++++++++++++++++++
fs/pstore/ram_core.c | 426 +++++++++++++++++++++++++++++++
include/linux/log2.h | 9 +
include/linux/pstore.h | 90 +++++++
include/linux/pstore_ram.h | 87 +++++++
include/linux/rslib.h | 109 ++++++++
include/printk.h | 3 +
include/stdio.h | 1 +
lib/Kconfig | 15 ++
lib/Makefile | 1 +
lib/reed_solomon/Makefile | 6 +
lib/reed_solomon/decode_rs.c | 271 ++++++++++++++++++++
lib/reed_solomon/encode_rs.c | 54 ++++
lib/reed_solomon/reed_solomon.c | 377 +++++++++++++++++++++++++++
lib/vsprintf.c | 24 ++
28 files changed, 2641 insertions(+), 65 deletions(-)
create mode 100644 fs/pstore/Kconfig
create mode 100644 fs/pstore/Makefile
create mode 100644 fs/pstore/fs.c
create mode 100644 fs/pstore/internal.h
create mode 100644 fs/pstore/platform.c
create mode 100644 fs/pstore/ram.c
create mode 100644 fs/pstore/ram_core.c
create mode 100644 include/linux/pstore.h
create mode 100644 include/linux/pstore_ram.h
create mode 100644 include/linux/rslib.h
create mode 100644 lib/reed_solomon/Makefile
create mode 100644 lib/reed_solomon/decode_rs.c
create mode 100644 lib/reed_solomon/encode_rs.c
create mode 100644 lib/reed_solomon/reed_solomon.c
--
2.6.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 1/9] arm: boards: karo-tx6x remove definition of DIV_ROUND_UP
2015-12-02 13:48 [PATCH 0/9] RAMOOPS read support for Barebox Markus Pargmann
@ 2015-12-02 13:48 ` Markus Pargmann
2015-12-02 13:48 ` [PATCH 2/9] log2: Add missing __rounddown_pow_of_two() Markus Pargmann
` (7 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Markus Pargmann @ 2015-12-02 13:48 UTC (permalink / raw)
To: barebox
DIV_ROUND_UP is defined in include/linux/kernel.h. Use that instead.
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
arch/arm/boards/karo-tx6x/board.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boards/karo-tx6x/board.c b/arch/arm/boards/karo-tx6x/board.c
index 6d9dd9a505f0..a921541bfc7f 100644
--- a/arch/arm/boards/karo-tx6x/board.c
+++ b/arch/arm/boards/karo-tx6x/board.c
@@ -21,6 +21,7 @@
#include <init.h>
#include <i2c/i2c.h>
#include <linux/clk.h>
+#include <linux/kernel.h>
#include <environment.h>
#include <mach/bbu.h>
#include <mach/imx6.h>
@@ -29,7 +30,6 @@
#define ETH_PHY_RST IMX_GPIO_NR(7, 6)
#define ETH_PHY_PWR IMX_GPIO_NR(3, 20)
#define ETH_PHY_INT IMX_GPIO_NR(7, 1)
-#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define DIV_ROUND(n,d) (((n) + ((d)/2)) / (d))
#define LTC3676_BUCK1 0x01
--
2.6.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 2/9] log2: Add missing __rounddown_pow_of_two()
2015-12-02 13:48 [PATCH 0/9] RAMOOPS read support for Barebox Markus Pargmann
2015-12-02 13:48 ` [PATCH 1/9] arm: boards: karo-tx6x remove definition of DIV_ROUND_UP Markus Pargmann
@ 2015-12-02 13:48 ` Markus Pargmann
2015-12-02 13:48 ` [PATCH 3/9] printk: Add missing include/declaration Markus Pargmann
` (6 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Markus Pargmann @ 2015-12-02 13:48 UTC (permalink / raw)
To: barebox
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
include/linux/log2.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/include/linux/log2.h b/include/linux/log2.h
index d9913f06bd09..36519e3aa38b 100644
--- a/include/linux/log2.h
+++ b/include/linux/log2.h
@@ -63,6 +63,15 @@ unsigned long __roundup_pow_of_two(unsigned long n)
return 1UL << fls(n - 1);
}
+/*
+ * round down to nearest power of two
+ */
+static inline __attribute__((const))
+unsigned long __rounddown_pow_of_two(unsigned long n)
+{
+ return 1UL << (fls_long(n) - 1);
+}
+
/**
* ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
* @n - parameter
--
2.6.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 3/9] printk: Add missing include/declaration
2015-12-02 13:48 [PATCH 0/9] RAMOOPS read support for Barebox Markus Pargmann
2015-12-02 13:48 ` [PATCH 1/9] arm: boards: karo-tx6x remove definition of DIV_ROUND_UP Markus Pargmann
2015-12-02 13:48 ` [PATCH 2/9] log2: Add missing __rounddown_pow_of_two() Markus Pargmann
@ 2015-12-02 13:48 ` Markus Pargmann
2015-12-02 13:48 ` [PATCH 4/9] vsprintf: Add scnprintf from kernel Markus Pargmann
` (5 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Markus Pargmann @ 2015-12-02 13:48 UTC (permalink / raw)
To: barebox
There are functions or structs used that do need these.
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
include/printk.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/include/printk.h b/include/printk.h
index a27ad514cfe1..822f64c61f7d 100644
--- a/include/printk.h
+++ b/include/printk.h
@@ -1,6 +1,8 @@
#ifndef __PRINTK_H
#define __PRINTK_H
+#include <linux/list.h>
+
#define MSG_EMERG 0 /* system is unusable */
#define MSG_ALERT 1 /* action must be taken immediately */
#define MSG_CRIT 2 /* critical conditions */
@@ -20,6 +22,7 @@
#endif
/* debugging and troubleshooting/diagnostic helpers. */
+struct device_d;
#ifndef CONFIG_CONSOLE_NONE
int dev_printf(int level, const struct device_d *dev, const char *format, ...)
--
2.6.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 4/9] vsprintf: Add scnprintf from kernel
2015-12-02 13:48 [PATCH 0/9] RAMOOPS read support for Barebox Markus Pargmann
` (2 preceding siblings ...)
2015-12-02 13:48 ` [PATCH 3/9] printk: Add missing include/declaration Markus Pargmann
@ 2015-12-02 13:48 ` Markus Pargmann
2015-12-02 13:48 ` [PATCH 5/9] lib: Import reed solomon code " Markus Pargmann
` (4 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Markus Pargmann @ 2015-12-02 13:48 UTC (permalink / raw)
To: barebox
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
include/stdio.h | 1 +
lib/vsprintf.c | 24 ++++++++++++++++++++++++
2 files changed, 25 insertions(+)
diff --git a/include/stdio.h b/include/stdio.h
index f1909117621d..d0817bd0715a 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -13,6 +13,7 @@ void serial_printf(const char *fmt, ...) __attribute__ ((format(__printf__, 1, 2
int sprintf(char *buf, const char *fmt, ...) __attribute__ ((format(__printf__, 2, 3)));
int snprintf(char *buf, size_t size, const char *fmt, ...) __attribute__ ((format(__printf__, 3, 4)));
+int scnprintf(char *buf, size_t size, const char *fmt, ...) __attribute__ ((format(__printf__, 3, 4)));
int vsprintf(char *buf, const char *fmt, va_list args);
char *asprintf(const char *fmt, ...) __attribute__ ((format(__printf__, 1, 2)));
char *vasprintf(const char *fmt, va_list ap);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 800ded7939eb..9b8e8cf5f8e3 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -595,6 +595,30 @@ int snprintf(char *buf, size_t size, const char *fmt, ...)
}
EXPORT_SYMBOL(snprintf);
+/**
+ * scnprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ *
+ * The return value is the number of characters written into @buf not including
+ * the trailing '\0'. If @size is == 0 the function returns 0.
+ */
+
+int scnprintf(char *buf, size_t size, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vscnprintf(buf, size, fmt, args);
+ va_end(args);
+
+ return i;
+}
+EXPORT_SYMBOL(scnprintf);
+
/* Simplified asprintf. */
char *vasprintf(const char *fmt, va_list ap)
{
--
2.6.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 5/9] lib: Import reed solomon code from kernel
2015-12-02 13:48 [PATCH 0/9] RAMOOPS read support for Barebox Markus Pargmann
` (3 preceding siblings ...)
2015-12-02 13:48 ` [PATCH 4/9] vsprintf: Add scnprintf from kernel Markus Pargmann
@ 2015-12-02 13:48 ` Markus Pargmann
2015-12-04 7:12 ` Sascha Hauer
2015-12-02 13:48 ` [PATCH 6/9] arm: Clarify memory layout calculation Markus Pargmann
` (3 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Markus Pargmann @ 2015-12-02 13:48 UTC (permalink / raw)
To: barebox
reed solomon code is used by RAMOOPS to check and fix data stored in
volatile memory.
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
include/linux/rslib.h | 109 ++++++++++++
lib/Kconfig | 15 ++
lib/Makefile | 1 +
lib/reed_solomon/Makefile | 6 +
lib/reed_solomon/decode_rs.c | 271 +++++++++++++++++++++++++++++
lib/reed_solomon/encode_rs.c | 54 ++++++
lib/reed_solomon/reed_solomon.c | 377 ++++++++++++++++++++++++++++++++++++++++
7 files changed, 833 insertions(+)
create mode 100644 include/linux/rslib.h
create mode 100644 lib/reed_solomon/Makefile
create mode 100644 lib/reed_solomon/decode_rs.c
create mode 100644 lib/reed_solomon/encode_rs.c
create mode 100644 lib/reed_solomon/reed_solomon.c
diff --git a/include/linux/rslib.h b/include/linux/rslib.h
new file mode 100644
index 000000000000..746580c1939c
--- /dev/null
+++ b/include/linux/rslib.h
@@ -0,0 +1,109 @@
+/*
+ * include/linux/rslib.h
+ *
+ * Overview:
+ * Generic Reed Solomon encoder / decoder library
+ *
+ * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
+ *
+ * RS code lifted from reed solomon library written by Phil Karn
+ * Copyright 2002 Phil Karn, KA9Q
+ *
+ * $Id: rslib.h,v 1.4 2005/11/07 11:14:52 gleixner Exp $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _RSLIB_H_
+#define _RSLIB_H_
+
+#include <linux/list.h>
+
+/**
+ * struct rs_control - rs control structure
+ *
+ * @mm: Bits per symbol
+ * @nn: Symbols per block (= (1<<mm)-1)
+ * @alpha_to: log lookup table
+ * @index_of: Antilog lookup table
+ * @genpoly: Generator polynomial
+ * @nroots: Number of generator roots = number of parity symbols
+ * @fcr: First consecutive root, index form
+ * @prim: Primitive element, index form
+ * @iprim: prim-th root of 1, index form
+ * @gfpoly: The primitive generator polynominal
+ * @gffunc: Function to generate the field, if non-canonical representation
+ * @users: Users of this structure
+ * @list: List entry for the rs control list
+*/
+struct rs_control {
+ int mm;
+ int nn;
+ uint16_t *alpha_to;
+ uint16_t *index_of;
+ uint16_t *genpoly;
+ int nroots;
+ int fcr;
+ int prim;
+ int iprim;
+ int gfpoly;
+ int (*gffunc)(int);
+ int users;
+ struct list_head list;
+};
+
+/* General purpose RS codec, 8-bit data width, symbol width 1-15 bit */
+#ifdef CONFIG_REED_SOLOMON_ENC8
+int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par,
+ uint16_t invmsk);
+#endif
+#ifdef CONFIG_REED_SOLOMON_DEC8
+int decode_rs8(struct rs_control *rs, uint8_t *data, uint16_t *par, int len,
+ uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,
+ uint16_t *corr);
+#endif
+
+/* General purpose RS codec, 16-bit data width, symbol width 1-15 bit */
+#ifdef CONFIG_REED_SOLOMON_ENC16
+int encode_rs16(struct rs_control *rs, uint16_t *data, int len, uint16_t *par,
+ uint16_t invmsk);
+#endif
+#ifdef CONFIG_REED_SOLOMON_DEC16
+int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len,
+ uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,
+ uint16_t *corr);
+#endif
+
+/* Create or get a matching rs control structure */
+struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
+ int nroots);
+struct rs_control *init_rs_non_canonical(int symsize, int (*func)(int),
+ int fcr, int prim, int nroots);
+
+/* Release a rs control structure */
+void free_rs(struct rs_control *rs);
+
+/** modulo replacement for galois field arithmetics
+ *
+ * @rs: the rs control structure
+ * @x: the value to reduce
+ *
+ * where
+ * rs->mm = number of bits per symbol
+ * rs->nn = (2^rs->mm) - 1
+ *
+ * Simple arithmetic modulo would return a wrong result for values
+ * >= 3 * rs->nn
+*/
+static inline int rs_modnn(struct rs_control *rs, int x)
+{
+ while (x >= rs->nn) {
+ x -= rs->nn;
+ x = (x >> rs->mm) + (x & rs->nn);
+ }
+ return x;
+}
+
+#endif
diff --git a/lib/Kconfig b/lib/Kconfig
index fbf9f0f34849..f2f3b5775ace 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -22,6 +22,21 @@ config XZ_DECOMPRESS
bool "include xz uncompression support"
select UNCOMPRESS
+config REED_SOLOMON
+ bool
+
+config REED_SOLOMON_ENC8
+ bool
+
+config REED_SOLOMON_DEC8
+ bool
+
+config REED_SOLOMON_ENC16
+ bool
+
+config REED_SOLOMON_DEC16
+ bool
+
config GENERIC_FIND_NEXT_BIT
def_bool n
diff --git a/lib/Makefile b/lib/Makefile
index abb34cfbdbeb..6ffa3e010434 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -56,3 +56,4 @@ obj-y += gcd.o
obj-y += hexdump.o
obj-$(CONFIG_FONTS) += fonts/
obj-$(CONFIG_BAREBOX_LOGO) += logo/
+obj-y += reed_solomon/
diff --git a/lib/reed_solomon/Makefile b/lib/reed_solomon/Makefile
new file mode 100644
index 000000000000..c3d7136827ed
--- /dev/null
+++ b/lib/reed_solomon/Makefile
@@ -0,0 +1,6 @@
+#
+# This is a modified version of reed solomon lib,
+#
+
+obj-$(CONFIG_REED_SOLOMON) += reed_solomon.o
+
diff --git a/lib/reed_solomon/decode_rs.c b/lib/reed_solomon/decode_rs.c
new file mode 100644
index 000000000000..0ec3f257ffdf
--- /dev/null
+++ b/lib/reed_solomon/decode_rs.c
@@ -0,0 +1,271 @@
+/*
+ * lib/reed_solomon/decode_rs.c
+ *
+ * Overview:
+ * Generic Reed Solomon encoder / decoder library
+ *
+ * Copyright 2002, Phil Karn, KA9Q
+ * May be used under the terms of the GNU General Public License (GPL)
+ *
+ * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de)
+ *
+ * $Id: decode_rs.c,v 1.7 2005/11/07 11:14:59 gleixner Exp $
+ *
+ */
+
+/* Generic data width independent code which is included by the
+ * wrappers.
+ */
+{
+ int deg_lambda, el, deg_omega;
+ int i, j, r, k, pad;
+ int nn = rs->nn;
+ int nroots = rs->nroots;
+ int fcr = rs->fcr;
+ int prim = rs->prim;
+ int iprim = rs->iprim;
+ uint16_t *alpha_to = rs->alpha_to;
+ uint16_t *index_of = rs->index_of;
+ uint16_t u, q, tmp, num1, num2, den, discr_r, syn_error;
+ /* Err+Eras Locator poly and syndrome poly The maximum value
+ * of nroots is 8. So the necessary stack size will be about
+ * 220 bytes max.
+ */
+ uint16_t lambda[nroots + 1], syn[nroots];
+ uint16_t b[nroots + 1], t[nroots + 1], omega[nroots + 1];
+ uint16_t root[nroots], reg[nroots + 1], loc[nroots];
+ int count = 0;
+ uint16_t msk = (uint16_t) rs->nn;
+
+ /* Check length parameter for validity */
+ pad = nn - nroots - len;
+ BUG_ON(pad < 0 || pad >= nn);
+
+ /* Does the caller provide the syndrome ? */
+ if (s != NULL)
+ goto decode;
+
+ /* form the syndromes; i.e., evaluate data(x) at roots of
+ * g(x) */
+ for (i = 0; i < nroots; i++)
+ syn[i] = (((uint16_t) data[0]) ^ invmsk) & msk;
+
+ for (j = 1; j < len; j++) {
+ for (i = 0; i < nroots; i++) {
+ if (syn[i] == 0) {
+ syn[i] = (((uint16_t) data[j]) ^
+ invmsk) & msk;
+ } else {
+ syn[i] = ((((uint16_t) data[j]) ^
+ invmsk) & msk) ^
+ alpha_to[rs_modnn(rs, index_of[syn[i]] +
+ (fcr + i) * prim)];
+ }
+ }
+ }
+
+ for (j = 0; j < nroots; j++) {
+ for (i = 0; i < nroots; i++) {
+ if (syn[i] == 0) {
+ syn[i] = ((uint16_t) par[j]) & msk;
+ } else {
+ syn[i] = (((uint16_t) par[j]) & msk) ^
+ alpha_to[rs_modnn(rs, index_of[syn[i]] +
+ (fcr+i)*prim)];
+ }
+ }
+ }
+ s = syn;
+
+ /* Convert syndromes to index form, checking for nonzero condition */
+ syn_error = 0;
+ for (i = 0; i < nroots; i++) {
+ syn_error |= s[i];
+ s[i] = index_of[s[i]];
+ }
+
+ if (!syn_error) {
+ /* if syndrome is zero, data[] is a codeword and there are no
+ * errors to correct. So return data[] unmodified
+ */
+ count = 0;
+ goto finish;
+ }
+
+ decode:
+ memset(&lambda[1], 0, nroots * sizeof(lambda[0]));
+ lambda[0] = 1;
+
+ if (no_eras > 0) {
+ /* Init lambda to be the erasure locator polynomial */
+ lambda[1] = alpha_to[rs_modnn(rs,
+ prim * (nn - 1 - eras_pos[0]))];
+ for (i = 1; i < no_eras; i++) {
+ u = rs_modnn(rs, prim * (nn - 1 - eras_pos[i]));
+ for (j = i + 1; j > 0; j--) {
+ tmp = index_of[lambda[j - 1]];
+ if (tmp != nn) {
+ lambda[j] ^=
+ alpha_to[rs_modnn(rs, u + tmp)];
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < nroots + 1; i++)
+ b[i] = index_of[lambda[i]];
+
+ /*
+ * Begin Berlekamp-Massey algorithm to determine error+erasure
+ * locator polynomial
+ */
+ r = no_eras;
+ el = no_eras;
+ while (++r <= nroots) { /* r is the step number */
+ /* Compute discrepancy at the r-th step in poly-form */
+ discr_r = 0;
+ for (i = 0; i < r; i++) {
+ if ((lambda[i] != 0) && (s[r - i - 1] != nn)) {
+ discr_r ^=
+ alpha_to[rs_modnn(rs,
+ index_of[lambda[i]] +
+ s[r - i - 1])];
+ }
+ }
+ discr_r = index_of[discr_r]; /* Index form */
+ if (discr_r == nn) {
+ /* 2 lines below: B(x) <-- x*B(x) */
+ memmove (&b[1], b, nroots * sizeof (b[0]));
+ b[0] = nn;
+ } else {
+ /* 7 lines below: T(x) <-- lambda(x)-discr_r*x*b(x) */
+ t[0] = lambda[0];
+ for (i = 0; i < nroots; i++) {
+ if (b[i] != nn) {
+ t[i + 1] = lambda[i + 1] ^
+ alpha_to[rs_modnn(rs, discr_r +
+ b[i])];
+ } else
+ t[i + 1] = lambda[i + 1];
+ }
+ if (2 * el <= r + no_eras - 1) {
+ el = r + no_eras - el;
+ /*
+ * 2 lines below: B(x) <-- inv(discr_r) *
+ * lambda(x)
+ */
+ for (i = 0; i <= nroots; i++) {
+ b[i] = (lambda[i] == 0) ? nn :
+ rs_modnn(rs, index_of[lambda[i]]
+ - discr_r + nn);
+ }
+ } else {
+ /* 2 lines below: B(x) <-- x*B(x) */
+ memmove(&b[1], b, nroots * sizeof(b[0]));
+ b[0] = nn;
+ }
+ memcpy(lambda, t, (nroots + 1) * sizeof(t[0]));
+ }
+ }
+
+ /* Convert lambda to index form and compute deg(lambda(x)) */
+ deg_lambda = 0;
+ for (i = 0; i < nroots + 1; i++) {
+ lambda[i] = index_of[lambda[i]];
+ if (lambda[i] != nn)
+ deg_lambda = i;
+ }
+ /* Find roots of error+erasure locator polynomial by Chien search */
+ memcpy(®[1], &lambda[1], nroots * sizeof(reg[0]));
+ count = 0; /* Number of roots of lambda(x) */
+ for (i = 1, k = iprim - 1; i <= nn; i++, k = rs_modnn(rs, k + iprim)) {
+ q = 1; /* lambda[0] is always 0 */
+ for (j = deg_lambda; j > 0; j--) {
+ if (reg[j] != nn) {
+ reg[j] = rs_modnn(rs, reg[j] + j);
+ q ^= alpha_to[reg[j]];
+ }
+ }
+ if (q != 0)
+ continue; /* Not a root */
+ /* store root (index-form) and error location number */
+ root[count] = i;
+ loc[count] = k;
+ /* If we've already found max possible roots,
+ * abort the search to save time
+ */
+ if (++count == deg_lambda)
+ break;
+ }
+ if (deg_lambda != count) {
+ /*
+ * deg(lambda) unequal to number of roots => uncorrectable
+ * error detected
+ */
+ count = -EBADMSG;
+ goto finish;
+ }
+ /*
+ * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
+ * x**nroots). in index form. Also find deg(omega).
+ */
+ deg_omega = deg_lambda - 1;
+ for (i = 0; i <= deg_omega; i++) {
+ tmp = 0;
+ for (j = i; j >= 0; j--) {
+ if ((s[i - j] != nn) && (lambda[j] != nn))
+ tmp ^=
+ alpha_to[rs_modnn(rs, s[i - j] + lambda[j])];
+ }
+ omega[i] = index_of[tmp];
+ }
+
+ /*
+ * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
+ * inv(X(l))**(fcr-1) and den = lambda_pr(inv(X(l))) all in poly-form
+ */
+ for (j = count - 1; j >= 0; j--) {
+ num1 = 0;
+ for (i = deg_omega; i >= 0; i--) {
+ if (omega[i] != nn)
+ num1 ^= alpha_to[rs_modnn(rs, omega[i] +
+ i * root[j])];
+ }
+ num2 = alpha_to[rs_modnn(rs, root[j] * (fcr - 1) + nn)];
+ den = 0;
+
+ /* lambda[i+1] for i even is the formal derivative
+ * lambda_pr of lambda[i] */
+ for (i = min(deg_lambda, nroots - 1) & ~1; i >= 0; i -= 2) {
+ if (lambda[i + 1] != nn) {
+ den ^= alpha_to[rs_modnn(rs, lambda[i + 1] +
+ i * root[j])];
+ }
+ }
+ /* Apply error to data */
+ if (num1 != 0 && loc[j] >= pad) {
+ uint16_t cor = alpha_to[rs_modnn(rs,index_of[num1] +
+ index_of[num2] +
+ nn - index_of[den])];
+ /* Store the error correction pattern, if a
+ * correction buffer is available */
+ if (corr) {
+ corr[j] = cor;
+ } else {
+ /* If a data buffer is given and the
+ * error is inside the message,
+ * correct it */
+ if (data && (loc[j] < (nn - nroots)))
+ data[loc[j] - pad] ^= cor;
+ }
+ }
+ }
+
+finish:
+ if (eras_pos != NULL) {
+ for (i = 0; i < count; i++)
+ eras_pos[i] = loc[i] - pad;
+ }
+ return count;
+
+}
diff --git a/lib/reed_solomon/encode_rs.c b/lib/reed_solomon/encode_rs.c
new file mode 100644
index 000000000000..0b5b1a6728ec
--- /dev/null
+++ b/lib/reed_solomon/encode_rs.c
@@ -0,0 +1,54 @@
+/*
+ * lib/reed_solomon/encode_rs.c
+ *
+ * Overview:
+ * Generic Reed Solomon encoder / decoder library
+ *
+ * Copyright 2002, Phil Karn, KA9Q
+ * May be used under the terms of the GNU General Public License (GPL)
+ *
+ * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de)
+ *
+ * $Id: encode_rs.c,v 1.5 2005/11/07 11:14:59 gleixner Exp $
+ *
+ */
+
+/* Generic data width independent code which is included by the
+ * wrappers.
+ * int encode_rsX (struct rs_control *rs, uintX_t *data, int len, uintY_t *par)
+ */
+{
+ int i, j, pad;
+ int nn = rs->nn;
+ int nroots = rs->nroots;
+ uint16_t *alpha_to = rs->alpha_to;
+ uint16_t *index_of = rs->index_of;
+ uint16_t *genpoly = rs->genpoly;
+ uint16_t fb;
+ uint16_t msk = (uint16_t) rs->nn;
+
+ /* Check length parameter for validity */
+ pad = nn - nroots - len;
+ if (pad < 0 || pad >= nn)
+ return -ERANGE;
+
+ for (i = 0; i < len; i++) {
+ fb = index_of[((((uint16_t) data[i])^invmsk) & msk) ^ par[0]];
+ /* feedback term is non-zero */
+ if (fb != nn) {
+ for (j = 1; j < nroots; j++) {
+ par[j] ^= alpha_to[rs_modnn(rs, fb +
+ genpoly[nroots - j])];
+ }
+ }
+ /* Shift */
+ memmove(&par[0], &par[1], sizeof(uint16_t) * (nroots - 1));
+ if (fb != nn) {
+ par[nroots - 1] = alpha_to[rs_modnn(rs,
+ fb + genpoly[0])];
+ } else {
+ par[nroots - 1] = 0;
+ }
+ }
+ return 0;
+}
diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c
new file mode 100644
index 000000000000..f9ea907bfef9
--- /dev/null
+++ b/lib/reed_solomon/reed_solomon.c
@@ -0,0 +1,377 @@
+/*
+ * lib/reed_solomon/reed_solomon.c
+ *
+ * Overview:
+ * Generic Reed Solomon encoder / decoder library
+ *
+ * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
+ *
+ * Reed Solomon code lifted from reed solomon library written by Phil Karn
+ * Copyright 2002 Phil Karn, KA9Q
+ *
+ * $Id: rslib.c,v 1.7 2005/11/07 11:14:59 gleixner Exp $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Description:
+ *
+ * The generic Reed Solomon library provides runtime configurable
+ * encoding / decoding of RS codes.
+ * Each user must call init_rs to get a pointer to a rs_control
+ * structure for the given rs parameters. This structure is either
+ * generated or a already available matching control structure is used.
+ * If a structure is generated then the polynomial arrays for
+ * fast encoding / decoding are built. This can take some time so
+ * make sure not to call this function from a time critical path.
+ * Usually a module / driver should initialize the necessary
+ * rs_control structure on module / driver init and release it
+ * on exit.
+ * The encoding puts the calculated syndrome into a given syndrome
+ * buffer.
+ * The decoding is a two step process. The first step calculates
+ * the syndrome over the received (data + syndrome) and calls the
+ * second stage, which does the decoding / error correction itself.
+ * Many hw encoders provide a syndrome calculation over the received
+ * data + syndrome and can call the second stage directly.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/rslib.h>
+#include <malloc.h>
+#include <module.h>
+#include <linux/string.h>
+#include <stdio.h>
+#include <asm-generic/errno.h>
+
+/* This list holds all currently allocated rs control structures */
+static LIST_HEAD (rslist);
+
+/**
+ * rs_init - Initialize a Reed-Solomon codec
+ * @symsize: symbol size, bits (1-8)
+ * @gfpoly: Field generator polynomial coefficients
+ * @gffunc: Field generator function
+ * @fcr: first root of RS code generator polynomial, index form
+ * @prim: primitive element to generate polynomial roots
+ * @nroots: RS code generator polynomial degree (number of roots)
+ *
+ * Allocate a control structure and the polynom arrays for faster
+ * en/decoding. Fill the arrays according to the given parameters.
+ */
+static struct rs_control *rs_init(int symsize, int gfpoly, int (*gffunc)(int),
+ int fcr, int prim, int nroots)
+{
+ struct rs_control *rs;
+ int i, j, sr, root, iprim;
+
+ /* Allocate the control structure */
+ rs = kmalloc(sizeof (struct rs_control), GFP_KERNEL);
+ if (rs == NULL)
+ return NULL;
+
+ INIT_LIST_HEAD(&rs->list);
+
+ rs->mm = symsize;
+ rs->nn = (1 << symsize) - 1;
+ rs->fcr = fcr;
+ rs->prim = prim;
+ rs->nroots = nroots;
+ rs->gfpoly = gfpoly;
+ rs->gffunc = gffunc;
+
+ /* Allocate the arrays */
+ rs->alpha_to = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL);
+ if (rs->alpha_to == NULL)
+ goto errrs;
+
+ rs->index_of = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL);
+ if (rs->index_of == NULL)
+ goto erralp;
+
+ rs->genpoly = kmalloc(sizeof(uint16_t) * (rs->nroots + 1), GFP_KERNEL);
+ if(rs->genpoly == NULL)
+ goto erridx;
+
+ /* Generate Galois field lookup tables */
+ rs->index_of[0] = rs->nn; /* log(zero) = -inf */
+ rs->alpha_to[rs->nn] = 0; /* alpha**-inf = 0 */
+ if (gfpoly) {
+ sr = 1;
+ for (i = 0; i < rs->nn; i++) {
+ rs->index_of[sr] = i;
+ rs->alpha_to[i] = sr;
+ sr <<= 1;
+ if (sr & (1 << symsize))
+ sr ^= gfpoly;
+ sr &= rs->nn;
+ }
+ } else {
+ sr = gffunc(0);
+ for (i = 0; i < rs->nn; i++) {
+ rs->index_of[sr] = i;
+ rs->alpha_to[i] = sr;
+ sr = gffunc(sr);
+ }
+ }
+ /* If it's not primitive, exit */
+ if(sr != rs->alpha_to[0])
+ goto errpol;
+
+ /* Find prim-th root of 1, used in decoding */
+ for(iprim = 1; (iprim % prim) != 0; iprim += rs->nn);
+ /* prim-th root of 1, index form */
+ rs->iprim = iprim / prim;
+
+ /* Form RS code generator polynomial from its roots */
+ rs->genpoly[0] = 1;
+ for (i = 0, root = fcr * prim; i < nroots; i++, root += prim) {
+ rs->genpoly[i + 1] = 1;
+ /* Multiply rs->genpoly[] by @**(root + x) */
+ for (j = i; j > 0; j--) {
+ if (rs->genpoly[j] != 0) {
+ rs->genpoly[j] = rs->genpoly[j -1] ^
+ rs->alpha_to[rs_modnn(rs,
+ rs->index_of[rs->genpoly[j]] + root)];
+ } else
+ rs->genpoly[j] = rs->genpoly[j - 1];
+ }
+ /* rs->genpoly[0] can never be zero */
+ rs->genpoly[0] =
+ rs->alpha_to[rs_modnn(rs,
+ rs->index_of[rs->genpoly[0]] + root)];
+ }
+ /* convert rs->genpoly[] to index form for quicker encoding */
+ for (i = 0; i <= nroots; i++)
+ rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
+ return rs;
+
+ /* Error exit */
+errpol:
+ kfree(rs->genpoly);
+erridx:
+ kfree(rs->index_of);
+erralp:
+ kfree(rs->alpha_to);
+errrs:
+ kfree(rs);
+ return NULL;
+}
+
+
+/**
+ * free_rs - Free the rs control structure, if it is no longer used
+ * @rs: the control structure which is not longer used by the
+ * caller
+ */
+void free_rs(struct rs_control *rs)
+{
+ rs->users--;
+ if(!rs->users) {
+ list_del(&rs->list);
+ kfree(rs->alpha_to);
+ kfree(rs->index_of);
+ kfree(rs->genpoly);
+ kfree(rs);
+ }
+}
+
+/**
+ * init_rs_internal - Find a matching or allocate a new rs control structure
+ * @symsize: the symbol size (number of bits)
+ * @gfpoly: the extended Galois field generator polynomial coefficients,
+ * with the 0th coefficient in the low order bit. The polynomial
+ * must be primitive;
+ * @gffunc: pointer to function to generate the next field element,
+ * or the multiplicative identity element if given 0. Used
+ * instead of gfpoly if gfpoly is 0
+ * @fcr: the first consecutive root of the rs code generator polynomial
+ * in index form
+ * @prim: primitive element to generate polynomial roots
+ * @nroots: RS code generator polynomial degree (number of roots)
+ */
+static struct rs_control *init_rs_internal(int symsize, int gfpoly,
+ int (*gffunc)(int), int fcr,
+ int prim, int nroots)
+{
+ struct list_head *tmp;
+ struct rs_control *rs;
+
+ /* Sanity checks */
+ if (symsize < 1)
+ return NULL;
+ if (fcr < 0 || fcr >= (1<<symsize))
+ return NULL;
+ if (prim <= 0 || prim >= (1<<symsize))
+ return NULL;
+ if (nroots < 0 || nroots >= (1<<symsize))
+ return NULL;
+
+ /* Walk through the list and look for a matching entry */
+ list_for_each(tmp, &rslist) {
+ rs = list_entry(tmp, struct rs_control, list);
+ if (symsize != rs->mm)
+ continue;
+ if (gfpoly != rs->gfpoly)
+ continue;
+ if (gffunc != rs->gffunc)
+ continue;
+ if (fcr != rs->fcr)
+ continue;
+ if (prim != rs->prim)
+ continue;
+ if (nroots != rs->nroots)
+ continue;
+ /* We have a matching one already */
+ rs->users++;
+ goto out;
+ }
+
+ /* Create a new one */
+ rs = rs_init(symsize, gfpoly, gffunc, fcr, prim, nroots);
+ if (rs) {
+ rs->users = 1;
+ list_add(&rs->list, &rslist);
+ }
+out:
+ return rs;
+}
+
+/**
+ * init_rs - Find a matching or allocate a new rs control structure
+ * @symsize: the symbol size (number of bits)
+ * @gfpoly: the extended Galois field generator polynomial coefficients,
+ * with the 0th coefficient in the low order bit. The polynomial
+ * must be primitive;
+ * @fcr: the first consecutive root of the rs code generator polynomial
+ * in index form
+ * @prim: primitive element to generate polynomial roots
+ * @nroots: RS code generator polynomial degree (number of roots)
+ */
+struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
+ int nroots)
+{
+ return init_rs_internal(symsize, gfpoly, NULL, fcr, prim, nroots);
+}
+
+/**
+ * init_rs_non_canonical - Find a matching or allocate a new rs control
+ * structure, for fields with non-canonical
+ * representation
+ * @symsize: the symbol size (number of bits)
+ * @gffunc: pointer to function to generate the next field element,
+ * or the multiplicative identity element if given 0. Used
+ * instead of gfpoly if gfpoly is 0
+ * @fcr: the first consecutive root of the rs code generator polynomial
+ * in index form
+ * @prim: primitive element to generate polynomial roots
+ * @nroots: RS code generator polynomial degree (number of roots)
+ */
+struct rs_control *init_rs_non_canonical(int symsize, int (*gffunc)(int),
+ int fcr, int prim, int nroots)
+{
+ return init_rs_internal(symsize, 0, gffunc, fcr, prim, nroots);
+}
+
+#ifdef CONFIG_REED_SOLOMON_ENC8
+/**
+ * encode_rs8 - Calculate the parity for data values (8bit data width)
+ * @rs: the rs control structure
+ * @data: data field of a given type
+ * @len: data length
+ * @par: parity data, must be initialized by caller (usually all 0)
+ * @invmsk: invert data mask (will be xored on data)
+ *
+ * The parity uses a uint16_t data type to enable
+ * symbol size > 8. The calling code must take care of encoding of the
+ * syndrome result for storage itself.
+ */
+int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par,
+ uint16_t invmsk)
+{
+#include "encode_rs.c"
+}
+EXPORT_SYMBOL_GPL(encode_rs8);
+#endif
+
+#ifdef CONFIG_REED_SOLOMON_DEC8
+/**
+ * decode_rs8 - Decode codeword (8bit data width)
+ * @rs: the rs control structure
+ * @data: data field of a given type
+ * @par: received parity data field
+ * @len: data length
+ * @s: syndrome data field (if NULL, syndrome is calculated)
+ * @no_eras: number of erasures
+ * @eras_pos: position of erasures, can be NULL
+ * @invmsk: invert data mask (will be xored on data, not on parity!)
+ * @corr: buffer to store correction bitmask on eras_pos
+ *
+ * The syndrome and parity uses a uint16_t data type to enable
+ * symbol size > 8. The calling code must take care of decoding of the
+ * syndrome result and the received parity before calling this code.
+ * Returns the number of corrected bits or -EBADMSG for uncorrectable errors.
+ */
+int decode_rs8(struct rs_control *rs, uint8_t *data, uint16_t *par, int len,
+ uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,
+ uint16_t *corr)
+{
+#include "decode_rs.c"
+}
+EXPORT_SYMBOL_GPL(decode_rs8);
+#endif
+
+#ifdef CONFIG_REED_SOLOMON_ENC16
+/**
+ * encode_rs16 - Calculate the parity for data values (16bit data width)
+ * @rs: the rs control structure
+ * @data: data field of a given type
+ * @len: data length
+ * @par: parity data, must be initialized by caller (usually all 0)
+ * @invmsk: invert data mask (will be xored on data, not on parity!)
+ *
+ * Each field in the data array contains up to symbol size bits of valid data.
+ */
+int encode_rs16(struct rs_control *rs, uint16_t *data, int len, uint16_t *par,
+ uint16_t invmsk)
+{
+#include "encode_rs.c"
+}
+EXPORT_SYMBOL_GPL(encode_rs16);
+#endif
+
+#ifdef CONFIG_REED_SOLOMON_DEC16
+/**
+ * decode_rs16 - Decode codeword (16bit data width)
+ * @rs: the rs control structure
+ * @data: data field of a given type
+ * @par: received parity data field
+ * @len: data length
+ * @s: syndrome data field (if NULL, syndrome is calculated)
+ * @no_eras: number of erasures
+ * @eras_pos: position of erasures, can be NULL
+ * @invmsk: invert data mask (will be xored on data, not on parity!)
+ * @corr: buffer to store correction bitmask on eras_pos
+ *
+ * Each field in the data array contains up to symbol size bits of valid data.
+ * Returns the number of corrected bits or -EBADMSG for uncorrectable errors.
+ */
+int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len,
+ uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,
+ uint16_t *corr)
+{
+#include "decode_rs.c"
+}
+EXPORT_SYMBOL_GPL(decode_rs16);
+#endif
+
+EXPORT_SYMBOL_GPL(init_rs);
+EXPORT_SYMBOL_GPL(init_rs_non_canonical);
+EXPORT_SYMBOL_GPL(free_rs);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Reed Solomon encoder/decoder");
+MODULE_AUTHOR("Phil Karn, Thomas Gleixner");
+
--
2.6.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 6/9] arm: Clarify memory layout calculation
2015-12-02 13:48 [PATCH 0/9] RAMOOPS read support for Barebox Markus Pargmann
` (4 preceding siblings ...)
2015-12-02 13:48 ` [PATCH 5/9] lib: Import reed solomon code " Markus Pargmann
@ 2015-12-02 13:48 ` Markus Pargmann
2015-12-04 7:09 ` Sascha Hauer
2015-12-02 13:48 ` [PATCH 7/9] arm: start: Add visible sdram region for barebox board data Markus Pargmann
` (2 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Markus Pargmann @ 2015-12-02 13:48 UTC (permalink / raw)
To: barebox
The memory calculations used are all hardcoded into three different
files, start-pbl.c, uncompress.c and start.c. To make this more readable
and reliable, this patch gathers these information in barebox-arm.h with
static inline functions for the calculation of the memory offsets.
This patch also adds proper handling of different barebox/board data
sizes. Currently only 1MB+Alignment of RAM is reserved for Barebox and
board data. This could be too small for bigger devicetrees and barebox.
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
arch/arm/cpu/start-pbl.c | 14 ++++------
arch/arm/cpu/start.c | 48 +++++++++++++++++++---------------
arch/arm/cpu/uncompress.c | 31 ++++++++++------------
arch/arm/include/asm/barebox-arm.h | 53 ++++++++++++++++++++++++++------------
4 files changed, 82 insertions(+), 64 deletions(-)
diff --git a/arch/arm/cpu/start-pbl.c b/arch/arm/cpu/start-pbl.c
index 2075ffeee75f..f723edc61318 100644
--- a/arch/arm/cpu/start-pbl.c
+++ b/arch/arm/cpu/start-pbl.c
@@ -54,8 +54,6 @@ __noreturn void barebox_single_pbl_start(unsigned long membase,
uint32_t endmem = membase + memsize;
unsigned long barebox_base;
- endmem -= STACK_SIZE; /* stack */
-
if (IS_ENABLED(CONFIG_PBL_RELOCATABLE))
relocate_to_current_adr();
@@ -67,7 +65,7 @@ __noreturn void barebox_single_pbl_start(unsigned long membase,
pg_len = pg_end - pg_start;
if (IS_ENABLED(CONFIG_RELOCATABLE))
- barebox_base = arm_barebox_image_place(membase + memsize);
+ barebox_base = arm_mem_barebox_image(membase, endmem, pg_len);
else
barebox_base = TEXT_BASE;
@@ -83,14 +81,12 @@ __noreturn void barebox_single_pbl_start(unsigned long membase,
setup_c();
if (IS_ENABLED(CONFIG_MMU_EARLY)) {
- endmem &= ~0x3fff;
- endmem -= SZ_16K; /* ttb */
- mmu_early_enable(membase, memsize, endmem);
+ unsigned long ttb = arm_mem_ttb(membase, endmem);
+ mmu_early_enable(membase, memsize, ttb);
}
- endmem -= SZ_128K; /* early malloc */
- free_mem_ptr = endmem;
- free_mem_end_ptr = free_mem_ptr + SZ_128K;
+ free_mem_ptr = arm_mem_early_malloc(membase, endmem);
+ free_mem_end_ptr = arm_mem_early_malloc_end(membase, endmem);
pbl_barebox_uncompress((void*)barebox_base, (void *)pg_start, pg_len);
diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index c054f3c4400c..e06c4c8f37a0 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -104,14 +104,31 @@ void *barebox_arm_boot_dtb(void)
return barebox_boarddata;
}
+static inline unsigned long arm_mem_boarddata(unsigned long membase,
+ unsigned long endmem,
+ unsigned long size)
+{
+ unsigned long mem;
+
+ mem = arm_mem_barebox_image(membase, endmem, barebox_image_size);
+ mem -= ALIGN(size, 64);
+
+ return mem;
+}
+
__noreturn void barebox_non_pbl_start(unsigned long membase,
unsigned long memsize, void *boarddata)
{
unsigned long endmem = membase + memsize;
unsigned long malloc_start, malloc_end;
+ unsigned long barebox_size = barebox_image_size +
+ ((unsigned long)&__bss_stop - (unsigned long)&__bss_start);
+ unsigned long arm_head_bottom;
if (IS_ENABLED(CONFIG_RELOCATABLE)) {
- unsigned long barebox_base = arm_barebox_image_place(endmem);
+ unsigned long barebox_base = arm_mem_barebox_image(membase,
+ endmem,
+ barebox_size);
relocate_to_adr(barebox_base);
}
@@ -122,19 +139,16 @@ __noreturn void barebox_non_pbl_start(unsigned long membase,
pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize);
arm_stack_top = endmem;
- endmem -= STACK_SIZE; /* Stack */
if (IS_ENABLED(CONFIG_MMU_EARLY)) {
-
- endmem &= ~0x3fff;
- endmem -= SZ_16K; /* ttb */
+ unsigned long ttb = arm_mem_ttb(membase, endmem);
if (IS_ENABLED(CONFIG_PBL_IMAGE)) {
arm_set_cache_functions();
} else {
- pr_debug("enabling MMU, ttb @ 0x%08lx\n", endmem);
+ pr_debug("enabling MMU, ttb @ 0x%08lx\n", ttb);
arm_early_mmu_cache_invalidate();
- mmu_early_enable(membase, memsize, endmem);
+ mmu_early_enable(membase, memsize, ttb);
}
}
@@ -155,24 +169,16 @@ __noreturn void barebox_non_pbl_start(unsigned long membase,
}
if (totalsize) {
- endmem -= ALIGN(totalsize, 64);
+ unsigned long mem = arm_mem_boarddata(membase, endmem,
+ totalsize);
pr_debug("found %s in boarddata, copying to 0x%lu\n",
- name, endmem);
- barebox_boarddata = memcpy((void *)endmem,
- boarddata, totalsize);
+ name, mem);
+ barebox_boarddata = memcpy((void *)mem, boarddata,
+ totalsize);
}
}
- if ((unsigned long)_text > membase + memsize ||
- (unsigned long)_text < membase)
- /*
- * barebox is either outside SDRAM or in another
- * memory bank, so we can use the whole bank for
- * malloc.
- */
- malloc_end = endmem;
- else
- malloc_end = (unsigned long)_text;
+ malloc_end = arm_head_bottom;
/*
* Maximum malloc space is the Kconfig value if given
diff --git a/arch/arm/cpu/uncompress.c b/arch/arm/cpu/uncompress.c
index dbf6b1e3f807..5bcce6b9e36d 100644
--- a/arch/arm/cpu/uncompress.c
+++ b/arch/arm/cpu/uncompress.c
@@ -52,8 +52,6 @@ void __noreturn barebox_multi_pbl_start(unsigned long membase,
void *pg_start;
unsigned long pc = get_pc();
- endmem -= STACK_SIZE; /* stack */
-
image_end = (void *)ld_var(__image_end) - get_runtime_offset();
if (IS_ENABLED(CONFIG_PBL_RELOCATABLE)) {
@@ -68,8 +66,16 @@ void __noreturn barebox_multi_pbl_start(unsigned long membase,
relocate_to_adr(membase);
}
+ /*
+ * image_end is the first location after the executable. It contains
+ * the size of the appended compressed binary followed by the binary.
+ */
+ pg_start = image_end + 1;
+ pg_len = *(image_end);
+
if (IS_ENABLED(CONFIG_RELOCATABLE))
- barebox_base = arm_barebox_image_place(membase + memsize);
+ barebox_base = arm_mem_barebox_image(membase, endmem,
+ pg_len);
else
barebox_base = TEXT_BASE;
@@ -78,22 +84,13 @@ void __noreturn barebox_multi_pbl_start(unsigned long membase,
pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize);
if (IS_ENABLED(CONFIG_MMU_EARLY)) {
- endmem &= ~0x3fff;
- endmem -= SZ_16K; /* ttb */
- pr_debug("enabling MMU, ttb @ 0x%08x\n", endmem);
- mmu_early_enable(membase, memsize, endmem);
+ unsigned long ttb = arm_mem_ttb(membase, endmem);
+ pr_debug("enabling MMU, ttb @ 0x%08lx\n", ttb);
+ mmu_early_enable(membase, memsize, ttb);
}
- endmem -= SZ_128K; /* early malloc */
- free_mem_ptr = endmem;
- free_mem_end_ptr = free_mem_ptr + SZ_128K;
-
- /*
- * image_end is the first location after the executable. It contains
- * the size of the appended compressed binary followed by the binary.
- */
- pg_start = image_end + 1;
- pg_len = *(image_end);
+ free_mem_ptr = arm_mem_early_malloc(membase, endmem);
+ free_mem_end_ptr = arm_mem_early_malloc_end(membase, endmem);
pr_debug("uncompressing barebox binary at 0x%p (size 0x%08x) to 0x%08lx\n",
pg_start, pg_len, barebox_base);
diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
index 76e356413aec..da7717538b61 100644
--- a/arch/arm/include/asm/barebox-arm.h
+++ b/arch/arm/include/asm/barebox-arm.h
@@ -94,25 +94,44 @@ static inline void arm_fixup_vectors(void)
void *barebox_arm_boot_dtb(void);
-/*
- * For relocatable binaries find a suitable start address for the
- * relocated binary. Beginning at the memory end substract the reserved
- * space and round down a bit at the end. This is used by the pbl to
- * extract the image to a suitable place so that the uncompressed image
- * does not have to copy itself to another place. Also it's used by
- * the uncompressed image to relocate itself to the same place.
- */
-static inline unsigned long arm_barebox_image_place(unsigned long endmem)
+static inline unsigned long arm_mem_stack(unsigned long membase,
+ unsigned long endmem)
+{
+ return endmem - STACK_SIZE;
+}
+
+static inline unsigned long arm_mem_ttb(unsigned long membase,
+ unsigned long endmem)
+{
+ endmem = arm_mem_stack(membase, endmem);
+ endmem &= ~(SZ_16K - 1);
+ endmem -= SZ_16K;
+
+ return endmem;
+}
+
+static inline unsigned long arm_mem_early_malloc(unsigned long membase,
+ unsigned long endmem)
{
- endmem -= STACK_SIZE;
- endmem -= SZ_32K; /* ttb */
- endmem -= SZ_128K; /* early malloc */
- endmem -= SZ_1M; /* place for barebox image */
-
- /*
- * round down to make translating the objdump easier
- */
+ return arm_mem_ttb(membase, endmem) - SZ_128K;
+}
+
+static inline unsigned long arm_mem_early_malloc_end(unsigned long membase,
+ unsigned long endmem)
+{
+ return arm_mem_ttb(membase, endmem);
+}
+
+static inline unsigned long arm_mem_barebox_image(unsigned long membase,
+ unsigned long endmem,
+ unsigned long size)
+{
+ endmem = arm_mem_ttb(membase, endmem);
+
+#ifdef CONFIG_RELOCATABLE
+ endmem -= size;
endmem &= ~(SZ_1M - 1);
+#endif
return endmem;
}
--
2.6.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 7/9] arm: start: Add visible sdram region for barebox board data
2015-12-02 13:48 [PATCH 0/9] RAMOOPS read support for Barebox Markus Pargmann
` (5 preceding siblings ...)
2015-12-02 13:48 ` [PATCH 6/9] arm: Clarify memory layout calculation Markus Pargmann
@ 2015-12-02 13:48 ` Markus Pargmann
2015-12-02 13:48 ` [PATCH 8/9] arm: Add RAMOOPS memory area Markus Pargmann
2015-12-02 13:48 ` [PATCH 9/9] fs: Add pstore filesystem Markus Pargmann
8 siblings, 0 replies; 18+ messages in thread
From: Markus Pargmann @ 2015-12-02 13:48 UTC (permalink / raw)
To: barebox
This helps to understand and find problems with the memory layout of
barebox. It adds another entry for the board data that barebox
allocated.
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
arch/arm/cpu/start.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index e06c4c8f37a0..4ad64b61e86a 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -34,6 +34,8 @@
#include "mmu-early.h"
unsigned long arm_stack_top;
+static unsigned long arm_head_bottom;
+static unsigned long arm_barebox_size;
static void *barebox_boarddata;
static bool blob_is_fdt(const void *blob)
@@ -116,6 +118,18 @@ static inline unsigned long arm_mem_boarddata(unsigned long membase,
return mem;
}
+static int barebox_memory_areas_init(void)
+{
+ unsigned long start = arm_head_bottom;
+ unsigned long size = arm_mem_barebox_image(0, arm_stack_top,
+ arm_barebox_size) -
+ arm_head_bottom;
+ request_sdram_region("board data", start, size);
+
+ return 0;
+}
+device_initcall(barebox_memory_areas_init);
+
__noreturn void barebox_non_pbl_start(unsigned long membase,
unsigned long memsize, void *boarddata)
{
@@ -123,7 +137,6 @@ __noreturn void barebox_non_pbl_start(unsigned long membase,
unsigned long malloc_start, malloc_end;
unsigned long barebox_size = barebox_image_size +
((unsigned long)&__bss_stop - (unsigned long)&__bss_start);
- unsigned long arm_head_bottom;
if (IS_ENABLED(CONFIG_RELOCATABLE)) {
unsigned long barebox_base = arm_mem_barebox_image(membase,
@@ -139,6 +152,9 @@ __noreturn void barebox_non_pbl_start(unsigned long membase,
pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize);
arm_stack_top = endmem;
+ arm_barebox_size = barebox_size;
+ arm_head_bottom = arm_mem_barebox_image(membase, endmem,
+ arm_barebox_size);
if (IS_ENABLED(CONFIG_MMU_EARLY)) {
unsigned long ttb = arm_mem_ttb(membase, endmem);
@@ -175,6 +191,7 @@ __noreturn void barebox_non_pbl_start(unsigned long membase,
name, mem);
barebox_boarddata = memcpy((void *)mem, boarddata,
totalsize);
+ arm_head_bottom = mem;
}
}
--
2.6.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 8/9] arm: Add RAMOOPS memory area
2015-12-02 13:48 [PATCH 0/9] RAMOOPS read support for Barebox Markus Pargmann
` (6 preceding siblings ...)
2015-12-02 13:48 ` [PATCH 7/9] arm: start: Add visible sdram region for barebox board data Markus Pargmann
@ 2015-12-02 13:48 ` Markus Pargmann
2015-12-04 7:07 ` Sascha Hauer
2015-12-02 13:48 ` [PATCH 9/9] fs: Add pstore filesystem Markus Pargmann
8 siblings, 1 reply; 18+ messages in thread
From: Markus Pargmann @ 2015-12-02 13:48 UTC (permalink / raw)
To: barebox
RAMOOPS is a driver that uses a reserved static memory region to store
the data from the last panic or boot. This helps to debug crashes at the
next boot while preserving the boot messages.
To guarantee a memory area that is not altered by barebox or the kernel,
this area is located at the end of the RAM right after barebox and
before the STACK. This ensures that changing barebox sizes do not
interfere with RAMOOPS.
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
arch/arm/cpu/start.c | 6 ++++++
arch/arm/include/asm/barebox-arm.h | 14 +++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index 4ad64b61e86a..d03d1edfaf18 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -118,6 +118,12 @@ static inline unsigned long arm_mem_boarddata(unsigned long membase,
return mem;
}
+unsigned long arm_mem_ramoops_get(void)
+{
+ return arm_mem_ramoops(0, arm_stack_top);
+}
+EXPORT_SYMBOL_GPL(arm_mem_ramoops_get);
+
static int barebox_memory_areas_init(void)
{
unsigned long start = arm_head_bottom;
diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
index da7717538b61..91f1747d2df4 100644
--- a/arch/arm/include/asm/barebox-arm.h
+++ b/arch/arm/include/asm/barebox-arm.h
@@ -122,11 +122,23 @@ static inline unsigned long arm_mem_early_malloc_end(unsigned long membase,
return arm_mem_ttb(membase, endmem);
}
+static inline unsigned long arm_mem_ramoops(unsigned long membase,
+ unsigned long endmem)
+{
+ endmem = arm_mem_ttb(membase, endmem);
+#ifdef CONFIG_FS_PSTORE_RAMOOPS
+ endmem -= CONFIG_FS_PSTORE_RAMOOPS_SIZE;
+ endmem &= ~(SZ_4K - 1); /* Align to 4K */
+#endif
+
+ return endmem;
+}
+
static inline unsigned long arm_mem_barebox_image(unsigned long membase,
unsigned long endmem,
unsigned long size)
{
- endmem = arm_mem_ttb(membase, endmem);
+ endmem = arm_mem_ramoops(membase, endmem);
#ifdef CONFIG_RELOCATABLE
endmem -= size;
--
2.6.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 9/9] fs: Add pstore filesystem
2015-12-02 13:48 [PATCH 0/9] RAMOOPS read support for Barebox Markus Pargmann
` (7 preceding siblings ...)
2015-12-02 13:48 ` [PATCH 8/9] arm: Add RAMOOPS memory area Markus Pargmann
@ 2015-12-02 13:48 ` Markus Pargmann
2015-12-02 18:37 ` Antony Pavlov
8 siblings, 1 reply; 18+ messages in thread
From: Markus Pargmann @ 2015-12-02 13:48 UTC (permalink / raw)
To: barebox
pstore is a persistent storage filesystem used for RAMOOPS. It is used
to store console logs, panics, ftrace and other information in case of a
crash/panic/oops/reboot.
pstore is implemented for barebox as a read-only filesystem at the
moment. It may be extended later on. The idea is to provide a way to
extract essential data from the last running kernel.
Most of the code is copied from the kernel. However this is only a
lightweight implementation without real write support yet.
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
common/startup.c | 5 +
fs/Kconfig | 2 +
fs/Makefile | 1 +
fs/pstore/Kconfig | 88 ++++++++
fs/pstore/Makefile | 10 +
fs/pstore/fs.c | 280 +++++++++++++++++++++++++
fs/pstore/internal.h | 19 ++
fs/pstore/platform.c | 138 ++++++++++++
fs/pstore/ram.c | 507 +++++++++++++++++++++++++++++++++++++++++++++
fs/pstore/ram_core.c | 426 +++++++++++++++++++++++++++++++++++++
include/linux/pstore.h | 90 ++++++++
include/linux/pstore_ram.h | 87 ++++++++
12 files changed, 1653 insertions(+)
create mode 100644 fs/pstore/Kconfig
create mode 100644 fs/pstore/Makefile
create mode 100644 fs/pstore/fs.c
create mode 100644 fs/pstore/internal.h
create mode 100644 fs/pstore/platform.c
create mode 100644 fs/pstore/ram.c
create mode 100644 fs/pstore/ram_core.c
create mode 100644 include/linux/pstore.h
create mode 100644 include/linux/pstore_ram.h
diff --git a/common/startup.c b/common/startup.c
index 4a303b297aaf..093a23ba08c9 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -60,6 +60,11 @@ static int mount_root(void)
mount("none", "efivarfs", "/efivars", NULL);
}
+ if (IS_ENABLED(CONFIG_FS_PSTORE)) {
+ mkdir("/pstore", 0);
+ mount("none", "pstore", "/pstore", NULL);
+ }
+
return 0;
}
fs_initcall(mount_root);
diff --git a/fs/Kconfig b/fs/Kconfig
index 9217bc81ea1e..5413a9295ccc 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -89,4 +89,6 @@ config FS_SMHFS
located on a debugging host connected to the target running
Barebox
+source fs/pstore/Kconfig
+
endmenu
diff --git a/fs/Makefile b/fs/Makefile
index 46932057c1b7..590c068e6045 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_FS_UIMAGEFS) += uimagefs.o
obj-$(CONFIG_FS_EFI) += efi.o
obj-$(CONFIG_FS_EFIVARFS) += efivarfs.o
obj-$(CONFIG_FS_SMHFS) += smhfs.o
+obj-y += pstore/
diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig
new file mode 100644
index 000000000000..2455b5629cb1
--- /dev/null
+++ b/fs/pstore/Kconfig
@@ -0,0 +1,88 @@
+menuconfig FS_PSTORE
+ bool
+ prompt "pstore fs support"
+ help
+ Support for persistent storage to read data from the last crash, like
+ panic, dmesg and ftrace.
+
+if FS_PSTORE
+
+config FS_PSTORE_RAMOOPS
+ bool
+ depends on RELOCATABLE
+ depends on ARM
+ select REED_SOLOMON
+ select REED_SOLOMON_ENC8
+ select REED_SOLOMON_DEC8
+ prompt "pstore RAM backend"
+ help
+ Here the data is stored in a specific memory area that is neither
+ overwritten by barebox nor the kernel.
+
+if FS_PSTORE_RAMOOPS
+
+config FS_PSTORE_RAMOOPS_RO
+ bool
+ default y
+ prompt "pstore RAM backend read only"
+ help
+ This prevents the data from being erased by reinitializing the ramoops
+ area with new empty ECCs. Select this if you want to see the same
+ ramoops in the kernel.
+
+config FS_PSTORE_RAMOOPS_SIZE
+ int
+ prompt "Size of the RAMOOPS area"
+ default 2097152
+ help
+ Size of the RAMOOPS area that is reserved. This is passed to the
+ kernel as well as argument. Default is 2MiB.
+
+config FS_PSTORE_RAMOOPS_CONSOLE_SIZE
+ int
+ prompt "Size of the console area"
+ default 131072 # 2^17
+ range 4096 1073741824 # Random upper limitation of 1GiB
+ help
+ Size of the RAMOOPS console area that is reserved. This is passed to
+ the kernel as well as argument. It should be a power of 2.
+
+config FS_PSTORE_RAMOOPS_FTRACE_SIZE
+ int
+ prompt "Size of the ftrace area"
+ default 131072 # 2^17
+ range 4096 1073741824 # Random upper limitation of 1GiB
+ help
+ Size of the RAMOOPS ftrace area that is reserved. This is passed to
+ the kernel as well as argument. It should be a power of 2.
+
+config FS_PSTORE_RAMOOPS_PMSG_SIZE
+ int
+ prompt "Size of the userspace message area"
+ default 131072 # 2^17
+ range 4096 1073741824 # Random upper limitation of 1GiB
+ help
+ Size of the RAMOOPS pmsg area that is reserved. This is passed to
+ the kernel as well as argument. It should be a power of 2.
+
+config FS_PSTORE_RAMOOPS_RECORD_SIZE
+ int
+ prompt "Size of each oops area"
+ default 131072 # 2^17
+ range 4096 1073741824 # Random upper limitation of 1GiB
+ help
+ Size of each RAMOOPS oops area. There are multiple oops/panic areas
+ to store individual oops/panic messages. This is the size of each of
+ these areas. It should be a power of 2.
+
+config FS_PSTORE_ECC_SIZE
+ int
+ prompt "ECC size"
+ default 16
+ help
+ ECC size used. This is the amount of bytes for reed solomon codes
+ that is used. 0 disables ECC.
+
+endif
+
+endif
diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile
new file mode 100644
index 000000000000..2d719e95f087
--- /dev/null
+++ b/fs/pstore/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the linux pstorefs routines.
+#
+
+obj-$(CONFIG_FS_PSTORE) += pstore.o
+
+pstore-objs += fs.o platform.o
+
+ramoops-objs += ram.o ram_core.o
+obj-$(CONFIG_FS_PSTORE_RAMOOPS) += ramoops.o
diff --git a/fs/pstore/fs.c b/fs/pstore/fs.c
new file mode 100644
index 000000000000..0e05d48ea041
--- /dev/null
+++ b/fs/pstore/fs.c
@@ -0,0 +1,280 @@
+/*
+ * Persistent Storage Barebox filesystem layer
+ * Copyright © 2015 Pengutronix, Markus Pargmann <mpa@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <fs.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fs.h>
+#include <malloc.h>
+#include <init.h>
+#include <linux/stat.h>
+#include <linux/err.h>
+#include <linux/pstore.h>
+#include <libbb.h>
+#include <rtc.h>
+#include <libfile.h>
+#include <linux/pstore.h>
+#include "internal.h"
+
+struct list_head allpstore = LIST_HEAD_INIT(allpstore);
+
+struct pstore_private {
+ char name[PSTORE_NAMELEN];
+ struct list_head list;
+ struct pstore_info *psi;
+ enum pstore_type_id type;
+ u64 id;
+ int count;
+ ssize_t size;
+ ssize_t pos;
+ char data[];
+};
+
+/*
+ * Make a regular file in the root directory of our file system.
+ * Load it up with "size" bytes of data from "buf".
+ * Set the mtime & ctime to the date that this record was originally stored.
+ */
+int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
+ char *data, bool compressed, size_t size,
+ struct pstore_info *psi)
+{
+ struct pstore_private *private, *pos;
+
+ list_for_each_entry(pos, &allpstore, list) {
+ if (pos->type == type && pos->id == id && pos->psi == psi)
+ return -EEXIST;
+ }
+
+ private = xzalloc(sizeof(*private) + size);
+ if (!private)
+ return -ENOMEM;
+ private->type = type;
+ private->id = id;
+ private->count = count;
+ private->psi = psi;
+
+ switch (type) {
+ case PSTORE_TYPE_DMESG:
+ scnprintf(private->name, sizeof(private->name),
+ "dmesg-%s-%lld%s", psname, id,
+ compressed ? ".enc.z" : "");
+ break;
+ case PSTORE_TYPE_CONSOLE:
+ scnprintf(private->name, sizeof(private->name),
+ "console-%s-%lld", psname, id);
+ break;
+ case PSTORE_TYPE_FTRACE:
+ scnprintf(private->name, sizeof(private->name),
+ "ftrace-%s-%lld", psname, id);
+ break;
+ case PSTORE_TYPE_MCE:
+ scnprintf(private->name, sizeof(private->name),
+ "mce-%s-%lld", psname, id);
+ break;
+ case PSTORE_TYPE_PPC_RTAS:
+ scnprintf(private->name, sizeof(private->name),
+ "rtas-%s-%lld", psname, id);
+ break;
+ case PSTORE_TYPE_PPC_OF:
+ scnprintf(private->name, sizeof(private->name),
+ "powerpc-ofw-%s-%lld", psname, id);
+ break;
+ case PSTORE_TYPE_PPC_COMMON:
+ scnprintf(private->name, sizeof(private->name),
+ "powerpc-common-%s-%lld", psname, id);
+ break;
+ case PSTORE_TYPE_PMSG:
+ scnprintf(private->name, sizeof(private->name),
+ "pmsg-%s-%lld", psname, id);
+ break;
+ case PSTORE_TYPE_UNKNOWN:
+ scnprintf(private->name, sizeof(private->name),
+ "unknown-%s-%lld", psname, id);
+ break;
+ default:
+ scnprintf(private->name, sizeof(private->name),
+ "type%d-%s-%lld", type, psname, id);
+ break;
+ }
+
+ memcpy(private->data, data, size);
+ private->size = size;
+
+ list_add(&private->list, &allpstore);
+
+ return 0;
+}
+
+static struct pstore_private *pstore_get_by_name(struct list_head *head,
+ const char *name)
+{
+ struct pstore_private *d;
+
+ if (!name)
+ return NULL;
+
+ list_for_each_entry(d, head, list) {
+ if (strcmp(d->name, name) == 0)
+ return d;
+ }
+
+ return NULL;
+}
+
+static int pstore_open(struct device_d *dev, FILE *file, const char *filename)
+{
+ struct list_head *head = dev->priv;
+ struct pstore_private *d;
+
+ if (filename[0] == '/')
+ filename++;
+
+ d = pstore_get_by_name(head, filename);
+ if (!d)
+ return -EINVAL;
+
+ file->size = d->size;
+ file->priv = d;
+ d->pos = 0;
+
+ return 0;
+}
+
+static int pstore_close(struct device_d *dev, FILE *file)
+{
+ return 0;
+}
+
+static int pstore_read(struct device_d *dev, FILE *file, void *buf,
+ size_t insize)
+{
+ struct pstore_private *d = file->priv;
+
+ memcpy(buf, &d->data[d->pos], insize);
+ d->pos += insize;
+
+ return insize;
+}
+
+static loff_t pstore_lseek(struct device_d *dev, FILE *file, loff_t pos)
+{
+ struct pstore_private *d = file->priv;
+
+ d->pos = pos;
+
+ return pos;
+}
+
+static DIR *pstore_opendir(struct device_d *dev, const char *pathname)
+{
+ DIR *dir;
+
+ dir = xzalloc(sizeof(DIR));
+
+ if (list_empty(&allpstore))
+ return dir;
+
+ dir->priv = list_first_entry(&allpstore, struct pstore_private, list);
+
+ return dir;
+}
+
+static struct dirent *pstore_readdir(struct device_d *dev, DIR *dir)
+{
+ struct pstore_private *d = dir->priv;
+
+ if (!d || &d->list == &allpstore)
+ return NULL;
+
+ strcpy(dir->d.d_name, d->name);
+ dir->priv = list_entry(d->list.next, struct pstore_private, list);
+
+ return &dir->d;
+}
+
+static int pstore_closedir(struct device_d *dev, DIR *dir)
+{
+ free(dir);
+
+ return 0;
+}
+
+static int pstore_stat(struct device_d *dev, const char *filename,
+ struct stat *s)
+{
+ struct pstore_private *d;
+
+ if (filename[0] == '/')
+ filename++;
+
+ d = pstore_get_by_name(&allpstore, filename);
+ if (!d)
+ return -EINVAL;
+
+ s->st_size = d->size;
+ s->st_mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO;
+
+ return 0;
+}
+
+static void pstore_remove(struct device_d *dev)
+{
+ struct pstore_private *d, *tmp;
+
+ list_for_each_entry_safe(d, tmp, &allpstore, list) {
+ free(d);
+ }
+}
+
+static int pstore_probe(struct device_d *dev)
+{
+ struct list_head *priv = &allpstore;
+
+ dev->priv = priv;
+
+ dev_dbg(dev, "mounted pstore\n");
+
+ return 0;
+}
+
+static struct fs_driver_d pstore_driver = {
+ .open = pstore_open,
+ .close = pstore_close,
+ .read = pstore_read,
+ .lseek = pstore_lseek,
+ .opendir = pstore_opendir,
+ .readdir = pstore_readdir,
+ .closedir = pstore_closedir,
+ .stat = pstore_stat,
+ .flags = FS_DRIVER_NO_DEV,
+ .type = filetype_uimage,
+ .drv = {
+ .probe = pstore_probe,
+ .remove = pstore_remove,
+ .name = "pstore",
+ }
+};
+
+static int pstore_init(void)
+{
+ return register_fs_driver(&pstore_driver);
+}
+coredevice_initcall(pstore_init);
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
new file mode 100644
index 000000000000..0a8df1f4e296
--- /dev/null
+++ b/fs/pstore/internal.h
@@ -0,0 +1,19 @@
+#ifndef __PSTORE_INTERNAL_H__
+#define __PSTORE_INTERNAL_H__
+
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/pstore.h>
+
+#define PSTORE_NAMELEN 64
+
+extern struct pstore_info *psinfo;
+
+extern void pstore_set_kmsg_bytes(int);
+extern void pstore_get_records(int);
+extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id,
+ int count, char *data, bool compressed,
+ size_t size, struct pstore_info *psi);
+extern int pstore_is_mounted(void);
+
+#endif
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
new file mode 100644
index 000000000000..dc2611f7328c
--- /dev/null
+++ b/fs/pstore/platform.c
@@ -0,0 +1,138 @@
+/*
+ * Persistent Storage - platform driver interface parts.
+ *
+ * Copyright (C) 2007-2008 Google, Inc.
+ * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) "pstore: " fmt
+
+#include <linux/types.h>
+#include <linux/pstore.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <malloc.h>
+#include <printk.h>
+#include <module.h>
+
+#include "internal.h"
+
+struct pstore_info *psinfo;
+
+static char *backend;
+
+/* How much of the console log to snapshot */
+static unsigned long kmsg_bytes = 10240;
+
+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)
+{
+ return psi->write_buf(type, reason, id, part, psinfo->buf, compressed,
+ size, psi);
+}
+
+/*
+ * platform specific persistent storage driver registers with
+ * us here. If pstore is already mounted, call the platform
+ * read function right away to populate the file system. If not
+ * then the pstore mount code will call us later to fill out
+ * the file system.
+ *
+ * Register with kmsg_dump to save last part of console log on panic.
+ */
+int pstore_register(struct pstore_info *psi)
+{
+ if (backend && strcmp(backend, psi->name))
+ return -EPERM;
+
+ spin_lock(&pstore_lock);
+ if (psinfo) {
+ spin_unlock(&pstore_lock);
+ return -EBUSY;
+ }
+
+ if (!psi->write)
+ psi->write = pstore_write_compat;
+ psinfo = psi;
+ mutex_init(&psinfo->read_mutex);
+ spin_unlock(&pstore_lock);
+
+ pstore_get_records(0);
+
+ pr_info("Registered %s as persistent store backend\n", psi->name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pstore_register);
+
+/*
+ * Read all the records from the persistent store. Create
+ * files in our filesystem. Don't warn about -EEXIST errors
+ * when we are re-scanning the backing store looking to add new
+ * error records.
+ */
+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;
+ int failed = 0, rc;
+ bool compressed;
+ int unzipped_len = -1;
+
+ if (!psi)
+ return;
+
+ mutex_lock(&psi->read_mutex);
+ 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)) {
+ 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);
+ if (unzipped_len < 0) {
+ /* Free buffer other than big oops */
+ kfree(buf);
+ buf = NULL;
+ } else
+ unzipped_len = -1;
+ if (rc && (rc != -EEXIST || !quiet))
+ failed++;
+ }
+ if (psi->close)
+ psi->close(psi);
+out:
+ mutex_unlock(&psi->read_mutex);
+
+ if (failed)
+ pr_warn("failed to load %d record(s) from '%s'\n",
+ failed, psi->name);
+}
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
new file mode 100644
index 000000000000..dc31ed16f923
--- /dev/null
+++ b/fs/pstore/ram.c
@@ -0,0 +1,507 @@
+/*
+ * RAM Oops/Panic logger
+ *
+ * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
+ * Copyright (C) 2011 Kees Cook <keescook@chromium.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/pstore.h>
+#include <linux/time.h>
+#include <linux/ioport.h>
+#include <linux/compiler.h>
+#include <linux/pstore_ram.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/log2.h>
+#include <malloc.h>
+#include <printk.h>
+#include <stdio.h>
+#include <globalvar.h>
+#include <init.h>
+#include <common.h>
+
+#define RAMOOPS_KERNMSG_HDR "===="
+#define MIN_MEM_SIZE 4096UL
+
+static const ulong record_size = CONFIG_FS_PSTORE_RAMOOPS_RECORD_SIZE;
+
+static const ulong ramoops_console_size = CONFIG_FS_PSTORE_RAMOOPS_CONSOLE_SIZE;
+
+static const ulong ramoops_ftrace_size = CONFIG_FS_PSTORE_RAMOOPS_FTRACE_SIZE;
+
+static const ulong ramoops_pmsg_size = CONFIG_FS_PSTORE_RAMOOPS_PMSG_SIZE;
+
+static const ulong mem_size = CONFIG_FS_PSTORE_RAMOOPS_SIZE;
+
+static const int dump_oops = 1;
+
+static const int ramoops_ecc = CONFIG_FS_PSTORE_ECC_SIZE;
+
+struct ramoops_context {
+ struct persistent_ram_zone **przs;
+ struct persistent_ram_zone *cprz;
+ struct persistent_ram_zone *fprz;
+ struct persistent_ram_zone *mprz;
+ phys_addr_t phys_addr;
+ unsigned long size;
+ unsigned int memtype;
+ size_t record_size;
+ size_t console_size;
+ size_t ftrace_size;
+ size_t pmsg_size;
+ int dump_oops;
+ struct persistent_ram_ecc_info ecc_info;
+ unsigned int max_dump_cnt;
+ unsigned int dump_write_cnt;
+ /* _read_cnt need clear on ramoops_pstore_open */
+ unsigned int dump_read_cnt;
+ unsigned int console_read_cnt;
+ unsigned int ftrace_read_cnt;
+ unsigned int pmsg_read_cnt;
+ struct pstore_info pstore;
+};
+
+static struct ramoops_platform_data *dummy_data;
+
+static int ramoops_pstore_open(struct pstore_info *psi)
+{
+ struct ramoops_context *cxt = psi->data;
+
+ cxt->dump_read_cnt = 0;
+ cxt->console_read_cnt = 0;
+ cxt->ftrace_read_cnt = 0;
+ cxt->pmsg_read_cnt = 0;
+ return 0;
+}
+
+static struct persistent_ram_zone *
+ramoops_get_next_prz(struct persistent_ram_zone *przs[], uint *c, uint max,
+ u64 *id,
+ enum pstore_type_id *typep, enum pstore_type_id type,
+ bool update)
+{
+ struct persistent_ram_zone *prz;
+ int i = (*c)++;
+
+ if (i >= max)
+ return NULL;
+
+ prz = przs[i];
+ if (!prz)
+ return NULL;
+
+ /* Update old/shadowed buffer. */
+ if (update)
+ persistent_ram_save_old(prz);
+
+ if (!persistent_ram_old_size(prz))
+ return NULL;
+
+ *typep = type;
+ *id = i;
+
+ return prz;
+}
+
+static bool prz_ok(struct persistent_ram_zone *prz)
+{
+ return !!prz && !!(persistent_ram_old_size(prz) +
+ persistent_ram_ecc_string(prz, NULL, 0));
+}
+
+static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
+ int *count, char **buf, bool *compressed,
+ struct pstore_info *psi)
+{
+ ssize_t size;
+ ssize_t ecc_notice_size;
+ struct ramoops_context *cxt = psi->data;
+ struct persistent_ram_zone *prz;
+
+ prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt,
+ cxt->max_dump_cnt, id, type,
+ PSTORE_TYPE_DMESG, 0);
+ if (!prz_ok(prz))
+ prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt,
+ 1, id, type, PSTORE_TYPE_CONSOLE, 0);
+ if (!prz_ok(prz))
+ prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt,
+ 1, id, type, PSTORE_TYPE_FTRACE, 0);
+ if (!prz_ok(prz))
+ prz = ramoops_get_next_prz(&cxt->mprz, &cxt->pmsg_read_cnt,
+ 1, id, type, PSTORE_TYPE_PMSG, 0);
+ if (!prz_ok(prz))
+ return 0;
+
+ if (!persistent_ram_old(prz))
+ return 0;
+
+ size = persistent_ram_old_size(prz);
+
+ /* ECC correction notice */
+ ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0);
+
+ *buf = kmalloc(size + ecc_notice_size + 1, GFP_KERNEL);
+ if (*buf == NULL)
+ return -ENOMEM;
+
+ memcpy(*buf, (char *)persistent_ram_old(prz), size);
+ persistent_ram_ecc_string(prz, *buf + size, ecc_notice_size + 1);
+
+ return size + ecc_notice_size;
+}
+
+static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
+ enum kmsg_dump_reason reason,
+ u64 *id, unsigned int part,
+ const char *buf,
+ bool compressed, size_t size,
+ struct pstore_info *psi)
+{
+ struct ramoops_context *cxt = psi->data;
+ struct persistent_ram_zone *prz;
+
+ if (type == PSTORE_TYPE_CONSOLE) {
+ if (!cxt->cprz)
+ return -ENOMEM;
+ persistent_ram_write(cxt->cprz, buf, size);
+ return 0;
+ } else if (type == PSTORE_TYPE_FTRACE) {
+ if (!cxt->fprz)
+ return -ENOMEM;
+ persistent_ram_write(cxt->fprz, buf, size);
+ return 0;
+ } else if (type == PSTORE_TYPE_PMSG) {
+ if (!cxt->mprz)
+ return -ENOMEM;
+ persistent_ram_write(cxt->mprz, buf, size);
+ return 0;
+ }
+
+ if (type != PSTORE_TYPE_DMESG)
+ return -EINVAL;
+
+ /* Explicitly only take the first part of any new crash.
+ * If our buffer is larger than kmsg_bytes, this can never happen,
+ * and if our buffer is smaller than kmsg_bytes, we don't want the
+ * report split across multiple records.
+ */
+ if (part != 1)
+ return -ENOSPC;
+
+ if (!cxt->przs)
+ return -ENOSPC;
+
+ prz = cxt->przs[cxt->dump_write_cnt];
+
+ persistent_ram_write(prz, buf, size);
+
+ cxt->dump_write_cnt = (cxt->dump_write_cnt + 1) % cxt->max_dump_cnt;
+
+ return 0;
+}
+
+static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count,
+ struct pstore_info *psi)
+{
+ struct ramoops_context *cxt = psi->data;
+ struct persistent_ram_zone *prz;
+
+ switch (type) {
+ case PSTORE_TYPE_DMESG:
+ if (id >= cxt->max_dump_cnt)
+ return -EINVAL;
+ prz = cxt->przs[id];
+ break;
+ case PSTORE_TYPE_CONSOLE:
+ prz = cxt->cprz;
+ break;
+ case PSTORE_TYPE_FTRACE:
+ prz = cxt->fprz;
+ break;
+ case PSTORE_TYPE_PMSG:
+ prz = cxt->mprz;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ persistent_ram_free_old(prz);
+ persistent_ram_zap(prz);
+
+ return 0;
+}
+
+static struct ramoops_context oops_cxt = {
+ .pstore = {
+ .name = "ramoops",
+ .open = ramoops_pstore_open,
+ .read = ramoops_pstore_read,
+ .write_buf = ramoops_pstore_write_buf,
+ .erase = ramoops_pstore_erase,
+ },
+};
+
+static void ramoops_free_przs(struct ramoops_context *cxt)
+{
+ int i;
+
+ cxt->max_dump_cnt = 0;
+ if (!cxt->przs)
+ return;
+
+ for (i = 0; !IS_ERR_OR_NULL(cxt->przs[i]); i++)
+ persistent_ram_free(cxt->przs[i]);
+ kfree(cxt->przs);
+}
+
+static int ramoops_init_przs(struct ramoops_context *cxt, phys_addr_t *paddr,
+ size_t dump_mem_sz)
+{
+ int err = -ENOMEM;
+ int i;
+
+ if (!cxt->record_size)
+ return 0;
+
+ if (*paddr + dump_mem_sz - cxt->phys_addr > cxt->size) {
+ pr_err("no room for dumps\n");
+ return -ENOMEM;
+ }
+
+ cxt->max_dump_cnt = dump_mem_sz / cxt->record_size;
+ if (!cxt->max_dump_cnt)
+ return -ENOMEM;
+
+ cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_dump_cnt,
+ GFP_KERNEL);
+ if (!cxt->przs) {
+ pr_err("failed to initialize a prz array for dumps\n");
+ goto fail_prz;
+ }
+
+ for (i = 0; i < cxt->max_dump_cnt; i++) {
+ size_t sz = cxt->record_size;
+
+ cxt->przs[i] = persistent_ram_new(*paddr, sz, 0,
+ &cxt->ecc_info,
+ cxt->memtype);
+ if (IS_ERR(cxt->przs[i])) {
+ err = PTR_ERR(cxt->przs[i]);
+ pr_err("failed to request mem region (0x%zx@0x%llx): %d\n",
+ sz, (unsigned long long)*paddr, err);
+ goto fail_prz;
+ }
+ *paddr += sz;
+ }
+
+ return 0;
+fail_prz:
+ ramoops_free_przs(cxt);
+ return err;
+}
+
+static int ramoops_init_prz(struct ramoops_context *cxt,
+ struct persistent_ram_zone **prz,
+ phys_addr_t *paddr, size_t sz, u32 sig)
+{
+ if (!sz)
+ return 0;
+
+ if (*paddr + sz - cxt->phys_addr > cxt->size) {
+ pr_err("no room for mem region (0x%zx@0x%llx) in (0x%lx@0x%llx)\n",
+ sz, (unsigned long long)*paddr,
+ cxt->size, (unsigned long long)cxt->phys_addr);
+ return -ENOMEM;
+ }
+
+ *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info,
+ cxt->memtype);
+ if (IS_ERR(*prz)) {
+ int err = PTR_ERR(*prz);
+
+ pr_err("failed to request mem region (0x%zx@0x%llx): %d\n",
+ sz, (unsigned long long)*paddr, err);
+ return err;
+ }
+
+ persistent_ram_zap(*prz);
+
+ *paddr += sz;
+
+ return 0;
+}
+
+static int ramoops_probe(struct ramoops_platform_data *pdata)
+{
+ struct ramoops_context *cxt = &oops_cxt;
+ size_t dump_mem_sz;
+ phys_addr_t paddr;
+ int err = -EINVAL;
+ char kernelargs[512];
+
+ /* Only a single ramoops area allowed at a time, so fail extra
+ * probes.
+ */
+ if (cxt->max_dump_cnt)
+ goto fail_out;
+
+ if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size &&
+ !pdata->ftrace_size && !pdata->pmsg_size)) {
+ pr_err("The memory size and the record/console size must be "
+ "non-zero\n");
+ goto fail_out;
+ }
+
+ if (pdata->record_size && !is_power_of_2(pdata->record_size))
+ pdata->record_size = rounddown_pow_of_two(pdata->record_size);
+ if (pdata->console_size && !is_power_of_2(pdata->console_size))
+ pdata->console_size = rounddown_pow_of_two(pdata->console_size);
+ if (pdata->ftrace_size && !is_power_of_2(pdata->ftrace_size))
+ pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size);
+ if (pdata->pmsg_size && !is_power_of_2(pdata->pmsg_size))
+ pdata->pmsg_size = rounddown_pow_of_two(pdata->pmsg_size);
+
+ cxt->size = pdata->mem_size;
+ cxt->phys_addr = pdata->mem_address;
+ cxt->memtype = pdata->mem_type;
+ cxt->record_size = pdata->record_size;
+ cxt->console_size = pdata->console_size;
+ cxt->ftrace_size = pdata->ftrace_size;
+ cxt->pmsg_size = pdata->pmsg_size;
+ cxt->dump_oops = pdata->dump_oops;
+ cxt->ecc_info = pdata->ecc_info;
+
+ paddr = cxt->phys_addr;
+
+ dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size
+ - cxt->pmsg_size;
+ err = ramoops_init_przs(cxt, &paddr, dump_mem_sz);
+ if (err)
+ goto fail_out;
+
+ err = ramoops_init_prz(cxt, &cxt->cprz, &paddr,
+ cxt->console_size, 0);
+ if (err)
+ goto fail_init_cprz;
+
+ err = ramoops_init_prz(cxt, &cxt->fprz, &paddr, cxt->ftrace_size, 0);
+ if (err)
+ goto fail_init_fprz;
+
+ err = ramoops_init_prz(cxt, &cxt->mprz, &paddr, cxt->pmsg_size, 0);
+ if (err)
+ goto fail_init_mprz;
+
+ cxt->pstore.data = cxt;
+ /*
+ * Console can handle any buffer size, so prefer LOG_LINE_MAX. If we
+ * have to handle dumps, we must have at least record_size buffer. And
+ * for ftrace, bufsize is irrelevant (if bufsize is 0, buf will be
+ * ZERO_SIZE_PTR).
+ */
+ if (cxt->console_size)
+ cxt->pstore.bufsize = 1024; /* LOG_LINE_MAX */
+ cxt->pstore.bufsize = max(cxt->record_size, cxt->pstore.bufsize);
+ cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL);
+ spin_lock_init(&cxt->pstore.buf_lock);
+ if (!cxt->pstore.buf) {
+ pr_err("cannot allocate pstore buffer\n");
+ err = -ENOMEM;
+ goto fail_clear;
+ }
+
+ err = pstore_register(&cxt->pstore);
+ if (err) {
+ pr_err("registering with pstore failed\n");
+ goto fail_buf;
+ }
+
+ pr_info("attached 0x%lx@0x%llx, ecc: %d/%d\n",
+ cxt->size, (unsigned long long)cxt->phys_addr,
+ cxt->ecc_info.ecc_size, cxt->ecc_info.block_size);
+
+ scnprintf(kernelargs, sizeof(kernelargs),
+ "ramoops.record_size=0x%x "
+ "ramoops.console_size=0x%x "
+ "ramoops.ftrace_size=0x%x "
+ "ramoops.pmsg_size=0x%x "
+ "ramoops.mem_address=0x%llx "
+ "ramoops.mem_size=0x%lx "
+ "ramoops.ecc=%d",
+ cxt->record_size,
+ cxt->console_size,
+ cxt->ftrace_size,
+ cxt->pmsg_size,
+ (unsigned long long)cxt->phys_addr,
+ mem_size,
+ ramoops_ecc);
+ globalvar_add_simple("linux.bootargs.ramoops", kernelargs);
+
+ of_add_reserve_entry(cxt->phys_addr, cxt->phys_addr + mem_size);
+
+ return 0;
+
+fail_buf:
+ kfree(cxt->pstore.buf);
+fail_clear:
+ cxt->pstore.bufsize = 0;
+ kfree(cxt->mprz);
+fail_init_mprz:
+ kfree(cxt->fprz);
+fail_init_fprz:
+ kfree(cxt->cprz);
+fail_init_cprz:
+ ramoops_free_przs(cxt);
+fail_out:
+ return err;
+}
+unsigned long arm_mem_ramoops_get(void);
+
+static void ramoops_register_dummy(void)
+{
+ dummy_data = kzalloc(sizeof(*dummy_data), GFP_KERNEL);
+ if (!dummy_data) {
+ pr_info("could not allocate pdata\n");
+ return;
+ }
+
+ dummy_data->mem_size = mem_size;
+ dummy_data->mem_address = arm_mem_ramoops_get();
+ dummy_data->mem_type = 0;
+ dummy_data->record_size = record_size;
+ dummy_data->console_size = ramoops_console_size;
+ dummy_data->ftrace_size = ramoops_ftrace_size;
+ dummy_data->pmsg_size = ramoops_pmsg_size;
+ dummy_data->dump_oops = dump_oops;
+ /*
+ * For backwards compatibility ramoops.ecc=1 means 16 bytes ECC
+ * (using 1 byte for ECC isn't much of use anyway).
+ */
+ dummy_data->ecc_info.ecc_size = ramoops_ecc == 1 ? 16 : ramoops_ecc;
+
+ ramoops_probe(dummy_data);
+}
+
+static int __init ramoops_init(void)
+{
+ ramoops_register_dummy();
+ return 0;
+}
+postcore_initcall(ramoops_init);
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
new file mode 100644
index 000000000000..d68d80900b50
--- /dev/null
+++ b/fs/pstore/ram_core.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "persistent_ram: " fmt
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/rslib.h>
+#include <linux/pstore_ram.h>
+#include <linux/string.h>
+#include <linux/rslib.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <memory.h>
+#include <common.h>
+
+struct persistent_ram_buffer {
+ uint32_t sig;
+ resource_size_t start;
+ resource_size_t size;
+ uint8_t data[0];
+};
+
+#define PERSISTENT_RAM_SIG (0x43474244) /* DBGC */
+
+static inline size_t buffer_size(struct persistent_ram_zone *prz)
+{
+ return prz->buffer->size;
+}
+
+static inline size_t buffer_start(struct persistent_ram_zone *prz)
+{
+ return prz->buffer->start;
+}
+
+/* increase and wrap the start pointer, returning the old value */
+static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
+{
+ int old;
+ int new;
+
+ old = prz->buffer->start;
+ new = old + a;
+ while (unlikely(new >= prz->buffer_size))
+ new -= prz->buffer_size;
+ prz->buffer->start = new;
+
+ return old;
+}
+
+/* increase the size counter until it hits the max size */
+static void buffer_size_add(struct persistent_ram_zone *prz, size_t a)
+{
+ size_t old;
+ size_t new;
+
+ old = prz->buffer->size;
+ if (old == prz->buffer_size)
+ return;
+
+ new = old + a;
+ if (new > prz->buffer_size)
+ new = prz->buffer_size;
+ prz->buffer->size = new;
+}
+
+static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz,
+ uint8_t *data, size_t len, uint8_t *ecc)
+{
+ int i;
+ uint16_t par[prz->ecc_info.ecc_size];
+
+ /* Initialize the parity buffer */
+ memset(par, 0, sizeof(par));
+ encode_rs8(prz->rs_decoder, data, len, par, 0);
+ for (i = 0; i < prz->ecc_info.ecc_size; i++)
+ ecc[i] = par[i];
+}
+
+static int persistent_ram_decode_rs8(struct persistent_ram_zone *prz,
+ void *data, size_t len, uint8_t *ecc)
+{
+ int i;
+ uint16_t par[prz->ecc_info.ecc_size];
+
+ for (i = 0; i < prz->ecc_info.ecc_size; i++)
+ par[i] = ecc[i];
+ return decode_rs8(prz->rs_decoder, data, par, len,
+ NULL, 0, NULL, 0, NULL);
+}
+
+static void notrace persistent_ram_update_ecc(struct persistent_ram_zone *prz,
+ unsigned int start, unsigned int count)
+{
+ struct persistent_ram_buffer *buffer = prz->buffer;
+ uint8_t *buffer_end = buffer->data + prz->buffer_size;
+ uint8_t *block;
+ uint8_t *par;
+ int ecc_block_size = prz->ecc_info.block_size;
+ int ecc_size = prz->ecc_info.ecc_size;
+ int size = ecc_block_size;
+
+ if (!ecc_size)
+ return;
+
+ block = buffer->data + (start & ~(ecc_block_size - 1));
+ par = prz->par_buffer + (start / ecc_block_size) * ecc_size;
+
+ do {
+ if (block + ecc_block_size > buffer_end)
+ size = buffer_end - block;
+ persistent_ram_encode_rs8(prz, block, size, par);
+ block += ecc_block_size;
+ par += ecc_size;
+ } while (block < buffer->data + start + count);
+}
+
+static void persistent_ram_update_header_ecc(struct persistent_ram_zone *prz)
+{
+ struct persistent_ram_buffer *buffer = prz->buffer;
+
+ if (!prz->ecc_info.ecc_size)
+ return;
+
+ persistent_ram_encode_rs8(prz, (uint8_t *)buffer, sizeof(*buffer),
+ prz->par_header);
+}
+
+static void persistent_ram_ecc_old(struct persistent_ram_zone *prz)
+{
+ struct persistent_ram_buffer *buffer = prz->buffer;
+ uint8_t *block;
+ uint8_t *par;
+
+ if (!prz->ecc_info.ecc_size)
+ return;
+
+ block = buffer->data;
+ par = prz->par_buffer;
+ while (block < buffer->data + buffer_size(prz)) {
+ int numerr;
+ int size = prz->ecc_info.block_size;
+ if (block + size > buffer->data + prz->buffer_size)
+ size = buffer->data + prz->buffer_size - block;
+ numerr = persistent_ram_decode_rs8(prz, block, size, par);
+ if (numerr > 0) {
+ pr_debug("error in block %p, %d\n", block, numerr);
+ prz->corrected_bytes += numerr;
+ } else if (numerr < 0) {
+ pr_debug("uncorrectable error in block %p\n", block);
+ prz->bad_blocks++;
+ }
+ block += prz->ecc_info.block_size;
+ par += prz->ecc_info.ecc_size;
+ }
+}
+
+static int persistent_ram_init_ecc(struct persistent_ram_zone *prz,
+ struct persistent_ram_ecc_info *ecc_info)
+{
+ int numerr;
+ struct persistent_ram_buffer *buffer = prz->buffer;
+ int ecc_blocks;
+ size_t ecc_total;
+
+ if (!ecc_info || !ecc_info->ecc_size)
+ return 0;
+
+ prz->ecc_info.block_size = ecc_info->block_size ?: 128;
+ prz->ecc_info.ecc_size = ecc_info->ecc_size ?: 16;
+ prz->ecc_info.symsize = ecc_info->symsize ?: 8;
+ prz->ecc_info.poly = ecc_info->poly ?: 0x11d;
+
+ ecc_blocks = DIV_ROUND_UP(prz->buffer_size - prz->ecc_info.ecc_size,
+ prz->ecc_info.block_size +
+ prz->ecc_info.ecc_size);
+ ecc_total = (ecc_blocks + 1) * prz->ecc_info.ecc_size;
+ if (ecc_total >= prz->buffer_size) {
+ pr_err("%s: invalid ecc_size %u (total %zu, buffer size %zu)\n",
+ __func__, prz->ecc_info.ecc_size,
+ ecc_total, prz->buffer_size);
+ return -EINVAL;
+ }
+
+ prz->buffer_size -= ecc_total;
+ prz->par_buffer = buffer->data + prz->buffer_size;
+ prz->par_header = prz->par_buffer +
+ ecc_blocks * prz->ecc_info.ecc_size;
+
+ /*
+ * first consecutive root is 0
+ * primitive element to generate roots = 1
+ */
+ prz->rs_decoder = init_rs(prz->ecc_info.symsize, prz->ecc_info.poly,
+ 0, 1, prz->ecc_info.ecc_size);
+ if (prz->rs_decoder == NULL) {
+ pr_info("init_rs failed\n");
+ return -EINVAL;
+ }
+
+ prz->corrected_bytes = 0;
+ prz->bad_blocks = 0;
+
+ numerr = persistent_ram_decode_rs8(prz, buffer, sizeof(*buffer),
+ prz->par_header);
+ if (numerr > 0) {
+ pr_info("error in header, %d\n", numerr);
+ prz->corrected_bytes += numerr;
+ } else if (numerr < 0) {
+ pr_info("uncorrectable error in header\n");
+ prz->bad_blocks++;
+ }
+
+ return 0;
+}
+
+ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
+ char *str, size_t len)
+{
+ ssize_t ret;
+
+ if (!prz->ecc_info.ecc_size)
+ return 0;
+
+ if (prz->corrected_bytes || prz->bad_blocks)
+ ret = snprintf(str, len, ""
+ "\n%d Corrected bytes, %d unrecoverable blocks\n",
+ prz->corrected_bytes, prz->bad_blocks);
+ else
+ ret = snprintf(str, len, "\nNo errors detected\n");
+
+ return ret;
+}
+
+static void notrace persistent_ram_update(struct persistent_ram_zone *prz,
+ const void *s, unsigned int start, unsigned int count)
+{
+ struct persistent_ram_buffer *buffer = prz->buffer;
+ memcpy(buffer->data + start, s, count);
+ persistent_ram_update_ecc(prz, start, count);
+}
+
+void persistent_ram_save_old(struct persistent_ram_zone *prz)
+{
+ struct persistent_ram_buffer *buffer = prz->buffer;
+ size_t size = buffer_size(prz);
+ size_t start = buffer_start(prz);
+
+ if (!size)
+ return;
+
+ if (!prz->old_log) {
+ persistent_ram_ecc_old(prz);
+ prz->old_log = kmalloc(size, GFP_KERNEL);
+ }
+ if (!prz->old_log) {
+ pr_err("failed to allocate buffer\n");
+ return;
+ }
+
+ prz->old_log_size = size;
+ memcpy(prz->old_log, &buffer->data[start], size - start);
+ memcpy(prz->old_log + size - start, &buffer->data[0], start);
+}
+
+int notrace persistent_ram_write(struct persistent_ram_zone *prz,
+ const void *s, unsigned int count)
+{
+ int rem;
+ int c = count;
+ size_t start;
+
+ if (unlikely(c > prz->buffer_size)) {
+ s += c - prz->buffer_size;
+ c = prz->buffer_size;
+ }
+
+ buffer_size_add(prz, c);
+
+ start = buffer_start_add(prz, c);
+
+ rem = prz->buffer_size - start;
+ if (unlikely(rem < c)) {
+ persistent_ram_update(prz, s, start, rem);
+ s += rem;
+ c -= rem;
+ start = 0;
+ }
+ persistent_ram_update(prz, s, start, c);
+
+ persistent_ram_update_header_ecc(prz);
+
+ return count;
+}
+
+size_t persistent_ram_old_size(struct persistent_ram_zone *prz)
+{
+ return prz->old_log_size;
+}
+
+void *persistent_ram_old(struct persistent_ram_zone *prz)
+{
+ return prz->old_log;
+}
+
+void persistent_ram_free_old(struct persistent_ram_zone *prz)
+{
+ kfree(prz->old_log);
+ prz->old_log = NULL;
+ prz->old_log_size = 0;
+}
+
+#ifdef CONFIG_FS_PSTORE_RAMOOPS_RO
+void persistent_ram_zap(struct persistent_ram_zone *prz)
+{
+}
+#else
+void persistent_ram_zap(struct persistent_ram_zone *prz)
+{
+ prz->buffer->start = 0;
+ prz->buffer->size = 0;
+ persistent_ram_update_header_ecc(prz);
+}
+#endif /* CONFIG_PSTORE_RAMOOPS_RO */
+
+static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
+ struct persistent_ram_zone *prz, int memtype)
+{
+ prz->res = request_sdram_region("persistent ram", start, size);
+ if (!prz->res)
+ return -ENOMEM;
+
+ prz->paddr = start;
+ prz->size = size;
+
+ prz->buffer = (void *)start;
+ prz->buffer_size = size - sizeof(struct persistent_ram_buffer);
+
+ return 0;
+}
+
+static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig,
+ struct persistent_ram_ecc_info *ecc_info)
+{
+ int ret;
+
+ ret = persistent_ram_init_ecc(prz, ecc_info);
+ if (ret)
+ return ret;
+
+ sig ^= PERSISTENT_RAM_SIG;
+
+ if (prz->buffer->sig == sig) {
+ if (buffer_size(prz) > prz->buffer_size ||
+ buffer_start(prz) > buffer_size(prz))
+ pr_info("found existing invalid buffer, size %zu, start %zu\n",
+ buffer_size(prz), buffer_start(prz));
+ else {
+ pr_debug("found existing buffer, size %zu, start %zu\n",
+ buffer_size(prz), buffer_start(prz));
+ persistent_ram_save_old(prz);
+ return 0;
+ }
+ } else {
+ pr_debug("no valid data in buffer (sig = 0x%08x)\n",
+ prz->buffer->sig);
+ }
+
+ prz->buffer->sig = sig;
+ persistent_ram_zap(prz);
+
+ return 0;
+}
+
+void persistent_ram_free(struct persistent_ram_zone *prz)
+{
+ if (!prz)
+ return;
+
+ if (prz->res) {
+ release_sdram_region(prz->res);
+ prz->res = NULL;
+ }
+
+ persistent_ram_free_old(prz);
+ kfree(prz);
+}
+
+struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
+ u32 sig, struct persistent_ram_ecc_info *ecc_info,
+ unsigned int memtype)
+{
+ struct persistent_ram_zone *prz;
+ int ret = -ENOMEM;
+
+ prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL);
+ if (!prz) {
+ pr_err("failed to allocate persistent ram zone\n");
+ goto err;
+ }
+
+ ret = persistent_ram_buffer_map(start, size, prz, memtype);
+ if (ret)
+ goto err;
+
+ ret = persistent_ram_post_init(prz, sig, ecc_info);
+ if (ret)
+ goto err;
+
+ return prz;
+err:
+ persistent_ram_free(prz);
+ return ERR_PTR(ret);
+}
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
new file mode 100644
index 000000000000..a925e143971c
--- /dev/null
+++ b/include/linux/pstore.h
@@ -0,0 +1,90 @@
+/*
+ * Persistent Storage - pstore.h
+ *
+ * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com>
+ *
+ * This code is the generic layer to export data records from platform
+ * level persistent storage via a file system.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _LINUX_PSTORE_H
+#define _LINUX_PSTORE_H
+
+#include <linux/time.h>
+#include <linux/types.h>
+#include <asm-generic/errno.h>
+
+/* types */
+enum pstore_type_id {
+ PSTORE_TYPE_DMESG = 0,
+ PSTORE_TYPE_MCE = 1,
+ PSTORE_TYPE_CONSOLE = 2,
+ PSTORE_TYPE_FTRACE = 3,
+ /* PPC64 partition types */
+ PSTORE_TYPE_PPC_RTAS = 4,
+ PSTORE_TYPE_PPC_OF = 5,
+ PSTORE_TYPE_PPC_COMMON = 6,
+ PSTORE_TYPE_PMSG = 7,
+ PSTORE_TYPE_UNKNOWN = 255
+};
+
+enum kmsg_dump_reason {
+ KMSG_DUMP_UNDEF,
+};
+
+struct module;
+
+struct pstore_info {
+ struct module *owner;
+ char *name;
+ char *buf;
+ size_t bufsize;
+ int flags;
+ int (*open)(struct pstore_info *psi);
+ int (*close)(struct pstore_info *psi);
+ ssize_t (*read)(u64 *id, enum pstore_type_id *type,
+ int *count, char **buf, bool *compressed,
+ struct pstore_info *psi);
+ int (*write)(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);
+ int (*write_buf)(enum pstore_type_id type,
+ enum kmsg_dump_reason reason, u64 *id,
+ unsigned int part, const char *buf, bool compressed,
+ size_t size, struct pstore_info *psi);
+ int (*erase)(enum pstore_type_id type, u64 id,
+ int count, struct pstore_info *psi);
+ void *data;
+};
+
+#define PSTORE_FLAGS_FRAGILE 1
+
+#ifdef CONFIG_FS_PSTORE
+extern int pstore_register(struct pstore_info *);
+extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason);
+#else
+static inline int
+pstore_register(struct pstore_info *psi)
+{
+ return -ENODEV;
+}
+static inline bool
+pstore_cannot_block_path(enum kmsg_dump_reason reason)
+{
+ return false;
+}
+#endif
+
+#endif /*_LINUX_PSTORE_H*/
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
new file mode 100644
index 000000000000..5ef823a57be9
--- /dev/null
+++ b/include/linux/pstore_ram.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
+ * Copyright (C) 2011 Kees Cook <keescook@chromium.org>
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __LINUX_PSTORE_RAM_H__
+#define __LINUX_PSTORE_RAM_H__
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/types.h>
+
+struct persistent_ram_buffer;
+struct rs_control;
+
+struct persistent_ram_ecc_info {
+ int block_size;
+ int ecc_size;
+ int symsize;
+ int poly;
+};
+
+struct persistent_ram_zone {
+ phys_addr_t paddr;
+ size_t size;
+ struct persistent_ram_buffer *buffer;
+ size_t buffer_size;
+ struct resource *res;
+
+ /* ECC correction */
+ char *par_buffer;
+ char *par_header;
+ struct rs_control *rs_decoder;
+ int corrected_bytes;
+ int bad_blocks;
+ struct persistent_ram_ecc_info ecc_info;
+
+ char *old_log;
+ size_t old_log_size;
+};
+
+struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
+ u32 sig, struct persistent_ram_ecc_info *ecc_info,
+ unsigned int memtype);
+void persistent_ram_free(struct persistent_ram_zone *prz);
+void persistent_ram_zap(struct persistent_ram_zone *prz);
+
+int persistent_ram_write(struct persistent_ram_zone *prz, const void *s,
+ unsigned int count);
+
+void persistent_ram_save_old(struct persistent_ram_zone *prz);
+size_t persistent_ram_old_size(struct persistent_ram_zone *prz);
+void *persistent_ram_old(struct persistent_ram_zone *prz);
+void persistent_ram_free_old(struct persistent_ram_zone *prz);
+ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
+ char *str, size_t len);
+
+/*
+ * Ramoops platform data
+ * @mem_size memory size for ramoops
+ * @mem_address physical memory address to contain ramoops
+ */
+
+struct ramoops_platform_data {
+ unsigned long mem_size;
+ unsigned long mem_address;
+ unsigned int mem_type;
+ unsigned long record_size;
+ unsigned long console_size;
+ unsigned long ftrace_size;
+ unsigned long pmsg_size;
+ int dump_oops;
+ struct persistent_ram_ecc_info ecc_info;
+};
+
+#endif
--
2.6.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 9/9] fs: Add pstore filesystem
2015-12-02 13:48 ` [PATCH 9/9] fs: Add pstore filesystem Markus Pargmann
@ 2015-12-02 18:37 ` Antony Pavlov
2015-12-04 13:10 ` Markus Pargmann
0 siblings, 1 reply; 18+ messages in thread
From: Antony Pavlov @ 2015-12-02 18:37 UTC (permalink / raw)
To: Markus Pargmann; +Cc: barebox
On Wed, 2 Dec 2015 14:48:51 +0100
Markus Pargmann <mpa@pengutronix.de> wrote:
> pstore is a persistent storage filesystem used for RAMOOPS. It is used
> to store console logs, panics, ftrace and other information in case of a
> crash/panic/oops/reboot.
>
> pstore is implemented for barebox as a read-only filesystem at the
> moment. It may be extended later on. The idea is to provide a way to
> extract essential data from the last running kernel.
>
> Most of the code is copied from the kernel. However this is only a
> lightweight implementation without real write support yet.
>
> Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
> ---
> common/startup.c | 5 +
> fs/Kconfig | 2 +
> fs/Makefile | 1 +
> fs/pstore/Kconfig | 88 ++++++++
> fs/pstore/Makefile | 10 +
> fs/pstore/fs.c | 280 +++++++++++++++++++++++++
> fs/pstore/internal.h | 19 ++
> fs/pstore/platform.c | 138 ++++++++++++
> fs/pstore/ram.c | 507 +++++++++++++++++++++++++++++++++++++++++++++
> fs/pstore/ram_core.c | 426 +++++++++++++++++++++++++++++++++++++
> include/linux/pstore.h | 90 ++++++++
> include/linux/pstore_ram.h | 87 ++++++++
> 12 files changed, 1653 insertions(+)
> create mode 100644 fs/pstore/Kconfig
> create mode 100644 fs/pstore/Makefile
> create mode 100644 fs/pstore/fs.c
> create mode 100644 fs/pstore/internal.h
> create mode 100644 fs/pstore/platform.c
> create mode 100644 fs/pstore/ram.c
> create mode 100644 fs/pstore/ram_core.c
> create mode 100644 include/linux/pstore.h
> create mode 100644 include/linux/pstore_ram.h
>
> diff --git a/common/startup.c b/common/startup.c
> index 4a303b297aaf..093a23ba08c9 100644
> --- a/common/startup.c
> +++ b/common/startup.c
> @@ -60,6 +60,11 @@ static int mount_root(void)
> mount("none", "efivarfs", "/efivars", NULL);
> }
>
> + if (IS_ENABLED(CONFIG_FS_PSTORE)) {
> + mkdir("/pstore", 0);
> + mount("none", "pstore", "/pstore", NULL);
> + }
> +
> return 0;
> }
> fs_initcall(mount_root);
> diff --git a/fs/Kconfig b/fs/Kconfig
> index 9217bc81ea1e..5413a9295ccc 100644
> --- a/fs/Kconfig
> +++ b/fs/Kconfig
> @@ -89,4 +89,6 @@ config FS_SMHFS
> located on a debugging host connected to the target running
> Barebox
>
> +source fs/pstore/Kconfig
> +
> endmenu
> diff --git a/fs/Makefile b/fs/Makefile
> index 46932057c1b7..590c068e6045 100644
> --- a/fs/Makefile
> +++ b/fs/Makefile
> @@ -14,3 +14,4 @@ obj-$(CONFIG_FS_UIMAGEFS) += uimagefs.o
> obj-$(CONFIG_FS_EFI) += efi.o
> obj-$(CONFIG_FS_EFIVARFS) += efivarfs.o
> obj-$(CONFIG_FS_SMHFS) += smhfs.o
> +obj-y += pstore/
Can we use
obj-$(CONFIG_FS_PSTORE) += pstore/
?
> diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig
> new file mode 100644
> index 000000000000..2455b5629cb1
> --- /dev/null
> +++ b/fs/pstore/Kconfig
> @@ -0,0 +1,88 @@
> +menuconfig FS_PSTORE
> + bool
> + prompt "pstore fs support"
--
Best regards,
Antony Pavlov
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 8/9] arm: Add RAMOOPS memory area
2015-12-02 13:48 ` [PATCH 8/9] arm: Add RAMOOPS memory area Markus Pargmann
@ 2015-12-04 7:07 ` Sascha Hauer
2015-12-04 13:30 ` Markus Pargmann
0 siblings, 1 reply; 18+ messages in thread
From: Sascha Hauer @ 2015-12-04 7:07 UTC (permalink / raw)
To: Markus Pargmann; +Cc: barebox
On Wed, Dec 02, 2015 at 02:48:50PM +0100, Markus Pargmann wrote:
> RAMOOPS is a driver that uses a reserved static memory region to store
> the data from the last panic or boot. This helps to debug crashes at the
> next boot while preserving the boot messages.
>
> To guarantee a memory area that is not altered by barebox or the kernel,
> this area is located at the end of the RAM right after barebox and
> before the STACK. This ensures that changing barebox sizes do not
> interfere with RAMOOPS.
>
> Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
> ---
> arch/arm/cpu/start.c | 6 ++++++
> arch/arm/include/asm/barebox-arm.h | 14 +++++++++++++-
> 2 files changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
> index 4ad64b61e86a..d03d1edfaf18 100644
> --- a/arch/arm/cpu/start.c
> +++ b/arch/arm/cpu/start.c
> @@ -118,6 +118,12 @@ static inline unsigned long arm_mem_boarddata(unsigned long membase,
> return mem;
> }
>
> +unsigned long arm_mem_ramoops_get(void)
> +{
> + return arm_mem_ramoops(0, arm_stack_top);
> +}
> +EXPORT_SYMBOL_GPL(arm_mem_ramoops_get);
> +
> static int barebox_memory_areas_init(void)
> {
> unsigned long start = arm_head_bottom;
> diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
> index da7717538b61..91f1747d2df4 100644
> --- a/arch/arm/include/asm/barebox-arm.h
> +++ b/arch/arm/include/asm/barebox-arm.h
> @@ -122,11 +122,23 @@ static inline unsigned long arm_mem_early_malloc_end(unsigned long membase,
> return arm_mem_ttb(membase, endmem);
> }
>
> +static inline unsigned long arm_mem_ramoops(unsigned long membase,
> + unsigned long endmem)
> +{
> + endmem = arm_mem_ttb(membase, endmem);
> +#ifdef CONFIG_FS_PSTORE_RAMOOPS
> + endmem -= CONFIG_FS_PSTORE_RAMOOPS_SIZE;
> + endmem &= ~(SZ_4K - 1); /* Align to 4K */
> +#endif
if (IS_ENABLED(CONFIG_FS_PSTORE_RAMOOPS)) please
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 6/9] arm: Clarify memory layout calculation
2015-12-02 13:48 ` [PATCH 6/9] arm: Clarify memory layout calculation Markus Pargmann
@ 2015-12-04 7:09 ` Sascha Hauer
0 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-12-04 7:09 UTC (permalink / raw)
To: Markus Pargmann; +Cc: barebox
On Wed, Dec 02, 2015 at 02:48:48PM +0100, Markus Pargmann wrote:
> The memory calculations used are all hardcoded into three different
> files, start-pbl.c, uncompress.c and start.c. To make this more readable
> and reliable, this patch gathers these information in barebox-arm.h with
> static inline functions for the calculation of the memory offsets.
>
> This patch also adds proper handling of different barebox/board data
> sizes. Currently only 1MB+Alignment of RAM is reserved for Barebox and
> board data. This could be too small for bigger devicetrees and barebox.
>
> Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
> ---
> +
> +static inline unsigned long arm_mem_barebox_image(unsigned long membase,
> + unsigned long endmem,
> + unsigned long size)
> +{
> + endmem = arm_mem_ttb(membase, endmem);
> +
> +#ifdef CONFIG_RELOCATABLE
> + endmem -= size;
> endmem &= ~(SZ_1M - 1);
> +#endif
if (IS_ENABLED(CONFIG_RELOCATABLE)) please
Otherwise this is a nice cleanup.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 5/9] lib: Import reed solomon code from kernel
2015-12-02 13:48 ` [PATCH 5/9] lib: Import reed solomon code " Markus Pargmann
@ 2015-12-04 7:12 ` Sascha Hauer
2015-12-04 13:22 ` Markus Pargmann
0 siblings, 1 reply; 18+ messages in thread
From: Sascha Hauer @ 2015-12-04 7:12 UTC (permalink / raw)
To: Markus Pargmann; +Cc: barebox
On Wed, Dec 02, 2015 at 02:48:47PM +0100, Markus Pargmann wrote:
> reed solomon code is used by RAMOOPS to check and fix data stored in
> volatile memory.
>
> Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
> ---
> include/linux/rslib.h | 109 ++++++++++++
> lib/Kconfig | 15 ++
> lib/Makefile | 1 +
> lib/reed_solomon/Makefile | 6 +
> lib/reed_solomon/decode_rs.c | 271 +++++++++++++++++++++++++++++
> lib/reed_solomon/encode_rs.c | 54 ++++++
> lib/reed_solomon/reed_solomon.c | 377 ++++++++++++++++++++++++++++++++++++++++
> 7 files changed, 833 insertions(+)
> create mode 100644 include/linux/rslib.h
> create mode 100644 lib/reed_solomon/Makefile
> create mode 100644 lib/reed_solomon/decode_rs.c
> create mode 100644 lib/reed_solomon/encode_rs.c
> create mode 100644 lib/reed_solomon/reed_solomon.c
>
> diff --git a/lib/Kconfig b/lib/Kconfig
> index fbf9f0f34849..f2f3b5775ace 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -22,6 +22,21 @@ config XZ_DECOMPRESS
> bool "include xz uncompression support"
> select UNCOMPRESS
>
> +config REED_SOLOMON
> + bool
> +
> +config REED_SOLOMON_ENC8
> + bool
> +
> +config REED_SOLOMON_DEC8
> + bool
> +
> +config REED_SOLOMON_ENC16
> + bool
> +
> +config REED_SOLOMON_DEC16
> + bool
> +
These fine grained config options seem unnecessary. Can we limit this to
a single config REED_SOLOMON only? The linker will discard unused
symbols anyway.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 9/9] fs: Add pstore filesystem
2015-12-02 18:37 ` Antony Pavlov
@ 2015-12-04 13:10 ` Markus Pargmann
0 siblings, 0 replies; 18+ messages in thread
From: Markus Pargmann @ 2015-12-04 13:10 UTC (permalink / raw)
To: Antony Pavlov; +Cc: barebox
[-- Attachment #1.1: Type: text/plain, Size: 3819 bytes --]
Hi,
On Wednesday 02 December 2015 21:37:13 Antony Pavlov wrote:
> On Wed, 2 Dec 2015 14:48:51 +0100
> Markus Pargmann <mpa@pengutronix.de> wrote:
>
> > pstore is a persistent storage filesystem used for RAMOOPS. It is used
> > to store console logs, panics, ftrace and other information in case of a
> > crash/panic/oops/reboot.
> >
> > pstore is implemented for barebox as a read-only filesystem at the
> > moment. It may be extended later on. The idea is to provide a way to
> > extract essential data from the last running kernel.
> >
> > Most of the code is copied from the kernel. However this is only a
> > lightweight implementation without real write support yet.
> >
> > Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
> > ---
> > common/startup.c | 5 +
> > fs/Kconfig | 2 +
> > fs/Makefile | 1 +
> > fs/pstore/Kconfig | 88 ++++++++
> > fs/pstore/Makefile | 10 +
> > fs/pstore/fs.c | 280 +++++++++++++++++++++++++
> > fs/pstore/internal.h | 19 ++
> > fs/pstore/platform.c | 138 ++++++++++++
> > fs/pstore/ram.c | 507 +++++++++++++++++++++++++++++++++++++++++++++
> > fs/pstore/ram_core.c | 426 +++++++++++++++++++++++++++++++++++++
> > include/linux/pstore.h | 90 ++++++++
> > include/linux/pstore_ram.h | 87 ++++++++
> > 12 files changed, 1653 insertions(+)
> > create mode 100644 fs/pstore/Kconfig
> > create mode 100644 fs/pstore/Makefile
> > create mode 100644 fs/pstore/fs.c
> > create mode 100644 fs/pstore/internal.h
> > create mode 100644 fs/pstore/platform.c
> > create mode 100644 fs/pstore/ram.c
> > create mode 100644 fs/pstore/ram_core.c
> > create mode 100644 include/linux/pstore.h
> > create mode 100644 include/linux/pstore_ram.h
> >
> > diff --git a/common/startup.c b/common/startup.c
> > index 4a303b297aaf..093a23ba08c9 100644
> > --- a/common/startup.c
> > +++ b/common/startup.c
> > @@ -60,6 +60,11 @@ static int mount_root(void)
> > mount("none", "efivarfs", "/efivars", NULL);
> > }
> >
> > + if (IS_ENABLED(CONFIG_FS_PSTORE)) {
> > + mkdir("/pstore", 0);
> > + mount("none", "pstore", "/pstore", NULL);
> > + }
> > +
> > return 0;
> > }
> > fs_initcall(mount_root);
> > diff --git a/fs/Kconfig b/fs/Kconfig
> > index 9217bc81ea1e..5413a9295ccc 100644
> > --- a/fs/Kconfig
> > +++ b/fs/Kconfig
> > @@ -89,4 +89,6 @@ config FS_SMHFS
> > located on a debugging host connected to the target running
> > Barebox
> >
> > +source fs/pstore/Kconfig
> > +
> > endmenu
> > diff --git a/fs/Makefile b/fs/Makefile
> > index 46932057c1b7..590c068e6045 100644
> > --- a/fs/Makefile
> > +++ b/fs/Makefile
> > @@ -14,3 +14,4 @@ obj-$(CONFIG_FS_UIMAGEFS) += uimagefs.o
> > obj-$(CONFIG_FS_EFI) += efi.o
> > obj-$(CONFIG_FS_EFIVARFS) += efivarfs.o
> > obj-$(CONFIG_FS_SMHFS) += smhfs.o
> > +obj-y += pstore/
>
> Can we use
>
> obj-$(CONFIG_FS_PSTORE) += pstore/
>
> ?
Yes, changed it so that this Makefile uses the config symbol and
pstore/Makefile is unconditional then.
Best Regards,
Markus
>
> > diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig
> > new file mode 100644
> > index 000000000000..2455b5629cb1
> > --- /dev/null
> > +++ b/fs/pstore/Kconfig
> > @@ -0,0 +1,88 @@
> > +menuconfig FS_PSTORE
> > + bool
> > + prompt "pstore fs support"
>
> --
> Best regards,
> Antony Pavlov
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
[-- Attachment #2: Type: text/plain, Size: 149 bytes --]
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 5/9] lib: Import reed solomon code from kernel
2015-12-04 7:12 ` Sascha Hauer
@ 2015-12-04 13:22 ` Markus Pargmann
0 siblings, 0 replies; 18+ messages in thread
From: Markus Pargmann @ 2015-12-04 13:22 UTC (permalink / raw)
To: Sascha Hauer; +Cc: barebox
[-- Attachment #1.1: Type: text/plain, Size: 2103 bytes --]
Hi,
On Friday 04 December 2015 08:12:55 Sascha Hauer wrote:
> On Wed, Dec 02, 2015 at 02:48:47PM +0100, Markus Pargmann wrote:
> > reed solomon code is used by RAMOOPS to check and fix data stored in
> > volatile memory.
> >
> > Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
> > ---
> > include/linux/rslib.h | 109 ++++++++++++
> > lib/Kconfig | 15 ++
> > lib/Makefile | 1 +
> > lib/reed_solomon/Makefile | 6 +
> > lib/reed_solomon/decode_rs.c | 271 +++++++++++++++++++++++++++++
> > lib/reed_solomon/encode_rs.c | 54 ++++++
> > lib/reed_solomon/reed_solomon.c | 377 ++++++++++++++++++++++++++++++++++++++++
> > 7 files changed, 833 insertions(+)
> > create mode 100644 include/linux/rslib.h
> > create mode 100644 lib/reed_solomon/Makefile
> > create mode 100644 lib/reed_solomon/decode_rs.c
> > create mode 100644 lib/reed_solomon/encode_rs.c
> > create mode 100644 lib/reed_solomon/reed_solomon.c
> >
>
> > diff --git a/lib/Kconfig b/lib/Kconfig
> > index fbf9f0f34849..f2f3b5775ace 100644
> > --- a/lib/Kconfig
> > +++ b/lib/Kconfig
> > @@ -22,6 +22,21 @@ config XZ_DECOMPRESS
> > bool "include xz uncompression support"
> > select UNCOMPRESS
> >
> > +config REED_SOLOMON
> > + bool
> > +
> > +config REED_SOLOMON_ENC8
> > + bool
> > +
> > +config REED_SOLOMON_DEC8
> > + bool
> > +
> > +config REED_SOLOMON_ENC16
> > + bool
> > +
> > +config REED_SOLOMON_DEC16
> > + bool
> > +
>
> These fine grained config options seem unnecessary. Can we limit this to
> a single config REED_SOLOMON only? The linker will discard unused
> symbols anyway.
Ok, I reduced this to just the single config symbol 'REED_SOLOMON'.
Best Regards,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
[-- Attachment #2: Type: text/plain, Size: 149 bytes --]
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 8/9] arm: Add RAMOOPS memory area
2015-12-04 7:07 ` Sascha Hauer
@ 2015-12-04 13:30 ` Markus Pargmann
2015-12-07 9:15 ` Sascha Hauer
0 siblings, 1 reply; 18+ messages in thread
From: Markus Pargmann @ 2015-12-04 13:30 UTC (permalink / raw)
To: Sascha Hauer; +Cc: barebox
[-- Attachment #1.1: Type: text/plain, Size: 2756 bytes --]
Hi,
On Friday 04 December 2015 08:07:40 Sascha Hauer wrote:
> On Wed, Dec 02, 2015 at 02:48:50PM +0100, Markus Pargmann wrote:
> > RAMOOPS is a driver that uses a reserved static memory region to store
> > the data from the last panic or boot. This helps to debug crashes at the
> > next boot while preserving the boot messages.
> >
> > To guarantee a memory area that is not altered by barebox or the kernel,
> > this area is located at the end of the RAM right after barebox and
> > before the STACK. This ensures that changing barebox sizes do not
> > interfere with RAMOOPS.
> >
> > Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
> > ---
> > arch/arm/cpu/start.c | 6 ++++++
> > arch/arm/include/asm/barebox-arm.h | 14 +++++++++++++-
> > 2 files changed, 19 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
> > index 4ad64b61e86a..d03d1edfaf18 100644
> > --- a/arch/arm/cpu/start.c
> > +++ b/arch/arm/cpu/start.c
> > @@ -118,6 +118,12 @@ static inline unsigned long arm_mem_boarddata(unsigned long membase,
> > return mem;
> > }
> >
> > +unsigned long arm_mem_ramoops_get(void)
> > +{
> > + return arm_mem_ramoops(0, arm_stack_top);
> > +}
> > +EXPORT_SYMBOL_GPL(arm_mem_ramoops_get);
> > +
> > static int barebox_memory_areas_init(void)
> > {
> > unsigned long start = arm_head_bottom;
> > diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
> > index da7717538b61..91f1747d2df4 100644
> > --- a/arch/arm/include/asm/barebox-arm.h
> > +++ b/arch/arm/include/asm/barebox-arm.h
> > @@ -122,11 +122,23 @@ static inline unsigned long arm_mem_early_malloc_end(unsigned long membase,
> > return arm_mem_ttb(membase, endmem);
> > }
> >
> > +static inline unsigned long arm_mem_ramoops(unsigned long membase,
> > + unsigned long endmem)
> > +{
> > + endmem = arm_mem_ttb(membase, endmem);
> > +#ifdef CONFIG_FS_PSTORE_RAMOOPS
> > + endmem -= CONFIG_FS_PSTORE_RAMOOPS_SIZE;
> > + endmem &= ~(SZ_4K - 1); /* Align to 4K */
> > +#endif
>
> if (IS_ENABLED(CONFIG_FS_PSTORE_RAMOOPS)) please
This doesn't work here. If CONFIG_FS_PSTORE_RAMOOPS is not defined,
CONFIG_FS_PSTORE_RAMOOPS_SIZE is undefined as well and compiling fails.
Is there any macro I should use for _SIZE here or any Kconfig setup that is
preferred for this situation?
Best Regards,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
[-- Attachment #2: Type: text/plain, Size: 149 bytes --]
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 8/9] arm: Add RAMOOPS memory area
2015-12-04 13:30 ` Markus Pargmann
@ 2015-12-07 9:15 ` Sascha Hauer
0 siblings, 0 replies; 18+ messages in thread
From: Sascha Hauer @ 2015-12-07 9:15 UTC (permalink / raw)
To: Markus Pargmann; +Cc: barebox
On Fri, Dec 04, 2015 at 02:30:34PM +0100, Markus Pargmann wrote:
> Hi,
>
> On Friday 04 December 2015 08:07:40 Sascha Hauer wrote:
> > On Wed, Dec 02, 2015 at 02:48:50PM +0100, Markus Pargmann wrote:
> > > RAMOOPS is a driver that uses a reserved static memory region to store
> > > the data from the last panic or boot. This helps to debug crashes at the
> > > next boot while preserving the boot messages.
> > >
> > > To guarantee a memory area that is not altered by barebox or the kernel,
> > > this area is located at the end of the RAM right after barebox and
> > > before the STACK. This ensures that changing barebox sizes do not
> > > interfere with RAMOOPS.
> > >
> > > Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
> > > ---
> > > arch/arm/cpu/start.c | 6 ++++++
> > > arch/arm/include/asm/barebox-arm.h | 14 +++++++++++++-
> > > 2 files changed, 19 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
> > > index 4ad64b61e86a..d03d1edfaf18 100644
> > > --- a/arch/arm/cpu/start.c
> > > +++ b/arch/arm/cpu/start.c
> > > @@ -118,6 +118,12 @@ static inline unsigned long arm_mem_boarddata(unsigned long membase,
> > > return mem;
> > > }
> > >
> > > +unsigned long arm_mem_ramoops_get(void)
> > > +{
> > > + return arm_mem_ramoops(0, arm_stack_top);
> > > +}
> > > +EXPORT_SYMBOL_GPL(arm_mem_ramoops_get);
> > > +
> > > static int barebox_memory_areas_init(void)
> > > {
> > > unsigned long start = arm_head_bottom;
> > > diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
> > > index da7717538b61..91f1747d2df4 100644
> > > --- a/arch/arm/include/asm/barebox-arm.h
> > > +++ b/arch/arm/include/asm/barebox-arm.h
> > > @@ -122,11 +122,23 @@ static inline unsigned long arm_mem_early_malloc_end(unsigned long membase,
> > > return arm_mem_ttb(membase, endmem);
> > > }
> > >
> > > +static inline unsigned long arm_mem_ramoops(unsigned long membase,
> > > + unsigned long endmem)
> > > +{
> > > + endmem = arm_mem_ttb(membase, endmem);
> > > +#ifdef CONFIG_FS_PSTORE_RAMOOPS
> > > + endmem -= CONFIG_FS_PSTORE_RAMOOPS_SIZE;
> > > + endmem &= ~(SZ_4K - 1); /* Align to 4K */
> > > +#endif
> >
> > if (IS_ENABLED(CONFIG_FS_PSTORE_RAMOOPS)) please
>
> This doesn't work here. If CONFIG_FS_PSTORE_RAMOOPS is not defined,
> CONFIG_FS_PSTORE_RAMOOPS_SIZE is undefined as well and compiling fails.
>
> Is there any macro I should use for _SIZE here or any Kconfig setup that is
> preferred for this situation?
Not that I know of. Just keep it as it is now.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2015-12-07 9:16 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-02 13:48 [PATCH 0/9] RAMOOPS read support for Barebox Markus Pargmann
2015-12-02 13:48 ` [PATCH 1/9] arm: boards: karo-tx6x remove definition of DIV_ROUND_UP Markus Pargmann
2015-12-02 13:48 ` [PATCH 2/9] log2: Add missing __rounddown_pow_of_two() Markus Pargmann
2015-12-02 13:48 ` [PATCH 3/9] printk: Add missing include/declaration Markus Pargmann
2015-12-02 13:48 ` [PATCH 4/9] vsprintf: Add scnprintf from kernel Markus Pargmann
2015-12-02 13:48 ` [PATCH 5/9] lib: Import reed solomon code " Markus Pargmann
2015-12-04 7:12 ` Sascha Hauer
2015-12-04 13:22 ` Markus Pargmann
2015-12-02 13:48 ` [PATCH 6/9] arm: Clarify memory layout calculation Markus Pargmann
2015-12-04 7:09 ` Sascha Hauer
2015-12-02 13:48 ` [PATCH 7/9] arm: start: Add visible sdram region for barebox board data Markus Pargmann
2015-12-02 13:48 ` [PATCH 8/9] arm: Add RAMOOPS memory area Markus Pargmann
2015-12-04 7:07 ` Sascha Hauer
2015-12-04 13:30 ` Markus Pargmann
2015-12-07 9:15 ` Sascha Hauer
2015-12-02 13:48 ` [PATCH 9/9] fs: Add pstore filesystem Markus Pargmann
2015-12-02 18:37 ` Antony Pavlov
2015-12-04 13:10 ` Markus Pargmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox