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