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