This patch groups environment variables using a non-invasive protocol. Grouping is achieved by setting a "grouping" variable to a string of variables, and setting the master grouping variable, "env_groups" to the list of these grouping variables.
For instance, setenv net ipaddr netmask gatewayip serverip setenv boot bootcmd bootdelay bootargs setenv env_groups net boot would print 4 variables grouped under net, 3 variables grouped under boot, and the rest of the variables grouped under "other". If env_groups is not defined, print behaves normally. Signed-off-by: John Schmoller <jschmol...@xes-inc.com> --- I'm interesetd in seeing peoples opinions of this implementation of grouping environment variables. My major concerns about this implementation are 1) Using parse_line() requires placing several potentially large char array (CONFIG_SYS_CBSIZE in size) on the stack. Parse_line() does seem to be the right tool for the job, though. 2) Trying to figure out which enviroment variables have already been printed in groups is less than elegant. Currently, it's a brute-force approach of looking through every entry until a variable is found in a group or not. Suggestions for cleaner algorithms here would be appreciated. Implementation notes: If env_groups is defined, none of the grouping variables will be printed. This seemed to clutter up the printenv output. Grouping environment variables will almost certainly lead to a reqirement for bumping up CONFIG_SYS_MAXARGS. Example output: => printenv === pci variables === pci1inboundmembus=0x00000000 pci1inboundmemphys=0x00000000 pci1inboundmemsize=0x08000000 pci1outboundmembus=0x80000000 pci1outboundmemphys=0x80000000 pci1outboundmemsize=0x40000000 pci1outboundiobus=0x00000000 pci1outboundiophys=0xe8000000 pci1outboundiosize=0x00800000 pci2outboundmembus=0xc0000000 pci2outboundmemphys=0xc0000000 pci2outboundmemsize=0x10000000 === boot variables === bootcmd_flash1=run set_bootargs; bootm 0xfef00000 - 0xfff00000 bootcmd_flash2=run set_bootargs; bootm 0xf6f00000 - 0xf7f00000 bootcmd=tftp 10000000 home/jschmoller/vxWorks.st;bootvx bootdelay=3 bootfile=/home/shared/pxe/pxelinux.0 bootcmd_net=run set_bootargs; $download_cmd $osaddr $osfile; if test $? -eq 0; then if test -n $fdtaddr; then $download_cmd $fdtaddr $fdtfile; if test $? -eq 0; then bootm $osaddr - $fdtaddr; else; echo FDT DOWNLOAD FAILED; fi; else; bootm $osaddr; fi; else; echo OS DOWNLOAD FAILED; fi; === prog variables === prog_uboot1=$download_cmd $loadaddr $ubootfile; if test $? -eq 0; then protect off 0xfff80000 +80000; erase 0xfff80000 +80000; cp.w $loadaddr 0xfff80000 40000; protect on 0xfff80000 +80000; cmp.b $loadaddr 0xfff80000 80000; if test $? -ne 0; then echo PROGRAM FAILED; else; echo PROGRAM SUCCEEDED; fi; else; echo DOWNLOAD FAILED; fi; prog_uboot2=$download_cmd $loadaddr $ubootfile; if test $? -eq 0; then protect off 0xf7f80000 +80000; erase 0xf7f80000 +80000; cp.w $loadaddr 0xf7f80000 40000; protect on 0xf7f80000 +80000; cmp.b $loadaddr 0xf7f80000 80000; if test $? -ne 0; then echo PROGRAM FAILED; else; echo PROGRAM SUCCEEDED; fi; else; echo DOWNLOAD FAILED; fi; ubootfile=home/jschmoller/u-boot.bin prog_os1=$download_cmd $osaddr $osfile; if test $? -eq 0; then erase 0xfef00000 +$filesize; cp.b $osaddr 0xfef00000 $filesize; cmp.b $osaddr 0xfef00000 $filesize; if test $? -ne 0; then echo OS PROGRAM FAILED; else; echo OS PROGRAM SUCCEEDED; fi; else; echo OS DOWNLOAD FAILED; fi; prog_os2=$download_cmd $osaddr $osfile; if test $? -eq 0; then erase 0xf6f00000 +$filesize; cp.b $osaddr 0xf6f00000 $filesize; cmp.b $osaddr 0xf6f00000 $filesize; if test $? -ne 0; then echo OS PROGRAM FAILED; else; echo OS PROGRAM SUCCEEDED; fi; else; echo OS DOWNLOAD FAILED; fi; osfile=/home/user/board.uImage osaddr=0x1000000 prog_fdt1=$download_cmd $fdtaddr $fdtfile; if test $? -eq 0; then erase 0xfff00000 +$filesize;cp.b $fdtaddr 0xfff00000 $filesize; cmp.b $fdtaddr 0xfff00000 $filesize; if test $? -ne 0; then echo FDT PROGRAM FAILED; else; echo FDT PROGRAM SUCCEEDED; fi; else; echo FDT DOWNLOAD FAILED; fi; prog_fdt2=$download_cmd $fdtaddr $fdtfile; if test $? -eq 0; then erase 0xf7f00000 +$filesize;cp.b $fdtaddr 0xf7f00000 $filesize; cmp.b $fdtaddr 0xf7f00000 $filesize; if test $? -ne 0; then echo FDT PROGRAM FAILED; else; echo FDT PROGRAM SUCCEEDED; fi; else; echo FDT DOWNLOAD FAILED; fi; fdtfile=/home/user/board.dtb fdtaddr=c00000 === net variables === ## Error: "ipaddr" not defined netmask=255.255.0.0 serverip=10.52.0.33 gatewayip=10.52.0.1 ethaddr=00:17:3c:00:5f:30 ethact=eTSEC1 === board variables === serial#=02091009 board_cfg=90030065B-1 board_rev=SB === junk variables === ## Error: group "junk" not defined === other variables === baudrate=115200 loads_echo=1 preboot= autoload=yes download_cmd=tftp console_args=console=ttyS0,115200 root_args=root=/dev/nfs rw misc_args=ip=on set_bootargs=setenv bootargs ${console_args} ${root_args} ${misc_args} loadaddr=0x1000000 pci2outboundiobus=0x00000000 pci2outboundiophys=0xe8800000 pci2outboundiosize=0x00800000 eth1addr=00:17:3c:00:5f:31 dnsip=10.52.0.1 skip_nand_bbt=yes pcidelay=1000 loadaddr=100000 bootargs=motetsec(0,0)host:/home/mstarzewski/xes8572-vxWorks.st h=10.52.0.33 e=10.52.143.154:ffff0000 u=drives pw=drives f=0x0 filesize=869D2 fileaddr=10000000 stdin=serial stdout=serial stderr=serial Environment size: 4148/32764 bytes => common/cmd_nvedit.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 110 insertions(+), 10 deletions(-) diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index eb89e9e..6420e17 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -71,6 +71,54 @@ SPI_FLASH|MG_DISK|NVRAM|NOWHERE} #define XMK_STR(x) #x #define MK_STR(x) XMK_STR(x) +enum { + PRINTENV_STATE_MATCHED = 0, + PRINTENV_STATE_ALL, + PRINTENV_STATE_SEARCH, + PRINTENV_STATE_GROUP +}; + +static int env_in_group(char *env) +{ + char *s; + char group_buf[CONFIG_SYS_CBSIZE]; + char *group_argv[CONFIG_SYS_MAXARGS + 1]; + int group_argc; + char env_buf[CONFIG_SYS_CBSIZE]; + char *env_argv[CONFIG_SYS_MAXARGS + 1]; + int env_argc; + int i, j; + + if (strcmp("env_groups", env) == 0) + return 1; + + if ((s = getenv("env_groups")) == NULL) + return 0; + + strcpy(group_buf, s); + group_argc = parse_line(group_buf, group_argv); + + /* Spin through all group variables specified in "env_groups" */ + for (i = 0; i < group_argc; i++) { + if ((s = getenv(group_argv[i])) == NULL) + continue; + + if (strcmp(group_argv[i], env) == 0) + return 1; + + strcpy(env_buf, s); + env_argc = parse_line(env_buf, env_argv); + + /* Spin through all vars contained in each group variable */ + for (j = 0; j < env_argc; j++) { + if (strcmp(env_argv[j], env) == 0) + return 1; + } + } + + return 0; +} + /************************************************************************ ************************************************************************/ @@ -101,30 +149,48 @@ int get_env_id (void) * state 0: finish printing this string and return (matched!) * state 1: no matching to be done; print everything * state 2: continue searching for matched name + * state 3: print all only if not found in a group */ static int printenv(char *name, int state) { - int i, j; - char c, buf[17]; + int i, j, prev_state, size; + char c, buf[17], *str, *addr; i = 0; buf[16] = '\0'; + prev_state = state; while (state && env_get_char(i) != '\0') { - if (state == 2 && envmatch((uchar *)name, i) >= 0) - state = 0; + if (state == PRINTENV_STATE_SEARCH && + envmatch((uchar *)name, i) >= 0) + state = PRINTENV_STATE_MATCHED; + + if (prev_state == PRINTENV_STATE_GROUP) { + addr = (char *)env_get_addr(i); + size = strchr(addr, '=') - addr; + str = malloc((size + 1) * sizeof(char)); + strncpy(str, addr, size); + str[size] = '\0'; + + if (env_in_group(str)) + state = PRINTENV_STATE_SEARCH; + else + state = PRINTENV_STATE_ALL; + + free(str); + } j = 0; do { buf[j++] = c = env_get_char(i++); if (j == sizeof(buf) - 1) { - if (state <= 1) + if (state != PRINTENV_STATE_SEARCH) puts(buf); j = 0; } } while (c != '\0'); - if (state <= 1) { + if (state != PRINTENV_STATE_SEARCH) { if (j) puts(buf); putc('\n'); @@ -134,7 +200,7 @@ static int printenv(char *name, int state) return -1; } - if (state == 0) + if (state == PRINTENV_STATE_MATCHED) i = 0; return i; } @@ -143,10 +209,44 @@ int do_printenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { int i; int rcode = 0; + char *s; + char group_buf[CONFIG_SYS_CBSIZE]; + char *group_argv[CONFIG_SYS_MAXARGS + 1]; + int group_argc; + char env_buf[CONFIG_SYS_CBSIZE]; + char *env_argv[CONFIG_SYS_MAXARGS + 1]; + int env_argc; if (argc == 1) { - /* print all env vars */ - rcode = printenv(NULL, 1); + if ((s = getenv("env_groups")) == NULL) { + /* print all env vars */ + rcode = printenv(NULL, PRINTENV_STATE_ALL); + } else { + /* print all env vars, but group them */ + strcpy(group_buf, s); + group_argc = parse_line(group_buf, group_argv); + + /* Cycle through all the groups in env_groups */ + for (i = 0; i < group_argc; i++) { + printf("=== %s variables ===\n", group_argv[i]); + if ((s = getenv(group_argv[i])) == NULL) { + printf("## Error: group \"%s", + group_argv[i]); + printf("\" not defined\n\n"); + continue; + } + + /* Recursively call printenv for each group */ + sprintf(env_buf, "printenv %s", s); + env_argc = parse_line(env_buf, env_argv); + do_printenv(cmdtp, flag, env_argc, env_argv); + putc('\n'); + } + + puts("=== other variables ===\n"); + rcode = printenv(NULL, PRINTENV_STATE_GROUP); + } + if (rcode < 0) return 1; printf("\nEnvironment size: %d/%ld bytes\n", @@ -157,7 +257,7 @@ int do_printenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) /* print selected env vars */ for (i = 1; i < argc; ++i) { char *name = argv[i]; - if (printenv(name, 2)) { + if (printenv(name, PRINTENV_STATE_SEARCH)) { printf("## Error: \"%s\" not defined\n", name); ++rcode; } -- 1.6.0.4 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot