1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
255b25561SMario Six
355b25561SMario Six #include <common.h>
455b25561SMario Six #include <command.h>
555b25561SMario Six #include <malloc.h>
655b25561SMario Six #include <mapmem.h>
755b25561SMario Six #include <linux/ctype.h>
855b25561SMario Six
955b25561SMario Six enum {
1055b25561SMario Six OP_ID_XOR,
1155b25561SMario Six OP_ID_AND,
1255b25561SMario Six OP_ID_OR,
1355b25561SMario Six };
1455b25561SMario Six
write_to_env_var(char * varname,u8 * result,ulong len)1555b25561SMario Six void write_to_env_var(char *varname, u8 *result, ulong len)
1655b25561SMario Six {
1755b25561SMario Six char *str_output;
1855b25561SMario Six char *str_ptr;
1955b25561SMario Six int i;
2055b25561SMario Six
2155b25561SMario Six str_output = malloc(len * 2 + 1);
2255b25561SMario Six str_ptr = str_output;
2355b25561SMario Six
2455b25561SMario Six for (i = 0; i < len; i++) {
2555b25561SMario Six sprintf(str_ptr, "%02x", result[i]);
2655b25561SMario Six str_ptr += 2;
2755b25561SMario Six }
2855b25561SMario Six *str_ptr = '\0';
2955b25561SMario Six setenv(varname, str_output);
3055b25561SMario Six
3155b25561SMario Six free(str_output);
3255b25561SMario Six }
3355b25561SMario Six
decode_hexstring(char * hexstr,u8 * result)3455b25561SMario Six void decode_hexstring(char *hexstr, u8 *result)
3555b25561SMario Six {
3655b25561SMario Six int i;
3755b25561SMario Six int acc = 0;
3855b25561SMario Six
3955b25561SMario Six for (i = 0; i < strlen(hexstr); ++i) {
4055b25561SMario Six char d = hexstr[i];
4155b25561SMario Six int value;
4255b25561SMario Six
4355b25561SMario Six if (isdigit(d))
4455b25561SMario Six value = (d - '0');
4555b25561SMario Six else
4655b25561SMario Six value = (islower(d) ? toupper(d) : d) - 'A' + 10;
4755b25561SMario Six
4855b25561SMario Six if (i % 2 == 0) {
4955b25561SMario Six acc = value * 16;
5055b25561SMario Six } else {
5155b25561SMario Six result[i / 2] = acc + value;
5255b25561SMario Six acc = 0;
5355b25561SMario Six }
5455b25561SMario Six }
5555b25561SMario Six }
5655b25561SMario Six
read_from_env_var(char * varname,u8 * result)5755b25561SMario Six void read_from_env_var(char *varname, u8 *result)
5855b25561SMario Six {
5955b25561SMario Six char *str_value;
6055b25561SMario Six
6155b25561SMario Six str_value = getenv(varname);
6255b25561SMario Six if (str_value)
6355b25561SMario Six decode_hexstring(str_value, result);
6455b25561SMario Six else
6555b25561SMario Six decode_hexstring(varname, result);
6655b25561SMario Six }
6755b25561SMario Six
read_from_mem(ulong addr,u8 * result,ulong len)6855b25561SMario Six void read_from_mem(ulong addr, u8 *result, ulong len)
6955b25561SMario Six {
7055b25561SMario Six u8 *src;
7155b25561SMario Six
7255b25561SMario Six src = map_sysmem(addr, len);
7355b25561SMario Six memcpy(result, src, len);
7455b25561SMario Six unmap_sysmem(src);
7555b25561SMario Six }
7655b25561SMario Six
write_to_mem(char * varname,u8 * result,ulong len)7755b25561SMario Six void write_to_mem(char *varname, u8 *result, ulong len)
7855b25561SMario Six {
7955b25561SMario Six ulong addr;
8055b25561SMario Six u8 *buf;
8155b25561SMario Six
8255b25561SMario Six addr = simple_strtoul(varname, NULL, 16);
8355b25561SMario Six buf = map_sysmem(addr, len);
8455b25561SMario Six memcpy(buf, result, len);
8555b25561SMario Six unmap_sysmem(buf);
8655b25561SMario Six }
8755b25561SMario Six
do_binop(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])8855b25561SMario Six static int do_binop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
8955b25561SMario Six {
9055b25561SMario Six ulong len;
9155b25561SMario Six u8 *result, *src1, *src2;
9255b25561SMario Six char *oparg, *lenarg, *src1arg, *src2arg, *destarg;
9355b25561SMario Six int i, op;
9455b25561SMario Six
9555b25561SMario Six if (argc < 5)
9655b25561SMario Six return CMD_RET_USAGE;
9755b25561SMario Six
9855b25561SMario Six oparg = argv[1];
9955b25561SMario Six lenarg = argv[2];
10055b25561SMario Six src1arg = argv[3];
10155b25561SMario Six src2arg = argv[4];
10255b25561SMario Six
10355b25561SMario Six if (!strcmp(oparg, "xor"))
10455b25561SMario Six op = OP_ID_XOR;
10555b25561SMario Six else if (!strcmp(oparg, "or"))
10655b25561SMario Six op = OP_ID_OR;
10755b25561SMario Six else if (!strcmp(oparg, "and"))
10855b25561SMario Six op = OP_ID_AND;
10955b25561SMario Six else
11055b25561SMario Six return CMD_RET_USAGE;
11155b25561SMario Six
11255b25561SMario Six len = simple_strtoul(lenarg, NULL, 10);
11355b25561SMario Six
11455b25561SMario Six src1 = malloc(len);
11555b25561SMario Six src2 = malloc(len);
11655b25561SMario Six
11755b25561SMario Six if (*src1arg == '*')
11855b25561SMario Six read_from_mem(simple_strtoul(src1arg + 1, NULL, 16), src1, len);
11955b25561SMario Six else
12055b25561SMario Six read_from_env_var(src1arg, src1);
12155b25561SMario Six
12255b25561SMario Six if (*src2arg == '*')
12355b25561SMario Six read_from_mem(simple_strtoul(src2arg + 1, NULL, 16), src2, len);
12455b25561SMario Six else
12555b25561SMario Six read_from_env_var(src2arg, src2);
12655b25561SMario Six
12755b25561SMario Six result = malloc(len);
12855b25561SMario Six
12955b25561SMario Six switch (op) {
13055b25561SMario Six case OP_ID_XOR:
13155b25561SMario Six for (i = 0; i < len; i++)
13255b25561SMario Six result[i] = src1[i] ^ src2[i];
13355b25561SMario Six break;
13455b25561SMario Six case OP_ID_OR:
13555b25561SMario Six for (i = 0; i < len; i++)
13655b25561SMario Six result[i] = src1[i] | src2[i];
13755b25561SMario Six break;
13855b25561SMario Six case OP_ID_AND:
13955b25561SMario Six for (i = 0; i < len; i++)
14055b25561SMario Six result[i] = src1[i] & src2[i];
14155b25561SMario Six break;
14255b25561SMario Six }
14355b25561SMario Six
14455b25561SMario Six if (argc == 5) {
14555b25561SMario Six for (i = 0; i < len; i++) {
14655b25561SMario Six printf("%02x ", result[i]);
14755b25561SMario Six if (i % 16 == 15)
14855b25561SMario Six puts("\n");
14955b25561SMario Six }
15055b25561SMario Six puts("\n");
15155b25561SMario Six
15255b25561SMario Six goto exit;
15355b25561SMario Six }
15455b25561SMario Six
15555b25561SMario Six destarg = argv[5];
15655b25561SMario Six
15755b25561SMario Six if (*destarg == '*')
15855b25561SMario Six write_to_mem(destarg + 1, result, len); /* Skip asterisk */
15955b25561SMario Six else
16055b25561SMario Six write_to_env_var(destarg, result, len);
16155b25561SMario Six exit:
16255b25561SMario Six free(result);
16355b25561SMario Six free(src2);
16455b25561SMario Six free(src1);
16555b25561SMario Six
16655b25561SMario Six return 0;
16755b25561SMario Six }
16855b25561SMario Six
16955b25561SMario Six U_BOOT_CMD(
17055b25561SMario Six binop, 6, 1, do_binop,
17155b25561SMario Six "compute binary operation",
17255b25561SMario Six "op count [*]src1 [*]src2 [[*]dest]\n"
17355b25561SMario Six " - 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."
17455b25561SMario Six );
175