--- /dev/null
+/*
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <linux/ctype.h>
+
+enum {
+ OP_ID_XOR,
+ OP_ID_AND,
+ OP_ID_OR,
+};
+
+void write_to_env_var(char *varname, u8 *result, ulong len)
+{
+ char *str_output;
+ char *str_ptr;
+ int i;
+
+ str_output = malloc(len * 2 + 1);
+ str_ptr = str_output;
+
+ for (i = 0; i < len; i++) {
+ sprintf(str_ptr, "%02x", result[i]);
+ str_ptr += 2;
+ }
+ *str_ptr = '\0';
+ setenv(varname, str_output);
+
+ free(str_output);
+}
+
+void decode_hexstring(char *hexstr, u8 *result)
+{
+ int i;
+ int acc = 0;
+
+ for (i = 0; i < strlen(hexstr); ++i) {
+ char d = hexstr[i];
+ int value;
+
+ if (isdigit(d))
+ value = (d - '0');
+ else
+ value = (islower(d) ? toupper(d) : d) - 'A' + 10;
+
+ if (i % 2 == 0) {
+ acc = value * 16;
+ } else {
+ result[i / 2] = acc + value;
+ acc = 0;
+ }
+ }
+}
+
+void read_from_env_var(char *varname, u8 *result)
+{
+ char *str_value;
+
+ str_value = getenv(varname);
+ if (str_value)
+ decode_hexstring(str_value, result);
+ else
+ decode_hexstring(varname, result);
+}
+
+void read_from_mem(ulong addr, u8 *result, ulong len)
+{
+ u8 *src;
+
+ src = map_sysmem(addr, len);
+ memcpy(result, src, len);
+ unmap_sysmem(src);
+}
+
+void write_to_mem(char *varname, u8 *result, ulong len)
+{
+ ulong addr;
+ u8 *buf;
+
+ addr = simple_strtoul(varname, NULL, 16);
+ buf = map_sysmem(addr, len);
+ memcpy(buf, result, len);
+ unmap_sysmem(buf);
+}
+
+static int do_binop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ ulong len;
+ u8 *result, *src1, *src2;
+ char *oparg, *lenarg, *src1arg, *src2arg, *destarg;
+ int i, op;
+
+ if (argc < 5)
+ return CMD_RET_USAGE;
+
+ oparg = argv[1];
+ lenarg = argv[2];
+ src1arg = argv[3];
+ src2arg = argv[4];
+
+ if (!strcmp(oparg, "xor"))
+ op = OP_ID_XOR;
+ else if (!strcmp(oparg, "or"))
+ op = OP_ID_OR;
+ else if (!strcmp(oparg, "and"))
+ op = OP_ID_AND;
+ else
+ return CMD_RET_USAGE;
+
+ len = simple_strtoul(lenarg, NULL, 10);
+
+ src1 = malloc(len);
+ src2 = malloc(len);
+
+ if (*src1arg == '*')
+ read_from_mem(simple_strtoul(src1arg + 1, NULL, 16), src1, len);
+ else
+ read_from_env_var(src1arg, src1);
+
+ if (*src2arg == '*')
+ read_from_mem(simple_strtoul(src2arg + 1, NULL, 16), src2, len);
+ else
+ read_from_env_var(src2arg, src2);
+
+ result = malloc(len);
+
+ switch (op) {
+ case OP_ID_XOR:
+ for (i = 0; i < len; i++)
+ result[i] = src1[i] ^ src2[i];
+ break;
+ case OP_ID_OR:
+ for (i = 0; i < len; i++)
+ result[i] = src1[i] | src2[i];
+ break;
+ case OP_ID_AND:
+ for (i = 0; i < len; i++)
+ result[i] = src1[i] & src2[i];
+ break;
+ }
+
+ if (argc == 5) {
+ for (i = 0; i < len; i++) {
+ printf("%02x ", result[i]);
+ if (i % 16 == 15)
+ puts("\n");
+ }
+ puts("\n");
+
+ goto exit;
+ }
+
+ destarg = argv[5];
+
+ if (*destarg == '*')
+ write_to_mem(destarg + 1, result, len); /* Skip asterisk */
+ else
+ write_to_env_var(destarg, result, len);
+exit:
+ free(result);
+ free(src2);
+ free(src1);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ binop, 6, 1, do_binop,
+ "compute binary operation",
+ "op count [*]src1 [*]src2 [[*]dest]\n"
+ " - 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."
+);