mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* Introduce non volatile device variables
@ 2016-07-06  8:20 Sascha Hauer
  2016-07-06  8:20 ` [PATCH 1/3] nvvar: Simplify by using nv_set() Sascha Hauer
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Sascha Hauer @ 2016-07-06  8:20 UTC (permalink / raw)
  To: Barebox List

So far we have non volatile (nv) variables which keep their values
over reboots. This series extends the concept to device
parameters. This can be used to configure devices and to preserve
the configuration over reboots. The non volatile device variables
are implemented as regular nv variables with a special namespace.
Every nv variable with the form "nv.dev.<devname>.<paramname>"
acts on the parameter <paramname> of the device named <devname>.

With this for example mtd partitioning can be stored:

 nv dev.nand0.partitions=4M(barebox),-(root)

Or videomodes:

 nv dev.fb0.mode="1280x1024"

It's planned to also replace the current network settings in /env/network/*
with this mechanism, but additional patches are necessary to make
dhcp work.

This is another step to make scripts in barebox simpler and sometimes
unnecessary.

Sascha

----------------------------------------------------------------
Sascha Hauer (3):
      nvvar: Simplify by using nv_set()
      nvvar: Simplify by using dev_set_param()
      Introduce non volatile device variables

 Documentation/user/variables.rst |  18 +++++
 common/globalvar.c               | 151 ++++++++++++++++++++++++++++++++-------
 include/globalvar.h              |   6 ++
 lib/parameter.c                  |   3 +
 4 files changed, 154 insertions(+), 24 deletions(-)

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

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

* [PATCH 1/3] nvvar: Simplify by using nv_set()
  2016-07-06  8:20 Introduce non volatile device variables Sascha Hauer
@ 2016-07-06  8:20 ` Sascha Hauer
  2016-07-06  8:20 ` [PATCH 2/3] nvvar: Simplify by using dev_set_param() Sascha Hauer
  2016-07-06  8:20 ` [PATCH 3/3] Introduce non volatile device variables Sascha Hauer
  2 siblings, 0 replies; 4+ messages in thread
From: Sascha Hauer @ 2016-07-06  8:20 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/globalvar.c | 13 ++-----------
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/common/globalvar.c b/common/globalvar.c
index 75e4d43..decd73c 100644
--- a/common/globalvar.c
+++ b/common/globalvar.c
@@ -124,19 +124,10 @@ int nvvar_add(const char *name, const char *value)
 	if (IS_ERR(p))
 		return PTR_ERR(p);
 
-	if (value) {
-		ret = dev_set_param(&global_device, name, value);
-		if (ret)
-			return ret;
-	} else {
+	if (!value)
 		value = dev_get_param(&global_device, name);
-		if (!value)
-			value = "";
-	}
-
-	p->value = xstrdup(value);
 
-	return nv_save(p->name, value);
+	return nv_set(&nv_device, p, value);
 }
 
 int nvvar_remove(const char *name)
-- 
2.8.1


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

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

* [PATCH 2/3] nvvar: Simplify by using dev_set_param()
  2016-07-06  8:20 Introduce non volatile device variables Sascha Hauer
  2016-07-06  8:20 ` [PATCH 1/3] nvvar: Simplify by using nv_set() Sascha Hauer
@ 2016-07-06  8:20 ` Sascha Hauer
  2016-07-06  8:20 ` [PATCH 3/3] Introduce non volatile device variables Sascha Hauer
  2 siblings, 0 replies; 4+ messages in thread
From: Sascha Hauer @ 2016-07-06  8:20 UTC (permalink / raw)
  To: Barebox List

The combination of get_param_by_name()/param->set() can be replaced
by using dev_set_param()

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/globalvar.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/common/globalvar.c b/common/globalvar.c
index decd73c..6687b03 100644
--- a/common/globalvar.c
+++ b/common/globalvar.c
@@ -70,17 +70,12 @@ static int nv_save(const char *name, const char *val)
 
 static int nv_set(struct device_d *dev, struct param_d *p, const char *val)
 {
-	struct param_d *gp;
 	int ret;
 
 	if (!val)
 		val = "";
 
-	gp = get_param_by_name(&global_device, p->name);
-	if (!gp)
-		return -EINVAL;
-
-	ret = gp->set(&global_device, gp, val);
+	ret = dev_set_param(&global_device, p->name, val);
 	if (ret)
 		return ret;
 
-- 
2.8.1


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

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

* [PATCH 3/3] Introduce non volatile device variables
  2016-07-06  8:20 Introduce non volatile device variables Sascha Hauer
  2016-07-06  8:20 ` [PATCH 1/3] nvvar: Simplify by using nv_set() Sascha Hauer
  2016-07-06  8:20 ` [PATCH 2/3] nvvar: Simplify by using dev_set_param() Sascha Hauer
@ 2016-07-06  8:20 ` Sascha Hauer
  2 siblings, 0 replies; 4+ messages in thread
From: Sascha Hauer @ 2016-07-06  8:20 UTC (permalink / raw)
  To: Barebox List

Non volatile device variables are used to make device parameters
persistent. They are like normal non volatile variables, but set
the values of the device parameters with the corresponding name.
Every nv variable beginning with nv.dev is a non volatile device
variable. They have the form nv.dev.<devname>.<paramname> and act
on the parameter <paramname> of the device named <devname>.

The non volatile device variables are designated for example for
video modes, ethernet device ip addresses or mtd partitioning.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 Documentation/user/variables.rst |  18 +++++
 common/globalvar.c               | 137 ++++++++++++++++++++++++++++++++++++---
 include/globalvar.h              |   6 ++
 lib/parameter.c                  |   3 +
 4 files changed, 154 insertions(+), 10 deletions(-)

diff --git a/Documentation/user/variables.rst b/Documentation/user/variables.rst
index 0abc25d..89aadf5 100644
--- a/Documentation/user/variables.rst
+++ b/Documentation/user/variables.rst
@@ -66,6 +66,24 @@ examples:
     model: myboard
   barebox@yourboard:/
 
+Non volatile device variables
+-----------------------------
+
+Non volatile device variables are used to make device parameters persistent. They
+are regular nv variables but are linked with other devices instead of the global
+device. Every nv variable in the form nv.dev.<devname>.<paramname> will be mirrored
+to the corresponding <devname>.<paramname> variable.
+
+This example changes the partitioning of the nand0 device:
+
+.. code-block:: sh
+  barebox@Phytec phyCARD-i.MX27:/ nv dev.nand0.partitions: 4M(barebox),1M(barebox-environment),-(root)
+  barebox@Phytec phyCARD-i.MX27:/ devinfo nand0
+    Parameters:
+    [...]
+    partitions: 4M(barebox),1M(barebox-environment),8M(kernel),1011M(root)
+    [...]
+
 .. _magicvars:
 
 Magic variables
diff --git a/common/globalvar.c b/common/globalvar.c
index 6687b03..c0958e1 100644
--- a/common/globalvar.c
+++ b/common/globalvar.c
@@ -68,17 +68,115 @@ static int nv_save(const char *name, const char *val)
 	return 0;
 }
 
+/**
+ * dev_param_init_from_nv - initialize a device parameter from nv variable
+ * @dev: The device
+ * @name: The parameter name
+ *
+ * This function initializes a newly created device parameter from the corresponding
+ * nv.dev.<devname>.<paramname> variable.
+ */
+void dev_param_init_from_nv(struct device_d *dev, const char *name)
+{
+	char *nvname;
+	const char *val;
+	int ret = 0;
+
+	if (dev == &nv_device)
+		return;
+	if (dev == &global_device)
+		return;
+
+	nvname = basprintf("dev.%s.%s", dev_name(dev), name);
+	val = dev_get_param(&nv_device, nvname);
+	if (val) {
+		ret = dev_set_param(dev, name, val);
+		if (ret)
+			pr_err("Cannot init param from nv: %s.%s=%s: %s\n",
+				dev_name(dev), name, val, strerror(-ret));
+	}
+
+	free(nvname);
+}
+
+/**
+ * nvvar_device_dispatch - dispatch dev.<dev>.<param> name into device and parameter name
+ * @name: The incoming name in the form dev.<dev>.<param>
+ * @dev: The returned device_d * belonging to <dev>
+ * @pname: the parameter name
+ *
+ * Given a dev.<dev>.<param> string this function finds the device_d * belonging to
+ * <dev> and the parameter name from <param>.
+ *
+ * Return: When incoming string does not belong to the device namespace (does not begin
+ * with "dev." this function returns 0. A value > 0 is returned when the incoming string
+ * is in the device namespace and the string can be dispatched into a device_d * and a
+ * parameter name. A negative error code is returned when the incoming string belongs to
+ * the device namespace, but cannot be dispatched.
+ */
+static int nvvar_device_dispatch(const char *name, struct device_d **dev,
+				 const char **pname)
+{
+	char *devname;
+	const char *dot;
+	int dotpos;
+
+	*dev = NULL;
+
+	if (strncmp(name, "dev.", 4))
+		return 0;
+
+	name += 4;
+
+	dot = strchr(name, '.');
+	if (!dot)
+		return -EINVAL;
+
+	dotpos = dot - name;
+
+	devname = xstrndup(name, dotpos);
+	*dev = get_device_by_name(devname);
+	free(devname);
+
+	if (*dev == &nv_device || *dev == &global_device)
+		return -EINVAL;
+
+	*pname = dot + 1;
+
+	return 1;
+}
+
 static int nv_set(struct device_d *dev, struct param_d *p, const char *val)
 {
 	int ret;
+	int devspace;
+	struct device_d *rdev;
+	const char *pname;
 
 	if (!val)
 		val = "";
 
-	ret = dev_set_param(&global_device, p->name, val);
-	if (ret)
+	ret = nvvar_device_dispatch(p->name, &rdev, &pname);
+	if (ret < 0)
 		return ret;
 
+	devspace = ret;
+
+	if (devspace) {
+		if (rdev) {
+			ret = dev_set_param(rdev, pname, val);
+			if (ret) {
+				pr_err("Cannot init param from nv: %s.%s=%s: %s\n",
+					dev_name(rdev), pname, val, strerror(-ret));
+				return ret;
+			}
+		}
+	} else {
+		ret = dev_set_param(&global_device, p->name, val);
+		if (ret)
+			return ret;
+	}
+
 	free(p->value);
 	p->value = xstrdup(val);
 
@@ -94,15 +192,26 @@ int nvvar_add(const char *name, const char *value)
 {
 	struct param_d *p, *gp;
 	int ret;
+	int devspace;
+	struct device_d *dev;
+	const char *pname;
 
 	if (!IS_ENABLED(CONFIG_NVVAR))
 		return -ENOSYS;
 
+	ret = nvvar_device_dispatch(name, &dev, &pname);
+	if (ret < 0)
+		return ret;
+
+	devspace = ret;
+
 	gp = get_param_by_name(&nv_device, name);
 	if (gp) {
-		ret = dev_set_param(&global_device, name, value);
-		if (ret)
-			return ret;
+		if (!devspace) {
+			ret = dev_set_param(&global_device, name, value);
+			if (ret)
+				return ret;
+		}
 
 		ret = dev_set_param(&nv_device, name, value);
 		if (ret)
@@ -111,16 +220,24 @@ int nvvar_add(const char *name, const char *value)
 		return 0;
 	}
 
-	ret = globalvar_add_simple(name, value);
-	if (ret && ret != -EEXIST)
-		return ret;
+	if (!devspace) {
+		ret = globalvar_add_simple(name, value);
+		if (ret && ret != -EEXIST)
+			return ret;
+	}
 
 	p = dev_add_param(&nv_device, name, nv_set, nv_get, 0);
 	if (IS_ERR(p))
 		return PTR_ERR(p);
 
-	if (!value)
-		value = dev_get_param(&global_device, name);
+	if (!value) {
+		if (devspace) {
+			if (dev)
+				value = dev_get_param(dev, pname);
+		} else {
+			value = dev_get_param(&global_device, name);
+		}
+	}
 
 	return nv_set(&nv_device, p, value);
 }
diff --git a/include/globalvar.h b/include/globalvar.h
index 5dfa371..67b97de 100644
--- a/include/globalvar.h
+++ b/include/globalvar.h
@@ -94,6 +94,8 @@ int nvvar_add(const char *name, const char *value);
 int nvvar_remove(const char *name);
 void globalvar_print(void);
 
+void dev_param_init_from_nv(struct device_d *dev, const char *name);
+
 #else
 static inline int globalvar_add_simple(const char *name, const char *value)
 {
@@ -165,6 +167,10 @@ static inline int nvvar_remove(const char *name)
 	return 0;
 }
 
+static inline void dev_param_init_from_nv(struct device_d *dev, const char *name)
+{
+}
+
 #endif
 
 #endif /* __GLOBALVAR_H */
diff --git a/lib/parameter.c b/lib/parameter.c
index 3d356fb..656a603 100644
--- a/lib/parameter.c
+++ b/lib/parameter.c
@@ -28,6 +28,7 @@
 #include <malloc.h>
 #include <driver.h>
 #include <string.h>
+#include <globalvar.h>
 #include <linux/err.h>
 
 struct param_d *get_param_by_name(struct device_d *dev, const char *name)
@@ -156,6 +157,8 @@ static int __dev_add_param(struct param_d *param, struct device_d *dev, const ch
 	param->dev = dev;
 	list_add_sort(&param->list, &dev->parameters, compare);
 
+	dev_param_init_from_nv(dev, name);
+
 	return 0;
 }
 
-- 
2.8.1


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

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

end of thread, other threads:[~2016-07-06  8:20 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-06  8:20 Introduce non volatile device variables Sascha Hauer
2016-07-06  8:20 ` [PATCH 1/3] nvvar: Simplify by using nv_set() Sascha Hauer
2016-07-06  8:20 ` [PATCH 2/3] nvvar: Simplify by using dev_set_param() Sascha Hauer
2016-07-06  8:20 ` [PATCH 3/3] Introduce non volatile device variables Sascha Hauer

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