From 9d0477f48864bc7ec1f9e3e320079d226232f167 Mon Sep 17 00:00:00 2001 From: Piotr Dymacz Date: Wed, 31 Aug 2016 18:29:27 +0200 Subject: [PATCH] Backport setexpr command, enable it by default, cleanup cmd_itest.c --- u-boot/common/cmd_itest.c | 247 +++++++++++++++++++------- u-boot/include/configs/qca9k_common.h | 1 + 2 files changed, 183 insertions(+), 65 deletions(-) diff --git a/u-boot/common/cmd_itest.c b/u-boot/common/cmd_itest.c index 805cf12..75148d4 100644 --- a/u-boot/common/cmd_itest.c +++ b/u-boot/common/cmd_itest.c @@ -32,6 +32,124 @@ #include #include +#if defined(CONFIG_CMD_ITEST) ||\ + defined(CONFIG_CMD_SETEXPR) + +extern int cmd_get_data_size(char* arg, int default_size); + +static ulong evalexp(char *s, int w) +{ + ulong *p; + ulong l = 0; + + /* + * If the parameter starts with a * then + * assume is a pointer to the value we want + */ + if (s[0] == '*') { + p = (ulong *)simple_strtoul(&s[1], NULL, 16); + l = *p; + } else { + l = simple_strtoul(s, NULL, 16); + } + + if (w < 4) + return l & ((1 << (w * 8)) - 1); + else + return l; +} +#endif /* CONFIG_CMD_ITEST || CONFIG_CMD_SETEXPR */ + +#if defined(CONFIG_CMD_SETEXPR) +int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong a, b, value; + char buf[16]; + int w; + + /* + * We take 3, 5, or 6 arguments: + * 3 : setexpr name value + * 5 : setexpr name val1 op val2 + * setexpr name [g]sub r s + * 6 : setexpr name [g]sub r s t + */ + + /* > 6 already tested by max command args */ + if ((argc < 3) || (argc == 4)) { + print_cmd_help(cmdtp); + return 1; + } + + w = cmd_get_data_size(argv[0], 4); + + a = evalexp(argv[2], w); + + /* Plain assignment: "setexpr name value" */ + if (argc == 3) { + sprintf(buf, "%X", a); + setenv(argv[1], buf); + return 0; + } + + /* Standard operators: "setexpr name val1 op val2" */ + if (argc != 5) { + print_cmd_help(cmdtp); + return 1; + } + + if (strlen(argv[3]) != 1) { + print_cmd_help(cmdtp); + return 1; + } + + b = evalexp(argv[4], w); + + switch (argv[3][0]) { + case '|': + value = a | b; + break; + case '&': + value = a & b; + break; + case '+': + value = a + b; + break; + case '^': + value = a ^ b; + break; + case '-': + value = a - b; + break; + case '*': + value = a * b; + break; + case '/': + value = a / b; + break; + case '%': + value = a % b; + break; + default: + printf("## Error: invalid op\n"); + return 1; + } + + sprintf(buf, "%X", value); + setenv(argv[1], buf); + + return 0; +} + +U_BOOT_CMD(setexpr, 6, 0, do_setexpr, "set env variable as the result of eval expr\n", + "[.b, .w, .l] name [*]val1 [*]val2\n" + "\t- set env variable 'name' to the result of the evaluated\n" + "\t expr specified by (can be &, |, ^, +, -, *, /, %)\n" + "\t size argument is only meaningful if val1 and/or val2 are memory addresses (*)\n" + "setexpr[.b, .w, .l] name [*]val\n" + "\t- load a 'val' into 'name' variable"); +#endif /* CONFIG_CMD_SETEXPR */ + #if defined(CONFIG_CMD_ITEST) #define EQ 0 @@ -42,8 +160,8 @@ #define GE 5 struct op_tbl_s { - char *op; /* operator string */ - int opcode; /* internal representation of opcode */ + char *op; /* Operator string */ + int opcode; /* Internal representation of opcode */ }; typedef struct op_tbl_s op_tbl_t; @@ -66,35 +184,17 @@ op_tbl_t op_table [] = { #define op_tbl_size (sizeof(op_table)/sizeof(op_table[0])) -extern int cmd_get_data_size(char* arg, int default_size); -static long evalexp(char *s, int w) +static char *evalstr(char *s) { - long *p; - long l = 0; - - /* if the parameter starts with a * then assume is a pointer to the value we want */ - if (s[0] == '*') { - p = (long *)simple_strtoul(&s[1], NULL, 16); - l = *p; - } else { - l = simple_strtoul(s, NULL, 16); - } - - if (w < 4) - return l & ((1 << (w * 8)) - 1); - else - return l; -} - -static char * evalstr(char *s) -{ - /* if the parameter starts with a * then assume a string pointer else its a literal */ - if (s[0] == '*') { + /* + * If the parameter starts with a * then + *assume a string pointer else its a literal + */ + if (s[0] == '*') return (char *)simple_strtoul(&s[1], NULL, 16); - } else { + else return s; - } } static int stringcomp(char *s, char *t, int op) @@ -105,40 +205,55 @@ static int stringcomp(char *s, char *t, int op) l = evalstr(s); r = evalstr(t); - /* we'll do a compare based on the length of the shortest string */ + /* We'll do a compare based on the length of the shortest string */ n = min(strlen(l), strlen(r)); p = strncmp(l, r, n); + switch (op) { - case EQ: return (p == 0); - case NE: return (p != 0); - case LT: return (p < 0); - case GT: return (p > 0); - case LE: return (p <= 0); - case GE: return (p >= 0); + case EQ: + return p == 0; + case NE: + return p != 0; + case LT: + return p < 0; + case GT: + return p > 0; + case LE: + return p <= 0; + case GE: + return p >= 0; } - return (0); + + return 0; } -static int arithcomp (char *s, char *t, int op, int w) +static int arithcomp(char *s, char *t, int op, int w) { - long l, r; + ulong l, r; - l = evalexp (s, w); - r = evalexp (t, w); + l = evalexp(s, w); + r = evalexp(t, w); switch (op) { - case EQ: return (l == r); - case NE: return (l != r); - case LT: return (l < r); - case GT: return (l > r); - case LE: return (l <= r); - case GE: return (l >= r); + case EQ: + return l == r; + case NE: + return l != r; + case LT: + return l < r; + case GT: + return l > r; + case LE: + return l <= r; + case GE: + return l >= r; } - return (0); + + return 0; } -int binary_test (char *op, char *arg1, char *arg2, int w) +static int binary_test(char *op, char *arg1, char *arg2, int w) { int len, i; op_tbl_t *optp; @@ -146,34 +261,35 @@ int binary_test (char *op, char *arg1, char *arg2, int w) len = strlen(op); for (optp = (op_tbl_t *)&op_table, i = 0; - i < op_tbl_size; - optp++, i++) { - - if ((strncmp (op, optp->op, len) == 0) && (len == strlen (optp->op))) { - if (w == 0) { - return (stringcomp(arg1, arg2, optp->opcode)); - } else { - return (arithcomp (arg1, arg2, optp->opcode, w)); - } + i < op_tbl_size; optp++, i++) { + if ((strncmp(op, optp->op, len) == 0) && + (len == strlen(optp->op))) { + if (w == 0) + return stringcomp(arg1, arg2, optp->opcode); + else + return arithcomp(arg1, arg2, optp->opcode, w); } } printf("## Error: unknown operator '%s'\n", op); - return 0; /* op code not found */ + + /* Op code not found */ + return 0; } -/* command line interface to the shell test */ -int do_itest ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ) +/* Command line interface to the shell test */ +int do_itest(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - int value, w; + int value, w; /* Validate arguments */ - if ((argc != 4)){ + if ((argc != 4)) { print_cmd_help(cmdtp); return 1; } - /* Check for a data width specification. + /* + * Check for a data width specification. * Defaults to long (4) if no specification. * Uses -2 as 'width' for .s (string) so as not to upset existing code */ @@ -181,10 +297,10 @@ int do_itest ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ) case 1: case 2: case 4: - value = binary_test (argv[2], argv[1], argv[3], w); + value = binary_test(argv[2], argv[1], argv[3], w); break; case -2: - value = binary_test (argv[2], argv[1], argv[3], 0); + value = binary_test(argv[2], argv[1], argv[3], 0); break; case -1: default: @@ -196,5 +312,6 @@ int do_itest ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ) return !value; } -U_BOOT_CMD(itest, 4, 0, do_itest, "return true/false on integer compare\n", "[.b, .w, .l, .s] [*]value1 [*]value2\n"); +U_BOOT_CMD(itest, 4, 0, do_itest, "return true/false on int compare\n", + "[.b, .w, .l, .s] [*]val1 [*]val2\n"); #endif /* CONFIG_CMD_ITEST */ diff --git a/u-boot/include/configs/qca9k_common.h b/u-boot/include/configs/qca9k_common.h index d13c99e..9ff25c9 100644 --- a/u-boot/include/configs/qca9k_common.h +++ b/u-boot/include/configs/qca9k_common.h @@ -116,6 +116,7 @@ #define CONFIG_CMD_LOADB #define CONFIG_CMD_BUTTON #define CONFIG_CMD_SLEEP +#define CONFIG_CMD_SETEXPR /* Simple upgrade scripts in environment */ #define CONFIG_UPG_SCRIPTS_UBOOT -- 2.25.1