diff options
Diffstat (limited to 'common/globalvar.c')
-rw-r--r-- | common/globalvar.c | 194 |
1 files changed, 149 insertions, 45 deletions
diff --git a/common/globalvar.c b/common/globalvar.c index 1bea7425d4..a83529f98f 100644 --- a/common/globalvar.c +++ b/common/globalvar.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-only + #include <common.h> #include <malloc.h> #include <globalvar.h> @@ -14,12 +16,12 @@ static int nv_dirty; -struct device_d global_device = { +struct device global_device = { .name = "global", .id = DEVICE_ID_SINGLE, }; -struct device_d nv_device = { +struct device nv_device = { .name = "nv", .id = DEVICE_ID_SINGLE, }; @@ -75,13 +77,19 @@ static int nv_save(const char *name, const char *val) if (ret) return ret; - if (once) { - pr_info("nv variable modified, will save nv variables on shutdown\n"); - once = 0; + if (IS_ENABLED(CONFIG_ENV_HANDLING)) { + if (once) { + pr_info("nv variable modified, will save nv variables on shutdown\n"); + once = 0; + } + nv_dirty = 1; + } else { + if (once) { + pr_info("nv variable modified, but won't be saved in this configuration\n"); + once = 0; + } } - nv_dirty = 1; - return 0; } @@ -93,7 +101,7 @@ static int nv_save(const char *name, const char *val) * 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) +void dev_param_init_from_nv(struct device *dev, const char *name) { char *nvname; const char *val; @@ -122,19 +130,19 @@ void dev_param_init_from_nv(struct device_d *dev, const char *name) /** * 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> + * @dev: The returned device * belonging to <dev> * @pname: the parameter name * - * Given a dev.<dev>.<param> string this function finds the device_d * belonging to + * Given a dev.<dev>.<param> string this function finds the device * 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 + * is in the device namespace and the string can be dispatched into a device * 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, +static int nvvar_device_dispatch(const char *name, struct device **dev, const char **pname) { char *devname; @@ -169,35 +177,36 @@ static int nvvar_device_dispatch(const char *name, struct device_d **dev, return 1; } -static int nv_set(struct device_d *dev, struct param_d *p, const char *val) +static int nv_set(struct device *dev, struct param_d *p, const char *name, + const char *val) { int ret; - if (!val) { - free(p->value); - return 0; + if (val) { + ret = dev_set_param(&global_device, name, val); + if (ret) + return ret; } - ret = dev_set_param(&global_device, p->name, val); - if (ret) - return ret; - - free(p->value); - p->value = xstrdup(val); + if (p) { + free(p->value); + p->value = xstrdup(val); + } return 0; } -static const char *nv_param_get(struct device_d *dev, struct param_d *p) +static const char *nv_param_get(struct device *dev, struct param_d *p) { return p->value ? p->value : ""; } -static int nv_param_set(struct device_d *dev, struct param_d *p, const char *val) +static int nv_param_set(struct device *dev, struct param_d *p, + const char *val) { int ret; - ret = nv_set(dev, p, val); + ret = nv_set(dev, p, p->name, val); if (ret) return ret; @@ -207,7 +216,7 @@ static int nv_param_set(struct device_d *dev, struct param_d *p, const char *val static int __nvvar_add(const char *name, const char *value) { struct param_d *p; - struct device_d *dev = NULL; + struct device *dev = NULL; const char *pname; int ret; @@ -228,7 +237,7 @@ static int __nvvar_add(const char *name, const char *value) return ret; if (value) - return nv_set(&nv_device, p, value); + return nv_set(&nv_device, p, name, value); ret = nvvar_device_dispatch(name, &dev, &pname); if (ret > 0) @@ -236,7 +245,7 @@ static int __nvvar_add(const char *name, const char *value) else value = dev_get_param(&global_device, name); - if (value) { + if (value && p) { free(p->value); p->value = xstrdup(value); } @@ -284,6 +293,53 @@ int nvvar_remove(const char *name) return ret; } +struct globalvar_deprecated { + char *newname; + char *oldname; + struct list_head list; +}; + +static LIST_HEAD(globalvar_deprecated_list); + +/* + * globalvar_alias_deprecated - add an alias + * + * @oldname: The old name for the variable + * @newname: The new name for the variable + * + * This function is a helper for globalvars that are renamed from one + * release to another. when a variable @oldname is found in the persistent + * environment a warning is issued and its value is written to @newname. + * + * Note that when both @oldname and @newname contain values then the values + * existing in @newname are overwritten. + */ +void globalvar_alias_deprecated(const char *oldname, const char *newname) +{ + struct globalvar_deprecated *gd; + + gd = xzalloc(sizeof(*gd)); + gd->newname = xstrdup(newname); + gd->oldname = xstrdup(oldname); + list_add_tail(&gd->list, &globalvar_deprecated_list); +} + +static const char *globalvar_new_name(const char *oldname) +{ + struct globalvar_deprecated *gd; + + list_for_each_entry(gd, &globalvar_deprecated_list, list) { + if (!strcmp(oldname, gd->oldname)) { + pr_warn("nv.%s is deprecated, converting to nv.%s\n", oldname, + gd->newname); + nv_dirty = 1; + return gd->newname; + } + } + + return oldname; +} + int nvvar_load(void) { char *val; @@ -299,6 +355,8 @@ int nvvar_load(void) return -ENOENT; while ((d = readdir(dir))) { + const char *n; + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; @@ -307,10 +365,11 @@ int nvvar_load(void) pr_debug("%s: Setting \"%s\" to \"%s\"\n", __func__, d->d_name, val); - ret = __nvvar_add(d->d_name, val); + n = globalvar_new_name(d->d_name); + ret = __nvvar_add(n, val); if (ret) pr_err("failed to create nv variable %s: %s\n", - d->d_name, strerror(-ret)); + n, strerror(-ret)); } closedir(dir); @@ -318,7 +377,7 @@ int nvvar_load(void) return 0; } -static void device_param_print(struct device_d *dev) +static void device_param_print(struct device *dev) { struct param_d *param; @@ -390,9 +449,15 @@ void globalvar_set_match(const char *match, const char *val) } } -static int globalvar_simple_set(struct device_d *dev, struct param_d *p, const char *val) +void globalvar_set(const char *name, const char *val) { - struct device_d *rdev; + dev_set_param(&global_device, name, val); +} + +static int globalvar_simple_set(struct device *dev, struct param_d *p, + const char *val) +{ + struct device *rdev; const char *pname = NULL; int ret; @@ -505,7 +570,8 @@ int globalvar_add_simple_int(const char *name, int *value, return 0; } -int globalvar_add_simple_bool(const char *name, int *value) +int globalvar_add_simple_uint64(const char *name, u64 *value, + const char *format) { struct param_d *p; int ret; @@ -514,8 +580,30 @@ int globalvar_add_simple_bool(const char *name, int *value) if (ret) return ret; - p = dev_add_param_bool(&global_device, name, NULL, NULL, - value, NULL); + p = dev_add_param_uint64(&global_device, name, NULL, NULL, + value, format, NULL); + + if (IS_ERR(p)) + return PTR_ERR(p); + + globalvar_nv_sync(name); + + return 0; +} + +int globalvar_add_bool(const char *name, + int (*set)(struct param_d *, void *), + int *value, void *priv) +{ + struct param_d *p; + int ret; + + ret = globalvar_remove_unqualified(name); + if (ret) + return ret; + + p = dev_add_param_bool(&global_device, name, set, NULL, + value, priv); if (IS_ERR(p)) return PTR_ERR(p); @@ -554,10 +642,7 @@ int globalvar_add_simple_bitmask(const char *name, unsigned long *value, p = dev_add_param_bitmask(&global_device, name, NULL, NULL, value, names, max, NULL); - if (IS_ERR(p)) - return PTR_ERR(p); - - return 0; + return PTR_ERR_OR_ZERO(p); } int globalvar_add_simple_ip(const char *name, IPaddr_t *ip) @@ -582,6 +667,8 @@ int globalvar_add_simple_ip(const char *name, IPaddr_t *ip) static int globalvar_init(void) { + const char *endianness; + register_device(&global_device); if (IS_ENABLED(CONFIG_NVVAR)) @@ -589,11 +676,27 @@ static int globalvar_init(void) globalvar_add_simple("version", UTS_RELEASE); + if (strlen(buildsystem_version_string) > 0) + globalvar_add_simple("buildsystem.version", buildsystem_version_string); + +#ifdef __BIG_ENDIAN + endianness = "big"; +#elif defined(__LITTLE_ENDIAN) + endianness = "little"; +#else +#error "could not determine byte order" +#endif + + globalvar_add_simple("endianness", endianness); + return 0; } pure_initcall(globalvar_init); -BAREBOX_MAGICVAR_NAMED(global_version, global.version, "The barebox version"); +BAREBOX_MAGICVAR(global.version, "The barebox version"); +BAREBOX_MAGICVAR(global.buildsystem.version, + "version of buildsystem barebox was built with"); +BAREBOX_MAGICVAR(global.endianness, "The barebox endianness"); /** * nvvar_save - save NV variables to persistent environment @@ -605,7 +708,7 @@ int nvvar_save(void) { struct param_d *param; const char *env = default_environment_path_get(); - int ret; + int ret = 0; #define TMPDIR "/.env.tmp" if (!nv_dirty || !env) return 0; @@ -644,8 +747,9 @@ static void nv_exit(void) } predevshutdown_exitcall(nv_exit); -static int nv_global_param_complete(struct device_d *dev, struct string_list *sl, - char *instr, int eval) +static int nv_global_param_complete(struct device *dev, + struct string_list *sl, + char *instr, int eval) { struct param_d *param; int len; @@ -666,7 +770,7 @@ static int nv_global_param_complete(struct device_d *dev, struct string_list *sl int nv_complete(struct string_list *sl, char *instr) { - struct device_d *dev; + struct device *dev; struct param_d *param; char *str; int len; |