]> git.sur5r.net Git - u-boot/blob - cmd/binop.c
mmc: avoid division by zero in meson_mmc_config_clock
[u-boot] / cmd / binop.c
1 /*
2  * SPDX-License-Identifier:     GPL-2.0+
3  */
4
5 #include <common.h>
6 #include <command.h>
7 #include <malloc.h>
8 #include <mapmem.h>
9 #include <linux/ctype.h>
10
11 enum {
12         OP_ID_XOR,
13         OP_ID_AND,
14         OP_ID_OR,
15 };
16
17 void write_to_env_var(char *varname, u8 *result, ulong len)
18 {
19         char *str_output;
20         char *str_ptr;
21         int i;
22
23         str_output = malloc(len * 2 + 1);
24         str_ptr = str_output;
25
26         for (i = 0; i < len; i++) {
27                 sprintf(str_ptr, "%02x", result[i]);
28                 str_ptr += 2;
29         }
30         *str_ptr = '\0';
31         setenv(varname, str_output);
32
33         free(str_output);
34 }
35
36 void decode_hexstring(char *hexstr, u8 *result)
37 {
38         int i;
39         int acc = 0;
40
41         for (i = 0; i < strlen(hexstr); ++i) {
42                 char d = hexstr[i];
43                 int value;
44
45                 if (isdigit(d))
46                         value = (d - '0');
47                 else
48                         value = (islower(d) ? toupper(d) : d) - 'A' + 10;
49
50                 if (i % 2 == 0) {
51                         acc = value * 16;
52                 } else {
53                         result[i / 2] = acc + value;
54                         acc = 0;
55                 }
56         }
57 }
58
59 void read_from_env_var(char *varname, u8 *result)
60 {
61         char *str_value;
62
63         str_value = getenv(varname);
64         if (str_value)
65                 decode_hexstring(str_value, result);
66         else
67                 decode_hexstring(varname, result);
68 }
69
70 void read_from_mem(ulong addr, u8 *result, ulong len)
71 {
72         u8 *src;
73
74         src = map_sysmem(addr, len);
75         memcpy(result, src, len);
76         unmap_sysmem(src);
77 }
78
79 void write_to_mem(char *varname, u8 *result, ulong len)
80 {
81         ulong addr;
82         u8 *buf;
83
84         addr = simple_strtoul(varname, NULL, 16);
85         buf = map_sysmem(addr, len);
86         memcpy(buf, result, len);
87         unmap_sysmem(buf);
88 }
89
90 static int do_binop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
91 {
92         ulong len;
93         u8 *result, *src1, *src2;
94         char *oparg, *lenarg, *src1arg, *src2arg, *destarg;
95         int i, op;
96
97         if (argc < 5)
98                 return CMD_RET_USAGE;
99
100         oparg = argv[1];
101         lenarg = argv[2];
102         src1arg = argv[3];
103         src2arg = argv[4];
104
105         if (!strcmp(oparg, "xor"))
106                 op = OP_ID_XOR;
107         else if (!strcmp(oparg, "or"))
108                 op = OP_ID_OR;
109         else if (!strcmp(oparg, "and"))
110                 op = OP_ID_AND;
111         else
112                 return CMD_RET_USAGE;
113
114         len = simple_strtoul(lenarg, NULL, 10);
115
116         src1 = malloc(len);
117         src2 = malloc(len);
118
119         if (*src1arg == '*')
120                 read_from_mem(simple_strtoul(src1arg + 1, NULL, 16), src1, len);
121         else
122                 read_from_env_var(src1arg, src1);
123
124         if (*src2arg == '*')
125                 read_from_mem(simple_strtoul(src2arg + 1, NULL, 16), src2, len);
126         else
127                 read_from_env_var(src2arg, src2);
128
129         result = malloc(len);
130
131         switch (op) {
132         case OP_ID_XOR:
133                 for (i = 0; i < len; i++)
134                         result[i] = src1[i] ^ src2[i];
135                 break;
136         case OP_ID_OR:
137                 for (i = 0; i < len; i++)
138                         result[i] = src1[i] | src2[i];
139                 break;
140         case OP_ID_AND:
141                 for (i = 0; i < len; i++)
142                         result[i] = src1[i] & src2[i];
143                 break;
144         }
145
146         if (argc == 5) {
147                 for (i = 0; i < len; i++) {
148                         printf("%02x ", result[i]);
149                         if (i % 16 == 15)
150                                 puts("\n");
151                 }
152                 puts("\n");
153
154                 goto exit;
155         }
156
157         destarg = argv[5];
158
159         if (*destarg == '*')
160                 write_to_mem(destarg + 1, result, len); /* Skip asterisk */
161         else
162                 write_to_env_var(destarg, result, len);
163 exit:
164         free(result);
165         free(src2);
166         free(src1);
167
168         return 0;
169 }
170
171 U_BOOT_CMD(
172         binop,  6,      1,      do_binop,
173         "compute binary operation",
174         "op count [*]src1 [*]src2 [[*]dest]\n"
175                 "    - compute binary operation of data at/in src1 and\n      src2 (either *memaddr, env var name or hex string)\n      and store result in/at dest, where op is one of\n      xor, or, and."
176 );