]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/cmd_setexpr.c
Make sure that argv[] argument pointers are not modified.
[karo-tx-uboot.git] / common / cmd_setexpr.c
1 /*
2  * Copyright 2008 Freescale Semiconductor, Inc.
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22
23 /*
24  * This file provides a shell like 'expr' function to return.
25  */
26
27 #include <common.h>
28 #include <config.h>
29 #include <command.h>
30
31 static ulong get_arg(char *s, int w)
32 {
33         ulong *p;
34
35         /*
36          * if the parameter starts with a '*' then assume
37          * it is a pointer to the value we want
38          */
39
40         if (s[0] == '*') {
41                 p = (ulong *)simple_strtoul(&s[1], NULL, 16);
42                 switch (w) {
43                 case 1: return((ulong)(*(uchar *)p));
44                 case 2: return((ulong)(*(ushort *)p));
45                 case 4:
46                 default: return(*p);
47                 }
48         } else {
49                 return simple_strtoul(s, NULL, 16);
50         }
51 }
52
53 int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
54 {
55         ulong a, b;
56         char buf[16];
57         int w;
58
59         /* Validate arguments */
60         if ((argc != 5) || (strlen(argv[3]) != 1)) {
61                 cmd_usage(cmdtp);
62                 return 1;
63         }
64
65         w = cmd_get_data_size(argv[0], 4);
66
67         a = get_arg(argv[2], w);
68         b = get_arg(argv[4], w);
69
70         switch (argv[3][0]) {
71         case '|': sprintf(buf, "%lx", (a | b)); break;
72         case '&': sprintf(buf, "%lx", (a & b)); break;
73         case '+': sprintf(buf, "%lx", (a + b)); break;
74         case '^': sprintf(buf, "%lx", (a ^ b)); break;
75         case '-': sprintf(buf, "%lx", (a - b)); break;
76         case '*': sprintf(buf, "%lx", (a * b)); break;
77         case '/': sprintf(buf, "%lx", (a / b)); break;
78         case '%': sprintf(buf, "%lx", (a % b)); break;
79         default:
80                 printf("invalid op\n");
81                 return 1;
82         }
83
84         setenv(argv[1], buf);
85
86         return 0;
87 }
88
89 U_BOOT_CMD(
90         setexpr, 5, 0, do_setexpr,
91         "set environment variable as the result of eval expression",
92         "[.b, .w, .l] name value1 <op> value2\n"
93         "    - set environment variable 'name' to the result of the evaluated\n"
94         "      express specified by <op>.  <op> can be &, |, ^, +, -, *, /, %\n"
95         "      size argument is only meaningful if value1 and/or value2 are memory addresses"
96 );