From patchwork Thu Sep 8 08:49:28 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerlando Falauto X-Patchwork-Id: 113878 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 53375B6F70 for ; Thu, 8 Sep 2011 19:00:01 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id E2BF9281B2; Thu, 8 Sep 2011 10:59:56 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id cMEeXc2ZKVLJ; Thu, 8 Sep 2011 10:59:56 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 36AAE2819E; Thu, 8 Sep 2011 10:59:54 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 19B2D2819E for ; Thu, 8 Sep 2011 10:59:52 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1pPQmEzaQr+c for ; Thu, 8 Sep 2011 10:59:50 +0200 (CEST) X-Greylist: delayed 602 seconds by postgrey-1.27 at theia; Thu, 08 Sep 2011 10:59:49 CEST X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail.de.keymile.com (mail.de.keymile.com [195.8.104.1]) by theia.denx.de (Postfix) with SMTP id 9F1C528185 for ; Thu, 8 Sep 2011 10:59:49 +0200 (CEST) Received: from mailrelay.de.keymile.net ([10.9.1.54]) by eSafe SMTP Relay 1315305936; Thu, 08 Sep 2011 10:49:45 +0200 Received: from chber1-10555x.ch.keymile.net (chber1-10555x.ch.keymile.net [172.31.31.112]) by mailrelay.de.keymile.net (8.12.2/8.12.2) with ESMTP id p888nXjO013535; Thu, 8 Sep 2011 10:49:34 +0200 (MEST) From: Gerlando Falauto To: u-boot@lists.denx.de Date: Thu, 8 Sep 2011 10:49:28 +0200 Message-Id: <1315471768-21608-1-git-send-email-gerlando.falauto@keymile.com> X-Mailer: git-send-email 1.7.1 MIME-Version: 1.0 X-ESAFE-STATUS: [srvhellgate.de.keymile.net] Mail clean Cc: Holger Brunck , Gerlando Falauto Subject: [U-Boot] [PATCH RFC] env: add command to set individual variables to default X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Here I am proposing an implementation for setting individual variables to their default values as outlined in http://www.denx.de/wiki/U-Boot/TaskSetEnvironmentDefaults For instance, to reset defautl values for variables bootcmd and bootdelay: => env default bootcmd bootdelay There are a few issues which are not fully covered. [In braces I put the behavior of this patch]. 1) Previous implementation of “env default” only worked for the whole environment, and “-f” was necessary in order to prevent the unexperienced user from messing up the environment by just typing command names. Should this behavior be kept? [Yes] 2) When a variable is not defined in the default environment, should it get deleted (if existing)? [Yes] Should a warning be issued? [No] What if it is neither defined in the current nor in the default env? 3) Should it be possible to disable this feature (i.e. to save space)? [No] Any suggestions for a meaningful configuration token? I was thinking of CONFIG_RESTORE_INDIVIDUAL_ENV_VARS. 4) This implementation comes mostly from himport_r(). It crossed my mind that it might also be useful to *import* individual variables from a file (rather that the default env). For instance: env import [flags] addr size vars... Would only import variables "vars" and ignore all others. With this idea in mind I kept all himport_r()'s support for external files (i.e., comments, separator other than '\0', quoting). If no one else envisions any use for such import commands, the code could obviously be much smaller and simpler. Signed-off-by: Gerlando Falauto Signed-off-by: Holger Brunck cc: Wolfgang Denk --- common/cmd_nvedit.c | 12 +++++- common/env_common.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++ include/environment.h | 3 + 3 files changed, 119 insertions(+), 2 deletions(-) diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index b2c88ba..9822785 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -580,10 +580,17 @@ int envmatch(uchar *s1, int i2) static int do_env_default(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - if ((argc != 2) || (strcmp(argv[1], "-f") != 0)) + /* Check that we have at least one argument */ + if (argc < 2) { return cmd_usage(cmdtp); + } else if ((argc == 2) && (strcmp(argv[1], "-f")) == 0) { + /* Reset the whole environment */ + set_default_env("## Resetting to default environment\n"); + return 0; + } - set_default_env("## Resetting to default environment\n"); + /* Reset individual variables */ + env_default_vars(argc-1, argv+1); return 0; } @@ -910,6 +917,7 @@ U_BOOT_CMD( "ask name [message] [size] - ask for environment variable\nenv " #endif "default -f - reset default environment\n" + "env default name [...] - reset variable(s) to their default value\n" #if defined(CONFIG_CMD_EDITENV) "env edit name - edit environment variable\n" #endif diff --git a/common/env_common.c b/common/env_common.c index c3e6388..b2d68f8 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -197,6 +197,112 @@ void set_default_env(const char *s) } /* + * import individual variables from an external environment + * (e.g. default environment). + * Most of this code comes straight from himport_r(). + */ +static int env_import_vars(const char *env, const size_t size, const char sep, + int nvars, char * const vars[]) +{ + char *data, *sp, *dp, *name, *value, *thisvalue; + int i; + + /* we allocate new space to make sure we can write to the array */ + data = malloc(size); + if (data == NULL) { + debug("env_default_vars: can't malloc %d bytes\n", size); + __set_errno(ENOMEM); + return 0; + } + + /* Loop through all passed variables */ + for (i = 0; i < nvars; i++) { + debug("looking for a default value for %s\n", vars[i]); + + memcpy(data, env, size); + dp = data; + + /* + * Unless proven otherwise, this variable + * does not exist in the default env + */ + thisvalue = ""; + /* Parse environment; allow for '\0' and 'sep' as separators */ + do { + /* skip leading white space */ + while ((*dp == ' ') || (*dp == '\t')) + ++dp; + + /* skip comment lines */ + if (*dp == '#') { + while (*dp && (*dp != sep)) + ++dp; + ++dp; + continue; + } + + /* parse name */ + for (name = dp; *dp != '=' && *dp && *dp != sep; ++dp) + ; + + /* deal with "name" and "name=" entries (delete var) */ + if (*dp == '\0' || *(dp + 1) == '\0' || + *dp == sep || *(dp + 1) == sep) { + if (*dp == '=') + *dp++ = '\0'; + *dp++ = '\0'; /* terminate name */ + + /* default is none */ + value = ""; + } else { + *dp++ = '\0'; /* terminate name */ + value = dp; /* value starts here */ + /* parse value; deal with escapes */ + for (sp = dp; *dp && (*dp != sep); ++dp) { + if ((*dp == '\\') && *(dp + 1)) + ++dp; + *sp++ = *dp; + } + *sp++ = '\0'; /* terminate value */ + } + + if (strcmp(name, vars[i]) == 0) { + debug("found variable: %s\n" + "default value: %s\n", name, value); + thisvalue = value; + /* exit from loop parsing the default env */ + break; + } + ++dp; + + } while ((dp < data + size) && *dp); + /* + * size check needed for text without '\0' termination + * (e.g. default environment) + */ + + debug("setting default value: %s=%s\n", vars[i], thisvalue); + setenv(vars[i], thisvalue); + } /* for-loop over i */ + + debug("env_default_vars: free(data = %p)\n", data); + free(data); + debug("env_default_vars: done\n"); + return 1; /* everything OK */ + +} + +/* [re]set individual variables to their value in the default environment */ +int env_default_vars(int nvars, char * const vars[]) +{ + /* Special use-case: import from default environment + (and use \0 as a separator) */ + return env_import_vars((const char *)default_environment, + sizeof(default_environment), '\0', + nvars, vars); +} + +/* * Check if CRC is valid and (if yes) import the environment. * Note that "buf" may or may not be aligned. */ diff --git a/include/environment.h b/include/environment.h index 53d92df..2c4d905 100644 --- a/include/environment.h +++ b/include/environment.h @@ -169,6 +169,9 @@ void env_crc_update (void); /* [re]set to the default environment */ void set_default_env(const char *s); +/* [re]set individual variables to their value in the default environment */ +int env_default_vars(int nvars, char * const vars[]); + /* Import from binary representation into hash table */ int env_import(const char *buf, int check);