116a2c0d5547cae3b3ad865ffb5089d8a4604842
[oweals/u-boot.git] / cmd / binop.c
1 // SPDX-License-Identifier: GPL-2.0+
2
3 #include <common.h>
4 #include <command.h>
5 #include <hexdump.h>
6 #include <malloc.h>
7 #include <mapmem.h>
8 #include <linux/ctype.h>
9
10 enum {
11         OP_ID_XOR,
12         OP_ID_AND,
13         OP_ID_OR,
14 };
15
16 void write_to_env_var(char *varname, u8 *result, ulong len)
17 {
18         char *str_output;
19         char *str_ptr;
20         int i;
21
22         str_output = malloc(len * 2 + 1);
23         str_ptr = str_output;
24
25         for (i = 0; i < len; i++) {
26                 sprintf(str_ptr, "%02x", result[i]);
27                 str_ptr += 2;
28         }
29         *str_ptr = '\0';
30         env_set(varname, str_output);
31
32         free(str_output);
33 }
34
35 void read_from_env_var(char *varname, u8 *result)
36 {
37         char *str_value;
38
39         str_value = env_get(varname);
40         if (str_value)
41                 hex2bin(result, str_value, strlen(str_value) / 2);
42         else
43                 hex2bin(result, varname, strlen(varname) / 2);
44 }
45
46 void read_from_mem(ulong addr, u8 *result, ulong len)
47 {
48         u8 *src;
49
50         src = map_sysmem(addr, len);
51         memcpy(result, src, len);
52         unmap_sysmem(src);
53 }
54
55 void write_to_mem(char *varname, u8 *result, ulong len)
56 {
57         ulong addr;
58         u8 *buf;
59
60         addr = simple_strtoul(varname, NULL, 16);
61         buf = map_sysmem(addr, len);
62         memcpy(buf, result, len);
63         unmap_sysmem(buf);
64 }
65
66 static int do_binop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
67 {
68         ulong len;
69         u8 *result, *src1, *src2;
70         char *oparg, *lenarg, *src1arg, *src2arg, *destarg;
71         int i, op;
72
73         if (argc < 5)
74                 return CMD_RET_USAGE;
75
76         oparg = argv[1];
77         lenarg = argv[2];
78         src1arg = argv[3];
79         src2arg = argv[4];
80
81         if (!strcmp(oparg, "xor"))
82                 op = OP_ID_XOR;
83         else if (!strcmp(oparg, "or"))
84                 op = OP_ID_OR;
85         else if (!strcmp(oparg, "and"))
86                 op = OP_ID_AND;
87         else
88                 return CMD_RET_USAGE;
89
90         len = simple_strtoul(lenarg, NULL, 10);
91
92         src1 = malloc(len);
93         src2 = malloc(len);
94
95         if (*src1arg == '*')
96                 read_from_mem(simple_strtoul(src1arg + 1, NULL, 16), src1, len);
97         else
98                 read_from_env_var(src1arg, src1);
99
100         if (*src2arg == '*')
101                 read_from_mem(simple_strtoul(src2arg + 1, NULL, 16), src2, len);
102         else
103                 read_from_env_var(src2arg, src2);
104
105         result = malloc(len);
106
107         switch (op) {
108         case OP_ID_XOR:
109                 for (i = 0; i < len; i++)
110                         result[i] = src1[i] ^ src2[i];
111                 break;
112         case OP_ID_OR:
113                 for (i = 0; i < len; i++)
114                         result[i] = src1[i] | src2[i];
115                 break;
116         case OP_ID_AND:
117                 for (i = 0; i < len; i++)
118                         result[i] = src1[i] & src2[i];
119                 break;
120         }
121
122         if (argc == 5) {
123                 for (i = 0; i < len; i++) {
124                         printf("%02x ", result[i]);
125                         if (i % 16 == 15)
126                                 puts("\n");
127                 }
128                 puts("\n");
129
130                 goto exit;
131         }
132
133         destarg = argv[5];
134
135         if (*destarg == '*')
136                 write_to_mem(destarg + 1, result, len); /* Skip asterisk */
137         else
138                 write_to_env_var(destarg, result, len);
139 exit:
140         free(result);
141         free(src2);
142         free(src1);
143
144         return 0;
145 }
146
147 U_BOOT_CMD(
148         binop,  6,      1,      do_binop,
149         "compute binary operation",
150         "op count [*]src1 [*]src2 [[*]dest]\n"
151                 "    - 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."
152 );