]> git.ipfire.org Git - thirdparty/u-boot.git/blob - common/main.c
move CLI prototypes to cli.h and add comments
[thirdparty/u-boot.git] / common / main.c
1 /*
2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * Add to readline cmdline-editing by
6 * (C) Copyright 2005
7 * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com>
8 *
9 * SPDX-License-Identifier: GPL-2.0+
10 */
11
12 /* #define DEBUG */
13
14 #include <common.h>
15 #include <cli.h>
16 #include <command.h>
17 #include <fdtdec.h>
18 #include <cli_hush.h>
19 #include <malloc.h>
20 #include <menu.h>
21 #include <post.h>
22 #include <version.h>
23 #include <watchdog.h>
24 #include <linux/ctype.h>
25
26 DECLARE_GLOBAL_DATA_PTR;
27
28 /*
29 * Board-specific Platform code can reimplement show_boot_progress () if needed
30 */
31 void inline __show_boot_progress (int val) {}
32 void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress")));
33
34 #define MAX_DELAY_STOP_STR 32
35
36 #define DEBUG_PARSER 0 /* set to 1 to debug */
37
38 #define debug_parser(fmt, args...) \
39 debug_cond(DEBUG_PARSER, fmt, ##args)
40
41 #ifndef DEBUG_BOOTKEYS
42 #define DEBUG_BOOTKEYS 0
43 #endif
44 #define debug_bootkeys(fmt, args...) \
45 debug_cond(DEBUG_BOOTKEYS, fmt, ##args)
46
47 char console_buffer[CONFIG_SYS_CBSIZE + 1]; /* console I/O buffer */
48
49 static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen);
50 static const char erase_seq[] = "\b \b"; /* erase sequence */
51 static const char tab_seq[] = " "; /* used to expand TABs */
52
53 #ifdef CONFIG_BOOT_RETRY_TIME
54 static uint64_t endtime = 0; /* must be set, default is instant timeout */
55 static int retry_time = -1; /* -1 so can call readline before main_loop */
56 #endif
57
58 #define endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk())
59
60 #ifndef CONFIG_BOOT_RETRY_MIN
61 #define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME
62 #endif
63
64 #ifdef CONFIG_MODEM_SUPPORT
65 int do_mdm_init = 0;
66 extern void mdm_init(void); /* defined in board.c */
67 #endif
68
69 /***************************************************************************
70 * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
71 * returns: 0 - no key string, allow autoboot 1 - got key string, abort
72 */
73 #if defined(CONFIG_BOOTDELAY)
74 # if defined(CONFIG_AUTOBOOT_KEYED)
75 static int abortboot_keyed(int bootdelay)
76 {
77 int abort = 0;
78 uint64_t etime = endtick(bootdelay);
79 struct {
80 char* str;
81 u_int len;
82 int retry;
83 }
84 delaykey [] = {
85 { str: getenv ("bootdelaykey"), retry: 1 },
86 { str: getenv ("bootdelaykey2"), retry: 1 },
87 { str: getenv ("bootstopkey"), retry: 0 },
88 { str: getenv ("bootstopkey2"), retry: 0 },
89 };
90
91 char presskey [MAX_DELAY_STOP_STR];
92 u_int presskey_len = 0;
93 u_int presskey_max = 0;
94 u_int i;
95
96 #ifndef CONFIG_ZERO_BOOTDELAY_CHECK
97 if (bootdelay == 0)
98 return 0;
99 #endif
100
101 # ifdef CONFIG_AUTOBOOT_PROMPT
102 printf(CONFIG_AUTOBOOT_PROMPT);
103 # endif
104
105 # ifdef CONFIG_AUTOBOOT_DELAY_STR
106 if (delaykey[0].str == NULL)
107 delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
108 # endif
109 # ifdef CONFIG_AUTOBOOT_DELAY_STR2
110 if (delaykey[1].str == NULL)
111 delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2;
112 # endif
113 # ifdef CONFIG_AUTOBOOT_STOP_STR
114 if (delaykey[2].str == NULL)
115 delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR;
116 # endif
117 # ifdef CONFIG_AUTOBOOT_STOP_STR2
118 if (delaykey[3].str == NULL)
119 delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2;
120 # endif
121
122 for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {
123 delaykey[i].len = delaykey[i].str == NULL ?
124 0 : strlen (delaykey[i].str);
125 delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ?
126 MAX_DELAY_STOP_STR : delaykey[i].len;
127
128 presskey_max = presskey_max > delaykey[i].len ?
129 presskey_max : delaykey[i].len;
130
131 debug_bootkeys("%s key:<%s>\n",
132 delaykey[i].retry ? "delay" : "stop",
133 delaykey[i].str ? delaykey[i].str : "NULL");
134 }
135
136 /* In order to keep up with incoming data, check timeout only
137 * when catch up.
138 */
139 do {
140 if (tstc()) {
141 if (presskey_len < presskey_max) {
142 presskey [presskey_len ++] = getc();
143 }
144 else {
145 for (i = 0; i < presskey_max - 1; i ++)
146 presskey [i] = presskey [i + 1];
147
148 presskey [i] = getc();
149 }
150 }
151
152 for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {
153 if (delaykey[i].len > 0 &&
154 presskey_len >= delaykey[i].len &&
155 memcmp (presskey + presskey_len - delaykey[i].len,
156 delaykey[i].str,
157 delaykey[i].len) == 0) {
158 debug_bootkeys("got %skey\n",
159 delaykey[i].retry ? "delay" :
160 "stop");
161
162 # ifdef CONFIG_BOOT_RETRY_TIME
163 /* don't retry auto boot */
164 if (! delaykey[i].retry)
165 retry_time = -1;
166 # endif
167 abort = 1;
168 }
169 }
170 } while (!abort && get_ticks() <= etime);
171
172 if (!abort)
173 debug_bootkeys("key timeout\n");
174
175 #ifdef CONFIG_SILENT_CONSOLE
176 if (abort)
177 gd->flags &= ~GD_FLG_SILENT;
178 #endif
179
180 return abort;
181 }
182
183 # else /* !defined(CONFIG_AUTOBOOT_KEYED) */
184
185 #ifdef CONFIG_MENUKEY
186 static int menukey = 0;
187 #endif
188
189 static int abortboot_normal(int bootdelay)
190 {
191 int abort = 0;
192 unsigned long ts;
193
194 #ifdef CONFIG_MENUPROMPT
195 printf(CONFIG_MENUPROMPT);
196 #else
197 if (bootdelay >= 0)
198 printf("Hit any key to stop autoboot: %2d ", bootdelay);
199 #endif
200
201 #if defined CONFIG_ZERO_BOOTDELAY_CHECK
202 /*
203 * Check if key already pressed
204 * Don't check if bootdelay < 0
205 */
206 if (bootdelay >= 0) {
207 if (tstc()) { /* we got a key press */
208 (void) getc(); /* consume input */
209 puts ("\b\b\b 0");
210 abort = 1; /* don't auto boot */
211 }
212 }
213 #endif
214
215 while ((bootdelay > 0) && (!abort)) {
216 --bootdelay;
217 /* delay 1000 ms */
218 ts = get_timer(0);
219 do {
220 if (tstc()) { /* we got a key press */
221 abort = 1; /* don't auto boot */
222 bootdelay = 0; /* no more delay */
223 # ifdef CONFIG_MENUKEY
224 menukey = getc();
225 # else
226 (void) getc(); /* consume input */
227 # endif
228 break;
229 }
230 udelay(10000);
231 } while (!abort && get_timer(ts) < 1000);
232
233 printf("\b\b\b%2d ", bootdelay);
234 }
235
236 putc('\n');
237
238 #ifdef CONFIG_SILENT_CONSOLE
239 if (abort)
240 gd->flags &= ~GD_FLG_SILENT;
241 #endif
242
243 return abort;
244 }
245 # endif /* CONFIG_AUTOBOOT_KEYED */
246
247 static int abortboot(int bootdelay)
248 {
249 #ifdef CONFIG_AUTOBOOT_KEYED
250 return abortboot_keyed(bootdelay);
251 #else
252 return abortboot_normal(bootdelay);
253 #endif
254 }
255 #endif /* CONFIG_BOOTDELAY */
256
257 /*
258 * Runs the given boot command securely. Specifically:
259 * - Doesn't run the command with the shell (run_command or parse_string_outer),
260 * since that's a lot of code surface that an attacker might exploit.
261 * Because of this, we don't do any argument parsing--the secure boot command
262 * has to be a full-fledged u-boot command.
263 * - Doesn't check for keypresses before booting, since that could be a
264 * security hole; also disables Ctrl-C.
265 * - Doesn't allow the command to return.
266 *
267 * Upon any failures, this function will drop into an infinite loop after
268 * printing the error message to console.
269 */
270
271 #if defined(CONFIG_BOOTDELAY) && defined(CONFIG_OF_CONTROL)
272 static void secure_boot_cmd(char *cmd)
273 {
274 cmd_tbl_t *cmdtp;
275 int rc;
276
277 if (!cmd) {
278 printf("## Error: Secure boot command not specified\n");
279 goto err;
280 }
281
282 /* Disable Ctrl-C just in case some command is used that checks it. */
283 disable_ctrlc(1);
284
285 /* Find the command directly. */
286 cmdtp = find_cmd(cmd);
287 if (!cmdtp) {
288 printf("## Error: \"%s\" not defined\n", cmd);
289 goto err;
290 }
291
292 /* Run the command, forcing no flags and faking argc and argv. */
293 rc = (cmdtp->cmd)(cmdtp, 0, 1, &cmd);
294
295 /* Shouldn't ever return from boot command. */
296 printf("## Error: \"%s\" returned (code %d)\n", cmd, rc);
297
298 err:
299 /*
300 * Not a whole lot to do here. Rebooting won't help much, since we'll
301 * just end up right back here. Just loop.
302 */
303 hang();
304 }
305
306 static void process_fdt_options(const void *blob)
307 {
308 ulong addr;
309
310 /* Add an env variable to point to a kernel payload, if available */
311 addr = fdtdec_get_config_int(gd->fdt_blob, "kernel-offset", 0);
312 if (addr)
313 setenv_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
314
315 /* Add an env variable to point to a root disk, if available */
316 addr = fdtdec_get_config_int(gd->fdt_blob, "rootdisk-offset", 0);
317 if (addr)
318 setenv_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
319 }
320 #endif /* CONFIG_OF_CONTROL */
321
322 #ifdef CONFIG_BOOTDELAY
323 static void process_boot_delay(void)
324 {
325 #ifdef CONFIG_OF_CONTROL
326 char *env;
327 #endif
328 char *s;
329 int bootdelay;
330 #ifdef CONFIG_BOOTCOUNT_LIMIT
331 unsigned long bootcount = 0;
332 unsigned long bootlimit = 0;
333 #endif /* CONFIG_BOOTCOUNT_LIMIT */
334
335 #ifdef CONFIG_BOOTCOUNT_LIMIT
336 bootcount = bootcount_load();
337 bootcount++;
338 bootcount_store (bootcount);
339 setenv_ulong("bootcount", bootcount);
340 bootlimit = getenv_ulong("bootlimit", 10, 0);
341 #endif /* CONFIG_BOOTCOUNT_LIMIT */
342
343 s = getenv ("bootdelay");
344 bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
345
346 #ifdef CONFIG_OF_CONTROL
347 bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay",
348 bootdelay);
349 #endif
350
351 debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);
352
353 #if defined(CONFIG_MENU_SHOW)
354 bootdelay = menu_show(bootdelay);
355 #endif
356 # ifdef CONFIG_BOOT_RETRY_TIME
357 init_cmd_timeout ();
358 # endif /* CONFIG_BOOT_RETRY_TIME */
359
360 #ifdef CONFIG_POST
361 if (gd->flags & GD_FLG_POSTFAIL) {
362 s = getenv("failbootcmd");
363 }
364 else
365 #endif /* CONFIG_POST */
366 #ifdef CONFIG_BOOTCOUNT_LIMIT
367 if (bootlimit && (bootcount > bootlimit)) {
368 printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
369 (unsigned)bootlimit);
370 s = getenv ("altbootcmd");
371 }
372 else
373 #endif /* CONFIG_BOOTCOUNT_LIMIT */
374 s = getenv ("bootcmd");
375 #ifdef CONFIG_OF_CONTROL
376 /* Allow the fdt to override the boot command */
377 env = fdtdec_get_config_string(gd->fdt_blob, "bootcmd");
378 if (env)
379 s = env;
380
381 process_fdt_options(gd->fdt_blob);
382
383 /*
384 * If the bootsecure option was chosen, use secure_boot_cmd().
385 * Always use 'env' in this case, since bootsecure requres that the
386 * bootcmd was specified in the FDT too.
387 */
388 if (fdtdec_get_config_int(gd->fdt_blob, "bootsecure", 0))
389 secure_boot_cmd(env);
390
391 #endif /* CONFIG_OF_CONTROL */
392
393 debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
394
395 if (bootdelay != -1 && s && !abortboot(bootdelay)) {
396 #if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC)
397 int prev = disable_ctrlc(1); /* disable Control C checking */
398 #endif
399
400 run_command_list(s, -1, 0);
401
402 #if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC)
403 disable_ctrlc(prev); /* restore Control C checking */
404 #endif
405 }
406
407 #ifdef CONFIG_MENUKEY
408 if (menukey == CONFIG_MENUKEY) {
409 s = getenv("menucmd");
410 if (s)
411 run_command_list(s, -1, 0);
412 }
413 #endif /* CONFIG_MENUKEY */
414 }
415 #endif /* CONFIG_BOOTDELAY */
416
417 void main_loop(void)
418 {
419 #ifndef CONFIG_SYS_HUSH_PARSER
420 static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
421 int len;
422 int rc = 1;
423 int flag;
424 #endif
425 #ifdef CONFIG_PREBOOT
426 char *p;
427 #endif
428
429 bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
430
431 #ifndef CONFIG_SYS_GENERIC_BOARD
432 puts("Warning: Your board does not use generic board. Please read\n");
433 puts("doc/README.generic-board and take action. Boards not\n");
434 puts("upgraded by the late 2014 may break or be removed.\n");
435 #endif
436
437 #ifdef CONFIG_MODEM_SUPPORT
438 debug("DEBUG: main_loop: do_mdm_init=%d\n", do_mdm_init);
439 if (do_mdm_init) {
440 char *str = strdup(getenv("mdm_cmd"));
441 setenv("preboot", str); /* set or delete definition */
442 if (str != NULL)
443 free(str);
444 mdm_init(); /* wait for modem connection */
445 }
446 #endif /* CONFIG_MODEM_SUPPORT */
447
448 #ifdef CONFIG_VERSION_VARIABLE
449 {
450 setenv("ver", version_string); /* set version variable */
451 }
452 #endif /* CONFIG_VERSION_VARIABLE */
453
454 #ifdef CONFIG_SYS_HUSH_PARSER
455 u_boot_hush_start();
456 #endif
457
458 #if defined(CONFIG_HUSH_INIT_VAR)
459 hush_init_var();
460 #endif
461
462 #ifdef CONFIG_PREBOOT
463 p = getenv("preboot");
464 if (p != NULL) {
465 # ifdef CONFIG_AUTOBOOT_KEYED
466 int prev = disable_ctrlc(1); /* disable Control C checking */
467 # endif
468
469 run_command_list(p, -1, 0);
470
471 # ifdef CONFIG_AUTOBOOT_KEYED
472 disable_ctrlc(prev); /* restore Control C checking */
473 # endif
474 }
475 #endif /* CONFIG_PREBOOT */
476
477 #if defined(CONFIG_UPDATE_TFTP)
478 update_tftp(0UL);
479 #endif /* CONFIG_UPDATE_TFTP */
480
481 #ifdef CONFIG_BOOTDELAY
482 process_boot_delay();
483 #endif
484 /*
485 * Main Loop for Monitor Command Processing
486 */
487 #ifdef CONFIG_SYS_HUSH_PARSER
488 parse_file_outer();
489 /* This point is never reached */
490 for (;;);
491 #else
492 for (;;) {
493 #ifdef CONFIG_BOOT_RETRY_TIME
494 if (rc >= 0) {
495 /* Saw enough of a valid command to
496 * restart the timeout.
497 */
498 reset_cmd_timeout();
499 }
500 #endif
501 len = readline (CONFIG_SYS_PROMPT);
502
503 flag = 0; /* assume no special flags for now */
504 if (len > 0)
505 strcpy (lastcommand, console_buffer);
506 else if (len == 0)
507 flag |= CMD_FLAG_REPEAT;
508 #ifdef CONFIG_BOOT_RETRY_TIME
509 else if (len == -2) {
510 /* -2 means timed out, retry autoboot
511 */
512 puts ("\nTimed out waiting for command\n");
513 # ifdef CONFIG_RESET_TO_RETRY
514 /* Reinit board to run initialization code again */
515 do_reset (NULL, 0, 0, NULL);
516 # else
517 return; /* retry autoboot */
518 # endif
519 }
520 #endif
521
522 if (len == -1)
523 puts ("<INTERRUPT>\n");
524 else
525 rc = run_command(lastcommand, flag);
526
527 if (rc <= 0) {
528 /* invalid command or not repeatable, forget it */
529 lastcommand[0] = 0;
530 }
531 }
532 #endif /*CONFIG_SYS_HUSH_PARSER*/
533 }
534
535 #ifdef CONFIG_BOOT_RETRY_TIME
536 /***************************************************************************
537 * initialize command line timeout
538 */
539 void init_cmd_timeout(void)
540 {
541 char *s = getenv ("bootretry");
542
543 if (s != NULL)
544 retry_time = (int)simple_strtol(s, NULL, 10);
545 else
546 retry_time = CONFIG_BOOT_RETRY_TIME;
547
548 if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN)
549 retry_time = CONFIG_BOOT_RETRY_MIN;
550 }
551
552 /***************************************************************************
553 * reset command line timeout to retry_time seconds
554 */
555 void reset_cmd_timeout(void)
556 {
557 endtime = endtick(retry_time);
558 }
559 #endif
560
561 #ifdef CONFIG_CMDLINE_EDITING
562
563 /*
564 * cmdline-editing related codes from vivi.
565 * Author: Janghoon Lyu <nandy@mizi.com>
566 */
567
568 #define putnstr(str,n) do { \
569 printf ("%.*s", (int)n, str); \
570 } while (0)
571
572 #define CTL_CH(c) ((c) - 'a' + 1)
573 #define CTL_BACKSPACE ('\b')
574 #define DEL ((char)255)
575 #define DEL7 ((char)127)
576 #define CREAD_HIST_CHAR ('!')
577
578 #define getcmd_putch(ch) putc(ch)
579 #define getcmd_getch() getc()
580 #define getcmd_cbeep() getcmd_putch('\a')
581
582 #define HIST_MAX 20
583 #define HIST_SIZE CONFIG_SYS_CBSIZE
584
585 static int hist_max;
586 static int hist_add_idx;
587 static int hist_cur = -1;
588 static unsigned hist_num;
589
590 static char *hist_list[HIST_MAX];
591 static char hist_lines[HIST_MAX][HIST_SIZE + 1]; /* Save room for NULL */
592
593 #define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1)
594
595 static void hist_init(void)
596 {
597 int i;
598
599 hist_max = 0;
600 hist_add_idx = 0;
601 hist_cur = -1;
602 hist_num = 0;
603
604 for (i = 0; i < HIST_MAX; i++) {
605 hist_list[i] = hist_lines[i];
606 hist_list[i][0] = '\0';
607 }
608 }
609
610 static void cread_add_to_hist(char *line)
611 {
612 strcpy(hist_list[hist_add_idx], line);
613
614 if (++hist_add_idx >= HIST_MAX)
615 hist_add_idx = 0;
616
617 if (hist_add_idx > hist_max)
618 hist_max = hist_add_idx;
619
620 hist_num++;
621 }
622
623 static char* hist_prev(void)
624 {
625 char *ret;
626 int old_cur;
627
628 if (hist_cur < 0)
629 return NULL;
630
631 old_cur = hist_cur;
632 if (--hist_cur < 0)
633 hist_cur = hist_max;
634
635 if (hist_cur == hist_add_idx) {
636 hist_cur = old_cur;
637 ret = NULL;
638 } else
639 ret = hist_list[hist_cur];
640
641 return (ret);
642 }
643
644 static char* hist_next(void)
645 {
646 char *ret;
647
648 if (hist_cur < 0)
649 return NULL;
650
651 if (hist_cur == hist_add_idx)
652 return NULL;
653
654 if (++hist_cur > hist_max)
655 hist_cur = 0;
656
657 if (hist_cur == hist_add_idx) {
658 ret = "";
659 } else
660 ret = hist_list[hist_cur];
661
662 return (ret);
663 }
664
665 #ifndef CONFIG_CMDLINE_EDITING
666 static void cread_print_hist_list(void)
667 {
668 int i;
669 unsigned long n;
670
671 n = hist_num - hist_max;
672
673 i = hist_add_idx + 1;
674 while (1) {
675 if (i > hist_max)
676 i = 0;
677 if (i == hist_add_idx)
678 break;
679 printf("%s\n", hist_list[i]);
680 n++;
681 i++;
682 }
683 }
684 #endif /* CONFIG_CMDLINE_EDITING */
685
686 #define BEGINNING_OF_LINE() { \
687 while (num) { \
688 getcmd_putch(CTL_BACKSPACE); \
689 num--; \
690 } \
691 }
692
693 #define ERASE_TO_EOL() { \
694 if (num < eol_num) { \
695 printf("%*s", (int)(eol_num - num), ""); \
696 do { \
697 getcmd_putch(CTL_BACKSPACE); \
698 } while (--eol_num > num); \
699 } \
700 }
701
702 #define REFRESH_TO_EOL() { \
703 if (num < eol_num) { \
704 wlen = eol_num - num; \
705 putnstr(buf + num, wlen); \
706 num = eol_num; \
707 } \
708 }
709
710 static void cread_add_char(char ichar, int insert, unsigned long *num,
711 unsigned long *eol_num, char *buf, unsigned long len)
712 {
713 unsigned long wlen;
714
715 /* room ??? */
716 if (insert || *num == *eol_num) {
717 if (*eol_num > len - 1) {
718 getcmd_cbeep();
719 return;
720 }
721 (*eol_num)++;
722 }
723
724 if (insert) {
725 wlen = *eol_num - *num;
726 if (wlen > 1) {
727 memmove(&buf[*num+1], &buf[*num], wlen-1);
728 }
729
730 buf[*num] = ichar;
731 putnstr(buf + *num, wlen);
732 (*num)++;
733 while (--wlen) {
734 getcmd_putch(CTL_BACKSPACE);
735 }
736 } else {
737 /* echo the character */
738 wlen = 1;
739 buf[*num] = ichar;
740 putnstr(buf + *num, wlen);
741 (*num)++;
742 }
743 }
744
745 static void cread_add_str(char *str, int strsize, int insert, unsigned long *num,
746 unsigned long *eol_num, char *buf, unsigned long len)
747 {
748 while (strsize--) {
749 cread_add_char(*str, insert, num, eol_num, buf, len);
750 str++;
751 }
752 }
753
754 static int cread_line(const char *const prompt, char *buf, unsigned int *len,
755 int timeout)
756 {
757 unsigned long num = 0;
758 unsigned long eol_num = 0;
759 unsigned long wlen;
760 char ichar;
761 int insert = 1;
762 int esc_len = 0;
763 char esc_save[8];
764 int init_len = strlen(buf);
765 int first = 1;
766
767 if (init_len)
768 cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len);
769
770 while (1) {
771 #ifdef CONFIG_BOOT_RETRY_TIME
772 while (!tstc()) { /* while no incoming data */
773 if (retry_time >= 0 && get_ticks() > endtime)
774 return (-2); /* timed out */
775 WATCHDOG_RESET();
776 }
777 #endif
778 if (first && timeout) {
779 uint64_t etime = endtick(timeout);
780
781 while (!tstc()) { /* while no incoming data */
782 if (get_ticks() >= etime)
783 return -2; /* timed out */
784 WATCHDOG_RESET();
785 }
786 first = 0;
787 }
788
789 ichar = getcmd_getch();
790
791 if ((ichar == '\n') || (ichar == '\r')) {
792 putc('\n');
793 break;
794 }
795
796 /*
797 * handle standard linux xterm esc sequences for arrow key, etc.
798 */
799 if (esc_len != 0) {
800 if (esc_len == 1) {
801 if (ichar == '[') {
802 esc_save[esc_len] = ichar;
803 esc_len = 2;
804 } else {
805 cread_add_str(esc_save, esc_len, insert,
806 &num, &eol_num, buf, *len);
807 esc_len = 0;
808 }
809 continue;
810 }
811
812 switch (ichar) {
813
814 case 'D': /* <- key */
815 ichar = CTL_CH('b');
816 esc_len = 0;
817 break;
818 case 'C': /* -> key */
819 ichar = CTL_CH('f');
820 esc_len = 0;
821 break; /* pass off to ^F handler */
822 case 'H': /* Home key */
823 ichar = CTL_CH('a');
824 esc_len = 0;
825 break; /* pass off to ^A handler */
826 case 'A': /* up arrow */
827 ichar = CTL_CH('p');
828 esc_len = 0;
829 break; /* pass off to ^P handler */
830 case 'B': /* down arrow */
831 ichar = CTL_CH('n');
832 esc_len = 0;
833 break; /* pass off to ^N handler */
834 default:
835 esc_save[esc_len++] = ichar;
836 cread_add_str(esc_save, esc_len, insert,
837 &num, &eol_num, buf, *len);
838 esc_len = 0;
839 continue;
840 }
841 }
842
843 switch (ichar) {
844 case 0x1b:
845 if (esc_len == 0) {
846 esc_save[esc_len] = ichar;
847 esc_len = 1;
848 } else {
849 puts("impossible condition #876\n");
850 esc_len = 0;
851 }
852 break;
853
854 case CTL_CH('a'):
855 BEGINNING_OF_LINE();
856 break;
857 case CTL_CH('c'): /* ^C - break */
858 *buf = '\0'; /* discard input */
859 return (-1);
860 case CTL_CH('f'):
861 if (num < eol_num) {
862 getcmd_putch(buf[num]);
863 num++;
864 }
865 break;
866 case CTL_CH('b'):
867 if (num) {
868 getcmd_putch(CTL_BACKSPACE);
869 num--;
870 }
871 break;
872 case CTL_CH('d'):
873 if (num < eol_num) {
874 wlen = eol_num - num - 1;
875 if (wlen) {
876 memmove(&buf[num], &buf[num+1], wlen);
877 putnstr(buf + num, wlen);
878 }
879
880 getcmd_putch(' ');
881 do {
882 getcmd_putch(CTL_BACKSPACE);
883 } while (wlen--);
884 eol_num--;
885 }
886 break;
887 case CTL_CH('k'):
888 ERASE_TO_EOL();
889 break;
890 case CTL_CH('e'):
891 REFRESH_TO_EOL();
892 break;
893 case CTL_CH('o'):
894 insert = !insert;
895 break;
896 case CTL_CH('x'):
897 case CTL_CH('u'):
898 BEGINNING_OF_LINE();
899 ERASE_TO_EOL();
900 break;
901 case DEL:
902 case DEL7:
903 case 8:
904 if (num) {
905 wlen = eol_num - num;
906 num--;
907 memmove(&buf[num], &buf[num+1], wlen);
908 getcmd_putch(CTL_BACKSPACE);
909 putnstr(buf + num, wlen);
910 getcmd_putch(' ');
911 do {
912 getcmd_putch(CTL_BACKSPACE);
913 } while (wlen--);
914 eol_num--;
915 }
916 break;
917 case CTL_CH('p'):
918 case CTL_CH('n'):
919 {
920 char * hline;
921
922 esc_len = 0;
923
924 if (ichar == CTL_CH('p'))
925 hline = hist_prev();
926 else
927 hline = hist_next();
928
929 if (!hline) {
930 getcmd_cbeep();
931 continue;
932 }
933
934 /* nuke the current line */
935 /* first, go home */
936 BEGINNING_OF_LINE();
937
938 /* erase to end of line */
939 ERASE_TO_EOL();
940
941 /* copy new line into place and display */
942 strcpy(buf, hline);
943 eol_num = strlen(buf);
944 REFRESH_TO_EOL();
945 continue;
946 }
947 #ifdef CONFIG_AUTO_COMPLETE
948 case '\t': {
949 int num2, col;
950
951 /* do not autocomplete when in the middle */
952 if (num < eol_num) {
953 getcmd_cbeep();
954 break;
955 }
956
957 buf[num] = '\0';
958 col = strlen(prompt) + eol_num;
959 num2 = num;
960 if (cmd_auto_complete(prompt, buf, &num2, &col)) {
961 col = num2 - num;
962 num += col;
963 eol_num += col;
964 }
965 break;
966 }
967 #endif
968 default:
969 cread_add_char(ichar, insert, &num, &eol_num, buf, *len);
970 break;
971 }
972 }
973 *len = eol_num;
974 buf[eol_num] = '\0'; /* lose the newline */
975
976 if (buf[0] && buf[0] != CREAD_HIST_CHAR)
977 cread_add_to_hist(buf);
978 hist_cur = hist_add_idx;
979
980 return 0;
981 }
982
983 #endif /* CONFIG_CMDLINE_EDITING */
984
985 /****************************************************************************/
986
987 /*
988 * Prompt for input and read a line.
989 * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0,
990 * time out when time goes past endtime (timebase time in ticks).
991 * Return: number of read characters
992 * -1 if break
993 * -2 if timed out
994 */
995 int readline (const char *const prompt)
996 {
997 /*
998 * If console_buffer isn't 0-length the user will be prompted to modify
999 * it instead of entering it from scratch as desired.
1000 */
1001 console_buffer[0] = '\0';
1002
1003 return readline_into_buffer(prompt, console_buffer, 0);
1004 }
1005
1006
1007 int readline_into_buffer(const char *const prompt, char *buffer, int timeout)
1008 {
1009 char *p = buffer;
1010 #ifdef CONFIG_CMDLINE_EDITING
1011 unsigned int len = CONFIG_SYS_CBSIZE;
1012 int rc;
1013 static int initted = 0;
1014
1015 /*
1016 * History uses a global array which is not
1017 * writable until after relocation to RAM.
1018 * Revert to non-history version if still
1019 * running from flash.
1020 */
1021 if (gd->flags & GD_FLG_RELOC) {
1022 if (!initted) {
1023 hist_init();
1024 initted = 1;
1025 }
1026
1027 if (prompt)
1028 puts (prompt);
1029
1030 rc = cread_line(prompt, p, &len, timeout);
1031 return rc < 0 ? rc : len;
1032
1033 } else {
1034 #endif /* CONFIG_CMDLINE_EDITING */
1035 char * p_buf = p;
1036 int n = 0; /* buffer index */
1037 int plen = 0; /* prompt length */
1038 int col; /* output column cnt */
1039 char c;
1040
1041 /* print prompt */
1042 if (prompt) {
1043 plen = strlen (prompt);
1044 puts (prompt);
1045 }
1046 col = plen;
1047
1048 for (;;) {
1049 #ifdef CONFIG_BOOT_RETRY_TIME
1050 while (!tstc()) { /* while no incoming data */
1051 if (retry_time >= 0 && get_ticks() > endtime)
1052 return (-2); /* timed out */
1053 WATCHDOG_RESET();
1054 }
1055 #endif
1056 WATCHDOG_RESET(); /* Trigger watchdog, if needed */
1057
1058 #ifdef CONFIG_SHOW_ACTIVITY
1059 while (!tstc()) {
1060 show_activity(0);
1061 WATCHDOG_RESET();
1062 }
1063 #endif
1064 c = getc();
1065
1066 /*
1067 * Special character handling
1068 */
1069 switch (c) {
1070 case '\r': /* Enter */
1071 case '\n':
1072 *p = '\0';
1073 puts ("\r\n");
1074 return p - p_buf;
1075
1076 case '\0': /* nul */
1077 continue;
1078
1079 case 0x03: /* ^C - break */
1080 p_buf[0] = '\0'; /* discard input */
1081 return -1;
1082
1083 case 0x15: /* ^U - erase line */
1084 while (col > plen) {
1085 puts (erase_seq);
1086 --col;
1087 }
1088 p = p_buf;
1089 n = 0;
1090 continue;
1091
1092 case 0x17: /* ^W - erase word */
1093 p=delete_char(p_buf, p, &col, &n, plen);
1094 while ((n > 0) && (*p != ' ')) {
1095 p=delete_char(p_buf, p, &col, &n, plen);
1096 }
1097 continue;
1098
1099 case 0x08: /* ^H - backspace */
1100 case 0x7F: /* DEL - backspace */
1101 p=delete_char(p_buf, p, &col, &n, plen);
1102 continue;
1103
1104 default:
1105 /*
1106 * Must be a normal character then
1107 */
1108 if (n < CONFIG_SYS_CBSIZE-2) {
1109 if (c == '\t') { /* expand TABs */
1110 #ifdef CONFIG_AUTO_COMPLETE
1111 /* if auto completion triggered just continue */
1112 *p = '\0';
1113 if (cmd_auto_complete(prompt, console_buffer, &n, &col)) {
1114 p = p_buf + n; /* reset */
1115 continue;
1116 }
1117 #endif
1118 puts (tab_seq+(col&07));
1119 col += 8 - (col&07);
1120 } else {
1121 char buf[2];
1122
1123 /*
1124 * Echo input using puts() to force an
1125 * LCD flush if we are using an LCD
1126 */
1127 ++col;
1128 buf[0] = c;
1129 buf[1] = '\0';
1130 puts(buf);
1131 }
1132 *p++ = c;
1133 ++n;
1134 } else { /* Buffer full */
1135 putc ('\a');
1136 }
1137 }
1138 }
1139 #ifdef CONFIG_CMDLINE_EDITING
1140 }
1141 #endif
1142 }
1143
1144 /****************************************************************************/
1145
1146 static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen)
1147 {
1148 char *s;
1149
1150 if (*np == 0) {
1151 return (p);
1152 }
1153
1154 if (*(--p) == '\t') { /* will retype the whole line */
1155 while (*colp > plen) {
1156 puts (erase_seq);
1157 (*colp)--;
1158 }
1159 for (s=buffer; s<p; ++s) {
1160 if (*s == '\t') {
1161 puts (tab_seq+((*colp) & 07));
1162 *colp += 8 - ((*colp) & 07);
1163 } else {
1164 ++(*colp);
1165 putc (*s);
1166 }
1167 }
1168 } else {
1169 puts (erase_seq);
1170 (*colp)--;
1171 }
1172 (*np)--;
1173 return (p);
1174 }
1175
1176 /****************************************************************************/
1177
1178 int parse_line (char *line, char *argv[])
1179 {
1180 int nargs = 0;
1181
1182 debug_parser("parse_line: \"%s\"\n", line);
1183 while (nargs < CONFIG_SYS_MAXARGS) {
1184
1185 /* skip any white space */
1186 while (isblank(*line))
1187 ++line;
1188
1189 if (*line == '\0') { /* end of line, no more args */
1190 argv[nargs] = NULL;
1191 debug_parser("parse_line: nargs=%d\n", nargs);
1192 return nargs;
1193 }
1194
1195 argv[nargs++] = line; /* begin of argument string */
1196
1197 /* find end of string */
1198 while (*line && !isblank(*line))
1199 ++line;
1200
1201 if (*line == '\0') { /* end of line, no more args */
1202 argv[nargs] = NULL;
1203 debug_parser("parse_line: nargs=%d\n", nargs);
1204 return nargs;
1205 }
1206
1207 *line++ = '\0'; /* terminate current arg */
1208 }
1209
1210 printf ("** Too many args (max. %d) **\n", CONFIG_SYS_MAXARGS);
1211
1212 debug_parser("parse_line: nargs=%d\n", nargs);
1213 return (nargs);
1214 }
1215
1216 /****************************************************************************/
1217
1218 #ifndef CONFIG_SYS_HUSH_PARSER
1219 static void process_macros (const char *input, char *output)
1220 {
1221 char c, prev;
1222 const char *varname_start = NULL;
1223 int inputcnt = strlen (input);
1224 int outputcnt = CONFIG_SYS_CBSIZE;
1225 int state = 0; /* 0 = waiting for '$' */
1226
1227 /* 1 = waiting for '(' or '{' */
1228 /* 2 = waiting for ')' or '}' */
1229 /* 3 = waiting for ''' */
1230 char *output_start = output;
1231
1232 debug_parser("[PROCESS_MACROS] INPUT len %zd: \"%s\"\n", strlen(input),
1233 input);
1234
1235 prev = '\0'; /* previous character */
1236
1237 while (inputcnt && outputcnt) {
1238 c = *input++;
1239 inputcnt--;
1240
1241 if (state != 3) {
1242 /* remove one level of escape characters */
1243 if ((c == '\\') && (prev != '\\')) {
1244 if (inputcnt-- == 0)
1245 break;
1246 prev = c;
1247 c = *input++;
1248 }
1249 }
1250
1251 switch (state) {
1252 case 0: /* Waiting for (unescaped) $ */
1253 if ((c == '\'') && (prev != '\\')) {
1254 state = 3;
1255 break;
1256 }
1257 if ((c == '$') && (prev != '\\')) {
1258 state++;
1259 } else {
1260 *(output++) = c;
1261 outputcnt--;
1262 }
1263 break;
1264 case 1: /* Waiting for ( */
1265 if (c == '(' || c == '{') {
1266 state++;
1267 varname_start = input;
1268 } else {
1269 state = 0;
1270 *(output++) = '$';
1271 outputcnt--;
1272
1273 if (outputcnt) {
1274 *(output++) = c;
1275 outputcnt--;
1276 }
1277 }
1278 break;
1279 case 2: /* Waiting for ) */
1280 if (c == ')' || c == '}') {
1281 int i;
1282 char envname[CONFIG_SYS_CBSIZE], *envval;
1283 int envcnt = input - varname_start - 1; /* Varname # of chars */
1284
1285 /* Get the varname */
1286 for (i = 0; i < envcnt; i++) {
1287 envname[i] = varname_start[i];
1288 }
1289 envname[i] = 0;
1290
1291 /* Get its value */
1292 envval = getenv (envname);
1293
1294 /* Copy into the line if it exists */
1295 if (envval != NULL)
1296 while ((*envval) && outputcnt) {
1297 *(output++) = *(envval++);
1298 outputcnt--;
1299 }
1300 /* Look for another '$' */
1301 state = 0;
1302 }
1303 break;
1304 case 3: /* Waiting for ' */
1305 if ((c == '\'') && (prev != '\\')) {
1306 state = 0;
1307 } else {
1308 *(output++) = c;
1309 outputcnt--;
1310 }
1311 break;
1312 }
1313 prev = c;
1314 }
1315
1316 if (outputcnt)
1317 *output = 0;
1318 else
1319 *(output - 1) = 0;
1320
1321 debug_parser("[PROCESS_MACROS] OUTPUT len %zd: \"%s\"\n",
1322 strlen(output_start), output_start);
1323 }
1324
1325 /****************************************************************************
1326 * returns:
1327 * 1 - command executed, repeatable
1328 * 0 - command executed but not repeatable, interrupted commands are
1329 * always considered not repeatable
1330 * -1 - not executed (unrecognized, bootd recursion or too many args)
1331 * (If cmd is NULL or "" or longer than CONFIG_SYS_CBSIZE-1 it is
1332 * considered unrecognized)
1333 *
1334 * WARNING:
1335 *
1336 * We must create a temporary copy of the command since the command we get
1337 * may be the result from getenv(), which returns a pointer directly to
1338 * the environment data, which may change magicly when the command we run
1339 * creates or modifies environment variables (like "bootp" does).
1340 */
1341 static int builtin_run_command(const char *cmd, int flag)
1342 {
1343 char cmdbuf[CONFIG_SYS_CBSIZE]; /* working copy of cmd */
1344 char *token; /* start of token in cmdbuf */
1345 char *sep; /* end of token (separator) in cmdbuf */
1346 char finaltoken[CONFIG_SYS_CBSIZE];
1347 char *str = cmdbuf;
1348 char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */
1349 int argc, inquotes;
1350 int repeatable = 1;
1351 int rc = 0;
1352
1353 debug_parser("[RUN_COMMAND] cmd[%p]=\"", cmd);
1354 if (DEBUG_PARSER) {
1355 /* use puts - string may be loooong */
1356 puts(cmd ? cmd : "NULL");
1357 puts("\"\n");
1358 }
1359 clear_ctrlc(); /* forget any previous Control C */
1360
1361 if (!cmd || !*cmd) {
1362 return -1; /* empty command */
1363 }
1364
1365 if (strlen(cmd) >= CONFIG_SYS_CBSIZE) {
1366 puts ("## Command too long!\n");
1367 return -1;
1368 }
1369
1370 strcpy (cmdbuf, cmd);
1371
1372 /* Process separators and check for invalid
1373 * repeatable commands
1374 */
1375
1376 debug_parser("[PROCESS_SEPARATORS] %s\n", cmd);
1377 while (*str) {
1378
1379 /*
1380 * Find separator, or string end
1381 * Allow simple escape of ';' by writing "\;"
1382 */
1383 for (inquotes = 0, sep = str; *sep; sep++) {
1384 if ((*sep=='\'') &&
1385 (*(sep-1) != '\\'))
1386 inquotes=!inquotes;
1387
1388 if (!inquotes &&
1389 (*sep == ';') && /* separator */
1390 ( sep != str) && /* past string start */
1391 (*(sep-1) != '\\')) /* and NOT escaped */
1392 break;
1393 }
1394
1395 /*
1396 * Limit the token to data between separators
1397 */
1398 token = str;
1399 if (*sep) {
1400 str = sep + 1; /* start of command for next pass */
1401 *sep = '\0';
1402 }
1403 else
1404 str = sep; /* no more commands for next pass */
1405 debug_parser("token: \"%s\"\n", token);
1406
1407 /* find macros in this token and replace them */
1408 process_macros (token, finaltoken);
1409
1410 /* Extract arguments */
1411 if ((argc = parse_line (finaltoken, argv)) == 0) {
1412 rc = -1; /* no command at all */
1413 continue;
1414 }
1415
1416 if (cmd_process(flag, argc, argv, &repeatable, NULL))
1417 rc = -1;
1418
1419 /* Did the user stop this? */
1420 if (had_ctrlc ())
1421 return -1; /* if stopped then not repeatable */
1422 }
1423
1424 return rc ? rc : repeatable;
1425 }
1426 #endif
1427
1428 /*
1429 * Run a command using the selected parser.
1430 *
1431 * @param cmd Command to run
1432 * @param flag Execution flags (CMD_FLAG_...)
1433 * @return 0 on success, or != 0 on error.
1434 */
1435 int run_command(const char *cmd, int flag)
1436 {
1437 #ifndef CONFIG_SYS_HUSH_PARSER
1438 /*
1439 * builtin_run_command can return 0 or 1 for success, so clean up
1440 * its result.
1441 */
1442 if (builtin_run_command(cmd, flag) == -1)
1443 return 1;
1444
1445 return 0;
1446 #else
1447 return parse_string_outer(cmd,
1448 FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
1449 #endif
1450 }
1451
1452 #ifndef CONFIG_SYS_HUSH_PARSER
1453 /**
1454 * Execute a list of command separated by ; or \n using the built-in parser.
1455 *
1456 * This function cannot take a const char * for the command, since if it
1457 * finds newlines in the string, it replaces them with \0.
1458 *
1459 * @param cmd String containing list of commands
1460 * @param flag Execution flags (CMD_FLAG_...)
1461 * @return 0 on success, or != 0 on error.
1462 */
1463 static int builtin_run_command_list(char *cmd, int flag)
1464 {
1465 char *line, *next;
1466 int rcode = 0;
1467
1468 /*
1469 * Break into individual lines, and execute each line; terminate on
1470 * error.
1471 */
1472 line = next = cmd;
1473 while (*next) {
1474 if (*next == '\n') {
1475 *next = '\0';
1476 /* run only non-empty commands */
1477 if (*line) {
1478 debug("** exec: \"%s\"\n", line);
1479 if (builtin_run_command(line, 0) < 0) {
1480 rcode = 1;
1481 break;
1482 }
1483 }
1484 line = next + 1;
1485 }
1486 ++next;
1487 }
1488 if (rcode == 0 && *line)
1489 rcode = (builtin_run_command(line, 0) >= 0);
1490
1491 return rcode;
1492 }
1493 #endif
1494
1495 int run_command_list(const char *cmd, int len, int flag)
1496 {
1497 int need_buff = 1;
1498 char *buff = (char *)cmd; /* cast away const */
1499 int rcode = 0;
1500
1501 if (len == -1) {
1502 len = strlen(cmd);
1503 #ifdef CONFIG_SYS_HUSH_PARSER
1504 /* hush will never change our string */
1505 need_buff = 0;
1506 #else
1507 /* the built-in parser will change our string if it sees \n */
1508 need_buff = strchr(cmd, '\n') != NULL;
1509 #endif
1510 }
1511 if (need_buff) {
1512 buff = malloc(len + 1);
1513 if (!buff)
1514 return 1;
1515 memcpy(buff, cmd, len);
1516 buff[len] = '\0';
1517 }
1518 #ifdef CONFIG_SYS_HUSH_PARSER
1519 rcode = parse_string_outer(buff, FLAG_PARSE_SEMICOLON);
1520 #else
1521 /*
1522 * This function will overwrite any \n it sees with a \0, which
1523 * is why it can't work with a const char *. Here we are making
1524 * using of internal knowledge of this function, to avoid always
1525 * doing a malloc() which is actually required only in a case that
1526 * is pretty rare.
1527 */
1528 rcode = builtin_run_command_list(buff, flag);
1529 if (need_buff)
1530 free(buff);
1531 #endif
1532
1533 return rcode;
1534 }
1535
1536 /****************************************************************************/
1537
1538 #if defined(CONFIG_CMD_RUN)
1539 int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
1540 {
1541 int i;
1542
1543 if (argc < 2)
1544 return CMD_RET_USAGE;
1545
1546 for (i=1; i<argc; ++i) {
1547 char *arg;
1548
1549 if ((arg = getenv (argv[i])) == NULL) {
1550 printf ("## Error: \"%s\" not defined\n", argv[i]);
1551 return 1;
1552 }
1553
1554 if (run_command_list(arg, -1, flag) != 0)
1555 return 1;
1556 }
1557 return 0;
1558 }
1559 #endif