summaryrefslogtreecommitdiffstats
path: root/Documentation/user
diff options
context:
space:
mode:
authorMarc Kleine-Budde <mkl@pengutronix.de>2016-08-24 12:22:40 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2016-09-22 11:44:23 +0200
commitcc532a3f733718526898c14f8137118b7d76a5bc (patch)
tree2addc58100c74b55f6477012f1d2f4df27de0c99 /Documentation/user
parent6d8beeaad1e1133ae48664223793394310b1db46 (diff)
downloadbarebox-cc532a3f733718526898c14f8137118b7d76a5bc.tar.gz
barebox-cc532a3f733718526898c14f8137118b7d76a5bc.tar.xz
boot: add framework for redundant boot scenarios
There are several use cases where a redundant Linux system is needed. The barebox bootchooser framework provides the building blocks to model different use cases without the need to start from the scratch over and over again. 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. See the documentation contained in this patch for more information. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'Documentation/user')
-rw-r--r--Documentation/user/bootchooser.rst274
-rw-r--r--Documentation/user/state.rst2
-rw-r--r--Documentation/user/user-manual.rst1
3 files changed, 277 insertions, 0 deletions
diff --git a/Documentation/user/bootchooser.rst b/Documentation/user/bootchooser.rst
new file mode 100644
index 0000000000..5baa66d9b9
--- /dev/null
+++ b/Documentation/user/bootchooser.rst
@@ -0,0 +1,274 @@
+Barebox Bootchooser
+===================
+
+In many cases embedded systems are layed out redundantly with multiple
+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
+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
+of a set of variables in the ``global.bootchooser.<targetname>`` namespace. The
+following configuration variables are needed to describe a bootchooser 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.
+
+``global.bootchooser.<targetname>.default_attempts``
+ The default number of attempts that a target shall be tried starting.
+``global.bootchooser.<targetname>.default_priority``
+ The default priority of a target.
+
+
+Additionally the following runtime variables are needed. Unlinke the configuration
+variables these are automatically changed 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.
+``global.bootchooser.<targetname>.remaining_attempts``
+ The remaining_attempts counter. Only targets with a remaining_attempts counter > 0
+ are started.
+
+The bootchooser algorithm generally only starts targets that have a priority
+> 0 and a remaining_attempts counter > 0.
+
+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.
+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 used to reset the remaining_attempts
+counter from the currently running system.
+
+.. _dt-utils: http://git.pengutronix.de/?p=tools/dt-utils.git;a=summary
+
+Bootchooser General Options
+---------------------------
+
+Additionally to the target options described above, bootchooser has some general
+options not specific to any target.
+
+``global.bootchooser.disable_on_zero_attempts``
+ Boolean flag. if 1, bootchooser disables a 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.
+``global.bootchooser.default_priority``
+ The default priority of a 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
+``global.bootchooser.reset_priorities``
+ A space separated list of events that cause bootchooser to reset the priorities of
+ all targets. Possible values:
+ * empty: priorities will never be reset
+ * all-zero: priorities will be reset when all targets have zero priority
+``global.bootchooser.retry``
+ If 1, bootchooser retries booting until one succeeds or no more valid targets exist.
+``global.bootchooser.state_prefix``
+ Variable prefix when bootchooser used with state framework as backend for storing runtime
+ data, see below.
+``global.bootchooser.targets``
+ Space separated list of targets that are used. For each entry in the list a corresponding
+ set of ``global.bootchooser.<name>``. 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``.
+
+Example
+-------
+
+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'.
+
+.. 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
+
+ # initialize target 'system1'
+ nv bootchooser.system1.boot=nand0.ubi.system1
+ nv bootchooser.system1.default_attempts=3
+ nv bootchooser.system1.default_priority=20
+
+ # make targets known
+ nv bootchooser.targets="system0 system1"
+
+ # retry until one target succeeds
+ nv bootchooser.retry="true"
+
+ # 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.
+
+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.
+
+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.
+
+Settings
+^^^^^^^^
+- ``global.bootchooser.reset_attempts="all-zero"``
+- ``global.bootchooser.reset_priorities="all-zero"``
+- ``global.bootchooser.disable_on_zero_attempts=0``
+- ``global.bootchooser.retry=1``
+- ``global.boot.default="bootchooser recovery"``
+- Userspace marks as good
+
+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.
+
+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.
+
+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).
+
+Settings
+^^^^^^^^
+
+- ``global.bootchooser.reset_attempts=""``
+- ``global.bootchooser.reset_priorities=""``
+- ``global.bootchooser.disable_on_zero_attempts=0``
+- ``global.bootchooser.retry=1``
+- ``global.boot.default="bootchooser recovery"``
+- Userspace marks as good
+
+Deployment
+^^^^^^^^^^
+
+#. barebox or flash robot fills all slots with valid systems
+#. barebox or flash robot marks slots 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
+
+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.
+
+Settings
+^^^^^^^^
+
+- ``global.bootchooser.reset_attempts="power-on"``
+- ``global.bootchooser.reset_priorities=""``
+- ``global.bootchooser.disable_on_zero_attempts=1``
+- ``global.bootchooser.retry=1``
+- ``global.boot.default="bootchooser recovery"``
+- Userspace marks as good
+
+Deployment
+^^^^^^^^^^
+
+- barebox or flash robot fills all slots with valid systems
+- barebox or flash robot marks slots 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:
+- A system that will be booted as recovery
+- A barebox script that will be started
+
+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
+- Reboot
+- If necessary update the now inactive, not yet updated slot the same way
+
+One way of updating systems is using RAUC_ which integrates well with the bootchooser
+in barebox.
+
+.. _RAUC: https://rauc.readthedocs.io/en/latest/ RAUC (
diff --git a/Documentation/user/state.rst b/Documentation/user/state.rst
index c401f105bd..5dd5c486e2 100644
--- a/Documentation/user/state.rst
+++ b/Documentation/user/state.rst
@@ -1,3 +1,5 @@
+.. _state_framework:
+
Barebox State Framework
=======================
diff --git a/Documentation/user/user-manual.rst b/Documentation/user/user-manual.rst
index 5841ea625c..435649f353 100644
--- a/Documentation/user/user-manual.rst
+++ b/Documentation/user/user-manual.rst
@@ -27,6 +27,7 @@ Contents:
usb
ubi
booting-linux
+ bootchooser
remote-control
system-setup
reset-reason