blob: 0002c66609e58e921c7d8a2b183cc655218b2fe6 [file] [log] [blame]
Mario Six8a4f6642018-03-28 14:39:18 +02001/*
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
11enum {
12 OP_ID_XOR,
13 OP_ID_AND,
14 OP_ID_OR,
15};
16
17void 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
36void 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
59void 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
70void 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
79void 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
90static 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);
163exit:
164 free(result);
165 free(src2);
166 free(src1);
167
168 return 0;
169}
170
171U_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);