summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2016-07-11 07:58:34 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2016-07-11 07:58:34 +0200
commit202cda9475558213cf799206caf0130d45164d7f (patch)
treeabe9c88fbf8336e9c89aa22cd1b7ad8cfbf23ed1 /common
parentbb73cb9427cdef4bb3a45ccfa10e30a50940ff09 (diff)
parent699b4f80254de45a6ff45dff0a863e457dea7d89 (diff)
downloadbarebox-202cda9475558213cf799206caf0130d45164d7f.tar.gz
barebox-202cda9475558213cf799206caf0130d45164d7f.tar.xz
Merge branch 'for-next/nvdevvars'
Diffstat (limited to 'common')
-rw-r--r--common/globalvar.c151
1 files changed, 127 insertions, 24 deletions
diff --git a/common/globalvar.c b/common/globalvar.c
index 75e4d43afb..c0958e11ea 100644
--- a/common/globalvar.c
+++ b/common/globalvar.c
@@ -68,22 +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)
{
- struct param_d *gp;
int ret;
+ int devspace;
+ struct device_d *rdev;
+ const char *pname;
if (!val)
val = "";
- gp = get_param_by_name(&global_device, p->name);
- if (!gp)
- return -EINVAL;
-
- ret = gp->set(&global_device, gp, 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);
@@ -99,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)
@@ -116,27 +220,26 @@ 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) {
- ret = dev_set_param(&global_device, name, value);
- if (ret)
- return ret;
- } else {
- value = dev_get_param(&global_device, name);
- if (!value)
- value = "";
+ if (!value) {
+ if (devspace) {
+ if (dev)
+ value = dev_get_param(dev, pname);
+ } else {
+ value = dev_get_param(&global_device, name);
+ }
}
- p->value = xstrdup(value);
-
- return nv_save(p->name, value);
+ return nv_set(&nv_device, p, value);
}
int nvvar_remove(const char *name)