mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* Rework of the state/bootchooser feature documentaiton
@ 2017-08-15 13:46 Juergen Borleis
  2017-08-15 13:46 ` [PATCH 1/7] docs/DS1307: fix layout Juergen Borleis
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Juergen Borleis @ 2017-08-15 13:46 UTC (permalink / raw)
  To: barebox

This is a rework of the documentation for the 'state framework' and
'bootchooser' feature. While at it, some fixes are included as well.

Comments are welcome.

Juergen


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/7] docs/DS1307: fix layout
  2017-08-15 13:46 Rework of the state/bootchooser feature documentaiton Juergen Borleis
@ 2017-08-15 13:46 ` Juergen Borleis
  2017-08-15 13:46 ` [PATCH 2/7] state: keep backward compatibility Juergen Borleis
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Juergen Borleis @ 2017-08-15 13:46 UTC (permalink / raw)
  To: barebox

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 Documentation/devicetree/bindings/rtc/dallas,ds1307.rst | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/rtc/dallas,ds1307.rst b/Documentation/devicetree/bindings/rtc/dallas,ds1307.rst
index 602f74b4d..5a75be40e 100644
--- a/Documentation/devicetree/bindings/rtc/dallas,ds1307.rst
+++ b/Documentation/devicetree/bindings/rtc/dallas,ds1307.rst
@@ -2,12 +2,14 @@ Dallas DS1307 I2C Serial Real-Time Clock
 ========================================
 
 Required properties:
+
 * ``compatible``: ``dallas,ds1307``, ``dallas,ds1308``, ``dallas,ds1338``
 	"maxim" can be used in place of "dallas"
 
 * ``reg``: I2C address for chip
 
 Optional properties:
+
 * ``ext-clock-input``: Enable external clock input pin
 * ``ext-clock-output``:  Enable square wave output.  The above two
   properties are mutually exclusive
@@ -19,7 +21,10 @@ Optional properties:
 The default is ext-clock-input, ext-clock-output, and ext-clock-bb
 disabled and ext-clock-rate of 1 Hz.
 
-Example::
+Example
+
+.. code-block:: text
+
 	ds1307: rtc@68 {
 		compatible = "dallas,ds1307";
 		reg = <0x68>;
-- 
2.11.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 2/7] state: keep backward compatibility
  2017-08-15 13:46 Rework of the state/bootchooser feature documentaiton Juergen Borleis
  2017-08-15 13:46 ` [PATCH 1/7] docs/DS1307: fix layout Juergen Borleis
@ 2017-08-15 13:46 ` Juergen Borleis
  2017-08-15 13:46 ` [PATCH 3/7] bootchooser: avoid a use after free Juergen Borleis
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Juergen Borleis @ 2017-08-15 13:46 UTC (permalink / raw)
  To: barebox

Previous 'state' variable set variants do not know and use metadata. The
'direct' storage backend's read function honors this, but not its
counterpart the write function. This makes an update of the 'state'
variable set impossible.
This change makes backward compatibility explicit, else it complains in
the read function as well. With some more debug output it helps the
developer to do things right.

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 common/Kconfig                       |  8 ++++++++
 common/state/backend_bucket_direct.c | 28 +++++++++++++++++++---------
 2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/common/Kconfig b/common/Kconfig
index bc7cb0fe7..57418cadc 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -937,6 +937,14 @@ config STATE_CRYPTO
 	  See Documentation/devicetree/bindings/barebox/barebox,state.rst
 	  for more information.
 
+config STATE_BACKWARD_COMPATIBLE
+	bool "backward compatible 'direct storage backend'"
+	depends on STATE
+	help
+	  With this option enabled the 'direct' storage backend keeps backward
+	  compatibility with older revisions of the state framework. Newer
+	  revisions expect an additional 'meta header' and fail otherwise.
+
 config BOOTCHOOSER
 	bool "bootchooser infrastructure"
 	depends on !SHELL_NONE
diff --git a/common/state/backend_bucket_direct.c b/common/state/backend_bucket_direct.c
index 4465ed0e4..958696ed9 100644
--- a/common/state/backend_bucket_direct.c
+++ b/common/state/backend_bucket_direct.c
@@ -69,6 +69,11 @@ static int state_backend_bucket_direct_read(struct state_backend_storage_bucket
 	if (meta.magic == direct_magic) {
 		read_len = meta.written_length;
 	} else {
+		if (!IS_ENABLED(CONFIG_STATE_BACKWARD_COMPATIBLE)) {
+			dev_err(direct->dev, "No meta data header found\n");
+			dev_dbg(direct->dev, "Enable backward compatibility or increase stride size\n");
+			return -EINVAL;
+		}
 		read_len = direct->max_size;
 		ret = lseek(direct->fd, direct->offset, SEEK_SET);
 		if (ret < 0) {
@@ -103,21 +108,26 @@ static int state_backend_bucket_direct_write(struct state_backend_storage_bucket
 	int ret;
 	struct state_backend_storage_bucket_direct_meta meta;
 
-	if (len > direct->max_size - sizeof(meta))
-		return -E2BIG;
-
 	ret = lseek(direct->fd, direct->offset, SEEK_SET);
 	if (ret < 0) {
 		dev_err(direct->dev, "Failed to seek file, %d\n", ret);
 		return ret;
 	}
 
-	meta.magic = direct_magic;
-	meta.written_length = len;
-	ret = write_full(direct->fd, &meta, sizeof(meta));
-	if (ret < 0) {
-		dev_err(direct->dev, "Failed to write metadata to file, %d\n", ret);
-		return ret;
+	/* write the meta data only if there is head room */
+	if (len <= direct->max_size - sizeof(meta)) {
+		meta.magic = direct_magic;
+		meta.written_length = len;
+		ret = write_full(direct->fd, &meta, sizeof(meta));
+		if (ret < 0) {
+			dev_err(direct->dev, "Failed to write metadata to file, %d\n", ret);
+			return ret;
+		}
+	} else {
+		if (!IS_ENABLED(CONFIG_STATE_BACKWARD_COMPATIBLE)) {
+			dev_dbg(direct->dev, "Too small stride size: must skip metadata! Increase stride size\n");
+			return -EINVAL;
+		}
 	}
 
 	ret = write_full(direct->fd, buf, len);
-- 
2.11.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 3/7] bootchooser: avoid a use after free
  2017-08-15 13:46 Rework of the state/bootchooser feature documentaiton Juergen Borleis
  2017-08-15 13:46 ` [PATCH 1/7] docs/DS1307: fix layout Juergen Borleis
  2017-08-15 13:46 ` [PATCH 2/7] state: keep backward compatibility Juergen Borleis
@ 2017-08-15 13:46 ` Juergen Borleis
  2017-08-15 13:46 ` [PATCH 4/7] bootchooser: allow an empty namespace Juergen Borleis
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Juergen Borleis @ 2017-08-15 13:46 UTC (permalink / raw)
  To: barebox

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 common/bootchooser.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/bootchooser.c b/common/bootchooser.c
index 455f290fa..69d980d6f 100644
--- a/common/bootchooser.c
+++ b/common/bootchooser.c
@@ -376,9 +376,9 @@ struct bootchooser *bootchooser_get(void)
 			bc->state_prefix = xstrdup(state_prefix);
 			bc->state = state_by_name(state_devname);
 			if (!bc->state) {
-				free(state_devname);
 				pr_err("Cannot get state '%s'\n",
 				       state_devname);
+				free(state_devname);
 				ret = -ENODEV;
 				goto err;
 			}
-- 
2.11.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 4/7] bootchooser: allow an empty namespace
  2017-08-15 13:46 Rework of the state/bootchooser feature documentaiton Juergen Borleis
                   ` (2 preceding siblings ...)
  2017-08-15 13:46 ` [PATCH 3/7] bootchooser: avoid a use after free Juergen Borleis
@ 2017-08-15 13:46 ` Juergen Borleis
  2017-08-15 13:46 ` [PATCH 5/7] docs: remove build warning Juergen Borleis
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Juergen Borleis @ 2017-08-15 13:46 UTC (permalink / raw)
  To: barebox

The bootchooser's documentation states the 'namespace' for the state
storage backend is optional. This change makes it really optional to allow
a flat state variable set definition for the 'bootchooser' as well.

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 common/bootchooser.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/common/bootchooser.c b/common/bootchooser.c
index 69d980d6f..83b15e0f7 100644
--- a/common/bootchooser.c
+++ b/common/bootchooser.c
@@ -367,12 +367,10 @@ struct bootchooser *bootchooser_get(void)
 			char *state_devname;
 
 			delim = strchr(state_prefix, '.');
-			if (!delim) {
-				pr_err("state_prefix '%s' has invalid format\n",
-				       state_prefix);
-				goto err;
-			}
-			state_devname = xstrndup(state_prefix, delim - state_prefix);
+			if (delim)
+				state_devname = xstrndup(state_prefix, delim - state_prefix);
+			else
+				state_devname = xstrdup(state_prefix);
 			bc->state_prefix = xstrdup(state_prefix);
 			bc->state = state_by_name(state_devname);
 			if (!bc->state) {
-- 
2.11.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 5/7] docs: remove build warning
  2017-08-15 13:46 Rework of the state/bootchooser feature documentaiton Juergen Borleis
                   ` (3 preceding siblings ...)
  2017-08-15 13:46 ` [PATCH 4/7] bootchooser: allow an empty namespace Juergen Borleis
@ 2017-08-15 13:46 ` Juergen Borleis
  2017-08-15 13:46 ` [PATCH 6/7] state: add debugging help Juergen Borleis
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Juergen Borleis @ 2017-08-15 13:46 UTC (permalink / raw)
  To: barebox

This change removes:

"devicetree/bindings/rtc/dallas,ds1307.rst: WARNING: document isn't included in any toctree" warning

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 Documentation/devicetree/index.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/index.rst b/Documentation/devicetree/index.rst
index c5992c0fc..de571547e 100644
--- a/Documentation/devicetree/index.rst
+++ b/Documentation/devicetree/index.rst
@@ -12,3 +12,4 @@ Contents:
    bindings/leds/*
    bindings/misc/*
    bindings/mtd/*
+   bindings/rtc/*
-- 
2.11.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 6/7] state: add debugging help
  2017-08-15 13:46 Rework of the state/bootchooser feature documentaiton Juergen Borleis
                   ` (4 preceding siblings ...)
  2017-08-15 13:46 ` [PATCH 5/7] docs: remove build warning Juergen Borleis
@ 2017-08-15 13:46 ` Juergen Borleis
  2017-08-15 13:46 ` [PATCH 7/7] docs: rework and extend the 'state' and 'bootchooser' documentation Juergen Borleis
  2017-09-06 12:19 ` Rework of the state/bootchooser feature documentaiton Sascha Hauer
  7 siblings, 0 replies; 9+ messages in thread
From: Juergen Borleis @ 2017-08-15 13:46 UTC (permalink / raw)
  To: barebox

While working on the state documentation it turns out to be helpful to have
more debug messages while a developer implements a 'state' variable set
and tries to configure it correctly.

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 common/state/backend_storage.c | 7 ++++++-
 common/state/state.c           | 2 ++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/common/state/backend_storage.c b/common/state/backend_storage.c
index d6e7adcf5..2e2478cb6 100644
--- a/common/state/backend_storage.c
+++ b/common/state/backend_storage.c
@@ -146,6 +146,7 @@ int state_storage_read(struct state_backend_storage *storage,
 	struct state_backend_storage_bucket *bucket, *bucket_used = NULL;
 	int ret;
 
+	dev_dbg(storage->dev, "Checking redundant buckets...\n");
 	/*
 	 * Iterate over all buckets. The first valid one we find is the
 	 * one we want to use.
@@ -164,8 +165,12 @@ int state_storage_read(struct state_backend_storage *storage,
 		ret = format->verify(format, magic, bucket->buf, &bucket->len, flags);
 		if (!ret && !bucket_used)
 			bucket_used = bucket;
+		if (ret)
+			dev_info(storage->dev, "Ignoring broken bucket %d@0x%08lx...\n", bucket->num, bucket->offset);
 	}
 
+	dev_dbg(storage->dev, "Checking redundant buckets finished.\n");
+
 	if (!bucket_used) {
 		dev_err(storage->dev, "Failed to find any valid state copy in any bucket\n");
 
@@ -386,7 +391,7 @@ int state_storage_init(struct state *state, const char *path,
 			dev_warn(storage->dev, "using old format circular storage type.\n");
 			circular = false;
 		} else {
-			dev_warn(storage->dev, "unknown storage type '%s'\n", storagetype);
+			dev_dbg(storage->dev, "unknown storage type '%s'\n", storagetype);
 			return -EINVAL;
 		}
 		return state_storage_mtd_buckets_init(storage, &meminfo, circular);
diff --git a/common/state/state.c b/common/state/state.c
index 121ba0c6d..18ffbe29a 100644
--- a/common/state/state.c
+++ b/common/state/state.c
@@ -608,11 +608,13 @@ struct state *state_new_from_node(struct device_node *node, char *path,
 
 	ret = of_property_read_string(node, "backend-type", &backend_type);
 	if (ret) {
+		dev_dbg(&state->dev, "Missing 'backend-type' property\n");
 		goto out_release_state;
 	}
 
 	ret = of_property_read_u32(node, "backend-stridesize", &stridesize);
 	if (ret) {
+		dev_dbg(&state->dev, "'backend-stridesize' property undefined, trying to continue without\n");
 		stridesize = 0;
 	}
 
-- 
2.11.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 7/7] docs: rework and extend the 'state' and 'bootchooser' documentation
  2017-08-15 13:46 Rework of the state/bootchooser feature documentaiton Juergen Borleis
                   ` (5 preceding siblings ...)
  2017-08-15 13:46 ` [PATCH 6/7] state: add debugging help Juergen Borleis
@ 2017-08-15 13:46 ` Juergen Borleis
  2017-09-06 12:19 ` Rework of the state/bootchooser feature documentaiton Sascha Hauer
  7 siblings, 0 replies; 9+ messages in thread
From: Juergen Borleis @ 2017-08-15 13:46 UTC (permalink / raw)
  To: barebox

Many links between sections and examples were added to give the developer
the help to get it work.

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 .../devicetree/bindings/barebox/barebox,state.rst  | 332 ++++++----
 Documentation/user/bootchooser.rst                 | 493 +++++++++++----
 Documentation/user/state.rst                       | 696 +++++++++++++++++++--
 3 files changed, 1204 insertions(+), 317 deletions(-)

diff --git a/Documentation/devicetree/bindings/barebox/barebox,state.rst b/Documentation/devicetree/bindings/barebox/barebox,state.rst
index 40d7bc2e6..4b1aade66 100644
--- a/Documentation/devicetree/bindings/barebox/barebox,state.rst
+++ b/Documentation/devicetree/bindings/barebox/barebox,state.rst
@@ -1,55 +1,89 @@
 .. _barebox,state:
 
-barebox state
+Barebox state
 =============
 
-Overview
---------
+A *state* variable set can be fully described as a devicetree based *state* node.
+This *state* node could be part of the regular platform's devicetree blob or it
+could be an extra devicetree solely for the *state*.
 
+Devicetree *state* Node
+-----------------------
 
-Boards often have the need to store variables in persistent memory.
-The constraints are often different from what the regular environment
-can do:
+A *state* node contains a description of a set of variables along with a
+place where the variable set gets stored.
 
-* compact binary format to make it suitable for small EEPROMs/MRAMs
-* atomic save/restore of the whole variable set
-* redundancy
+Required Properties
+###################
 
-``barebox,state`` is a framework to describe, access, store and
-restore a set of variables. A state variable set can be fully
-described in a devicetree node. This node could be part of the regular
-devicetree blob or it could be an extra devicetree solely for the
-state. The state variable set contains variables of different types
-and a place to store the variable set.
+* ``compatible``: should be ``barebox,state``
+* ``magic``: a 32bit number
+* ``backend``: phandle to persistent memory
+* ``backend-type``: defines the *state* variable set storage format
+* additionally a *state* node must have an alias in the ``/aliases`` node pointing
+  to it.
 
-A state node contains a description of a set of variables along with a
-place where the variables are stored.
+.. _barebox,state_magic:
 
-Required properties:
+The ``magic`` property is a unique number which identifies the *state* variable
+set's variable types and their layout. It should be kept stable as long as the
+variable types and the layout are kept stable. It should also be kept stable
+if new trailing variables are added to the existing layout to be backward
+compatible. Only if the *state* variable set's variable types and/or their layout
+change, the ``magic`` property's number must be changed to be unique again
+with the new *state* variable set's content.
 
-* ``compatible``: should be ``barebox,state``;
-* ``magic``: A 32bit number used as a magic to identify the state
-* ``backend``: contains a phandle to the device/partition which holds the
-  actual state data.
-* ``backend-type``: should be ``raw`` or ``dtb``.
-* additionally a state node must have an alias in the /aliases/ node pointing
-  to it.
+.. important:: You should not use the values 0x2354fdf3 and 0x14fa2d02 for your
+   magic value. They're already reserved by the ``direct`` and ``circular``
+   storage backends.
 
-Optional properties:
+The ``backend`` property uses the *phandle* mechanism to link the *state* to
+a real persistent memory. Refer :ref:`Backend <state_framework,backends>` for
+supported persistent memories.
 
-* ``algo``: A HMAC algorithm used to detect manipulation of the data
-  or header, sensible values follow this pattern ``hmac(<HASH>)``,
-  e.g. ``hmac(sha256)``. Only used for ``raw``.
-* ``backend-stridesize``: Maximum size per copy of the data. Only important for
-  non-MTD devices
-* ``backend-storage-type``: Normally the correct storage type is detected auto-
-  matically. The circular backend supports the option ``noncircular`` to fall
-  back to an old storage format.
+The ``backend-type`` should be ``raw`` or ``dtb``. Refer
+:ref:`Backend Types <state_framework,backend_types>` for further details.
 
-Variable nodes
---------------
+Optional Properties
+###################
 
-These are subnodes of a state node each describing a single
+* ``backend-stridesize``: stride counted in bytes. See note below.
+* ``backend-storage-type``: Defines the backend storage type to ``direct`` or
+  ``circular``. Defaults to ``circular`` for media which requires erase cycles.
+* ``algo``: A HMAC algorithm used to detect manipulation of the data
+  or header, sensible values follow this pattern ``hmac(<HASH>)``,
+  e.g. ``hmac(sha256)``. Only available for the ``backend-type`` ``raw``.
+
+.. note:: For the ``backend-storage-type`` the keyword ``noncircular`` is still
+   supported as a fall back to an old storage format. Recommendation is to not
+   use this type anymore.
+
+.. _barebox,state_backend_stridesize:
+
+The ``backend-stridesize`` is still optional but required whenever the
+underlaying backend doesn't provide an information how to pad an instance of a
+*state* variable set. This is valid for all underlaying backends which supports
+writes on a byte-by-byte manner or don't have eraseblocks (EEPROM, SRAM and NOR
+type flash backends).
+The ``backend-stridesize`` value is used by the ``direct`` backend storage type
+to place the redundant *state* variable set copies side by side in the backend.
+And it's used by the ``circular`` backend storage type to place the *state*
+variable set copies side by side into the eraseblock.
+You should calculate the ``backend-stridesize`` value very carefully based on
+the used ``backend-type``, the size of the used backend (e.g. partition size
+for example) and its eraseblock size. Refer
+:ref:`Backend Types <state_framework,backend_types>`.
+
+.. note:: It might be useful to add some spare space to the
+   ``backend-stridesize`` to ensure the ability to extend the *state* variable
+   set later on.
+
+.. _barebox,state_variable:
+
+Variable Subnodes
+-----------------
+
+These are subnodes of a *state* node each describing a single
 variable. The node name may end with ``@<ADDRESS>``, but the suffix is
 stripped from the variable name.
 
@@ -57,105 +91,161 @@ State variables have a type. Currenty supported types are: ``uint8``,
 ``uint32``, ``enum32``, ``mac`` address or ``string`` (fixed length string).
 Variable length strings are not planned.
 
-Required properties:
+Required Properties
+###################
 
 * ``reg``: Standard ``reg`` property with ``#address-cells = <1>`` and
   ``#size-cells = <1>``. Defines the ``offset`` and ``size`` of the
-  variable in the ``raw`` backend. ``size`` must fit the node
+  variable in the ``raw`` backend. ``size`` **must fit** the node
   ``type``. Variables are not allowed to overlap.
-* ``type``: Should be ``uint8``, ``uint32``, ``int32``. ``enum32``, ``mac``
+* ``type``: Should be ``uint8``, ``uint32``, ``enum32``, ``mac``
   or ``string`` for the type of the variable
-* ``names``: For ``enum32`` values only, this specifies the values
-  possible for ``enum32``.
-
-Optional properties:
-
-* ``default``: The default value if the variable cannot be read from
-  storage. For ``enum32`` values it is an integer representing an
-  offset into the names array.
-
-Example::
-
-  /aliases {
-  	state = &state;
-  };
-
-  state: state {
-  	magic = <0x27031977>;
-  	compatible = "barebox,state";
-  	backend-type = "raw";
-  	backend = <&state_part>;
-
-  	foo {
-  		reg = <0x00 0x4>;
-  		type = "uint32";
-  		default = <0x0>;
-  	};
-
-  	bar {
-  		reg = <0x10 0x4>;
-  		type = "enum32";
-  		names = "baz", "qux";
-  		default = <1>;
-  	};
-  };
-
-  &nand_flash {
-  	partitions {
-  		compatible = "fixed-partitions";
-  		#address-cells = <1>;
-  		#size-cells = <1>;
-  		state_part: state@10000 {
-  			label = "state";
-  			reg = <0x10000 0x10000>;
-  		};
-  	};
-  };
-
-Variable Types
---------------
-
-* ``uint8``:
-* ``uint32``:
-* ``int32``:
-* ``enum32``: The ``default`` value is an integer representing an
-  offset into the names array.
-* ``mac``:
-* ``string``: The length of the string excluding the trailing 0 is
-  determined by the length given in the ``reg`` property.
-
-Backends
---------
-
-Currently two backends exist. The raw backend is a very compact format
-consisting of a magic value for identification, the raw values and a
-CRC. Two copies are maintained for making sure that during update the
-storage device still contains a valid state. The dtb backend stores
-the state as a devicetree binary blob. This is exactly the original
-devicetree description of the state itself, but additionally contains
-the actual values of the variables. Unlike the raw state backend the
-dtb state backend can describe itself.
+* ``names``: For ``enum32`` values only, this specifies the possible values for
+  ``enum32``.
+
+Optional Properties
+###################
+
+* ``default``: The default value if the variable's content cannot be read from
+  the backend. For ``enum32`` values it is an integer representing an offset
+  into the names array.
+
+.. note:: Since the ``default`` property is optional, keep in mind you may need
+   a valid default value if other instances (like the bootchooser for example)
+   depends on it. Due to this, a ``default`` might be a required property instead.
+
+Variable Examples
+#################
+
+``uint8``:
+
+.. code-block:: text
+
+   uint8_example@0 {
+       reg = <0x0 0x1>;
+       type = "uint8";
+       default = <0x00>;
+   };
+
+``uint32``:
+
+.. code-block:: text
+
+   uint32_example@0 {
+       reg = <0x0 0x4>;
+       type = "uint32";
+       default = <100>;
+   };
+
+``enum32``:
+
+.. code-block:: text
+
+   enum_example@0 {
+       reg = <0x0 0x4>;
+       type = "enum32";
+       names = "value#1", "value#2";
+       default = <1>; /* selects "value#2" as the default */
+   };
+
+``mac``:
+
+.. code-block:: text
+
+   mac_example@0 {
+       reg = <0x0 0x6>;
+       type = "mac";
+   };
+
+Since a 'MAC' is a unique system identifier it makes no sense for a default
+value here. It must be set individually at run-time instead.
+
+``string``:
+
+.. code-block:: text
+
+   name {
+       reg = <0x0 0x10>;
+       type = "string";
+   };
+
+In this example the length of the string is limited to 16 characters.
+
+.. _barebox,state_hmac:
 
 HMAC
 ----
 
-With the optional property ``algo = "hmac(<HASH>)";`` a HMAC algorithm
-can be defined to detect unauthorized modification of the state's
+With the optional property ``algo = "hmac(<HASH>)";`` an HMAC algorithm
+can be defined to detect unauthorized modification of the state's variable set
 header and/or data. For this to work the HMAC and the selected hash
 algorithm have to be compiled into barebox.
 
 The shared secret for the HMAC is requested via
 ``keystore_get_secret()``, using the state's name, from the barebox
 simple keystore. It's up to the developer to populate the keystore via
-``keystore_set_secret()`` in beforehand.
+``keystore_set_secret()`` in beforehand. Refer :ref:`command_keystore` for
+further details.
+
+.. _barebox,state_setup:
+
+Configuring the *state* variable set
+------------------------------------
+
+Since the *state* variable set is intended to be shared between the bootloader
+and the kernel, the view to the *state* variable set must be the same in both
+worlds.
+
+This can be achieved by defining all *state* variable set related definitions
+inside the barebox's devicetree only. It's **not** required to keep and maintain
+the same information inside the Linux kernel's devicetree again.
+
+When barebox is instructed to load and forward a devicetree to a Linux kernel
+to be started, it "silently" copies all *state* variable set related definitions
+from its own devicetree into the Linux kernel devicetree. This way both worlds
+behave the same when *state* variable sets should be read or modified.
+
+In order to enable barebox to copy the required information to a dedicated
+location inside the Linux kernel devicetree the name of the memory node to
+store the *state* variable set must be the same in the barebox's devicetree
+and the operating system's devicetree.
+
+With this "interconnection" barebox extends the operating system's devicetree
+with:
+
+- the layout and variable definition of the *state* variable set (in case of
+  the ``raw`` backend-type)
+- the store definition (backend type, backend storage type and so on)
+- partitioning information for the persistent memory in question (on demand)
+- the connection between the backend and the memory (device, partition)
+
+Example:
+
+Lets assume the barebox's devicetree uses the name ``persistent_state_memory@01``
+to define its own *state* variable set backend.
+
+Barebox's devicetree defines:
+
+.. code-block:: text
+
+   persistent_state_memory@01 {
+       compatible = "somevalue";
+       reg = <1>;
+
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       state: partition@0 {
+            label = "state";
+            reg = <0x0 0x100>;
+       };
+   };
 
-Frontend
---------
+The operating system's devicetree defines instead:
 
-As frontend a state instance is a regular barebox device which has
-device parameters for the state variables. With this the variables can
-be accessed like normal shell variables. The ``state`` command is used
-to save/restore a state to the backend device.
+.. code-block:: text
 
-After initializing the variable can be accessed with ``$state.foo``.
-``state -s`` stores the state to eeprom.
+   persistent_state_memory@01 {
+       compatible = "somevalue";
+       reg = <1>;
+   };
diff --git a/Documentation/user/bootchooser.rst b/Documentation/user/bootchooser.rst
index cef1d4abb..3d473b596 100644
--- a/Documentation/user/bootchooser.rst
+++ b/Documentation/user/bootchooser.rst
@@ -1,178 +1,217 @@
+.. _bootchooser:
+
 Barebox Bootchooser
 ===================
 
 In many cases embedded systems are layed out redundantly with multiple
-kernels and multiple root file systems. The bootchooser framework provides
+kernels and multiple root file systems. The *bootchooser* framework provides
 the building blocks to model different use cases without the need to start
 from scratch over and over again.
 
-The bootchooser works on abstract boot targets, each with a set of properties
+The *bootchooser* works on abstract boot targets, each with a set of properties
 and implements an algorithm which selects the highest priority target to boot.
 
 Bootchooser Targets
 -------------------
 
-A bootchooser target represents one target that barebox can boot. It consists
+A *bootchooser* boot target represents one target that barebox can boot. It consists
 of a set of variables in the ``global.bootchooser.<targetname>`` namespace. The
-following configuration variables are needed to describe a bootchooser target:
+following configuration variables are needed to describe a *bootchooser* boot target:
 
 ``global.bootchooser.<targetname>.boot``
-  This controls what barebox actually boots for this target. This string can contain
-  anything that the :ref:`boot <command_boot>` command understands.
+  This controls what barebox actually boots for this boot target. This string can
+  contain anything that the :ref:`boot <command_boot>` command understands.
 
 ``global.bootchooser.<targetname>.default_attempts``
-  The default number of attempts that a target shall be tried starting.
+  The default number of attempts that a boot target shall be tried before skipping it.
 ``global.bootchooser.<targetname>.default_priority``
-  The default priority of a target.
+  The default priority of a boot target.
 
 
-Additionally the following runtime variables are needed. Unlinke the configuration
-variables these are automatically changed by the bootchooser algorithm:
+Additionally the following run-time variables are needed. Unlike the configuration
+variables their values are automatically updated by the *bootchooser* algorithm:
 
 ``global.bootchooser.<targetname>.priority``
-  The current priority of the target. Higher numbers have higher priorities. A priority
-  of 0 means the target is disabled and won't be started.
+  The current ``priority`` of the boot target. Higher numbers have higher priorities.
+  A ``priority`` of 0 means the boot target is disabled and won't be started.
 ``global.bootchooser.<targetname>.remaining_attempts``
-  The remaining_attempts counter. Only targets with a remaining_attempts counter > 0
-  are started.
+  The ``remaining_attempts`` counter. Only boot targets with a ``remaining_attempts``
+  counter > 0 are started.
+
+The *bootchooser* algorithm generally only starts boot targets that have a ``priority``
+> 0 and a ``remaining_attempts`` counter > 0.
 
-The bootchooser algorithm generally only starts targets that have a priority
-> 0 and a remaining_attempts counter > 0.
+.. _bootchooser,algorithm:
 
 The Bootchooser Algorithm
 -------------------------
 
-The bootchooser algorithm is very simple. It works with two variables per target
-and some optional flags. The variables are the remaining_attempts counter that
-tells how many times the target will be started. The other variable is the priority,
-the target with the highest priority will be used first, a zero priority means
-the target is disabled.
-
-When booting, bootchooser starts the target with the highest priority that has a
-nonzero remaining_attempts counter. With every start of a target the remaining
-attempts counter of this target is decremented by one. This means every targets
-remaining_attempts counter reaches zero sooner or later and the target won't be
-booted anymore. To prevent that, the remaining_attempts counter must be reset to
-its default. There are different flags in the bootchooser which control resetting
-the remaining_attempts counter, controlled by the ``global.bootchooser.reset_attempts``
-variable. It holds a list of space separated flags. Possible values are:
-
-- ``power-on``: The remaining_attempts counters of all enabled targets are reset
-  after a power-on reset (``$global.system.reset="POR"``). This means after a power
-  cycle all targets will be tried again for the configured number of retries
-- ``all-zero``: The remaining_attempts counters of all enabled targets are reset
-  when none of them has any remaining_attempts left.
-
-Additionally the remaining_attempts counter can be reset manually using the
-:ref:`command_bootchooser` command. This allows for custom conditions under which
-a system is marked as good.
+The *bootchooser* algorithm is very simple. It works with two variables per boot target
+and some optional flags. The variables are the ``remaining_attempts`` counter that
+tells how many times the boot target will be started. The other variable is the ``priority``,
+the boot target with the highest ``priority`` will be used first, a zero ``priority``
+means the boot target is disabled.
+
+When booting, *bootchooser* starts the boot target with the highest ``priority`` that
+has a non-zero ``remaining_attempts`` counter. With every start of a boot target the
+``remaining_attempts`` counter of this boot target is decremented by one. This means
+every boot target's ``remaining_attempts`` counter reaches zero sooner or later and
+the boot target won't be booted anymore. To prevent that, the ``remaining_attempts``
+counter must be reset to its default. There are different flags in the
+*bootchooser* which control resetting the ``remaining_attempts`` counter,
+controlled by the ``global.bootchooser.reset_attempts`` variable. It holds a
+list of space separated flags. Possible values are:
+
+- empty: counters will never be reset
+- ``power-on``: The ``remaining_attempts`` counters of all enabled boot targets are reset
+  after a ``power-on`` reset (``$global.system.reset="POR"``). This means after a power
+  cycle all boot targets will be tried again for the configured number of retries.
+- ``all-zero``: The ``remaining_attempts`` counters of all enabled boot targets are
+  reset when none of them has any ``remaining_attempts`` left.
+
+Additionally the ``remaining_attempts`` counter can be reset manually using the
+:ref:`bootchoser command <command_bootchooser>`. This allows for custom conditions
+under which a system is marked as good.
 In case only the booted system itself knows when it is in a good state, the
-barebox-state tool from the dt-utils_ package can be used to reset the remaining_attempts
-counter from the currently running system.
+barebox-state tool from the dt-utils_ package can be used to reset the
+``remaining_attempts`` counter from the running system.
 
 .. _dt-utils: http://git.pengutronix.de/?p=tools/dt-utils.git;a=summary
 
-Bootchooser General Options
+General Bootchooser Options
 ---------------------------
 
-Additionally to the target options described above, bootchooser has some general
-options not specific to any target.
+In addition to the boot target options described above, *bootchooser* has some general
+options not specific to any boot target.
 
 ``global.bootchooser.disable_on_zero_attempts``
-  Boolean flag. If set to 1, bootchooser disables a target (sets priority to 0) whenever
-  the remaining attempts counter reaches 0.
+  Boolean flag. If set to 1, *bootchooser* disables a boot target (sets priority
+  to 0) whenever the remaining attempts counter reaches 0.
 ``global.bootchooser.default_attempts``
-  The default number of attempts that a target shall be tried starting, used when not
-  overwritten with the target specific variable of the same name.
+  The default number of attempts that a boot target shall be tried before skipping
+  it, used when not overwritten with the boot target specific variable of the same
+  name.
 ``global.bootchooser.default_priority``
-  The default priority of a target when not overwritten with the target specific variable
-  of the same name.
+  The default priority of a boot target when not overwritten with the target
+  specific variable of the same name.
 ``global.bootchooser.reset_attempts``
-  A space separated list of events that cause bootchooser to reset the
-  remaining_attempts counters of each target that has a non zero priority. Possible values:
-
-  * empty: counters will never be reset``
-  * power-on: counters will be reset after power-on-reset
-  * all-zero: counters will be reset when all targets have zero remaining attempts
+  Already described in :ref:`Bootchooser Algorithm <bootchooser,algorithm>`
 ``global.bootchooser.reset_priorities``
-  A space separated list of events that cause bootchooser to reset the priorities of
-  all targets. Possible values:
+  A space separated list of events that cause *bootchooser* to reset the priorities of
+  all boot targets. Possible values:
 
   * empty: priorities will never be reset
-  * all-zero: priorities will be reset when all targets have zero priority
+  * ``all-zero``: priorities will be reset when all targets have zero priority
 ``global.bootchooser.retry``
-  If set to 1, bootchooser retries booting until one succeeds or no more valid targets
-  exist.
+  If set to 1, *bootchooser* retries booting until one succeeds or no more valid
+  boot targets exist.
+  Otherwise the ``boot`` command will return with an error after the first failed
+  boot target.
 ``global.bootchooser.state_prefix``
-  Variable prefix when bootchooser is used with the state framework as backend for storing
-  runtime data, see below.
+  Variable prefix when *bootchooser* is used with the *state* framework as backend
+  for storing run-time data, see below.
 ``global.bootchooser.targets``
-  Space separated list of targets that are used. For each entry in the list a corresponding
+  Space separated list of boot targets that are used. For each entry in the list
+  a corresponding
   set of ``global.bootchooser.<targetname>.<variablename>`` variables must exist.
 ``global.bootchooser.last_chosen``
-  bootchooser sets this to the target that was chosen on last boot (index).
-
-Using the State Framework as Backend for Runtime Variable Data
---------------------------------------------------------------
-
-Normally the data that is modified by the bootchooser during runtime is stored
-in global variables (backed with NV). Alternatively the :ref:`state_framework`
-can be used for this data, which allows to store this data redundantly
-and in small EEPROM spaces. See :ref:`state_framework` to setup the state framework.
-During barebox runtime each state instance will create a device
-(usually named 'state' when only one is used) with a set of parameters. Set
-``global.bootchooser.state_prefix`` to the name of the device and optionally the
-namespace inside this device. For example when your state device is called 'state'
-and inside that the 'bootchooser' namespace is used for describing the targets,
-then set ``global.bootchooser.state_prefix`` to ``state.bootchooser``.
+  *bootchooser* sets this to the boot target that was chosen on last boot (index).
 
-Example
--------
+.. _bootchooser,setup_example:
+
+Setup Example
+-------------
+
+We want to set up a redundant machine with two bootable systems within one shared
+memory, here a NAND type flash memory with a UBI partition. We have a 512 MiB NAND
+type flash, to be used only for the root filesystem. The devicetree doesn't
+define any partition, because we want to run one UBI partition with two volumens
+for the redundant root filesystems on this flash memory.
+
+.. code-block:: text
 
-The following example shows how to initialize two targets, 'system0' and 'system1'.
-Both boot from an UBIFS on nand0, the former has a priority of 21 and boots from
-the volume 'system0' whereas the latter has a priority of 20 and boots from
-the volume 'system1'.
+   nand@0 {
+      [...]
+   };
+
+In order to configure this machine the following steps can be used:
 
 .. code-block:: sh
 
-  # initialize target 'system0'
-  nv bootchooser.system0.boot=nand0.ubi.system0
-  nv bootchooser.system0.default_attempts=3
-  nv bootchooser.system0.default_priority=21
+   ubiformat /dev/nand0 -y
+   ubiattach /dev/nand0
+   ubimkvol /dev/nand0.ubi root_filesystem_1 256MiB
+   ubimkvol /dev/nand0.ubi root_filesystem_2 0
+
+The last command creates a volume which fills the remaining available space
+on the NAND type flash memory, which will be most of the time smaller than
+256 MiB due to factory bad blocks and lost data blocks for UBI's management.
+
+After this preparation we can find two devices in ``/dev``:
+
+- ``nand0.ubi.root_filesystem_1``
+- ``nand0.ubi.root_filesystem_2``
+
+These two devices can now be populated with their filesystem content. In our
+example here we additionally assume, that these root filesystems contain a Linux
+kernel with its corresponding devicetree via boot spec (refer to
+:ref:`Bootloader Spec <bootloader_spec>` for further details).
+
+Either device can be booted with the :ref:`boot <command_boot>` command command,
+and thus can be used by the *bootchooser* and we can start to configure the
+*bootchooser* variables.
+
+The following example shows how to initialize two boot targets, ``system1`` and
+``system2``. Both boot from a UBIFS on ``nand0``, the former has a priority of
+21 and boots from the volume ``root_filesystem_1`` whereas the latter has a
+priority of 20 and boots from the volume ``root_filesystem_2``.
+
+.. code-block:: sh
 
   # initialize target 'system1'
-  nv bootchooser.system1.boot=nand0.ubi.system1
+  nv bootchooser.system1.boot=nand0.ubi.root_filesystem_1
   nv bootchooser.system1.default_attempts=3
-  nv bootchooser.system1.default_priority=20
+  nv bootchooser.system1.default_priority=21
+
+  # initialize target 'system2'
+  nv bootchooser.system2.boot=nand0.ubi.root_filesystem_2
+  nv bootchooser.system2.default_attempts=3
+  nv bootchooser.system2.default_priority=20
 
   # make targets known
-  nv bootchooser.targets="system0 system1"
+  nv bootchooser.targets="system1 system2"
 
   # retry until one target succeeds
-  nv bootchooser.retry="true"
+  nv bootchooser.retry=1
 
   # First try bootchooser, when no targets remain boot from network
   nv boot.default="bootchooser net"
 
-Note that this example is for testing, normally the NV variables would be
-initialized directly by files in the default environment, not with a script.
+.. note:: This example is for testing only, normally the NV variables would be
+   initialized directly by files in the default environment, not with a script.
+
+The run-time values are stored in environment variables as well. Alternatively,
+they can be stored in a *state* variable set instead. Refer to
+:ref:`using the state framework <bootchooser,state_framework>` for further
+details.
 
 Scenarios
 ---------
 
-This section describes some scenarios that can be solved with bootchooser. All
-scenarios assume multiple slots that can be booted, where 'multiple' is anything
-higher than one.
+This section describes some scenarios that can be handled by bootchooser. All
+scenarios assume multiple boot targets that can be booted, where 'multiple' is
+anything higher than one.
 
 Scenario 1
 ##########
 
-A system that shall always boot without user interaction. Staying in the bootloader
-is not an option. In this scenario a target is started for the configured number
-of remaining attempts. If it cannot successfully be started, the next target is chosen.
-This happens until no targets are left to start, then all remaining attempts are
-reset to their defaults and the first target is tried again.
+- a system that shall always boot without user interaction
+- staying in the bootloader is not an option.
+
+In this scenario a boot target is started for the configured number of remaining
+attempts. If it cannot be started successfully, the next boot target is chosen.
+This repeats until no boot targets are left to start, then all remaining attempts
+are reset to their defaults and the first boot target is tried again.
 
 Settings
 ^^^^^^^^
@@ -186,22 +225,26 @@ Settings
 Deployment
 ^^^^^^^^^^
 
-#. barebox or flash robot fills all slots with valid systems.
-#. The all-zero settings will lead to automatically enabling the slots, no
-   default settings are needed here.
+#. barebox or flash robot fills all boot targets with valid systems.
+#. The all-zero settings will lead to automatically enabling the boot targets,
+   no default settings are needed here.
 
 Recovery
 ^^^^^^^^
 
-Recovery will only be called when all targets are not startable (That is, no valid
-Kernel found or read failure). Once a target is startable (A valid kernel is found
-and started) Bootchooser will never fall through to the recovery target.
+Recovery will only be called when all boot targets are not startable (That is,
+no valid kernel found or read failure). Once a boot target is startable (a
+valid kernel is found and started) *bootchooser* will never fall through to
+the recovery boot target.
 
 Scenario 2
 ##########
 
-A system with multiple slots, a slot that was booted three times without success
-shall never be booted again (except after update or user interaction).
+- a system with multiple boot targets
+- one recovery system
+
+A boot target that was booted three times without success shall never be booted
+again (except after update or user interaction).
 
 Settings
 ^^^^^^^^
@@ -216,23 +259,27 @@ Settings
 Deployment
 ^^^^^^^^^^
 
-#. barebox or flash robot fills all slots with valid systems.
-#. barebox or flash robot marks slots as good or state contains non zero
+#. barebox or flash robot fills all boot targets with valid systems.
+#. barebox or flash robot marks boot targets as good or *state* contains non zero
    defaults for the remaining_attempts/priorities.
 
 Recovery
 ^^^^^^^^
-done by 'recovery' boot target which is booted after the bootchooser falls through due to
-the lack of bootable targets. This target can be:
 
-- A system that will be booted as recovery.
-- A barebox script that will be started.
+Done by 'recovery' boot target which is booted after the *bootchooser* falls
+through due to the lack of bootable targets. This boot target can be:
+
+- a system that will be booted as recovery.
+- a barebox script that will be started.
 
 Scenario 3
 ##########
 
-A system with multiple slots and one recovery system. Booting a slot three times
-without success disables it. A power cycle shall not be counted as failed boot.
+- a system with multiple boot targets
+- one recovery system
+- a power cycle shall not be counted as failed boot.
+
+Booting a boot target three times without success disables it.
 
 Settings
 ^^^^^^^^
@@ -247,33 +294,205 @@ Settings
 Deployment
 ^^^^^^^^^^
 
-#. barebox or flash robot fills all slots with valid systems.
-#. barebox or flash robot marks slots as good.
+#. barebox or flash robot fills all boot targets with valid systems.
+#. barebox or flash robot marks boot targets as good.
 
 Recovery
 ^^^^^^^^
 
-Done by 'recovery' boot target which is booted after the bootchooser falls through
-due to the lack of bootable targets. This target can be:
+Done by 'recovery' boot target which is booted after the *bootchooser* falls
+through due to the lack of bootable targets. This target can be:
+
+- a system that will be booted as recovery.
+- a barebox script that will be started.
 
-- A system that will be booted as recovery.
-- A barebox script that will be started.
+.. _bootchooser,state_framework:
+
+Using the *State* Framework as Backend for Run-Time Variable Data
+-----------------------------------------------------------------
+
+Usually the *bootchooser* modifies its data in global variables which are
+connected to :ref:`non volatile variables <config_device>`.
+
+Alternatively the :ref:`state_framework` can be used for this data, which
+allows to store this data redundantly in some kind of persistent memory.
+
+In order to let the *bootchooser* use the *state* framework for its storage
+backend, configure the ``bootchooser.state_prefix`` variable with the *state*
+variable set instance name.
+
+Usually a generic *state* variable set in the devicetree is defined like this
+(refer to :ref:`barebox,state` for more details):
+
+.. code-block:: text
+
+   some_kind_of_state {
+      [...]
+   };
+
+At barebox run-time this will result in a *state* variable set instance called
+*some_kind_of_state*. You can also store variables unrelated to *bootchooser* (a
+serial number, MAC address, …) in it.
+
+Extending this *state* variable set by information required by the *bootchooser*
+is simply done by adding so called 'boot targets' and optionally one ``last_chosen``
+node. It then looks like:
+
+.. code-block:: text
+
+   some_kind_of_state {
+     [...]
+     boot_target_1 {
+         [...]
+     };
+     boot_target_2 {
+         [...]
+     };
+   };
+
+It could makes sense to store the result of the last *bootchooser* operation
+in the *state* variable set as well. In order to do so, add a node with the name
+``last_chosen`` to the *state* variable set. *bootchooser* will use it if present.
+The *state' variable set definition then looks like:
+
+.. code-block:: text
+
+   some_kind_of_state {
+     [...]
+     boot_target_1 {
+         [...]
+     };
+     boot_target_2 {
+         [...]
+     };
+     last_chosen {
+         reg = <offset 0x4>;
+         type = "uint32";
+     };
+   };
+
+The ``boot_target_*`` names shown above aren't variables themselves (like the other
+variables in the *state* variable set), they are named containers instead, which
+are used to group variables specific to *bootchooser*.
+
+A 'boot target' container has the following fixed content:
+
+.. code-block:: text
+
+   some_boot_target {
+          #address-cells = <1>;
+          #size-cells = <1>;
+
+          remaining_attempts {
+              [...]
+              default = <some value>; /* -> read note below */
+          };
+
+          priority {
+              [...]
+              default = <some value>; /* -> read note below */
+          };
+   };
+
+.. important:: Since each variable in a *state* variable set requires a ``reg``
+   property, the value of its ``reg`` property must be unique, e.g. the offsets
+   must be consecutive from a global point of view, as they describe the
+   storage layout in the backend memory.
+
+So, ``remaining_attempts`` and ``priority`` are required variable nodes and are
+used to setup the corresponding run-time environment variables in the
+``global.bootchooser.<targetname>`` namespace.
+
+.. important:: It is important to provide a ``default`` value for each variable
+   for the case when the *state* variable set backend memory is uninitialized.
+   This is also true if default values through the *bootchooser's* environment
+   variables are defined (e.g. ``bootchooser.default_attempts``,
+   ``bootchooser.default_priority`` and their corresponding boot target specific
+   variables). The former ones are forwarded to the *bootchooser* to make a
+   decision, the latter ones are used by the *bootchooser* to make a decision
+   the next time.
+
+Example
+#######
+
+For this example we use the same system and its setup described in
+:ref:`setup example <bootchooser,setup_example>`. The resulting devicetree
+content for the *state* variable set looks like:
+
+.. code-block:: text
+
+   system_state {
+        [...]
+        system1 {
+             #address-cells = <1>;
+             #size-cells = <1>;
+             remaining_attempts@0 {
+                 reg = <0x0 0x4>;
+                 type = "uint32";
+                 default = <3>;
+             };
+             priority@4 {
+                 reg = <0x4 0x4>;
+                 type = "uint32";
+                 default = <20>;
+             };
+        };
+
+        system2 {
+             #address-cells = <1>;
+             #size-cells = <1>;
+             remaining_attempts@8 {
+                 reg = <0x8 0x4>;
+                 type = "uint32";
+                 default = <3>;
+             };
+             priority@c {
+                 reg = <0xc 0x4>;
+                 type = "uint32";
+                 default = <21>;
+             };
+        };
+
+        last_chosen@10 {
+             reg = <0x10 0x4>;
+             type = "uint32";
+        };
+   };
+
+.. important:: While the ``system1/2`` nodes suggest a different namespace inside the
+   *state* variable set, the actual variable's ``reg``-properties and their offset
+   part are always relative to the whole *state* variable set and thus must be
+   consecutive globally.
+
+To make *bootchooser* use the so called ``system_state`` *state* variable set
+instead of the NV run-time environment variables, we just set:
+
+.. code-block:: text
+
+   global.bootchooser.state_prefix=system_state
+
+.. note:: Its a good idea to keep the ``bootchooser.<targetname>.default_priority``
+   and ``bootchooser.<targetname>.default_attempts`` values in sync with the
+   corresponding default values in the devicetree.
 
 Updating systems
 ----------------
 
-Updating a slot is the same among the different scenarios. It is assumed that the
-update is done under a running Linux system which can be one of the regular bootchooser
-slots or a dedicated recovery system. For the regular slots updating is done like:
-
-- Set the priority of the inactive slot to 0.
-- Update the inactive slot.
-- Set priority of the inactive slot to a higher value than the active slot.
-- Set remaining_attempts of the inactive slot to nonzero.
+Updating a boot target is the same among the different scenarios. It is assumed
+that the update is done under a running Linux system which can be one of the
+regular *bootchooser* boot targets or a dedicated recovery system. For the
+regular *bootchooser* boot targets updating is done like:
+
+- Disable the inactive (e.g. not used right now) boot target by setting its
+  ``priority`` to 0.
+- Update the inactive boot target.
+- Set ``remaining_attempts`` of the inactive boot target to nonzero.
+- Enable the inactive boot target by setting its ``priority`` to a higher value
+  than any other boot target (including the used one right now).
 - Reboot.
-- If necessary update the now inactive, not yet updated slot the same way.
+- If necessary update the now inactive, not yet updated boot target the same way.
 
-One way of updating systems is using RAUC_ which integrates well with the bootchooser
+One way of updating systems is using RAUC_ which integrates well with the *bootchooser*
 in barebox.
 
-.. _RAUC: https://rauc.readthedocs.io/en/latest/ RAUC (
+.. _RAUC: https://rauc.readthedocs.io/en/latest/
diff --git a/Documentation/user/state.rst b/Documentation/user/state.rst
index 73c4be815..7d6c5770d 100644
--- a/Documentation/user/state.rst
+++ b/Documentation/user/state.rst
@@ -3,65 +3,643 @@
 Barebox State Framework
 =======================
 
-The state framework is build to exchange data between Barebox and Linux
-userspace using a non-volatile storage. There are several components involved.
-Barebox has a state driver to access the variables. For the Linux Userspace
-there is a userspace tool.
-
-Devicetree
-----------
-
-Currently the devicetree defines the layout of the variables and data.
-Variables are fixed size. Several types are supported, see the binding
-documentation for details.
-
-Data Formats
-------------
-
-The state data can be stored in different ways. Currently two formats are
-available, ``raw`` and ``dtb``. Both format the state data differently.
-Basically these are serializers. The raw serializer additionally supports a
-HMAC algorithm to detect manipulations.
-
-The data is always stored in a logical unit called ``bucket``. A ``bucket`` has
-its own size depending on some external contraints. These contraints are listed
-in more detail below depending on the used memory type and storage backend. A
-``bucket`` stores exactly one state. A default number of three buckets is used
-to store data redundantely.
-
-Redundancy
-----------
-
-The state framework is safe against powerfailures during write operations. To
-archieve that multiple buckets are stored to disk. When writing all buckets are
-written in order. When reading, the buckets are read in order and the first
-one found that passes CRC tests is used. When all data is read the buckets
-containing invalid or outdated data are written with the data just read. Also
-NAND blocks need cleanup due to excessive bitflips are rewritten in this step.
-With this it is made sure that after successful initialization of a state the
-data on the storage device is consistent and redundant.
-
-Storage Backends
-----------------
-
-The serialized data can be stored to different backends. Currently two
-implementations exist, ``circular`` and ``direct``. The state framework automatically
-selects the correct backend depending on the storage medium. Media requiring
-erase operations (NAND, NOR flash) use the ``circular`` backend, others use the ``direct``
-backend. The purpose of the ``circular`` backend is to save erase cycles which may
-wear out the flash blocks. It continuously fills eraseblocks with updated data
-and only when an eraseblock if fully written erases it and starts over writing
-new data to the same eraseblock again.
-
-For all backends multiple copies are written to handle read errors.
-
-Commands
+Boards often have the need to store variable sets in persistent memory. barebox
+could handle that with its regular environment. But the constraints for such a
+variable set are often different from what the regular environment can do:
+
+* compact binary format to make it suitable for small non-volatile memories
+* atomic save/restore of the whole variable set
+* redundancy
+
+*state* is a framework to describe, access, store and restore a set of variables
+and is prepared to exchange/share data between barebox and Linux userspace using
+some kind of persistent memory.
+
+Already known users of the *state* information are the :ref:`bootchooser` and
+RAUC_.
+
+.. _RAUC: https://rauc.readthedocs.io/en/latest/
+
+barebox itself uses a *state* driver to access the variables in the
+persistent memory. For the Linux run-time there is a userspace tool_ to do
+the same.
+
+.. _tool: https://git.pengutronix.de/cgit/tools/dt-utils/
+
+To define a *state* variable set, a devicetree based description is used. Refer to
+:ref:`barebox,state` for further details.
+
+There are several software components involved, which are described in this
+section.
+
+.. _state_framework,backends:
+
+Backends (e.g. Supported Memory Types)
+--------------------------------------
+
+Some non-volatile memory is need for storing a *state* variable set:
+
+- all kinds of NOR flash memories
+- all kinds of NAND flash memories
+- MRAM
+- EEPROM
+- all kind of SRAMs (backup battery assumed)
+
+For classic MTDs (NOR/NAND/SRAM), a partition is required and understood by
+the Linux kernel as well to define the location inside the device where to store
+the *state* variable set. For non-MTDs (MRAM/EEPROM) a different approach is
+required to define the location where to store the *state* variable set.
+
+.. _state_framework,backend_types:
+
+Backend-Types (e.g. *state* storage format)
+-------------------------------------------
+
+The *state* variable set itself can be stored in different ways. Currently two
+formats are available, ``raw`` and ``dtb``.
+
+Both serialize the *state* variable set differently.
+
+.. note:: The ``raw`` serializer additionally supports an HMAC algorithm to
+   detect manipulations. Refer to :ref:`HMAC <barebox,state_hmac>` for further
+   details.
+
+.. _state_framework,raw:
+
+The ``raw`` *state* storage format
+##################################
+
+``raw`` means the *state* variable set is a simple binary data blob only. In
+order to handle it, the *state* framework puts a management header in front of
+the binary data blob with the following content and layout:
+
+ +---------+---------+---------------------------------------------------+
+ | Offset  |   Size  |    Content                                        |
+ +---------+---------+---------------------------------------------------+
+ |  0x00   | 4 bytes | 'magic value'                                     |
+ +---------+---------+---------------------------------------------------+
+ |  0x04   | 2 bytes | reserved, filled with zero bits                   |
+ +---------+---------+---------------------------------------------------+
+ |  0x06   | 2 bytes | byte count of binary data blob                    |
+ +---------+---------+---------------------------------------------------+
+ |  0x08   | 4 bytes | CRC32 of binary data blob (offset 0x10...)        |
+ +---------+---------+---------------------------------------------------+
+ |  0x0c   | 4 bytes | CRC32 of header (offset 0x00...0x0b)              |
+ +---------+---------+---------------------------------------------------+
+ | 0x10... |         | binary data blob                                  |
+ +---------+---------+---------------------------------------------------+
+
+- 'magic value' is an unsigned value with native endianness, refer to
+  :ref:`'magic' property <barebox,state_magic>` about its value.
+- 'byte count' is an unsigned value with native endianness
+- 'binary data blob CRC32' is an unsigned value with native endianness
+- 'header CRC32' is an unsigned value with native endianness
+
+.. note:: the 32-bit CRC calculation uses the polynomial:
+
+  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
+
+Since the binary data blob has no built-in description of the embedded *state*
+variable set, it depends on an external layout definition to encode
+and decode it correctly. A devicetree based description is used to describe the
+embedded *state* variable set. Refer to
+:ref:`Variable Subnodes <barebox,state_variable>` for further details.
+
+.. important:: It is important to share this layout definition in all
+   'worlds' which want to read or manipulate the *state* variable set. This
+   includes offsets, sizes and endianesses of the binary data. Refer to
+   :ref:`Configuring the state variable set <barebox,state_setup>` on how to
+   setup barebox to ensure this is done automatically for devicetree based
+   operating systems.
+
+.. note:: When calculating the ``backend-stridesize`` take the header overhead
+   into account. The header overhead is always 16 bytes.
+
+.. _state_framework,dtb:
+
+The ``dtb`` *state* storage format
+##################################
+
+.. note:: The ``dtb`` backend type isn't well tested. Use the ``raw`` backend
+          when in doubt.
+
+The ``dtb`` backend type stores the *state* variable set as a devicetree binary
+blob. This is exactly the original devicetree description of the *state* variable
+set itself, but additionally contains the actual values of the variable set.
+Unlike the ``raw`` *state* backend the ``dtb`` *state* backend can describe itself.
+
+.. _state_framework,backend_storage_type:
+
+Backend Storage Types (e.g. media storage layout)
+-------------------------------------------------
+
+The serialized data (``raw`` or ``dtb``) can be stored to different backend
+storage types. These types are dedicated to different memory types.
+
+Currently two backend storage type implementations do exist, ``circular`` and
+``direct``.
+
+The state framework can select the correct backend storage type depending on the
+backend medium. Media requiring erase operations (NAND, NOR flash) defaults to
+the ``circular`` backend storage type automatically. In contrast EEPROMs and
+RAMs are candidates for the ``direct`` backend storage type.
+
+Direct Storage Backend
+######################
+
+This kind of backend storage type is intended to be used with persistent RAMs or
+EEPROMs.
+These media are characterized by:
+
+- memory cells can be simply written at any time (no previous erase required)
+- memory cells can be written as often as required (unlimted or very high endurance)
+- can be written on a byte-by-byte manner
+
+Example: MRAM with 64 bytes at device's offset 0:
+
+.. code-block:: text
+
+    0                                                                 0x3f
+    +-------------------------------------------------------------------+
+    |                                                                   |
+    +-------------------------------------------------------------------+
+
+Writing the *state* variable set always happens at the same offset:
+
+.. code-block:: text
+
+    0                                                                 0x3f
+    +-------------------------------------------+-----------------------+
+    |                 copy                      |                       |
+    +-------------------------------------------+-----------------------+
+
+.. important:: The ``direct`` storage backend needs 8 bytes of additional space
+   per *state* variable set for its meta data.
+
+Circular Storage Backend
+########################
+
+This kind of backend storage type is intended to be used with regular flash memory devices.
+
+Flash memories are characterized by:
+
+- only erased memory cells can be written with new data
+- written data cannot be written twice (at least not for modern flash devices)
+- erase can happen on eraseblock sizes only (detectable, physical value)
+- an eraseblock only supports a limited number of write-erase-cycles (as low as a few thousand cycles)
+
+The purpose of the ``circular`` backend storage type is to save erase cycles
+which may wear out the flash's eraseblocks. This type instead incrementally fills
+an eraseblock with updated data and only when an eraseblock
+is fully written, it erases it and starts over writing new data to the same
+eraseblock again.
+
+**NOR type flash memory is additionally characterized by**
+
+- can be written on a byte-by-byte manner
+
+.. _state_framework,nor:
+
+Example: NOR type flash memory with 64 kiB eraseblock size
+
+.. code-block:: text
+
+    0                                                                0x0ffff
+    +--------------------------------------------------------------------+
+    |                                                                    |
+    +--------------------------------------------------------------------+
+    |<--------------------------- eraseblock --------------------------->|
+
+Writing the *state* variable set the very first time:
+
+.. code-block:: text
+
+    0
+    +------------+------------
+    |   copy     |
+    |    #1      |
+    +------------+------------
+    |<- stride ->|
+    |<---- eraseblock -------
+
+'copy#1' will be used.
+
+Changing the *state* variable set the first time (e.g. writing it the second time):
+
+.. code-block:: text
+
+    0
+    +------------+------------+------------
+    |   copy     |   copy     |
+    |    #1      |    #2      |
+    +------------+------------+------------
+    |<- stride ->|<- stride ->|
+    |<------------- eraseblock -----------
+
+'copy#2' will now be used and 'copy#1' will be ignored.
+
+Changing the *state* variable set the n-th time:
+
+.. code-block:: text
+
+    0                                                                0x0ffff
+    +------------+------------+-------- -------+------------+------------+
+    |   copy     |   copy     |                |    copy    |   copy     |
+    |    #1      |    #2      |                |    #n-1    |    #n      |
+    +------------+------------+-------- -------+------------+------------+
+    |<- stride ->|<- stride ->|                |<- stride ->|<- stride ->|
+    |<---------------------------- eraseblock -------------------------->|
+
+'copy#n' will now be used and all other copies will be ignored.
+
+The next time the *state* variable set changes again, the whole block will be
+erased and the *state* variable set gets stored at the first position inside
+the eraseblock again. This reduces the need for a flash memory erase by factors.
+
+**NAND type flash memory is additionally characterized by**
+
+- organized in pages (size is a detectable, physical value)
+- writes can only happen in multiples of the page size (which much less than the eraseblock size)
+- partially writing a page can be limited in count or be entirely forbidden (in
+  the case of *MLC* NANDs)
+
+Example: NAND type flash memory with 128 kiB eraseblock size and 2 kiB page
+size and a 2 kiB write size
+
+.. code-block:: text
+
+    0                                                             0x20000
+    +------+------+------+------+---- ----+------+------+------+------+
+    | page | page | page | page |         | page | page | page | page |
+    |  #1  |  #2  |  #3  |  #4  |         | #61  | #62  | #63  | #64  |
+    +------+------+------+------+---- ----+------+------+------+------+
+    |<-------------------------- eraseblock ------------------------->|
+
+Writing the *state* variable set the very first time:
+
+.. code-block:: text
+
+    |<--- page #1---->|
+    +-------+---------+--
+    | copy  |         |
+    |  #1   |         |
+    +-------+---------+--
+    |<---- eraseblock ---
+
+'copy#1' will be used.
+
+Changing the *state* variable set the first time (e.g. writing it the second time):
+
+.. code-block:: text
+
+    |<-- page #1 -->|<-- page #2 -->|
+    +-------+-------+-------+-------+----
+    | copy  |       | copy  |       |
+    |  #1   |       |  #2   |       |
+    +-------+-------+-------+-------+----
+    |<--------- eraseblock --------------
+
+'copy#2' will now be used and 'copy#1' will be ignored.
+
+Changing the *state* variable set the 64th time:
+
+.. code-block:: text
+
+    |<-- page #1 -->|<-- page #2 -->|        |<- page #63 -->|<- page #64 -->|
+    +-------+-------+-------+-------+--    --+-------+-------+-------+-------+
+    | copy  |       | copy  |       |        | copy  |       | copy  |       |
+    |  #1   |       |  #2   |       |        |  #63  |       |  #64  |       |
+    +-------+-------+-------+-------+--    --+-------+-------+-------+-------+
+    |<----------------------------- eraseblock ----------------------------->|
+
+'copy#n' will now be used and all other copies will be ignored.
+
+The next time the *state* variable set changes again, the eraseblock will be
+erased and the *state* variable set gets stored at the first position inside
+the eraseblock again. This significantly reduces the need for a block erases.
+
+.. important:: One copy of the *state* variable set is limited to the page size
+   of the used backend (e.g. NAND type flash memory)
+
+Redundant *state* variable set copies
+-------------------------------------
+
+To avoid data loss when changing the *state* variable set, more than one
+*state* variable set copy can be stored into the backend. Whenever the *state*
+variable set changes, only one *state* variable set copy gets changed at a time.
+In the case of an interruption and/or power loss resulting into an incomplete
+write to the backend, the system can fall back to a different *state* variable
+set copy (previous *state* variable set).
+
+Direct Storage Backend Redundancy
+#################################
+
+For this kind of backend storage type a value for the stride size must be
+defined by the developer (refer to
+:ref:`backend-stridesize <barebox,state_backend_stridesize>`).
+
+It always stores **three** redundant copies of the backend-type. Keep this in
+mind when calculating the stride size and defining the backend size (e.g. the
+size of a partition).
+
+.. code-block:: text
+
+    +----------------+------+----------------+------+----------------+------+
+    | redundant copy | free | redundant copy | free | redundant copy | free |
+    +----------------+------+----------------+------+----------------+------+
+    |<---- stride size ---->|<---- stride size ---->|<---- stride size ---->|
+
+.. important:: The ``direct`` storage backend needs 8 bytes of additional space
+   per *state* variable set for its meta data. Keep this in mind when calculating
+   the stridesize. For example, if your variable set needs 8 bytes, the ``raw``
+   header needs 16 bytes and the ``direct`` storage backend additionally 8 bytes.
+   The full space for one *state* variable set is now 8 + 16 + 8 = 32 bytes.
+
+Circular Storage Backend Redundancy
+###################################
+
+**NOR type flash memory**
+
+Redundant copies of the *state* variable set are stored based on the memory's
+eraseblocks and this size is automatically detected at run-time.
+It needs a stride size as well, because a NOR type flash memory can be written
+on a byte-by-byte manner.
+In contrast to the ``direct`` storage backend redundancy, the
+stride size for the ``circular`` storage backend redundancy defines the
+side-by-side location of the *state* variable set copies.
+
+.. code-block:: text
+
+    |<X>|<X>|...
+    +--------------------------------+--------------------------------+--
+    |C#1|C#2|C#3|C#4|C#5|            |C#1|C#2|C#3|C#4|C#5|            |
+    +--------------------------------+--------------------------------+--
+    |<--------- eraseblock --------->|<--------- eraseblock --------->|<-
+    |<------- redundant area ------->|<------- redundant area ------->|<-
+
+*<X>* defines the stride size, *C#1*, *C#2* the *state* variable set copies.
+
+Since these kinds of MTD devices are partitioned, its a good practice to always
+reserve multiple eraseblocks for the barebox's *state* feature. Keep in mind:
+Even NOR type flash memories can be worn out.
+
+**NAND type flash memory**
+
+Redundant copies of the *state* variable set are stored based on the memory's
+eraseblocks and this size is automatically detected at run-time.
+
+.. code-block:: text
+
+    +------+------+--- ---+------+------+------+------+--- ---+------+------+--
+    | copy | copy |       | copy | copy | copy | copy |       | copy | copy |
+    |  #1  |  #2  |       | #63  | #64  |  #1  |  #2  |       | #63  | #64  |
+    +------+------+--- ---+------+------+------+------+--- ---+------+------+--
+    |<----------- eraseblock ---------->|<----------- eraseblock ---------->|<-
+    |<-------- redundant area --------->|<-------- redundant area --------->|<-
+
+Since these kinds of MTD devices are partitioned, its a good practice to always
+reserve multiple eraseblocks for the barebox's *state* feature. Keep in mind:
+NAND type flash memories can be worn out, factory bad blocks can exist from the
+beginning.
+
+Handling of Bad Blocks
+----------------------
+
+NAND type flash memory can have factory bad eraseblocks and more bad
+eraseblocks can appear over the life time of the memory. They are detected by
+the MTD layer, marked as bad and never used again.
+
+.. important:: If NAND type flash memory should be used as a backend, at least
+   three eraseblocks are used to keep three redundant copies of the *state*
+   variable set. You should add some spare eraseblocks to the backend
+   partition by increasing the partition's size to a suitable value to handle
+   factory bad eraseblocks and worn-out eraseblocks.
+
+Examples
+--------
+
+The following examples intends to show how to setup and interconnect all
+required components for various non-volatile memories.
+
+All examples use just one *state* variable of type *uint8* named ``variable``
+to keep them simple. For the ``raw`` backend-type it means one *state*
+variable set has a size of 17 bytes (16 bytes header plus one byte variables).
+
+.. note:: The mentioned ``aliases`` and the *state* variable set node entries
+   are members of the devicetree's root node.
+
+.. note:: For a more detailed description of the used *state* variable set
+   properties here, refer to :ref:`barebox,state`.
+
+NOR flash memories
+##################
+
+This type of memory can be written on a single byte/word basis (depending on its bus
+width), but must be erased prior writing the same byte/word again and erasing
+must happen on an eraseblock basis. Typical eraseblock sizes are 128 kiB or
+(much) larger for parallel NOR flashes and 4 kiB or larger for serial NOR
+flashes.
+
+From the Linux kernel perspective this type of memory is a *Memory Technologie
+Device* (aka 'MTD') and handled by barebox in the same manner. It needs a
+partition configuration.
+
+The following devicetree node entry defines some kind of NOR flash memory and
+a partition at a specific offset to be used as the backend for the
+*state* variable set.
+
+.. code-block:: text
+
+	norflash@0 {
+		backend_state_nor: partition@120000 {
+			[...]
+		};
+	};
+
+With this 'backend' definition its possible to define the *state* variable set
+content, its backend-type and *state* variable set layout.
+
+.. code-block:: text
+
+	aliases {
+		state = &state_nor;
+	};
+
+	state_nor: nor_state_memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "barebox,state";
+		magic = <0x512890a0>;
+		backend-type = "raw";
+		backend = <&backend_state_nor>;
+		backend-storage-type = "circular";
+		backend-stridesize = <32>;
+
+		variable {
+			reg = <0x0 0x1>;
+			type ="uint8";
+			default = <0x1>;
+		};
+	};
+
+NAND flash memories
+###################
+
+This type of memory can be written on a *page* base (typically 512 bytes,
+2048 or (much) larger), but must be erased prior writing the same page again and
+erasing must happen on an eraseblock base. Typical eraseblock sizes are
+64 kiB or (much) larger.
+
+From the Linux kernel perspective this type of memory is a *Memory Technologie
+Device* (aka 'MTD') and handled by barebox in the same manner. It needs a
+partition configuration.
+
+The following devicetree node entry defines some kind of NAND flash memory and
+a partition at a specific offset inside it to be used as the backend for the
+*state* variable set.
+
+.. code-block:: text
+
+	nandflash@0 {
+		backend_state_nand: partition@500000 {
+			[...]
+		};
+	};
+
+With this 'backend' definition its possible to define the *state* variable set
+content, its backend-type and *state* variable layout.
+
+.. code-block:: text
+
+	aliases {
+		state = &state_nand;
+	};
+
+	state_nand: nand_state_memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "barebox,state";
+		magic = <0xab67421f>;
+		backend-type = "raw";
+		backend = <&backend_state_nand>;
+		backend-storage-type = "circular";
+
+		variable {
+			reg = <0x0 0x1>;
+			type ="uint8";
+			default = <0x1>;
+		};
+	};
+
+SRAM
+####
+
+This type of memory can be written on a byte base and there is no need for an
+erase prior writing a new value.
+
+From the Linux kernel perspective this type of memory is a *Memory Technologie
+Device* (aka 'MTD') and handled by barebox in the same manner. It needs a
+partition definition.
+
+The following devicetree node entry defines some kind of SRAM memory and
+a partition at a specific offset inside it to be used as the backend for the
+*state* variable set.
+
+.. code-block:: text
+
+	sram@0 {
+		backend_state_sram: partition@10000 {
+			[...]
+		};
+	};
+
+With this 'backend' definition its possible to define the *state* variable set
+content, its backend-type and *state* variable layout.
+
+.. code-block:: text
+
+	aliases {
+		state = &state_sram;
+	};
+
+	state_sram: sram_state_memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "barebox,state";
+		magic = <0xab67421f>;
+		backend-type = "raw";
+		backend = <&backend_state_sram>;
+		backend-storage-type = "direct";
+		backend-stridesize = <32>;
+
+		variable {
+			reg = <0x0 0x1>;
+			type ="uint8";
+			default = <0x1>;
+		};
+	};
+
+EEPROM
+######
+
+This type of memory can be written on a byte base and must be erased prior
+writing, but in contrast to the other flash memories, an EEPROM does the erase
+of the address to be written to by its own, so its transparent to the
+application.
+
+While from the Linux kernel perspective this type of memory does not support
+partitions, barebox and the *state* userland tool will use partition definitions
+on an EEPROM memory as well, to exactly define the location in a generic manner
+within the EEPROM.
+
+.. code-block:: text
+
+	eeprom@50 {
+		partitions {
+			compatible = "fixed-partitions";
+			#size-cells = <1>;
+			#address-cells = <1>;
+			backend_state_eeprom: eeprom_state_memory@400 {
+				reg = <0x400 0x100>;
+				label = "state-eeprom";
+			};
+		};
+	};
+};
+
+With this 'backend' definition its possible to define the *state* variable set
+content, its backend-type and *state* variable layout.
+
+.. code-block:: text
+
+	aliases {
+		state = &state_eeprom;
+	};
+
+	state_eeprom: eeprom_memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "barebox,state";
+		magic = <0x344682db>;
+		backend-type = "raw";
+		backend = <&backend_state_eeprom>;
+		backend-storage-type = "direct";
+		backend-stridesize = <32>;
+
+		variable {
+			reg = <0x0 0x1>;
+			type ="uint8";
+			default = <0x1>;
+		};
+	};
+
+Frontend
 --------
 
-The ``state`` command can be used to store and manipulate the state. Using
-``state`` without argument lists you all available states with their name.
-``devinfo STATE_NAME`` shows you all variables and their values. ``state -s``
-stores the state.
+As frontend a *state* instance is a regular barebox device which has
+device parameters for the *state* variables. With this the variables can
+be accessed like normal shell variables. The ``state`` command is used
+to save/restore a *state* variable set to the backend device.
 
-Starting Barebox will automatically load the last written state. If loading the
-state fails the defaults are used.
+After initializing the variable can be accessed with ``$state.foo``.
+``state -s`` stores the *state* to the backend device.
-- 
2.11.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Rework of the state/bootchooser feature documentaiton
  2017-08-15 13:46 Rework of the state/bootchooser feature documentaiton Juergen Borleis
                   ` (6 preceding siblings ...)
  2017-08-15 13:46 ` [PATCH 7/7] docs: rework and extend the 'state' and 'bootchooser' documentation Juergen Borleis
@ 2017-09-06 12:19 ` Sascha Hauer
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2017-09-06 12:19 UTC (permalink / raw)
  To: Juergen Borleis; +Cc: barebox

On Tue, Aug 15, 2017 at 03:46:29PM +0200, Juergen Borleis wrote:
> This is a rework of the documentation for the 'state framework' and
> 'bootchooser' feature. While at it, some fixes are included as well.
> 
> Comments are welcome.
> 

Applied, thanks

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] 9+ messages in thread

end of thread, other threads:[~2017-09-06 12:20 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-15 13:46 Rework of the state/bootchooser feature documentaiton Juergen Borleis
2017-08-15 13:46 ` [PATCH 1/7] docs/DS1307: fix layout Juergen Borleis
2017-08-15 13:46 ` [PATCH 2/7] state: keep backward compatibility Juergen Borleis
2017-08-15 13:46 ` [PATCH 3/7] bootchooser: avoid a use after free Juergen Borleis
2017-08-15 13:46 ` [PATCH 4/7] bootchooser: allow an empty namespace Juergen Borleis
2017-08-15 13:46 ` [PATCH 5/7] docs: remove build warning Juergen Borleis
2017-08-15 13:46 ` [PATCH 6/7] state: add debugging help Juergen Borleis
2017-08-15 13:46 ` [PATCH 7/7] docs: rework and extend the 'state' and 'bootchooser' documentation Juergen Borleis
2017-09-06 12:19 ` Rework of the state/bootchooser feature documentaiton Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox