Merge branch 'mem' of git://git.denx.de/u-boot-x86
[platform/kernel/u-boot.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 static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
54 {
55         ulong a, b;
56         ulong value;
57         int w;
58
59         /* Validate arguments */
60         if (argc != 5 && argc != 3)
61                 return CMD_RET_USAGE;
62         if (argc == 5 && strlen(argv[3]) != 1)
63                 return CMD_RET_USAGE;
64
65         w = cmd_get_data_size(argv[0], 4);
66
67         a = get_arg(argv[2], w);
68
69         if (argc == 3) {
70                 setenv_hex(argv[1], a);
71
72                 return 0;
73         }
74
75         b = get_arg(argv[4], w);
76
77         switch (argv[3][0]) {
78         case '|':
79                 value = a | b;
80                 break;
81         case '&':
82                 value = a & b;
83                 break;
84         case '+':
85                 value = a + b;
86                 break;
87         case '^':
88                 value = a ^ b;
89                 break;
90         case '-':
91                 value = a - b;
92                 break;
93         case '*':
94                 value = a * b;
95                 break;
96         case '/':
97                 value = a / b;
98                 break;
99         case '%':
100                 value = a % b;
101                 break;
102         default:
103                 printf("invalid op\n");
104                 return 1;
105         }
106
107         setenv_hex(argv[1], value);
108
109         return 0;
110 }
111
112 U_BOOT_CMD(
113         setexpr, 5, 0, do_setexpr,
114         "set environment variable as the result of eval expression",
115         "[.b, .w, .l] name [*]value1 <op> [*]value2\n"
116         "    - set environment variable 'name' to the result of the evaluated\n"
117         "      express specified by <op>.  <op> can be &, |, ^, +, -, *, /, %\n"
118         "      size argument is only meaningful if value1 and/or value2 are\n"
119         "      memory addresses (*)\n"
120         "setexpr[.b, .w, .l] name *value\n"
121         "    - load a memory address into a variable"
122 );