xref: /rk3399_rockchip-uboot/common/main.c (revision fbcdf32af74102276a154895f325d2cd92d1a3e9)
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 <command.h>
32 #include <fdtdec.h>
33 #include <hush.h>
34 #include <malloc.h>
35 #include <menu.h>
36 #include <post.h>
37 #include <version.h>
38 #include <watchdog.h>
39 #include <linux/ctype.h>
40 
41 DECLARE_GLOBAL_DATA_PTR;
42 
43 /*
44  * Board-specific Platform code can reimplement show_boot_progress () if needed
45  */
46 void inline __show_boot_progress (int val) {}
47 void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress")));
48 
49 #define MAX_DELAY_STOP_STR 32
50 
51 #undef DEBUG_PARSER
52 
53 char        console_buffer[CONFIG_SYS_CBSIZE + 1];	/* console I/O buffer	*/
54 
55 static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen);
56 static const char erase_seq[] = "\b \b";		/* erase sequence	*/
57 static const char   tab_seq[] = "        ";		/* used to expand TABs	*/
58 
59 #ifdef CONFIG_BOOT_RETRY_TIME
60 static uint64_t endtime = 0;  /* must be set, default is instant timeout */
61 static int      retry_time = -1; /* -1 so can call readline before main_loop */
62 #endif
63 
64 #define	endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk())
65 
66 #ifndef CONFIG_BOOT_RETRY_MIN
67 #define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME
68 #endif
69 
70 #ifdef CONFIG_MODEM_SUPPORT
71 int do_mdm_init = 0;
72 extern void mdm_init(void); /* defined in board.c */
73 #endif
74 
75 /***************************************************************************
76  * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
77  * returns: 0 -  no key string, allow autoboot 1 - got key string, abort
78  */
79 #if defined(CONFIG_BOOTDELAY)
80 # if defined(CONFIG_AUTOBOOT_KEYED)
81 static int abortboot_keyed(int bootdelay)
82 {
83 	int abort = 0;
84 	uint64_t etime = endtick(bootdelay);
85 	struct {
86 		char* str;
87 		u_int len;
88 		int retry;
89 	}
90 	delaykey [] = {
91 		{ str: getenv ("bootdelaykey"),  retry: 1 },
92 		{ str: getenv ("bootdelaykey2"), retry: 1 },
93 		{ str: getenv ("bootstopkey"),   retry: 0 },
94 		{ str: getenv ("bootstopkey2"),  retry: 0 },
95 	};
96 
97 	char presskey [MAX_DELAY_STOP_STR];
98 	u_int presskey_len = 0;
99 	u_int presskey_max = 0;
100 	u_int i;
101 
102 #ifndef CONFIG_ZERO_BOOTDELAY_CHECK
103 	if (bootdelay == 0)
104 		return 0;
105 #endif
106 
107 #  ifdef CONFIG_AUTOBOOT_PROMPT
108 	printf(CONFIG_AUTOBOOT_PROMPT);
109 #  endif
110 
111 #  ifdef CONFIG_AUTOBOOT_DELAY_STR
112 	if (delaykey[0].str == NULL)
113 		delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
114 #  endif
115 #  ifdef CONFIG_AUTOBOOT_DELAY_STR2
116 	if (delaykey[1].str == NULL)
117 		delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2;
118 #  endif
119 #  ifdef CONFIG_AUTOBOOT_STOP_STR
120 	if (delaykey[2].str == NULL)
121 		delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR;
122 #  endif
123 #  ifdef CONFIG_AUTOBOOT_STOP_STR2
124 	if (delaykey[3].str == NULL)
125 		delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2;
126 #  endif
127 
128 	for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {
129 		delaykey[i].len = delaykey[i].str == NULL ?
130 				    0 : strlen (delaykey[i].str);
131 		delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ?
132 				    MAX_DELAY_STOP_STR : delaykey[i].len;
133 
134 		presskey_max = presskey_max > delaykey[i].len ?
135 				    presskey_max : delaykey[i].len;
136 
137 #  if DEBUG_BOOTKEYS
138 		printf("%s key:<%s>\n",
139 		       delaykey[i].retry ? "delay" : "stop",
140 		       delaykey[i].str ? delaykey[i].str : "NULL");
141 #  endif
142 	}
143 
144 	/* In order to keep up with incoming data, check timeout only
145 	 * when catch up.
146 	 */
147 	do {
148 		if (tstc()) {
149 			if (presskey_len < presskey_max) {
150 				presskey [presskey_len ++] = getc();
151 			}
152 			else {
153 				for (i = 0; i < presskey_max - 1; i ++)
154 					presskey [i] = presskey [i + 1];
155 
156 				presskey [i] = getc();
157 			}
158 		}
159 
160 		for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {
161 			if (delaykey[i].len > 0 &&
162 			    presskey_len >= delaykey[i].len &&
163 			    memcmp (presskey + presskey_len - delaykey[i].len,
164 				    delaykey[i].str,
165 				    delaykey[i].len) == 0) {
166 #  if DEBUG_BOOTKEYS
167 				printf("got %skey\n",
168 				       delaykey[i].retry ? "delay" : "stop");
169 #  endif
170 
171 #  ifdef CONFIG_BOOT_RETRY_TIME
172 				/* don't retry auto boot */
173 				if (! delaykey[i].retry)
174 					retry_time = -1;
175 #  endif
176 				abort = 1;
177 			}
178 		}
179 	} while (!abort && get_ticks() <= etime);
180 
181 #  if DEBUG_BOOTKEYS
182 	if (!abort)
183 		puts("key timeout\n");
184 #  endif
185 
186 #ifdef CONFIG_SILENT_CONSOLE
187 	if (abort)
188 		gd->flags &= ~GD_FLG_SILENT;
189 #endif
190 
191 	return abort;
192 }
193 
194 # else	/* !defined(CONFIG_AUTOBOOT_KEYED) */
195 
196 #ifdef CONFIG_MENUKEY
197 static int menukey = 0;
198 #endif
199 
200 static int abortboot_normal(int bootdelay)
201 {
202 	int abort = 0;
203 	unsigned long ts;
204 
205 #ifdef CONFIG_MENUPROMPT
206 	printf(CONFIG_MENUPROMPT);
207 #else
208 	if (bootdelay >= 0)
209 		printf("Hit any key to stop autoboot: %2d ", bootdelay);
210 #endif
211 
212 #if defined CONFIG_ZERO_BOOTDELAY_CHECK
213 	/*
214 	 * Check if key already pressed
215 	 * Don't check if bootdelay < 0
216 	 */
217 	if (bootdelay >= 0) {
218 		if (tstc()) {	/* we got a key press	*/
219 			(void) getc();  /* consume input	*/
220 			puts ("\b\b\b 0");
221 			abort = 1;	/* don't auto boot	*/
222 		}
223 	}
224 #endif
225 
226 	while ((bootdelay > 0) && (!abort)) {
227 		--bootdelay;
228 		/* delay 1000 ms */
229 		ts = get_timer(0);
230 		do {
231 			if (tstc()) {	/* we got a key press	*/
232 				abort  = 1;	/* don't auto boot	*/
233 				bootdelay = 0;	/* no more delay	*/
234 # ifdef CONFIG_MENUKEY
235 				menukey = getc();
236 # else
237 				(void) getc();  /* consume input	*/
238 # endif
239 				break;
240 			}
241 			udelay(10000);
242 		} while (!abort && get_timer(ts) < 1000);
243 
244 		printf("\b\b\b%2d ", bootdelay);
245 	}
246 
247 	putc('\n');
248 
249 #ifdef CONFIG_SILENT_CONSOLE
250 	if (abort)
251 		gd->flags &= ~GD_FLG_SILENT;
252 #endif
253 
254 	return abort;
255 }
256 # endif	/* CONFIG_AUTOBOOT_KEYED */
257 
258 static int abortboot(int bootdelay)
259 {
260 #ifdef CONFIG_AUTOBOOT_KEYED
261 	return abortboot_keyed(bootdelay);
262 #else
263 	return abortboot_normal(bootdelay);
264 #endif
265 }
266 #endif	/* CONFIG_BOOTDELAY */
267 
268 /*
269  * Runs the given boot command securely.  Specifically:
270  * - Doesn't run the command with the shell (run_command or parse_string_outer),
271  *   since that's a lot of code surface that an attacker might exploit.
272  *   Because of this, we don't do any argument parsing--the secure boot command
273  *   has to be a full-fledged u-boot command.
274  * - Doesn't check for keypresses before booting, since that could be a
275  *   security hole; also disables Ctrl-C.
276  * - Doesn't allow the command to return.
277  *
278  * Upon any failures, this function will drop into an infinite loop after
279  * printing the error message to console.
280  */
281 
282 #if defined(CONFIG_BOOTDELAY) && defined(CONFIG_OF_CONTROL)
283 static void secure_boot_cmd(char *cmd)
284 {
285 	cmd_tbl_t *cmdtp;
286 	int rc;
287 
288 	if (!cmd) {
289 		printf("## Error: Secure boot command not specified\n");
290 		goto err;
291 	}
292 
293 	/* Disable Ctrl-C just in case some command is used that checks it. */
294 	disable_ctrlc(1);
295 
296 	/* Find the command directly. */
297 	cmdtp = find_cmd(cmd);
298 	if (!cmdtp) {
299 		printf("## Error: \"%s\" not defined\n", cmd);
300 		goto err;
301 	}
302 
303 	/* Run the command, forcing no flags and faking argc and argv. */
304 	rc = (cmdtp->cmd)(cmdtp, 0, 1, &cmd);
305 
306 	/* Shouldn't ever return from boot command. */
307 	printf("## Error: \"%s\" returned (code %d)\n", cmd, rc);
308 
309 err:
310 	/*
311 	 * Not a whole lot to do here.  Rebooting won't help much, since we'll
312 	 * just end up right back here.  Just loop.
313 	 */
314 	hang();
315 }
316 
317 static void process_fdt_options(const void *blob)
318 {
319 	ulong addr;
320 
321 	/* Add an env variable to point to a kernel payload, if available */
322 	addr = fdtdec_get_config_int(gd->fdt_blob, "kernel-offset", 0);
323 	if (addr)
324 		setenv_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
325 
326 	/* Add an env variable to point to a root disk, if available */
327 	addr = fdtdec_get_config_int(gd->fdt_blob, "rootdisk-offset", 0);
328 	if (addr)
329 		setenv_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
330 }
331 #endif /* CONFIG_OF_CONTROL */
332 
333 #ifdef CONFIG_BOOTDELAY
334 static void process_boot_delay(void)
335 {
336 #ifdef CONFIG_OF_CONTROL
337 	char *env;
338 #endif
339 	char *s;
340 	int bootdelay;
341 #ifdef CONFIG_BOOTCOUNT_LIMIT
342 	unsigned long bootcount = 0;
343 	unsigned long bootlimit = 0;
344 #endif /* CONFIG_BOOTCOUNT_LIMIT */
345 
346 #ifdef CONFIG_BOOTCOUNT_LIMIT
347 	bootcount = bootcount_load();
348 	bootcount++;
349 	bootcount_store (bootcount);
350 	setenv_ulong("bootcount", bootcount);
351 	bootlimit = getenv_ulong("bootlimit", 10, 0);
352 #endif /* CONFIG_BOOTCOUNT_LIMIT */
353 
354 	s = getenv ("bootdelay");
355 	bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
356 
357 	debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);
358 
359 #if defined(CONFIG_MENU_SHOW)
360 	bootdelay = menu_show(bootdelay);
361 #endif
362 # ifdef CONFIG_BOOT_RETRY_TIME
363 	init_cmd_timeout ();
364 # endif	/* CONFIG_BOOT_RETRY_TIME */
365 
366 #ifdef CONFIG_POST
367 	if (gd->flags & GD_FLG_POSTFAIL) {
368 		s = getenv("failbootcmd");
369 	}
370 	else
371 #endif /* CONFIG_POST */
372 #ifdef CONFIG_BOOTCOUNT_LIMIT
373 	if (bootlimit && (bootcount > bootlimit)) {
374 		printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
375 		        (unsigned)bootlimit);
376 		s = getenv ("altbootcmd");
377 	}
378 	else
379 #endif /* CONFIG_BOOTCOUNT_LIMIT */
380 		s = getenv ("bootcmd");
381 #ifdef CONFIG_OF_CONTROL
382 	/* Allow the fdt to override the boot command */
383 	env = fdtdec_get_config_string(gd->fdt_blob, "bootcmd");
384 	if (env)
385 		s = env;
386 
387 	process_fdt_options(gd->fdt_blob);
388 
389 	/*
390 	 * If the bootsecure option was chosen, use secure_boot_cmd().
391 	 * Always use 'env' in this case, since bootsecure requres that the
392 	 * bootcmd was specified in the FDT too.
393 	 */
394 	if (fdtdec_get_config_int(gd->fdt_blob, "bootsecure", 0))
395 		secure_boot_cmd(env);
396 
397 #endif /* CONFIG_OF_CONTROL */
398 
399 	debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
400 
401 	if (bootdelay != -1 && s && !abortboot(bootdelay)) {
402 #ifdef CONFIG_AUTOBOOT_KEYED
403 		int prev = disable_ctrlc(1);	/* disable Control C checking */
404 #endif
405 
406 		run_command_list(s, -1, 0);
407 
408 #ifdef CONFIG_AUTOBOOT_KEYED
409 		disable_ctrlc(prev);	/* restore Control C checking */
410 #endif
411 	}
412 
413 #ifdef CONFIG_MENUKEY
414 	if (menukey == CONFIG_MENUKEY) {
415 		s = getenv("menucmd");
416 		if (s)
417 			run_command_list(s, -1, 0);
418 	}
419 #endif /* CONFIG_MENUKEY */
420 }
421 #endif /* CONFIG_BOOTDELAY */
422 
423 void main_loop(void)
424 {
425 #ifndef CONFIG_SYS_HUSH_PARSER
426 	static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
427 	int len;
428 	int rc = 1;
429 	int flag;
430 #endif
431 #ifdef CONFIG_PREBOOT
432 	char *p;
433 #endif
434 
435 	bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
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 #ifdef DEBUG_PARSER
1183 	printf ("parse_line: \"%s\"\n", line);
1184 #endif
1185 	while (nargs < CONFIG_SYS_MAXARGS) {
1186 
1187 		/* skip any white space */
1188 		while (isblank(*line))
1189 			++line;
1190 
1191 		if (*line == '\0') {	/* end of line, no more args	*/
1192 			argv[nargs] = NULL;
1193 #ifdef DEBUG_PARSER
1194 		printf ("parse_line: nargs=%d\n", nargs);
1195 #endif
1196 			return (nargs);
1197 		}
1198 
1199 		argv[nargs++] = line;	/* begin of argument string	*/
1200 
1201 		/* find end of string */
1202 		while (*line && !isblank(*line))
1203 			++line;
1204 
1205 		if (*line == '\0') {	/* end of line, no more args	*/
1206 			argv[nargs] = NULL;
1207 #ifdef DEBUG_PARSER
1208 		printf ("parse_line: nargs=%d\n", nargs);
1209 #endif
1210 			return (nargs);
1211 		}
1212 
1213 		*line++ = '\0';		/* terminate current arg	 */
1214 	}
1215 
1216 	printf ("** Too many args (max. %d) **\n", CONFIG_SYS_MAXARGS);
1217 
1218 #ifdef DEBUG_PARSER
1219 	printf ("parse_line: nargs=%d\n", nargs);
1220 #endif
1221 	return (nargs);
1222 }
1223 
1224 /****************************************************************************/
1225 
1226 #ifndef CONFIG_SYS_HUSH_PARSER
1227 static void process_macros (const char *input, char *output)
1228 {
1229 	char c, prev;
1230 	const char *varname_start = NULL;
1231 	int inputcnt = strlen (input);
1232 	int outputcnt = CONFIG_SYS_CBSIZE;
1233 	int state = 0;		/* 0 = waiting for '$'  */
1234 
1235 	/* 1 = waiting for '(' or '{' */
1236 	/* 2 = waiting for ')' or '}' */
1237 	/* 3 = waiting for '''  */
1238 #ifdef DEBUG_PARSER
1239 	char *output_start = output;
1240 
1241 	printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen (input),
1242 		input);
1243 #endif
1244 
1245 	prev = '\0';		/* previous character   */
1246 
1247 	while (inputcnt && outputcnt) {
1248 		c = *input++;
1249 		inputcnt--;
1250 
1251 		if (state != 3) {
1252 			/* remove one level of escape characters */
1253 			if ((c == '\\') && (prev != '\\')) {
1254 				if (inputcnt-- == 0)
1255 					break;
1256 				prev = c;
1257 				c = *input++;
1258 			}
1259 		}
1260 
1261 		switch (state) {
1262 		case 0:	/* Waiting for (unescaped) $    */
1263 			if ((c == '\'') && (prev != '\\')) {
1264 				state = 3;
1265 				break;
1266 			}
1267 			if ((c == '$') && (prev != '\\')) {
1268 				state++;
1269 			} else {
1270 				*(output++) = c;
1271 				outputcnt--;
1272 			}
1273 			break;
1274 		case 1:	/* Waiting for (        */
1275 			if (c == '(' || c == '{') {
1276 				state++;
1277 				varname_start = input;
1278 			} else {
1279 				state = 0;
1280 				*(output++) = '$';
1281 				outputcnt--;
1282 
1283 				if (outputcnt) {
1284 					*(output++) = c;
1285 					outputcnt--;
1286 				}
1287 			}
1288 			break;
1289 		case 2:	/* Waiting for )        */
1290 			if (c == ')' || c == '}') {
1291 				int i;
1292 				char envname[CONFIG_SYS_CBSIZE], *envval;
1293 				int envcnt = input - varname_start - 1;	/* Varname # of chars */
1294 
1295 				/* Get the varname */
1296 				for (i = 0; i < envcnt; i++) {
1297 					envname[i] = varname_start[i];
1298 				}
1299 				envname[i] = 0;
1300 
1301 				/* Get its value */
1302 				envval = getenv (envname);
1303 
1304 				/* Copy into the line if it exists */
1305 				if (envval != NULL)
1306 					while ((*envval) && outputcnt) {
1307 						*(output++) = *(envval++);
1308 						outputcnt--;
1309 					}
1310 				/* Look for another '$' */
1311 				state = 0;
1312 			}
1313 			break;
1314 		case 3:	/* Waiting for '        */
1315 			if ((c == '\'') && (prev != '\\')) {
1316 				state = 0;
1317 			} else {
1318 				*(output++) = c;
1319 				outputcnt--;
1320 			}
1321 			break;
1322 		}
1323 		prev = c;
1324 	}
1325 
1326 	if (outputcnt)
1327 		*output = 0;
1328 	else
1329 		*(output - 1) = 0;
1330 
1331 #ifdef DEBUG_PARSER
1332 	printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n",
1333 		strlen (output_start), output_start);
1334 #endif
1335 }
1336 
1337 /****************************************************************************
1338  * returns:
1339  *	1  - command executed, repeatable
1340  *	0  - command executed but not repeatable, interrupted commands are
1341  *	     always considered not repeatable
1342  *	-1 - not executed (unrecognized, bootd recursion or too many args)
1343  *           (If cmd is NULL or "" or longer than CONFIG_SYS_CBSIZE-1 it is
1344  *           considered unrecognized)
1345  *
1346  * WARNING:
1347  *
1348  * We must create a temporary copy of the command since the command we get
1349  * may be the result from getenv(), which returns a pointer directly to
1350  * the environment data, which may change magicly when the command we run
1351  * creates or modifies environment variables (like "bootp" does).
1352  */
1353 static int builtin_run_command(const char *cmd, int flag)
1354 {
1355 	char cmdbuf[CONFIG_SYS_CBSIZE];	/* working copy of cmd		*/
1356 	char *token;			/* start of token in cmdbuf	*/
1357 	char *sep;			/* end of token (separator) in cmdbuf */
1358 	char finaltoken[CONFIG_SYS_CBSIZE];
1359 	char *str = cmdbuf;
1360 	char *argv[CONFIG_SYS_MAXARGS + 1];	/* NULL terminated	*/
1361 	int argc, inquotes;
1362 	int repeatable = 1;
1363 	int rc = 0;
1364 
1365 #ifdef DEBUG_PARSER
1366 	printf ("[RUN_COMMAND] cmd[%p]=\"", cmd);
1367 	puts (cmd ? cmd : "NULL");	/* use puts - string may be loooong */
1368 	puts ("\"\n");
1369 #endif
1370 
1371 	clear_ctrlc();		/* forget any previous Control C */
1372 
1373 	if (!cmd || !*cmd) {
1374 		return -1;	/* empty command */
1375 	}
1376 
1377 	if (strlen(cmd) >= CONFIG_SYS_CBSIZE) {
1378 		puts ("## Command too long!\n");
1379 		return -1;
1380 	}
1381 
1382 	strcpy (cmdbuf, cmd);
1383 
1384 	/* Process separators and check for invalid
1385 	 * repeatable commands
1386 	 */
1387 
1388 #ifdef DEBUG_PARSER
1389 	printf ("[PROCESS_SEPARATORS] %s\n", cmd);
1390 #endif
1391 	while (*str) {
1392 
1393 		/*
1394 		 * Find separator, or string end
1395 		 * Allow simple escape of ';' by writing "\;"
1396 		 */
1397 		for (inquotes = 0, sep = str; *sep; sep++) {
1398 			if ((*sep=='\'') &&
1399 			    (*(sep-1) != '\\'))
1400 				inquotes=!inquotes;
1401 
1402 			if (!inquotes &&
1403 			    (*sep == ';') &&	/* separator		*/
1404 			    ( sep != str) &&	/* past string start	*/
1405 			    (*(sep-1) != '\\'))	/* and NOT escaped	*/
1406 				break;
1407 		}
1408 
1409 		/*
1410 		 * Limit the token to data between separators
1411 		 */
1412 		token = str;
1413 		if (*sep) {
1414 			str = sep + 1;	/* start of command for next pass */
1415 			*sep = '\0';
1416 		}
1417 		else
1418 			str = sep;	/* no more commands for next pass */
1419 #ifdef DEBUG_PARSER
1420 		printf ("token: \"%s\"\n", token);
1421 #endif
1422 
1423 		/* find macros in this token and replace them */
1424 		process_macros (token, finaltoken);
1425 
1426 		/* Extract arguments */
1427 		if ((argc = parse_line (finaltoken, argv)) == 0) {
1428 			rc = -1;	/* no command at all */
1429 			continue;
1430 		}
1431 
1432 		if (cmd_process(flag, argc, argv, &repeatable, NULL))
1433 			rc = -1;
1434 
1435 		/* Did the user stop this? */
1436 		if (had_ctrlc ())
1437 			return -1;	/* if stopped then not repeatable */
1438 	}
1439 
1440 	return rc ? rc : repeatable;
1441 }
1442 #endif
1443 
1444 /*
1445  * Run a command using the selected parser.
1446  *
1447  * @param cmd	Command to run
1448  * @param flag	Execution flags (CMD_FLAG_...)
1449  * @return 0 on success, or != 0 on error.
1450  */
1451 int run_command(const char *cmd, int flag)
1452 {
1453 #ifndef CONFIG_SYS_HUSH_PARSER
1454 	/*
1455 	 * builtin_run_command can return 0 or 1 for success, so clean up
1456 	 * its result.
1457 	 */
1458 	if (builtin_run_command(cmd, flag) == -1)
1459 		return 1;
1460 
1461 	return 0;
1462 #else
1463 	return parse_string_outer(cmd,
1464 			FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
1465 #endif
1466 }
1467 
1468 #ifndef CONFIG_SYS_HUSH_PARSER
1469 /**
1470  * Execute a list of command separated by ; or \n using the built-in parser.
1471  *
1472  * This function cannot take a const char * for the command, since if it
1473  * finds newlines in the string, it replaces them with \0.
1474  *
1475  * @param cmd	String containing list of commands
1476  * @param flag	Execution flags (CMD_FLAG_...)
1477  * @return 0 on success, or != 0 on error.
1478  */
1479 static int builtin_run_command_list(char *cmd, int flag)
1480 {
1481 	char *line, *next;
1482 	int rcode = 0;
1483 
1484 	/*
1485 	 * Break into individual lines, and execute each line; terminate on
1486 	 * error.
1487 	 */
1488 	line = next = cmd;
1489 	while (*next) {
1490 		if (*next == '\n') {
1491 			*next = '\0';
1492 			/* run only non-empty commands */
1493 			if (*line) {
1494 				debug("** exec: \"%s\"\n", line);
1495 				if (builtin_run_command(line, 0) < 0) {
1496 					rcode = 1;
1497 					break;
1498 				}
1499 			}
1500 			line = next + 1;
1501 		}
1502 		++next;
1503 	}
1504 	if (rcode == 0 && *line)
1505 		rcode = (builtin_run_command(line, 0) >= 0);
1506 
1507 	return rcode;
1508 }
1509 #endif
1510 
1511 int run_command_list(const char *cmd, int len, int flag)
1512 {
1513 	int need_buff = 1;
1514 	char *buff = (char *)cmd;	/* cast away const */
1515 	int rcode = 0;
1516 
1517 	if (len == -1) {
1518 		len = strlen(cmd);
1519 #ifdef CONFIG_SYS_HUSH_PARSER
1520 		/* hush will never change our string */
1521 		need_buff = 0;
1522 #else
1523 		/* the built-in parser will change our string if it sees \n */
1524 		need_buff = strchr(cmd, '\n') != NULL;
1525 #endif
1526 	}
1527 	if (need_buff) {
1528 		buff = malloc(len + 1);
1529 		if (!buff)
1530 			return 1;
1531 		memcpy(buff, cmd, len);
1532 		buff[len] = '\0';
1533 	}
1534 #ifdef CONFIG_SYS_HUSH_PARSER
1535 	rcode = parse_string_outer(buff, FLAG_PARSE_SEMICOLON);
1536 #else
1537 	/*
1538 	 * This function will overwrite any \n it sees with a \0, which
1539 	 * is why it can't work with a const char *. Here we are making
1540 	 * using of internal knowledge of this function, to avoid always
1541 	 * doing a malloc() which is actually required only in a case that
1542 	 * is pretty rare.
1543 	 */
1544 	rcode = builtin_run_command_list(buff, flag);
1545 	if (need_buff)
1546 		free(buff);
1547 #endif
1548 
1549 	return rcode;
1550 }
1551 
1552 /****************************************************************************/
1553 
1554 #if defined(CONFIG_CMD_RUN)
1555 int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
1556 {
1557 	int i;
1558 
1559 	if (argc < 2)
1560 		return CMD_RET_USAGE;
1561 
1562 	for (i=1; i<argc; ++i) {
1563 		char *arg;
1564 
1565 		if ((arg = getenv (argv[i])) == NULL) {
1566 			printf ("## Error: \"%s\" not defined\n", argv[i]);
1567 			return 1;
1568 		}
1569 
1570 		if (run_command(arg, flag) != 0)
1571 			return 1;
1572 	}
1573 	return 0;
1574 }
1575 #endif
1576