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