Merge branch 'for-next/state'
This commit is contained in:
commit
ee0035e5cc
|
@ -0,0 +1,107 @@
|
|||
barebox,state
|
||||
=============
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
|
||||
Boards often have the need to store variables in persistent memory.
|
||||
The constraints are often different from what the regular environment
|
||||
can do:
|
||||
|
||||
* compact binary format to make it suitable for small EEPROMs/MRAMs
|
||||
* atomic save/restore of the whole variable set
|
||||
* redundancy
|
||||
|
||||
``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.
|
||||
|
||||
A state node contains a description of a set of variables along with a
|
||||
place where the variables are stored.
|
||||
|
||||
Required properties:
|
||||
|
||||
* ``compatible``: should be ``barebox,state``;
|
||||
* ``magic``: A 32bit number used as a magic to identify the state
|
||||
|
||||
Optional properties:
|
||||
|
||||
* ``backend``: describes where the data for this state is stored
|
||||
* ``backend-type``: should be ``raw`` or ``dtb``.
|
||||
|
||||
Variable nodes
|
||||
--------------
|
||||
|
||||
These are subnodes of a state node each describing a single
|
||||
variable. The node name may end with ``@<ADDRESS>``, but the suffix is
|
||||
sripped from the variable name.
|
||||
|
||||
State variables have a type. Currenty supported types are: ``uint32``,
|
||||
``enum32`` and ``mac`` address. Fixed length strings are planned but
|
||||
not implemented. Variable length strings are not planned.
|
||||
|
||||
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
|
||||
``type``. Variables are not allowed to overlap.
|
||||
* ``type``: Should be ``uint32``, ``enum32`` or ``mac`` 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::
|
||||
|
||||
state: state@0 {
|
||||
magic = <0x27031977>;
|
||||
compatible = "barebox,state";
|
||||
backend-type = "raw";
|
||||
backend = &eeprom, "partname:state";
|
||||
|
||||
foo {
|
||||
reg = <0x00 0x4>;
|
||||
type = "u32";
|
||||
default = <0x0>;
|
||||
};
|
||||
|
||||
bar {
|
||||
reg = <0x10 0x4>;
|
||||
type = "enum32";
|
||||
names = "baz", "qux";
|
||||
default ="qux";
|
||||
};
|
||||
};
|
||||
|
||||
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.
|
||||
|
||||
Frontend
|
||||
--------
|
||||
|
||||
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.
|
||||
|
||||
After initializing the variable can be accessed with ``$state.foo``.
|
||||
``state -s`` stores the state to eeprom.
|
|
@ -2096,6 +2096,11 @@ config CMD_TIME
|
|||
Note: This command depends on COMMAND being interruptible,
|
||||
otherwise the timer may overrun resulting in incorrect results
|
||||
|
||||
config CMD_STATE
|
||||
tristate
|
||||
depends on STATE
|
||||
prompt "state"
|
||||
|
||||
# end Miscellaneous commands
|
||||
endmenu
|
||||
|
||||
|
|
|
@ -110,3 +110,4 @@ obj-$(CONFIG_CMD_FIRMWARELOAD) += firmwareload.o
|
|||
obj-$(CONFIG_CMD_CMP) += cmp.o
|
||||
obj-$(CONFIG_CMD_NV) += nv.o
|
||||
obj-$(CONFIG_CMD_DEFAULTENV) += defaultenv.o
|
||||
obj-$(CONFIG_CMD_STATE) += state.o
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Jan Luebbe <j.luebbe@pengutronix.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <getopt.h>
|
||||
#include <command.h>
|
||||
#include <state.h>
|
||||
|
||||
static int do_state(int argc, char *argv[])
|
||||
{
|
||||
int opt, ret = 0;
|
||||
struct state *state = NULL;
|
||||
int do_save = 0, do_load = 0;
|
||||
const char *statename = "state";
|
||||
|
||||
while ((opt = getopt(argc, argv, "sl")) > 0) {
|
||||
switch (opt) {
|
||||
case 's':
|
||||
do_save = 1;
|
||||
break;
|
||||
case 'l':
|
||||
do_load = 1;
|
||||
break;
|
||||
default:
|
||||
return COMMAND_ERROR_USAGE;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_save && do_load)
|
||||
return COMMAND_ERROR_USAGE;
|
||||
|
||||
if (!do_save && !do_load) {
|
||||
state_info();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
statename = argv[optind];
|
||||
|
||||
state = state_by_name(statename);
|
||||
if (!state) {
|
||||
printf("cannot find state %s\n", statename);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (do_save)
|
||||
ret = state_save(state);
|
||||
else if (do_load)
|
||||
ret = state_load(state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const __maybe_unused char cmd_state_help[] =
|
||||
"Usage: state [OPTIONS] [STATENAME]\n"
|
||||
"\n"
|
||||
"options:\n"
|
||||
"-s save state\n"
|
||||
"-l load state\n";
|
||||
|
||||
BAREBOX_CMD_START(state)
|
||||
.cmd = do_state,
|
||||
BAREBOX_CMD_DESC("handle state information")
|
||||
BAREBOX_CMD_GROUP(CMD_GRP_MISC)
|
||||
BAREBOX_CMD_HELP(cmd_state_help)
|
||||
BAREBOX_CMD_END
|
|
@ -706,6 +706,13 @@ config BAREBOXCRC32_TARGET
|
|||
config POLLER
|
||||
bool "generic polling infrastructure"
|
||||
|
||||
config STATE
|
||||
bool "generic state infrastructure"
|
||||
depends on OF_BAREBOX_DRIVERS
|
||||
select ENVIRONMENT_VARIABLES
|
||||
select OFTREE
|
||||
select PARAMETER
|
||||
|
||||
config RESET_SOURCE
|
||||
bool "detect Reset cause"
|
||||
depends on GLOBALVAR
|
||||
|
|
|
@ -42,6 +42,7 @@ obj-$(CONFIG_POLLER) += poller.o
|
|||
obj-$(CONFIG_RESET_SOURCE) += reset_source.o
|
||||
obj-$(CONFIG_SHELL_HUSH) += hush.o
|
||||
obj-$(CONFIG_SHELL_SIMPLE) += parser.o
|
||||
obj-$(CONFIG_STATE) += state.o
|
||||
obj-$(CONFIG_UIMAGE) += image.o uimage.o
|
||||
obj-$(CONFIG_MENUTREE) += menutree.o
|
||||
obj-$(CONFIG_EFI_GUID) += efi-guid.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,4 +15,8 @@ config SRAM
|
|||
help
|
||||
This driver adds support for memory mapped SRAM.
|
||||
|
||||
config STATE_DRV
|
||||
tristate "state driver"
|
||||
depends on STATE
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
|
||||
obj-$(CONFIG_JTAG) += jtag.o
|
||||
obj-$(CONFIG_SRAM) += sram.o
|
||||
obj-$(CONFIG_STATE_DRV) += state.o
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Sascha Hauer <s.hauer@pengutronix.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <driver.h>
|
||||
#include <init.h>
|
||||
#include <malloc.h>
|
||||
#include <of.h>
|
||||
#include <state.h>
|
||||
|
||||
#include <linux/err.h>
|
||||
|
||||
static int state_probe(struct device_d *dev)
|
||||
{
|
||||
struct device_node *np = dev->device_node;
|
||||
struct state *state;
|
||||
const char *alias;
|
||||
const char *backend_type = NULL;
|
||||
int ret;
|
||||
char *path;
|
||||
|
||||
if (!np)
|
||||
return -EINVAL;
|
||||
|
||||
alias = of_alias_get(np);
|
||||
if (!alias)
|
||||
alias = "state";
|
||||
|
||||
state = state_new_from_node(alias, np);
|
||||
if (IS_ERR(state))
|
||||
return PTR_ERR(state);
|
||||
|
||||
ret = of_find_path(np, "backend", &path);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_info(dev, "outpath: %s\n", path);
|
||||
|
||||
ret = of_property_read_string(np, "backend-type", &backend_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
else if (!strcmp(backend_type, "raw"))
|
||||
ret = state_backend_raw_file(state, path, 0, 0);
|
||||
else if (!strcmp(backend_type, "dtb"))
|
||||
ret = state_backend_dtb_file(state, path);
|
||||
else
|
||||
dev_warn(dev, "invalid backend type: %s\n", backend_type);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
state_load(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused struct of_device_id state_ids[] = {
|
||||
{
|
||||
.compatible = "barebox,state",
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
|
||||
static struct driver_d state_driver = {
|
||||
.name = "state",
|
||||
.probe = state_probe,
|
||||
.of_compatible = DRV_OF_COMPAT(state_ids),
|
||||
};
|
||||
device_platform_driver(state_driver);
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef __STATE_H
|
||||
#define __STATE_H
|
||||
|
||||
struct state;
|
||||
|
||||
int state_backend_dtb_file(struct state *state, const char *path);
|
||||
int state_backend_raw_file(struct state *state, const char *path,
|
||||
off_t offset, size_t size);
|
||||
|
||||
struct state *state_new_from_fdt(const char *name, void *fdt);
|
||||
struct state *state_new_from_node(const char *name, struct device_node *node);
|
||||
|
||||
struct state *state_by_name(const char *name);
|
||||
struct state *state_by_node(const struct device_node *node);
|
||||
int state_get_name(const struct state *state, char const **name);
|
||||
|
||||
int state_load(struct state *state);
|
||||
int state_save(struct state *state);
|
||||
void state_info(void);
|
||||
|
||||
#endif /* __STATE_H */
|
Loading…
Reference in New Issue