xref: /rk3399_rockchip-uboot/cmd/itest.c (revision 00caae6d47645e68d6e5277aceb69592b49381a6)
12e192b24SSimon Glass /*
22e192b24SSimon Glass  * (C) Copyright 2003
32e192b24SSimon Glass  * Tait Electronics Limited, Christchurch, New Zealand
42e192b24SSimon Glass  *
52e192b24SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
62e192b24SSimon Glass  */
72e192b24SSimon Glass 
82e192b24SSimon Glass /*
92e192b24SSimon Glass  * This file provides a shell like 'test' function to return
102e192b24SSimon Glass  * true/false from an integer or string compare of two memory
112e192b24SSimon Glass  * locations or a location and a scalar/literal.
122e192b24SSimon Glass  * A few parts were lifted from bash 'test' command
132e192b24SSimon Glass  */
142e192b24SSimon Glass 
152e192b24SSimon Glass #include <common.h>
162e192b24SSimon Glass #include <config.h>
172e192b24SSimon Glass #include <command.h>
182e192b24SSimon Glass #include <mapmem.h>
192e192b24SSimon Glass 
202e192b24SSimon Glass #include <asm/io.h>
212e192b24SSimon Glass 
222e192b24SSimon Glass #define EQ	0
232e192b24SSimon Glass #define NE	1
242e192b24SSimon Glass #define LT	2
252e192b24SSimon Glass #define GT	3
262e192b24SSimon Glass #define LE	4
272e192b24SSimon Glass #define GE	5
282e192b24SSimon Glass 
292e192b24SSimon Glass struct op_tbl_s {
302e192b24SSimon Glass 	char	*op;		/* operator string */
312e192b24SSimon Glass 	int	opcode;		/* internal representation of opcode */
322e192b24SSimon Glass };
332e192b24SSimon Glass 
342e192b24SSimon Glass typedef struct op_tbl_s op_tbl_t;
352e192b24SSimon Glass 
362e192b24SSimon Glass static const op_tbl_t op_table [] = {
372e192b24SSimon Glass 	{ "-lt", LT },
382e192b24SSimon Glass 	{ "<"  , LT },
392e192b24SSimon Glass 	{ "-gt", GT },
402e192b24SSimon Glass 	{ ">"  , GT },
412e192b24SSimon Glass 	{ "-eq", EQ },
422e192b24SSimon Glass 	{ "==" , EQ },
432e192b24SSimon Glass 	{ "-ne", NE },
442e192b24SSimon Glass 	{ "!=" , NE },
452e192b24SSimon Glass 	{ "<>" , NE },
462e192b24SSimon Glass 	{ "-ge", GE },
472e192b24SSimon Glass 	{ ">=" , GE },
482e192b24SSimon Glass 	{ "-le", LE },
492e192b24SSimon Glass 	{ "<=" , LE },
502e192b24SSimon Glass };
512e192b24SSimon Glass 
evalexp(char * s,int w)522e192b24SSimon Glass static long evalexp(char *s, int w)
532e192b24SSimon Glass {
542e192b24SSimon Glass 	long l = 0;
552e192b24SSimon Glass 	unsigned long addr;
562e192b24SSimon Glass 	void *buf;
572e192b24SSimon Glass 
582e192b24SSimon Glass 	/* if the parameter starts with a * then assume is a pointer to the value we want */
592e192b24SSimon Glass 	if (s[0] == '*') {
602e192b24SSimon Glass 		addr = simple_strtoul(&s[1], NULL, 16);
612e192b24SSimon Glass 		buf = map_physmem(addr, w, MAP_WRBACK);
62986fe378SStephen Warren 		if (!buf && addr) {
632e192b24SSimon Glass 			puts("Failed to map physical memory\n");
642e192b24SSimon Glass 			return 0;
652e192b24SSimon Glass 		}
662e192b24SSimon Glass 		switch (w) {
672e192b24SSimon Glass 		case 1:
68dafd6488SKunihiko Hayashi 			l = (long)(*(u8 *)buf);
692e192b24SSimon Glass 			break;
702e192b24SSimon Glass 		case 2:
71dafd6488SKunihiko Hayashi 			l = (long)(*(u16 *)buf);
722e192b24SSimon Glass 			break;
732e192b24SSimon Glass 		case 4:
74dafd6488SKunihiko Hayashi 			l = (long)(*(u32 *)buf);
752e192b24SSimon Glass 			break;
762e192b24SSimon Glass 		}
772e192b24SSimon Glass 		unmap_physmem(buf, w);
782e192b24SSimon Glass 		return l;
792e192b24SSimon Glass 	} else {
802e192b24SSimon Glass 		l = simple_strtoul(s, NULL, 16);
812e192b24SSimon Glass 	}
822e192b24SSimon Glass 
832c79fd40SSebastien Colleur 	/* avoid overflow on mask calculus */
842c79fd40SSebastien Colleur 	return (w >= sizeof(long)) ? l : (l & ((1UL << (w * 8)) - 1));
852e192b24SSimon Glass }
862e192b24SSimon Glass 
evalstr(char * s)872e192b24SSimon Glass static char * evalstr(char *s)
882e192b24SSimon Glass {
892e192b24SSimon Glass 	/* if the parameter starts with a * then assume a string pointer else its a literal */
902e192b24SSimon Glass 	if (s[0] == '*') {
912e192b24SSimon Glass 		return (char *)simple_strtoul(&s[1], NULL, 16);
922e192b24SSimon Glass 	} else if (s[0] == '$') {
932e192b24SSimon Glass 		int i = 2;
942e192b24SSimon Glass 
952e192b24SSimon Glass 		if (s[1] != '{')
962e192b24SSimon Glass 			return NULL;
972e192b24SSimon Glass 
982e192b24SSimon Glass 		while (s[i] != '}') {
992e192b24SSimon Glass 			if (s[i] == 0)
1002e192b24SSimon Glass 				return NULL;
1012e192b24SSimon Glass 			i++;
1022e192b24SSimon Glass 		}
1032e192b24SSimon Glass 		s[i] = 0;
104*00caae6dSSimon Glass 		return  env_get((const char *)&s[2]);
1052e192b24SSimon Glass 	} else {
1062e192b24SSimon Glass 		return s;
1072e192b24SSimon Glass 	}
1082e192b24SSimon Glass }
1092e192b24SSimon Glass 
stringcomp(char * s,char * t,int op)1102e192b24SSimon Glass static int stringcomp(char *s, char *t, int op)
1112e192b24SSimon Glass {
1122e192b24SSimon Glass 	int p;
1132e192b24SSimon Glass 	char *l, *r;
1142e192b24SSimon Glass 
1152e192b24SSimon Glass 	l = evalstr(s);
1162e192b24SSimon Glass 	r = evalstr(t);
1172e192b24SSimon Glass 
1182e192b24SSimon Glass 	p = strcmp(l, r);
1192e192b24SSimon Glass 	switch (op) {
1202e192b24SSimon Glass 	case EQ: return (p == 0);
1212e192b24SSimon Glass 	case NE: return (p != 0);
1222e192b24SSimon Glass 	case LT: return (p < 0);
1232e192b24SSimon Glass 	case GT: return (p > 0);
1242e192b24SSimon Glass 	case LE: return (p <= 0);
1252e192b24SSimon Glass 	case GE: return (p >= 0);
1262e192b24SSimon Glass 	}
1272e192b24SSimon Glass 	return (0);
1282e192b24SSimon Glass }
1292e192b24SSimon Glass 
arithcomp(char * s,char * t,int op,int w)1302e192b24SSimon Glass static int arithcomp (char *s, char *t, int op, int w)
1312e192b24SSimon Glass {
1322e192b24SSimon Glass 	long l, r;
1332e192b24SSimon Glass 
1342e192b24SSimon Glass 	l = evalexp (s, w);
1352e192b24SSimon Glass 	r = evalexp (t, w);
1362e192b24SSimon Glass 
1372e192b24SSimon Glass 	switch (op) {
1382e192b24SSimon Glass 	case EQ: return (l == r);
1392e192b24SSimon Glass 	case NE: return (l != r);
1402e192b24SSimon Glass 	case LT: return (l < r);
1412e192b24SSimon Glass 	case GT: return (l > r);
1422e192b24SSimon Glass 	case LE: return (l <= r);
1432e192b24SSimon Glass 	case GE: return (l >= r);
1442e192b24SSimon Glass 	}
1452e192b24SSimon Glass 	return (0);
1462e192b24SSimon Glass }
1472e192b24SSimon Glass 
binary_test(char * op,char * arg1,char * arg2,int w)1482e192b24SSimon Glass static int binary_test(char *op, char *arg1, char *arg2, int w)
1492e192b24SSimon Glass {
1502e192b24SSimon Glass 	int len, i;
1512e192b24SSimon Glass 	const op_tbl_t *optp;
1522e192b24SSimon Glass 
1532e192b24SSimon Glass 	len = strlen(op);
1542e192b24SSimon Glass 
1552e192b24SSimon Glass 	for (optp = (op_tbl_t *)&op_table, i = 0;
1562e192b24SSimon Glass 	     i < ARRAY_SIZE(op_table);
1572e192b24SSimon Glass 	     optp++, i++) {
1582e192b24SSimon Glass 
1592e192b24SSimon Glass 		if ((strncmp (op, optp->op, len) == 0) && (len == strlen (optp->op))) {
1602e192b24SSimon Glass 			if (w == 0) {
1612e192b24SSimon Glass 				return (stringcomp(arg1, arg2, optp->opcode));
1622e192b24SSimon Glass 			} else {
1632e192b24SSimon Glass 				return (arithcomp (arg1, arg2, optp->opcode, w));
1642e192b24SSimon Glass 			}
1652e192b24SSimon Glass 		}
1662e192b24SSimon Glass 	}
1672e192b24SSimon Glass 
1682e192b24SSimon Glass 	printf("Unknown operator '%s'\n", op);
1692e192b24SSimon Glass 	return 0;	/* op code not found */
1702e192b24SSimon Glass }
1712e192b24SSimon Glass 
1722e192b24SSimon Glass /* command line interface to the shell test */
do_itest(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])1732e192b24SSimon Glass static int do_itest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1742e192b24SSimon Glass {
1752e192b24SSimon Glass 	int	value, w;
1762e192b24SSimon Glass 
1772e192b24SSimon Glass 	/* Validate arguments */
1782e192b24SSimon Glass 	if ((argc != 4))
1792e192b24SSimon Glass 		return CMD_RET_USAGE;
1802e192b24SSimon Glass 
1812e192b24SSimon Glass 	/* Check for a data width specification.
1822e192b24SSimon Glass 	 * Defaults to long (4) if no specification.
1832e192b24SSimon Glass 	 * Uses -2 as 'width' for .s (string) so as not to upset existing code
1842e192b24SSimon Glass 	 */
1852e192b24SSimon Glass 	switch (w = cmd_get_data_size(argv[0], 4)) {
1862e192b24SSimon Glass 	case 1:
1872e192b24SSimon Glass 	case 2:
1882e192b24SSimon Glass 	case 4:
1892e192b24SSimon Glass 		value = binary_test (argv[2], argv[1], argv[3], w);
1902e192b24SSimon Glass 		break;
1912e192b24SSimon Glass 	case -2:
1922e192b24SSimon Glass 		value = binary_test (argv[2], argv[1], argv[3], 0);
1932e192b24SSimon Glass 		break;
1942e192b24SSimon Glass 	case -1:
1952e192b24SSimon Glass 	default:
1962e192b24SSimon Glass 		puts("Invalid data width specifier\n");
1972e192b24SSimon Glass 		value = 0;
1982e192b24SSimon Glass 		break;
1992e192b24SSimon Glass 	}
2002e192b24SSimon Glass 
2012e192b24SSimon Glass 	return !value;
2022e192b24SSimon Glass }
2032e192b24SSimon Glass 
2042e192b24SSimon Glass U_BOOT_CMD(
2052e192b24SSimon Glass 	itest, 4, 0, do_itest,
2062e192b24SSimon Glass 	"return true/false on integer compare",
2072e192b24SSimon Glass 	"[.b, .w, .l, .s] [*]value1 <op> [*]value2"
2082e192b24SSimon Glass );
209