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