xref: /rk3399_rockchip-uboot/cmd/itest.c (revision 2e192b245ed36a63bab0ef576999a95e23f60ecd)
1*2e192b24SSimon Glass /*
2*2e192b24SSimon Glass  * (C) Copyright 2003
3*2e192b24SSimon Glass  * Tait Electronics Limited, Christchurch, New Zealand
4*2e192b24SSimon Glass  *
5*2e192b24SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
6*2e192b24SSimon Glass  */
7*2e192b24SSimon Glass 
8*2e192b24SSimon Glass /*
9*2e192b24SSimon Glass  * This file provides a shell like 'test' function to return
10*2e192b24SSimon Glass  * true/false from an integer or string compare of two memory
11*2e192b24SSimon Glass  * locations or a location and a scalar/literal.
12*2e192b24SSimon Glass  * A few parts were lifted from bash 'test' command
13*2e192b24SSimon Glass  */
14*2e192b24SSimon Glass 
15*2e192b24SSimon Glass #include <common.h>
16*2e192b24SSimon Glass #include <config.h>
17*2e192b24SSimon Glass #include <command.h>
18*2e192b24SSimon Glass #include <mapmem.h>
19*2e192b24SSimon Glass 
20*2e192b24SSimon Glass #include <asm/io.h>
21*2e192b24SSimon Glass 
22*2e192b24SSimon Glass #define EQ	0
23*2e192b24SSimon Glass #define NE	1
24*2e192b24SSimon Glass #define LT	2
25*2e192b24SSimon Glass #define GT	3
26*2e192b24SSimon Glass #define LE	4
27*2e192b24SSimon Glass #define GE	5
28*2e192b24SSimon Glass 
29*2e192b24SSimon Glass struct op_tbl_s {
30*2e192b24SSimon Glass 	char	*op;		/* operator string */
31*2e192b24SSimon Glass 	int	opcode;		/* internal representation of opcode */
32*2e192b24SSimon Glass };
33*2e192b24SSimon Glass 
34*2e192b24SSimon Glass typedef struct op_tbl_s op_tbl_t;
35*2e192b24SSimon Glass 
36*2e192b24SSimon Glass static const op_tbl_t op_table [] = {
37*2e192b24SSimon Glass 	{ "-lt", LT },
38*2e192b24SSimon Glass 	{ "<"  , LT },
39*2e192b24SSimon Glass 	{ "-gt", GT },
40*2e192b24SSimon Glass 	{ ">"  , GT },
41*2e192b24SSimon Glass 	{ "-eq", EQ },
42*2e192b24SSimon Glass 	{ "==" , EQ },
43*2e192b24SSimon Glass 	{ "-ne", NE },
44*2e192b24SSimon Glass 	{ "!=" , NE },
45*2e192b24SSimon Glass 	{ "<>" , NE },
46*2e192b24SSimon Glass 	{ "-ge", GE },
47*2e192b24SSimon Glass 	{ ">=" , GE },
48*2e192b24SSimon Glass 	{ "-le", LE },
49*2e192b24SSimon Glass 	{ "<=" , LE },
50*2e192b24SSimon Glass };
51*2e192b24SSimon Glass 
52*2e192b24SSimon Glass static long evalexp(char *s, int w)
53*2e192b24SSimon Glass {
54*2e192b24SSimon Glass 	long l = 0;
55*2e192b24SSimon Glass 	unsigned long addr;
56*2e192b24SSimon Glass 	void *buf;
57*2e192b24SSimon Glass 
58*2e192b24SSimon Glass 	/* if the parameter starts with a * then assume is a pointer to the value we want */
59*2e192b24SSimon Glass 	if (s[0] == '*') {
60*2e192b24SSimon Glass 		addr = simple_strtoul(&s[1], NULL, 16);
61*2e192b24SSimon Glass 		buf = map_physmem(addr, w, MAP_WRBACK);
62*2e192b24SSimon Glass 		if (!buf) {
63*2e192b24SSimon Glass 			puts("Failed to map physical memory\n");
64*2e192b24SSimon Glass 			return 0;
65*2e192b24SSimon Glass 		}
66*2e192b24SSimon Glass 		switch (w) {
67*2e192b24SSimon Glass 		case 1:
68*2e192b24SSimon Glass 			l = (long)(*(unsigned char *)buf);
69*2e192b24SSimon Glass 			break;
70*2e192b24SSimon Glass 		case 2:
71*2e192b24SSimon Glass 			l = (long)(*(unsigned short *)buf);
72*2e192b24SSimon Glass 			break;
73*2e192b24SSimon Glass 		case 4:
74*2e192b24SSimon Glass 			l = (long)(*(unsigned long *)buf);
75*2e192b24SSimon Glass 			break;
76*2e192b24SSimon Glass 		}
77*2e192b24SSimon Glass 		unmap_physmem(buf, w);
78*2e192b24SSimon Glass 		return l;
79*2e192b24SSimon Glass 	} else {
80*2e192b24SSimon Glass 		l = simple_strtoul(s, NULL, 16);
81*2e192b24SSimon Glass 	}
82*2e192b24SSimon Glass 
83*2e192b24SSimon Glass 	return l & ((1UL << (w * 8)) - 1);
84*2e192b24SSimon Glass }
85*2e192b24SSimon Glass 
86*2e192b24SSimon Glass static char * evalstr(char *s)
87*2e192b24SSimon Glass {
88*2e192b24SSimon Glass 	/* if the parameter starts with a * then assume a string pointer else its a literal */
89*2e192b24SSimon Glass 	if (s[0] == '*') {
90*2e192b24SSimon Glass 		return (char *)simple_strtoul(&s[1], NULL, 16);
91*2e192b24SSimon Glass 	} else if (s[0] == '$') {
92*2e192b24SSimon Glass 		int i = 2;
93*2e192b24SSimon Glass 
94*2e192b24SSimon Glass 		if (s[1] != '{')
95*2e192b24SSimon Glass 			return NULL;
96*2e192b24SSimon Glass 
97*2e192b24SSimon Glass 		while (s[i] != '}') {
98*2e192b24SSimon Glass 			if (s[i] == 0)
99*2e192b24SSimon Glass 				return NULL;
100*2e192b24SSimon Glass 			i++;
101*2e192b24SSimon Glass 		}
102*2e192b24SSimon Glass 		s[i] = 0;
103*2e192b24SSimon Glass 		return  getenv((const char *)&s[2]);
104*2e192b24SSimon Glass 	} else {
105*2e192b24SSimon Glass 		return s;
106*2e192b24SSimon Glass 	}
107*2e192b24SSimon Glass }
108*2e192b24SSimon Glass 
109*2e192b24SSimon Glass static int stringcomp(char *s, char *t, int op)
110*2e192b24SSimon Glass {
111*2e192b24SSimon Glass 	int p;
112*2e192b24SSimon Glass 	char *l, *r;
113*2e192b24SSimon Glass 
114*2e192b24SSimon Glass 	l = evalstr(s);
115*2e192b24SSimon Glass 	r = evalstr(t);
116*2e192b24SSimon Glass 
117*2e192b24SSimon Glass 	p = strcmp(l, r);
118*2e192b24SSimon Glass 	switch (op) {
119*2e192b24SSimon Glass 	case EQ: return (p == 0);
120*2e192b24SSimon Glass 	case NE: return (p != 0);
121*2e192b24SSimon Glass 	case LT: return (p < 0);
122*2e192b24SSimon Glass 	case GT: return (p > 0);
123*2e192b24SSimon Glass 	case LE: return (p <= 0);
124*2e192b24SSimon Glass 	case GE: return (p >= 0);
125*2e192b24SSimon Glass 	}
126*2e192b24SSimon Glass 	return (0);
127*2e192b24SSimon Glass }
128*2e192b24SSimon Glass 
129*2e192b24SSimon Glass static int arithcomp (char *s, char *t, int op, int w)
130*2e192b24SSimon Glass {
131*2e192b24SSimon Glass 	long l, r;
132*2e192b24SSimon Glass 
133*2e192b24SSimon Glass 	l = evalexp (s, w);
134*2e192b24SSimon Glass 	r = evalexp (t, w);
135*2e192b24SSimon Glass 
136*2e192b24SSimon Glass 	switch (op) {
137*2e192b24SSimon Glass 	case EQ: return (l == r);
138*2e192b24SSimon Glass 	case NE: return (l != r);
139*2e192b24SSimon Glass 	case LT: return (l < r);
140*2e192b24SSimon Glass 	case GT: return (l > r);
141*2e192b24SSimon Glass 	case LE: return (l <= r);
142*2e192b24SSimon Glass 	case GE: return (l >= r);
143*2e192b24SSimon Glass 	}
144*2e192b24SSimon Glass 	return (0);
145*2e192b24SSimon Glass }
146*2e192b24SSimon Glass 
147*2e192b24SSimon Glass static int binary_test(char *op, char *arg1, char *arg2, int w)
148*2e192b24SSimon Glass {
149*2e192b24SSimon Glass 	int len, i;
150*2e192b24SSimon Glass 	const op_tbl_t *optp;
151*2e192b24SSimon Glass 
152*2e192b24SSimon Glass 	len = strlen(op);
153*2e192b24SSimon Glass 
154*2e192b24SSimon Glass 	for (optp = (op_tbl_t *)&op_table, i = 0;
155*2e192b24SSimon Glass 	     i < ARRAY_SIZE(op_table);
156*2e192b24SSimon Glass 	     optp++, i++) {
157*2e192b24SSimon Glass 
158*2e192b24SSimon Glass 		if ((strncmp (op, optp->op, len) == 0) && (len == strlen (optp->op))) {
159*2e192b24SSimon Glass 			if (w == 0) {
160*2e192b24SSimon Glass 				return (stringcomp(arg1, arg2, optp->opcode));
161*2e192b24SSimon Glass 			} else {
162*2e192b24SSimon Glass 				return (arithcomp (arg1, arg2, optp->opcode, w));
163*2e192b24SSimon Glass 			}
164*2e192b24SSimon Glass 		}
165*2e192b24SSimon Glass 	}
166*2e192b24SSimon Glass 
167*2e192b24SSimon Glass 	printf("Unknown operator '%s'\n", op);
168*2e192b24SSimon Glass 	return 0;	/* op code not found */
169*2e192b24SSimon Glass }
170*2e192b24SSimon Glass 
171*2e192b24SSimon Glass /* command line interface to the shell test */
172*2e192b24SSimon Glass static int do_itest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
173*2e192b24SSimon Glass {
174*2e192b24SSimon Glass 	int	value, w;
175*2e192b24SSimon Glass 
176*2e192b24SSimon Glass 	/* Validate arguments */
177*2e192b24SSimon Glass 	if ((argc != 4))
178*2e192b24SSimon Glass 		return CMD_RET_USAGE;
179*2e192b24SSimon Glass 
180*2e192b24SSimon Glass 	/* Check for a data width specification.
181*2e192b24SSimon Glass 	 * Defaults to long (4) if no specification.
182*2e192b24SSimon Glass 	 * Uses -2 as 'width' for .s (string) so as not to upset existing code
183*2e192b24SSimon Glass 	 */
184*2e192b24SSimon Glass 	switch (w = cmd_get_data_size(argv[0], 4)) {
185*2e192b24SSimon Glass 	case 1:
186*2e192b24SSimon Glass 	case 2:
187*2e192b24SSimon Glass 	case 4:
188*2e192b24SSimon Glass 		value = binary_test (argv[2], argv[1], argv[3], w);
189*2e192b24SSimon Glass 		break;
190*2e192b24SSimon Glass 	case -2:
191*2e192b24SSimon Glass 		value = binary_test (argv[2], argv[1], argv[3], 0);
192*2e192b24SSimon Glass 		break;
193*2e192b24SSimon Glass 	case -1:
194*2e192b24SSimon Glass 	default:
195*2e192b24SSimon Glass 		puts("Invalid data width specifier\n");
196*2e192b24SSimon Glass 		value = 0;
197*2e192b24SSimon Glass 		break;
198*2e192b24SSimon Glass 	}
199*2e192b24SSimon Glass 
200*2e192b24SSimon Glass 	return !value;
201*2e192b24SSimon Glass }
202*2e192b24SSimon Glass 
203*2e192b24SSimon Glass U_BOOT_CMD(
204*2e192b24SSimon Glass 	itest, 4, 0, do_itest,
205*2e192b24SSimon Glass 	"return true/false on integer compare",
206*2e192b24SSimon Glass 	"[.b, .w, .l, .s] [*]value1 <op> [*]value2"
207*2e192b24SSimon Glass );
208