xref: /openbmc/u-boot/common/main.c (revision 18d66533ac773f59efc93e5c19971fad5e6af82f)
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
1560