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