Update QCA956x GPIO OUT functions list
[oweals/u-boot_mod.git] / u-boot / common / command.c
1 /*
2  * (C) Copyright 2000-2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier: GPL-2.0
6  */
7
8 /* Command Processor Table */
9 #include <common.h>
10 #include <command.h>
11
12 void print_cmd_help(cmd_tbl_t *cmdtp)
13 {
14 #ifdef CFG_LONGHELP
15         if (cmdtp->help != NULL) {
16                 printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->help);
17         } else {
18                 printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
19         }
20 #else
21         printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
22 #endif
23 }
24
25 int do_version(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
26 {
27         extern char version_string[];
28
29         puts("Version and build date:\n");
30         printf("  %s, " MK_STR(CONFIG_BUILD_DATE_UTC) "\n\n", version_string);
31
32         puts("Modification by:\n");
33         puts("  Piotr Dymacz <piotr@dymacz.pl>\n");
34         puts("  https://github.com/pepe2k/u-boot_mod\n\n");
35
36         return 0;
37 }
38
39 U_BOOT_CMD(version, 1, 1, do_version, "print U-Boot version\n", NULL);
40
41 #if defined(CONFIG_CMD_ECHO)
42 int do_echo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
43 {
44         int i;
45         int putnl = 1;
46
47         for (i = 1; i < argc; i++) {
48                 char *p = argv[i];
49                 char *nls; /* new-line suppression */
50
51                 if (i > 1)
52                         putc(' ');
53
54                 nls = strstr(p, "\\c");
55                 if (nls) {
56                         char *prenls = p;
57
58                         putnl = 0;
59                         /*
60                          * be paranoid and guess that someone might
61                          * say \c more than once
62                          */
63                         while (nls) {
64                                 *nls = '\0';
65                                 puts(prenls);
66                                 *nls = '\\';
67                                 prenls = nls + 2;
68                                 nls = strstr(prenls, "\\c");
69                         }
70                         puts(prenls);
71                 } else {
72                         puts(p);
73                 }
74         }
75
76         if (putnl)
77                 putc('\n');
78
79         return 0;
80 }
81
82 U_BOOT_CMD(echo, CFG_MAXARGS, 1, do_echo,
83         "echo args to console\n", "[args..]\n"
84         "\t- echo args to console; \\c suppresses newline\n");
85 #endif /* CONFIG_CMD_ECHO */
86
87 #ifdef CFG_HUSH_PARSER
88 int do_test(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
89 {
90         char **ap;
91         int adv, expr, last_expr, last_cmp, left, neg;
92
93         /* args? */
94         if (argc < 3)
95                 return 1;
96
97         last_expr = 0;
98         left = argc - 1;
99         ap = argv + 1;
100
101         if (left > 0 && strcmp(ap[0], "!") == 0) {
102                 neg = 1;
103                 ap++;
104                 left--;
105         } else {
106                 neg = 0;
107         }
108
109         expr = -1;
110         last_cmp = -1;
111         last_expr = -1;
112
113         while (left > 0) {
114                 if (strcmp(ap[0], "-o") == 0 ||
115                     strcmp(ap[0], "-a") == 0) {
116                         adv = 1;
117                 } else if (strcmp(ap[0], "-z") == 0 ||
118                            strcmp(ap[0], "-n") == 0) {
119                         adv = 2;
120                 } else {
121                         adv = 3;
122                 }
123
124                 if (left < adv) {
125                         expr = 1;
126                         break;
127                 }
128
129                 if (adv == 1) {
130                         if (strcmp(ap[0], "-o") == 0) {
131                                 last_expr = expr;
132                                 last_cmp = 0;
133                         } else if (strcmp(ap[0], "-a") == 0) {
134                                 last_expr = expr;
135                                 last_cmp = 1;
136                         } else {
137                                 expr = 1;
138                                 break;
139                         }
140                 }
141
142                 if (adv == 2) {
143                         if (strcmp(ap[0], "-z") == 0) {
144                                 expr = strlen(ap[1]) == 0 ? 1 : 0;
145                         } else if (strcmp(ap[0], "-n") == 0) {
146                                 expr = strlen(ap[1]) == 0 ? 0 : 1;
147                         } else {
148                                 expr = 1;
149                                 break;
150                         }
151
152                         if (last_cmp == 0) {
153                                 expr = last_expr || expr;
154                         } else if (last_cmp == 1) {
155                                 expr = last_expr && expr;
156                         }
157
158                         last_cmp = -1;
159                 }
160
161                 if (adv == 3) {
162                         if (strcmp(ap[1], "=") == 0) {
163                                 expr = strcmp(ap[0], ap[2]) == 0;
164                         } else if (strcmp(ap[1], "!=") == 0) {
165                                 expr = strcmp(ap[0], ap[2]) != 0;
166                         } else if (strcmp(ap[1], ">") == 0) {
167                                 expr = strcmp(ap[0], ap[2]) > 0;
168                         } else if (strcmp(ap[1], "<") == 0) {
169                                 expr = strcmp(ap[0], ap[2]) < 0;
170                         } else if (strcmp(ap[1], "-eq") == 0) {
171                                 expr = simple_strtol(ap[0], NULL, 10)
172                                        == simple_strtol(ap[2], NULL, 10);
173                         } else if (strcmp(ap[1], "-ne") == 0) {
174                                 expr = simple_strtol(ap[0], NULL, 10)
175                                        != simple_strtol(ap[2], NULL, 10);
176                         } else if (strcmp(ap[1], "-lt") == 0) {
177                                 expr = simple_strtol(ap[0], NULL, 10)
178                                        < simple_strtol(ap[2], NULL, 10);
179                         } else if (strcmp(ap[1], "-le") == 0) {
180                                 expr = simple_strtol(ap[0], NULL, 10)
181                                        <= simple_strtol(ap[2], NULL, 10);
182                         } else if (strcmp(ap[1], "-gt") == 0) {
183                                 expr = simple_strtol(ap[0], NULL, 10)
184                                        > simple_strtol(ap[2], NULL, 10);
185                         } else if (strcmp(ap[1], "-ge") == 0) {
186                                 expr = simple_strtol(ap[0], NULL, 10)
187                                        >= simple_strtol(ap[2], NULL, 10);
188                         } else {
189                                 expr = 1;
190                                 break;
191                         }
192
193                         if (last_cmp == 0) {
194                                 expr = last_expr || expr;
195                         } else if (last_cmp == 1) {
196                                 expr = last_expr && expr;
197                         }
198
199                         last_cmp = -1;
200                 }
201
202                 ap += adv; left -= adv;
203         }
204
205         if (neg)
206                 expr = !expr;
207
208         expr = !expr;
209
210         return expr;
211 }
212
213 U_BOOT_CMD(test, CFG_MAXARGS, 1, do_test,
214         "minimal test like /bin/sh\n", "[args..]\n"
215         "\t- test functionality\n");
216
217 int do_exit(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
218 {
219         int r = 0;
220
221         if (argc > 1)
222                 r = simple_strtoul(argv[1], NULL, 10);
223
224         return (-r - 2);
225 }
226
227 U_BOOT_CMD(exit, 2, 1, do_exit,
228         "exit script\n", "\n\t- exit functionality\n");
229 #endif /* CFG_HUSH_PARSER */
230
231 /*
232  * Use puts() instead of printf() to avoid printf buffer overflow
233  * for long help messages
234  */
235 int do_help(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
236 {
237         int i;
238         int rcode = 0;
239
240         /* Show list of commands */
241         if (argc == 1) {
242                 /* Pointer arith! */
243                 int cmd_items = &__u_boot_cmd_end - &__u_boot_cmd_start;
244
245                 cmd_tbl_t *cmd_array[cmd_items];
246                 int i, j, swaps, max_len = 0;
247
248                 /* Make array of commands from .uboot_cmd section */
249                 cmdtp = &__u_boot_cmd_start;
250
251                 for (i = 0; i < cmd_items; i++) {
252                         cmd_array[i] = cmdtp++;
253                 }
254
255                 /* Sort command list (trivial bubble sort) */
256                 for (i = cmd_items - 1; i > 0; --i) {
257                         swaps = 0;
258                         for (j = 0; j < i; ++j) {
259                                 const char *name = cmd_array[j]->name;
260
261                                 if (strlen(name) >= max_len)
262                                         max_len = strlen(name);
263
264                                 if (strcmp(cmd_array[j]->name,
265                                            cmd_array[j + 1]->name) > 0) {
266                                         cmd_tbl_t *tmp;
267                                         tmp = cmd_array[j];
268                                         cmd_array[j] = cmd_array[j + 1];
269                                         cmd_array[j + 1] = tmp;
270                                         ++swaps;
271                                 }
272                         }
273
274                         if (!swaps)
275                                 break;
276                 }
277
278                 /* Print short help (usage) */
279                 for (i = 0; i < cmd_items; i++) {
280                         const char *usage = cmd_array[i]->usage;
281                         const char *name = cmd_array[i]->name;
282
283                         /* Allow user abort */
284                         if (ctrlc())
285                                 return 1;
286
287                         if (usage == NULL)
288                                 continue;
289
290                         /* Print aligned command name and usage */
291                         printf("%-*s - ", max_len, name);
292                         puts(usage);
293                 }
294
295                 puts("\n");
296                 return 0;
297         }
298
299         /* Command help (long version) */
300         for (i = 1; i < argc; ++i) {
301                 if ((cmdtp = find_cmd(argv[i])) != NULL) {
302 #ifdef  CFG_LONGHELP
303                         /* Found - print (long) help info */
304                         puts(cmdtp->name);
305                         putc(' ');
306
307                         if (cmdtp->help) {
308                                 puts(cmdtp->help);
309                         } else {
310                                 puts("- there is no help for this command\n");
311                                 rcode = 1;
312                         }
313
314                         putc('\n');
315 #else
316                         if (cmdtp->usage)
317                                 puts(cmdtp->usage);
318 #endif /* CFG_LONGHELP */
319                 } else {
320                         printf("Unknown command '%s' - try 'help' without arguments\n\n", argv[i]);
321                         rcode = 1;
322                 }
323         }
324
325         return rcode;
326 }
327
328 U_BOOT_CMD(help, CFG_MAXARGS, 1, do_help,
329         "print embedded help\n", "[command ...]\n"
330         "\t- show help information for 'command' or short usage of all commands\n");
331
332 /* This do not ust the U_BOOT_CMD macro as ? can't be used in symbol names */
333 #ifdef CFG_LONGHELP
334 cmd_tbl_t __u_boot_cmd_question_mark Struct_Section = {"?", CFG_MAXARGS, 1, do_help, "alias for 'help'\n", NULL};
335 #else
336 cmd_tbl_t __u_boot_cmd_question_mark Struct_Section = {"?", CFG_MAXARGS, 1, do_help, "alias for 'help'\n"};
337 #endif /* CFG_LONGHELP */
338
339 /*
340  * Find command table entry for a command
341  */
342 cmd_tbl_t *find_cmd(const char *cmd)
343 {
344         int len;
345         int n_found = 0;
346         const char *p;
347         cmd_tbl_t *cmdtp;
348         cmd_tbl_t *cmdtp_temp = &__u_boot_cmd_start; /*Init value */
349
350         /*
351          * Some commands allow length modifiers (like "cp.b");
352          * compare command name only until first dot.
353          */
354         len = ((p = strchr(cmd, '.')) == NULL) ? strlen(cmd) : (p - cmd);
355
356         for (cmdtp = &__u_boot_cmd_start; cmdtp != &__u_boot_cmd_end; cmdtp++) {
357                 if (strncmp(cmd, cmdtp->name, len) == 0) {
358                         /* Full match? */
359                         if (len == strlen(cmdtp->name))
360                                 return cmdtp;
361
362                         /* Abbreviated command ? */
363                         cmdtp_temp = cmdtp;
364                         n_found++;
365                 }
366         }
367
368         /* Exactly one match */
369         if (n_found == 1)
370                 return(cmdtp_temp);
371
372         /* Not found or ambiguous command */
373         return NULL;
374 }