blob: 116a2c0d5547cae3b3ad865ffb5089d8a4604842 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Mario Six8a4f6642018-03-28 14:39:18 +02002
3#include <common.h>
4#include <command.h>
Mario Six0c2b3c72019-01-28 09:43:43 +01005#include <hexdump.h>
Mario Six8a4f6642018-03-28 14:39:18 +02006#include <malloc.h>
7#include <mapmem.h>
8#include <linux/ctype.h>
9
10enum {
11 OP_ID_XOR,
12 OP_ID_AND,
13 OP_ID_OR,
14};
15
16void 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';
Mario Six3d829722019-01-28 09:43:42 +010030 env_set(varname, str_output);
Mario Six8a4f6642018-03-28 14:39:18 +020031
32 free(str_output);
33}
34
Mario Six8a4f6642018-03-28 14:39:18 +020035void read_from_env_var(char *varname, u8 *result)
36{
37 char *str_value;
38
Mario Six3d829722019-01-28 09:43:42 +010039 str_value = env_get(varname);
Mario Six8a4f6642018-03-28 14:39:18 +020040 if (str_value)
Mario Six0c2b3c72019-01-28 09:43:43 +010041 hex2bin(result, str_value, strlen(str_value) / 2);
Mario Six8a4f6642018-03-28 14:39:18 +020042 else
Mario Six0c2b3c72019-01-28 09:43:43 +010043 hex2bin(result, varname, strlen(varname) / 2);
Mario Six8a4f6642018-03-28 14:39:18 +020044}
45
46void 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
55void 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
66static 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);
139exit:
140 free(result);
141 free(src2);
142 free(src1);
143
144 return 0;
145}
146
147U_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);