summaryrefslogtreecommitdiffstats
path: root/Documentation/user/state.rst
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/user/state.rst')
-rw-r--r--Documentation/user/state.rst696
1 files changed, 637 insertions, 59 deletions
diff --git a/Documentation/user/state.rst b/Documentation/user/state.rst
index 73c4be8159..7d6c5770d5 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.