xref: /openbmc/u-boot/cmd/binop.c (revision e8f80a5a)
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