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