diff options
-rw-r--r-- | Documentation/user/variables.rst | 18 | ||||
-rw-r--r-- | common/globalvar.c | 137 | ||||
-rw-r--r-- | include/globalvar.h | 6 | ||||
-rw-r--r-- | lib/parameter.c | 3 |
4 files changed, 154 insertions, 10 deletions
diff --git a/Documentation/user/variables.rst b/Documentation/user/variables.rst index 0abc25d98a..89aadf58fd 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 6687b03bf0..c0958e11ea 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 5dfa371409..67b97de486 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 3d356fb972..656a6037c6 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(¶m->list, &dev->parameters, compare); + dev_param_init_from_nv(dev, name); + return 0; } |