1c609719bSwdenk /* 2c609719bSwdenk * (C) Copyright 2000 3c609719bSwdenk * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4c609719bSwdenk * 5c609719bSwdenk * See file CREDITS for list of people who contributed to this 6c609719bSwdenk * project. 7c609719bSwdenk * 8c609719bSwdenk * This program is free software; you can redistribute it and/or 9c609719bSwdenk * modify it under the terms of the GNU General Public License as 10c609719bSwdenk * published by the Free Software Foundation; either version 2 of 11c609719bSwdenk * the License, or (at your option) any later version. 12c609719bSwdenk * 13c609719bSwdenk * This program is distributed in the hope that it will be useful, 14c609719bSwdenk * but WITHOUT ANY WARRANTY; without even the implied warranty of 15c609719bSwdenk * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16c609719bSwdenk * GNU General Public License for more details. 17c609719bSwdenk * 18c609719bSwdenk * You should have received a copy of the GNU General Public License 19c609719bSwdenk * along with this program; if not, write to the Free Software 20c609719bSwdenk * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21c609719bSwdenk * MA 02111-1307 USA 22c609719bSwdenk */ 23c609719bSwdenk 24a6c7ad2fSwdenk /* #define DEBUG */ 25a6c7ad2fSwdenk 26c609719bSwdenk #include <common.h> 27c609719bSwdenk #include <watchdog.h> 28c609719bSwdenk #include <command.h> 29c609719bSwdenk #include <malloc.h> 30c609719bSwdenk 31c609719bSwdenk #ifdef CFG_HUSH_PARSER 32c609719bSwdenk #include <hush.h> 33c609719bSwdenk #endif 34c609719bSwdenk 35bdccc4feSwdenk #include <post.h> 36bdccc4feSwdenk 378bde7f77Swdenk #if defined(CONFIG_BOOT_RETRY_TIME) && defined(CONFIG_RESET_TO_RETRY) 388bde7f77Swdenk extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); /* for do_reset() prototype */ 398bde7f77Swdenk #endif 408bde7f77Swdenk 418bde7f77Swdenk extern int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); 428bde7f77Swdenk 438bde7f77Swdenk 44c609719bSwdenk #define MAX_DELAY_STOP_STR 32 45c609719bSwdenk 46c609719bSwdenk static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen); 47c609719bSwdenk static int parse_line (char *, char *[]); 48c609719bSwdenk #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) 49c609719bSwdenk static int abortboot(int); 50c609719bSwdenk #endif 51c609719bSwdenk 52c609719bSwdenk #undef DEBUG_PARSER 53c609719bSwdenk 54c609719bSwdenk char console_buffer[CFG_CBSIZE]; /* console I/O buffer */ 55c609719bSwdenk 56c609719bSwdenk static char erase_seq[] = "\b \b"; /* erase sequence */ 57c609719bSwdenk static char tab_seq[] = " "; /* used to expand TABs */ 58c609719bSwdenk 59c609719bSwdenk #ifdef CONFIG_BOOT_RETRY_TIME 60c609719bSwdenk static uint64_t endtime = 0; /* must be set, default is instant timeout */ 61c609719bSwdenk static int retry_time = -1; /* -1 so can call readline before main_loop */ 62c609719bSwdenk #endif 63c609719bSwdenk 64c609719bSwdenk #define endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk()) 65c609719bSwdenk 66c609719bSwdenk #ifndef CONFIG_BOOT_RETRY_MIN 67c609719bSwdenk #define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME 68c609719bSwdenk #endif 69c609719bSwdenk 70c609719bSwdenk #ifdef CONFIG_MODEM_SUPPORT 71c609719bSwdenk int do_mdm_init = 0; 72c609719bSwdenk extern void mdm_init(void); /* defined in board.c */ 73c609719bSwdenk #endif 74c609719bSwdenk 75c609719bSwdenk /*************************************************************************** 76c609719bSwdenk * Watch for 'delay' seconds for autoboot stop or autoboot delay string. 77c609719bSwdenk * returns: 0 - no key string, allow autoboot 78c609719bSwdenk * 1 - got key string, abort 79c609719bSwdenk */ 80c609719bSwdenk #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) 81c609719bSwdenk # if defined(CONFIG_AUTOBOOT_KEYED) 82c609719bSwdenk static __inline__ int abortboot(int bootdelay) 83c609719bSwdenk { 84c609719bSwdenk int abort = 0; 85c609719bSwdenk uint64_t etime = endtick(bootdelay); 86c609719bSwdenk struct 87c609719bSwdenk { 88c609719bSwdenk char* str; 89c609719bSwdenk u_int len; 90c609719bSwdenk int retry; 91c609719bSwdenk } 92c609719bSwdenk delaykey [] = 93c609719bSwdenk { 94c609719bSwdenk { str: getenv ("bootdelaykey"), retry: 1 }, 95c609719bSwdenk { str: getenv ("bootdelaykey2"), retry: 1 }, 96c609719bSwdenk { str: getenv ("bootstopkey"), retry: 0 }, 97c609719bSwdenk { str: getenv ("bootstopkey2"), retry: 0 }, 98c609719bSwdenk }; 99c609719bSwdenk 100c609719bSwdenk char presskey [MAX_DELAY_STOP_STR]; 101c609719bSwdenk u_int presskey_len = 0; 102c609719bSwdenk u_int presskey_max = 0; 103c609719bSwdenk u_int i; 104c609719bSwdenk 1058cb8143eSdzu #ifdef CONFIG_SILENT_CONSOLE 1068cb8143eSdzu { 1078cb8143eSdzu DECLARE_GLOBAL_DATA_PTR; 1088cb8143eSdzu 1098cb8143eSdzu if (gd->flags & GD_FLG_SILENT) { 1108cb8143eSdzu /* Restore serial console */ 1118cb8143eSdzu console_assign (stdout, "serial"); 1128cb8143eSdzu console_assign (stderr, "serial"); 1138cb8143eSdzu } 1148cb8143eSdzu } 1158cb8143eSdzu #endif 1168cb8143eSdzu 117c609719bSwdenk # ifdef CONFIG_AUTOBOOT_PROMPT 118c609719bSwdenk printf (CONFIG_AUTOBOOT_PROMPT, bootdelay); 119c609719bSwdenk # endif 120c609719bSwdenk 121c609719bSwdenk # ifdef CONFIG_AUTOBOOT_DELAY_STR 122c609719bSwdenk if (delaykey[0].str == NULL) 123c609719bSwdenk delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR; 124c609719bSwdenk # endif 125c609719bSwdenk # ifdef CONFIG_AUTOBOOT_DELAY_STR2 126c609719bSwdenk if (delaykey[1].str == NULL) 127c609719bSwdenk delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2; 128c609719bSwdenk # endif 129c609719bSwdenk # ifdef CONFIG_AUTOBOOT_STOP_STR 130c609719bSwdenk if (delaykey[2].str == NULL) 131c609719bSwdenk delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR; 132c609719bSwdenk # endif 133c609719bSwdenk # ifdef CONFIG_AUTOBOOT_STOP_STR2 134c609719bSwdenk if (delaykey[3].str == NULL) 135c609719bSwdenk delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2; 136c609719bSwdenk # endif 137c609719bSwdenk 138c609719bSwdenk for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) { 139c609719bSwdenk delaykey[i].len = delaykey[i].str == NULL ? 140c609719bSwdenk 0 : strlen (delaykey[i].str); 141c609719bSwdenk delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ? 142c609719bSwdenk MAX_DELAY_STOP_STR : delaykey[i].len; 143c609719bSwdenk 144c609719bSwdenk presskey_max = presskey_max > delaykey[i].len ? 145c609719bSwdenk presskey_max : delaykey[i].len; 146c609719bSwdenk 147c609719bSwdenk # if DEBUG_BOOTKEYS 148c609719bSwdenk printf("%s key:<%s>\n", 149c609719bSwdenk delaykey[i].retry ? "delay" : "stop", 150c609719bSwdenk delaykey[i].str ? delaykey[i].str : "NULL"); 151c609719bSwdenk # endif 152c609719bSwdenk } 153c609719bSwdenk 154c609719bSwdenk /* In order to keep up with incoming data, check timeout only 155c609719bSwdenk * when catch up. 156c609719bSwdenk */ 157c609719bSwdenk while (!abort && get_ticks() <= etime) { 158c609719bSwdenk for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) { 159c609719bSwdenk if (delaykey[i].len > 0 && 160c609719bSwdenk presskey_len >= delaykey[i].len && 161c609719bSwdenk memcmp (presskey + presskey_len - delaykey[i].len, 162c609719bSwdenk delaykey[i].str, 163c609719bSwdenk delaykey[i].len) == 0) { 164c609719bSwdenk # if DEBUG_BOOTKEYS 165c609719bSwdenk printf("got %skey\n", 166c609719bSwdenk delaykey[i].retry ? "delay" : "stop"); 167c609719bSwdenk # endif 168c609719bSwdenk 169c609719bSwdenk # ifdef CONFIG_BOOT_RETRY_TIME 170c609719bSwdenk /* don't retry auto boot */ 171c609719bSwdenk if (! delaykey[i].retry) 172c609719bSwdenk retry_time = -1; 173c609719bSwdenk # endif 174c609719bSwdenk abort = 1; 175c609719bSwdenk } 176c609719bSwdenk } 177c609719bSwdenk 178c609719bSwdenk if (tstc()) { 179c609719bSwdenk if (presskey_len < presskey_max) { 180c609719bSwdenk presskey [presskey_len ++] = getc(); 181c609719bSwdenk } 182c609719bSwdenk else { 183c609719bSwdenk for (i = 0; i < presskey_max - 1; i ++) 184c609719bSwdenk presskey [i] = presskey [i + 1]; 185c609719bSwdenk 186c609719bSwdenk presskey [i] = getc(); 187c609719bSwdenk } 188c609719bSwdenk } 189c609719bSwdenk } 190c609719bSwdenk # if DEBUG_BOOTKEYS 191c609719bSwdenk if (!abort) 1924b9206edSwdenk puts ("key timeout\n"); 193c609719bSwdenk # endif 194c609719bSwdenk 1958cb8143eSdzu #ifdef CONFIG_SILENT_CONSOLE 1968cb8143eSdzu { 1978cb8143eSdzu DECLARE_GLOBAL_DATA_PTR; 1988cb8143eSdzu 1998cb8143eSdzu if (abort) { 2008cb8143eSdzu /* permanently enable normal console output */ 2018cb8143eSdzu gd->flags &= ~(GD_FLG_SILENT); 2028cb8143eSdzu } else if (gd->flags & GD_FLG_SILENT) { 2038cb8143eSdzu /* Restore silent console */ 2048cb8143eSdzu console_assign (stdout, "nulldev"); 2058cb8143eSdzu console_assign (stderr, "nulldev"); 2068cb8143eSdzu } 2078cb8143eSdzu } 2088cb8143eSdzu #endif 2098cb8143eSdzu 210c609719bSwdenk return abort; 211c609719bSwdenk } 212c609719bSwdenk 213c609719bSwdenk # else /* !defined(CONFIG_AUTOBOOT_KEYED) */ 214c609719bSwdenk 215c7de829cSwdenk #ifdef CONFIG_MENUKEY 216c7de829cSwdenk static int menukey = 0; 217c7de829cSwdenk #endif 218c7de829cSwdenk 219c609719bSwdenk static __inline__ int abortboot(int bootdelay) 220c609719bSwdenk { 221c609719bSwdenk int abort = 0; 222c609719bSwdenk 223f72da340Swdenk #ifdef CONFIG_SILENT_CONSOLE 224f72da340Swdenk { 225f72da340Swdenk DECLARE_GLOBAL_DATA_PTR; 226f72da340Swdenk 227f72da340Swdenk if (gd->flags & GD_FLG_SILENT) { 228f72da340Swdenk /* Restore serial console */ 229f72da340Swdenk console_assign (stdout, "serial"); 230f72da340Swdenk console_assign (stderr, "serial"); 231f72da340Swdenk } 232f72da340Swdenk } 233f72da340Swdenk #endif 234f72da340Swdenk 235c7de829cSwdenk #ifdef CONFIG_MENUPROMPT 236c7de829cSwdenk printf(CONFIG_MENUPROMPT, bootdelay); 237c7de829cSwdenk #else 238c609719bSwdenk printf("Hit any key to stop autoboot: %2d ", bootdelay); 239c7de829cSwdenk #endif 240c609719bSwdenk 241c609719bSwdenk #if defined CONFIG_ZERO_BOOTDELAY_CHECK 242c609719bSwdenk /* 243c609719bSwdenk * Check if key already pressed 244c609719bSwdenk * Don't check if bootdelay < 0 245c609719bSwdenk */ 246c609719bSwdenk if (bootdelay >= 0) { 247c609719bSwdenk if (tstc()) { /* we got a key press */ 248c609719bSwdenk (void) getc(); /* consume input */ 2494b9206edSwdenk puts ("\b\b\b 0"); 250f72da340Swdenk abort = 1; /* don't auto boot */ 251c609719bSwdenk } 252c609719bSwdenk } 253c609719bSwdenk #endif 254c609719bSwdenk 255f72da340Swdenk while ((bootdelay > 0) && (!abort)) { 256c609719bSwdenk int i; 257c609719bSwdenk 258c609719bSwdenk --bootdelay; 259c609719bSwdenk /* delay 100 * 10ms */ 260c609719bSwdenk for (i=0; !abort && i<100; ++i) { 261c609719bSwdenk if (tstc()) { /* we got a key press */ 262c609719bSwdenk abort = 1; /* don't auto boot */ 263c609719bSwdenk bootdelay = 0; /* no more delay */ 264c7de829cSwdenk # ifdef CONFIG_MENUKEY 265c7de829cSwdenk menukey = getc(); 266c7de829cSwdenk # else 267c609719bSwdenk (void) getc(); /* consume input */ 268c7de829cSwdenk # endif 269c609719bSwdenk break; 270c609719bSwdenk } 271c609719bSwdenk udelay (10000); 272c609719bSwdenk } 273c609719bSwdenk 274c609719bSwdenk printf ("\b\b\b%2d ", bootdelay); 275c609719bSwdenk } 276c609719bSwdenk 277c609719bSwdenk putc ('\n'); 278c609719bSwdenk 279f72da340Swdenk #ifdef CONFIG_SILENT_CONSOLE 280f72da340Swdenk { 281f72da340Swdenk DECLARE_GLOBAL_DATA_PTR; 282f72da340Swdenk 283f72da340Swdenk if (abort) { 284f72da340Swdenk /* permanently enable normal console output */ 285f72da340Swdenk gd->flags &= ~(GD_FLG_SILENT); 286f72da340Swdenk } else if (gd->flags & GD_FLG_SILENT) { 287f72da340Swdenk /* Restore silent console */ 288f72da340Swdenk console_assign (stdout, "nulldev"); 289f72da340Swdenk console_assign (stderr, "nulldev"); 290f72da340Swdenk } 291f72da340Swdenk } 292f72da340Swdenk #endif 293f72da340Swdenk 294c609719bSwdenk return abort; 295c609719bSwdenk } 296c609719bSwdenk # endif /* CONFIG_AUTOBOOT_KEYED */ 297c609719bSwdenk #endif /* CONFIG_BOOTDELAY >= 0 */ 298c609719bSwdenk 299c609719bSwdenk /****************************************************************************/ 300c609719bSwdenk 301c609719bSwdenk void main_loop (void) 302c609719bSwdenk { 303c609719bSwdenk #ifndef CFG_HUSH_PARSER 304c609719bSwdenk static char lastcommand[CFG_CBSIZE] = { 0, }; 305c609719bSwdenk int len; 306c609719bSwdenk int rc = 1; 307c609719bSwdenk int flag; 308c609719bSwdenk #endif 309c609719bSwdenk 310c609719bSwdenk #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) 311c609719bSwdenk char *s; 312c609719bSwdenk int bootdelay; 313c609719bSwdenk #endif 314c609719bSwdenk #ifdef CONFIG_PREBOOT 315c609719bSwdenk char *p; 316c609719bSwdenk #endif 317bdccc4feSwdenk #ifdef CONFIG_BOOTCOUNT_LIMIT 318bdccc4feSwdenk unsigned long bootcount = 0; 319bdccc4feSwdenk unsigned long bootlimit = 0; 320bdccc4feSwdenk char *bcs; 321bdccc4feSwdenk char bcs_set[16]; 322bdccc4feSwdenk #endif /* CONFIG_BOOTCOUNT_LIMIT */ 323c609719bSwdenk 324c609719bSwdenk #if defined(CONFIG_VFD) && defined(VFD_TEST_LOGO) 325c609719bSwdenk ulong bmp = 0; /* default bitmap */ 326c609719bSwdenk extern int trab_vfd (ulong bitmap); 327c609719bSwdenk 328c609719bSwdenk #ifdef CONFIG_MODEM_SUPPORT 329c609719bSwdenk if (do_mdm_init) 330c609719bSwdenk bmp = 1; /* alternate bitmap */ 331c609719bSwdenk #endif 332c609719bSwdenk trab_vfd (bmp); 333c609719bSwdenk #endif /* CONFIG_VFD && VFD_TEST_LOGO */ 334c609719bSwdenk 335bdccc4feSwdenk #ifdef CONFIG_BOOTCOUNT_LIMIT 336bdccc4feSwdenk bootcount = bootcount_load(); 337bdccc4feSwdenk bootcount++; 338bdccc4feSwdenk bootcount_store (bootcount); 339bdccc4feSwdenk sprintf (bcs_set, "%lu", bootcount); 340bdccc4feSwdenk setenv ("bootcount", bcs_set); 341bdccc4feSwdenk bcs = getenv ("bootlimit"); 342bdccc4feSwdenk bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0; 343bdccc4feSwdenk #endif /* CONFIG_BOOTCOUNT_LIMIT */ 344bdccc4feSwdenk 345c609719bSwdenk #ifdef CONFIG_MODEM_SUPPORT 346c609719bSwdenk debug ("DEBUG: main_loop: do_mdm_init=%d\n", do_mdm_init); 347c609719bSwdenk if (do_mdm_init) { 348c609719bSwdenk uchar *str = strdup(getenv("mdm_cmd")); 349c609719bSwdenk setenv ("preboot", str); /* set or delete definition */ 350c609719bSwdenk if (str != NULL) 351c609719bSwdenk free (str); 352c609719bSwdenk mdm_init(); /* wait for modem connection */ 353c609719bSwdenk } 354c609719bSwdenk #endif /* CONFIG_MODEM_SUPPORT */ 355c609719bSwdenk 3560587597cSstroese #ifdef CONFIG_VERSION_VARIABLE 3570587597cSstroese { 3580587597cSstroese extern char version_string[]; 3590587597cSstroese 3600587597cSstroese setenv ("ver", version_string); /* set version variable */ 3610587597cSstroese } 3620587597cSstroese #endif /* CONFIG_VERSION_VARIABLE */ 3630587597cSstroese 364c609719bSwdenk #ifdef CFG_HUSH_PARSER 365c609719bSwdenk u_boot_hush_start (); 366c609719bSwdenk #endif 367c609719bSwdenk 368c609719bSwdenk #ifdef CONFIG_PREBOOT 369c609719bSwdenk if ((p = getenv ("preboot")) != NULL) { 370c609719bSwdenk # ifdef CONFIG_AUTOBOOT_KEYED 371c609719bSwdenk int prev = disable_ctrlc(1); /* disable Control C checking */ 372c609719bSwdenk # endif 373c609719bSwdenk 374c609719bSwdenk # ifndef CFG_HUSH_PARSER 375c609719bSwdenk run_command (p, 0); 376c609719bSwdenk # else 377c609719bSwdenk parse_string_outer(p, FLAG_PARSE_SEMICOLON | 378c609719bSwdenk FLAG_EXIT_FROM_LOOP); 379c609719bSwdenk # endif 380c609719bSwdenk 381c609719bSwdenk # ifdef CONFIG_AUTOBOOT_KEYED 382c609719bSwdenk disable_ctrlc(prev); /* restore Control C checking */ 383c609719bSwdenk # endif 384c609719bSwdenk } 385c609719bSwdenk #endif /* CONFIG_PREBOOT */ 386c609719bSwdenk 387c609719bSwdenk #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) 388c609719bSwdenk s = getenv ("bootdelay"); 389c609719bSwdenk bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; 390c609719bSwdenk 391a6c7ad2fSwdenk debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay); 392c609719bSwdenk 393c609719bSwdenk # ifdef CONFIG_BOOT_RETRY_TIME 3946dd652faSwdenk init_cmd_timeout (); 395c609719bSwdenk # endif /* CONFIG_BOOT_RETRY_TIME */ 396c609719bSwdenk 397bdccc4feSwdenk #ifdef CONFIG_BOOTCOUNT_LIMIT 398bdccc4feSwdenk if (bootlimit && (bootcount > bootlimit)) { 399bdccc4feSwdenk printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n", 400bdccc4feSwdenk (unsigned)bootlimit); 401bdccc4feSwdenk s = getenv ("altbootcmd"); 402bdccc4feSwdenk } 403bdccc4feSwdenk else 404bdccc4feSwdenk #endif /* CONFIG_BOOTCOUNT_LIMIT */ 405c609719bSwdenk s = getenv ("bootcmd"); 406a6c7ad2fSwdenk 407a6c7ad2fSwdenk debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>"); 408a6c7ad2fSwdenk 409c609719bSwdenk if (bootdelay >= 0 && s && !abortboot (bootdelay)) { 410c609719bSwdenk # ifdef CONFIG_AUTOBOOT_KEYED 411c609719bSwdenk int prev = disable_ctrlc(1); /* disable Control C checking */ 412c609719bSwdenk # endif 413c609719bSwdenk 414c609719bSwdenk # ifndef CFG_HUSH_PARSER 415c609719bSwdenk run_command (s, 0); 416c609719bSwdenk # else 417c609719bSwdenk parse_string_outer(s, FLAG_PARSE_SEMICOLON | 418c609719bSwdenk FLAG_EXIT_FROM_LOOP); 419c609719bSwdenk # endif 420c609719bSwdenk 421c609719bSwdenk # ifdef CONFIG_AUTOBOOT_KEYED 422c609719bSwdenk disable_ctrlc(prev); /* restore Control C checking */ 423c609719bSwdenk # endif 424c609719bSwdenk } 425c7de829cSwdenk 426c7de829cSwdenk # ifdef CONFIG_MENUKEY 427a6c7ad2fSwdenk if (menukey == CONFIG_MENUKEY) { 428c7de829cSwdenk s = getenv("menucmd"); 429a6c7ad2fSwdenk if (s) { 430c7de829cSwdenk # ifndef CFG_HUSH_PARSER 431c7de829cSwdenk run_command (s, bd, 0); 432c7de829cSwdenk # else 433c7de829cSwdenk parse_string_outer(s, FLAG_PARSE_SEMICOLON | 434c7de829cSwdenk FLAG_EXIT_FROM_LOOP); 435c7de829cSwdenk # endif 436c7de829cSwdenk } 437c7de829cSwdenk } 438c7de829cSwdenk #endif /* CONFIG_MENUKEY */ 439c609719bSwdenk #endif /* CONFIG_BOOTDELAY */ 440c609719bSwdenk 441c7de829cSwdenk #ifdef CONFIG_AMIGAONEG3SE 442c7de829cSwdenk { 443c7de829cSwdenk extern void video_banner(void); 444c7de829cSwdenk video_banner(); 445c7de829cSwdenk } 446c7de829cSwdenk #endif 447c7de829cSwdenk 448c609719bSwdenk /* 449c609719bSwdenk * Main Loop for Monitor Command Processing 450c609719bSwdenk */ 451c609719bSwdenk #ifdef CFG_HUSH_PARSER 452c609719bSwdenk parse_file_outer(); 453c609719bSwdenk /* This point is never reached */ 454c609719bSwdenk for (;;); 455c609719bSwdenk #else 456c609719bSwdenk for (;;) { 457c609719bSwdenk #ifdef CONFIG_BOOT_RETRY_TIME 458c609719bSwdenk if (rc >= 0) { 459c609719bSwdenk /* Saw enough of a valid command to 460c609719bSwdenk * restart the timeout. 461c609719bSwdenk */ 462c609719bSwdenk reset_cmd_timeout(); 463c609719bSwdenk } 464c609719bSwdenk #endif 465c609719bSwdenk len = readline (CFG_PROMPT); 466c609719bSwdenk 467c609719bSwdenk flag = 0; /* assume no special flags for now */ 468c609719bSwdenk if (len > 0) 469c609719bSwdenk strcpy (lastcommand, console_buffer); 470c609719bSwdenk else if (len == 0) 471c609719bSwdenk flag |= CMD_FLAG_REPEAT; 472c609719bSwdenk #ifdef CONFIG_BOOT_RETRY_TIME 473c609719bSwdenk else if (len == -2) { 474c609719bSwdenk /* -2 means timed out, retry autoboot 475c609719bSwdenk */ 4764b9206edSwdenk puts ("\nTimed out waiting for command\n"); 477c609719bSwdenk # ifdef CONFIG_RESET_TO_RETRY 478c609719bSwdenk /* Reinit board to run initialization code again */ 479c609719bSwdenk do_reset (NULL, 0, 0, NULL); 480c609719bSwdenk # else 481c609719bSwdenk return; /* retry autoboot */ 482c609719bSwdenk # endif 483c609719bSwdenk } 484c609719bSwdenk #endif 485c609719bSwdenk 486c609719bSwdenk if (len == -1) 4874b9206edSwdenk puts ("<INTERRUPT>\n"); 488c609719bSwdenk else 489c609719bSwdenk rc = run_command (lastcommand, flag); 490c609719bSwdenk 491c609719bSwdenk if (rc <= 0) { 492c609719bSwdenk /* invalid command or not repeatable, forget it */ 493c609719bSwdenk lastcommand[0] = 0; 494c609719bSwdenk } 495c609719bSwdenk } 496c609719bSwdenk #endif /*CFG_HUSH_PARSER*/ 497c609719bSwdenk } 498c609719bSwdenk 4996dd652faSwdenk #ifdef CONFIG_BOOT_RETRY_TIME 5006dd652faSwdenk /*************************************************************************** 5016dd652faSwdenk * initialise command line timeout 5026dd652faSwdenk */ 5036dd652faSwdenk void init_cmd_timeout(void) 5046dd652faSwdenk { 5056dd652faSwdenk char *s = getenv ("bootretry"); 5066dd652faSwdenk 5076dd652faSwdenk if (s != NULL) 508b028f715Swdenk retry_time = (int)simple_strtol(s, NULL, 10); 5096dd652faSwdenk else 5106dd652faSwdenk retry_time = CONFIG_BOOT_RETRY_TIME; 5116dd652faSwdenk 5126dd652faSwdenk if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN) 5136dd652faSwdenk retry_time = CONFIG_BOOT_RETRY_MIN; 5146dd652faSwdenk } 5156dd652faSwdenk 516c609719bSwdenk /*************************************************************************** 517c609719bSwdenk * reset command line timeout to retry_time seconds 518c609719bSwdenk */ 519c609719bSwdenk void reset_cmd_timeout(void) 520c609719bSwdenk { 521c609719bSwdenk endtime = endtick(retry_time); 522c609719bSwdenk } 523c609719bSwdenk #endif 524c609719bSwdenk 525c609719bSwdenk /****************************************************************************/ 526c609719bSwdenk 527c609719bSwdenk /* 528c609719bSwdenk * Prompt for input and read a line. 529c609719bSwdenk * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0, 530c609719bSwdenk * time out when time goes past endtime (timebase time in ticks). 531c609719bSwdenk * Return: number of read characters 532c609719bSwdenk * -1 if break 533c609719bSwdenk * -2 if timed out 534c609719bSwdenk */ 535c609719bSwdenk int readline (const char *const prompt) 536c609719bSwdenk { 537c609719bSwdenk char *p = console_buffer; 538c609719bSwdenk int n = 0; /* buffer index */ 539c609719bSwdenk int plen = 0; /* prompt length */ 540c609719bSwdenk int col; /* output column cnt */ 541c609719bSwdenk char c; 542c609719bSwdenk 543c609719bSwdenk /* print prompt */ 544c609719bSwdenk if (prompt) { 545c609719bSwdenk plen = strlen (prompt); 546c609719bSwdenk puts (prompt); 547c609719bSwdenk } 548c609719bSwdenk col = plen; 549c609719bSwdenk 550c609719bSwdenk for (;;) { 551c609719bSwdenk #ifdef CONFIG_BOOT_RETRY_TIME 552c609719bSwdenk while (!tstc()) { /* while no incoming data */ 553c609719bSwdenk if (retry_time >= 0 && get_ticks() > endtime) 554c609719bSwdenk return (-2); /* timed out */ 555c609719bSwdenk } 556c609719bSwdenk #endif 557c609719bSwdenk WATCHDOG_RESET(); /* Trigger watchdog, if needed */ 558c609719bSwdenk 559c609719bSwdenk #ifdef CONFIG_SHOW_ACTIVITY 560c609719bSwdenk while (!tstc()) { 561c609719bSwdenk extern void show_activity(int arg); 562c609719bSwdenk show_activity(0); 563c609719bSwdenk } 564c609719bSwdenk #endif 565c609719bSwdenk c = getc(); 566c609719bSwdenk 567c609719bSwdenk /* 568c609719bSwdenk * Special character handling 569c609719bSwdenk */ 570c609719bSwdenk switch (c) { 571c609719bSwdenk case '\r': /* Enter */ 572c609719bSwdenk case '\n': 573c609719bSwdenk *p = '\0'; 574c609719bSwdenk puts ("\r\n"); 575c609719bSwdenk return (p - console_buffer); 576c609719bSwdenk 577*27aa8186Swdenk case '\0': /* nul */ 578*27aa8186Swdenk continue; 579*27aa8186Swdenk 580c609719bSwdenk case 0x03: /* ^C - break */ 581c609719bSwdenk console_buffer[0] = '\0'; /* discard input */ 582c609719bSwdenk return (-1); 583c609719bSwdenk 584c609719bSwdenk case 0x15: /* ^U - erase line */ 585c609719bSwdenk while (col > plen) { 586c609719bSwdenk puts (erase_seq); 587c609719bSwdenk --col; 588c609719bSwdenk } 589c609719bSwdenk p = console_buffer; 590c609719bSwdenk n = 0; 591c609719bSwdenk continue; 592c609719bSwdenk 593c609719bSwdenk case 0x17: /* ^W - erase word */ 594c609719bSwdenk p=delete_char(console_buffer, p, &col, &n, plen); 595c609719bSwdenk while ((n > 0) && (*p != ' ')) { 596c609719bSwdenk p=delete_char(console_buffer, p, &col, &n, plen); 597c609719bSwdenk } 598c609719bSwdenk continue; 599c609719bSwdenk 600c609719bSwdenk case 0x08: /* ^H - backspace */ 601c609719bSwdenk case 0x7F: /* DEL - backspace */ 602c609719bSwdenk p=delete_char(console_buffer, p, &col, &n, plen); 603c609719bSwdenk continue; 604c609719bSwdenk 605c609719bSwdenk default: 606c609719bSwdenk /* 607c609719bSwdenk * Must be a normal character then 608c609719bSwdenk */ 609c609719bSwdenk if (n < CFG_CBSIZE-2) { 610c609719bSwdenk if (c == '\t') { /* expand TABs */ 611c609719bSwdenk puts (tab_seq+(col&07)); 612c609719bSwdenk col += 8 - (col&07); 613c609719bSwdenk } else { 614c609719bSwdenk ++col; /* echo input */ 615c609719bSwdenk putc (c); 616c609719bSwdenk } 617c609719bSwdenk *p++ = c; 618c609719bSwdenk ++n; 619c609719bSwdenk } else { /* Buffer full */ 620c609719bSwdenk putc ('\a'); 621c609719bSwdenk } 622c609719bSwdenk } 623c609719bSwdenk } 624c609719bSwdenk } 625c609719bSwdenk 626c609719bSwdenk /****************************************************************************/ 627c609719bSwdenk 628c609719bSwdenk static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen) 629c609719bSwdenk { 630c609719bSwdenk char *s; 631c609719bSwdenk 632c609719bSwdenk if (*np == 0) { 633c609719bSwdenk return (p); 634c609719bSwdenk } 635c609719bSwdenk 636c609719bSwdenk if (*(--p) == '\t') { /* will retype the whole line */ 637c609719bSwdenk while (*colp > plen) { 638c609719bSwdenk puts (erase_seq); 639c609719bSwdenk (*colp)--; 640c609719bSwdenk } 641c609719bSwdenk for (s=buffer; s<p; ++s) { 642c609719bSwdenk if (*s == '\t') { 643c609719bSwdenk puts (tab_seq+((*colp) & 07)); 644c609719bSwdenk *colp += 8 - ((*colp) & 07); 645c609719bSwdenk } else { 646c609719bSwdenk ++(*colp); 647c609719bSwdenk putc (*s); 648c609719bSwdenk } 649c609719bSwdenk } 650c609719bSwdenk } else { 651c609719bSwdenk puts (erase_seq); 652c609719bSwdenk (*colp)--; 653c609719bSwdenk } 654c609719bSwdenk (*np)--; 655c609719bSwdenk return (p); 656c609719bSwdenk } 657c609719bSwdenk 658c609719bSwdenk /****************************************************************************/ 659c609719bSwdenk 660c609719bSwdenk int parse_line (char *line, char *argv[]) 661c609719bSwdenk { 662c609719bSwdenk int nargs = 0; 663c609719bSwdenk 664c609719bSwdenk #ifdef DEBUG_PARSER 665c609719bSwdenk printf ("parse_line: \"%s\"\n", line); 666c609719bSwdenk #endif 667c609719bSwdenk while (nargs < CFG_MAXARGS) { 668c609719bSwdenk 669c609719bSwdenk /* skip any white space */ 670c609719bSwdenk while ((*line == ' ') || (*line == '\t')) { 671c609719bSwdenk ++line; 672c609719bSwdenk } 673c609719bSwdenk 674c609719bSwdenk if (*line == '\0') { /* end of line, no more args */ 675c609719bSwdenk argv[nargs] = NULL; 676c609719bSwdenk #ifdef DEBUG_PARSER 677c609719bSwdenk printf ("parse_line: nargs=%d\n", nargs); 678c609719bSwdenk #endif 679c609719bSwdenk return (nargs); 680c609719bSwdenk } 681c609719bSwdenk 682c609719bSwdenk argv[nargs++] = line; /* begin of argument string */ 683c609719bSwdenk 684c609719bSwdenk /* find end of string */ 685c609719bSwdenk while (*line && (*line != ' ') && (*line != '\t')) { 686c609719bSwdenk ++line; 687c609719bSwdenk } 688c609719bSwdenk 689c609719bSwdenk if (*line == '\0') { /* end of line, no more args */ 690c609719bSwdenk argv[nargs] = NULL; 691c609719bSwdenk #ifdef DEBUG_PARSER 692c609719bSwdenk printf ("parse_line: nargs=%d\n", nargs); 693c609719bSwdenk #endif 694c609719bSwdenk return (nargs); 695c609719bSwdenk } 696c609719bSwdenk 697c609719bSwdenk *line++ = '\0'; /* terminate current arg */ 698c609719bSwdenk } 699c609719bSwdenk 700c609719bSwdenk printf ("** Too many args (max. %d) **\n", CFG_MAXARGS); 701c609719bSwdenk 702c609719bSwdenk #ifdef DEBUG_PARSER 703c609719bSwdenk printf ("parse_line: nargs=%d\n", nargs); 704c609719bSwdenk #endif 705c609719bSwdenk return (nargs); 706c609719bSwdenk } 707c609719bSwdenk 708c609719bSwdenk /****************************************************************************/ 709c609719bSwdenk 710c609719bSwdenk static void process_macros (const char *input, char *output) 711c609719bSwdenk { 712c609719bSwdenk char c, prev; 713c609719bSwdenk const char *varname_start = NULL; 714c609719bSwdenk int inputcnt = strlen (input); 715c609719bSwdenk int outputcnt = CFG_CBSIZE; 716c609719bSwdenk int state = 0; /* 0 = waiting for '$' */ 717c609719bSwdenk /* 1 = waiting for '(' */ 718c609719bSwdenk /* 2 = waiting for ')' */ 719a25f862bSwdenk /* 3 = waiting for ''' */ 720c609719bSwdenk #ifdef DEBUG_PARSER 721c609719bSwdenk char *output_start = output; 722c609719bSwdenk 723c609719bSwdenk printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(input), input); 724c609719bSwdenk #endif 725c609719bSwdenk 726c609719bSwdenk prev = '\0'; /* previous character */ 727c609719bSwdenk 728c609719bSwdenk while (inputcnt && outputcnt) { 729c609719bSwdenk c = *input++; 730c609719bSwdenk inputcnt--; 731c609719bSwdenk 732a25f862bSwdenk if (state!=3) { 733c609719bSwdenk /* remove one level of escape characters */ 734c609719bSwdenk if ((c == '\\') && (prev != '\\')) { 735c609719bSwdenk if (inputcnt-- == 0) 736c609719bSwdenk break; 737c609719bSwdenk prev = c; 738c609719bSwdenk c = *input++; 739c609719bSwdenk } 740a25f862bSwdenk } 741c609719bSwdenk 742c609719bSwdenk switch (state) { 743c609719bSwdenk case 0: /* Waiting for (unescaped) $ */ 744a25f862bSwdenk if ((c == '\'') && (prev != '\\')) { 745a25f862bSwdenk state = 3; 746a25f862bSwdenk break; 747a25f862bSwdenk } 748c609719bSwdenk if ((c == '$') && (prev != '\\')) { 749c609719bSwdenk state++; 750c609719bSwdenk } else { 751c609719bSwdenk *(output++) = c; 752c609719bSwdenk outputcnt--; 753c609719bSwdenk } 754c609719bSwdenk break; 755c609719bSwdenk case 1: /* Waiting for ( */ 756c609719bSwdenk if (c == '(') { 757c609719bSwdenk state++; 758c609719bSwdenk varname_start = input; 759c609719bSwdenk } else { 760c609719bSwdenk state = 0; 761c609719bSwdenk *(output++) = '$'; 762c609719bSwdenk outputcnt--; 763c609719bSwdenk 764c609719bSwdenk if (outputcnt) { 765c609719bSwdenk *(output++) = c; 766c609719bSwdenk outputcnt--; 767c609719bSwdenk } 768c609719bSwdenk } 769c609719bSwdenk break; 770c609719bSwdenk case 2: /* Waiting for ) */ 771c609719bSwdenk if (c == ')') { 772c609719bSwdenk int i; 773c609719bSwdenk char envname[CFG_CBSIZE], *envval; 774c609719bSwdenk int envcnt = input-varname_start-1; /* Varname # of chars */ 775c609719bSwdenk 776c609719bSwdenk /* Get the varname */ 777c609719bSwdenk for (i = 0; i < envcnt; i++) { 778c609719bSwdenk envname[i] = varname_start[i]; 779c609719bSwdenk } 780c609719bSwdenk envname[i] = 0; 781c609719bSwdenk 782c609719bSwdenk /* Get its value */ 783c609719bSwdenk envval = getenv (envname); 784c609719bSwdenk 785c609719bSwdenk /* Copy into the line if it exists */ 786c609719bSwdenk if (envval != NULL) 787c609719bSwdenk while ((*envval) && outputcnt) { 788c609719bSwdenk *(output++) = *(envval++); 789c609719bSwdenk outputcnt--; 790c609719bSwdenk } 791c609719bSwdenk /* Look for another '$' */ 792c609719bSwdenk state = 0; 793c609719bSwdenk } 794c609719bSwdenk break; 795a25f862bSwdenk case 3: /* Waiting for ' */ 796a25f862bSwdenk if ((c == '\'') && (prev != '\\')) { 797a25f862bSwdenk state = 0; 798a25f862bSwdenk } else { 799a25f862bSwdenk *(output++) = c; 800a25f862bSwdenk outputcnt--; 801c609719bSwdenk } 802a25f862bSwdenk break; 803a25f862bSwdenk } 804c609719bSwdenk prev = c; 805c609719bSwdenk } 806c609719bSwdenk 807c609719bSwdenk if (outputcnt) 808c609719bSwdenk *output = 0; 809c609719bSwdenk 810c609719bSwdenk #ifdef DEBUG_PARSER 811c609719bSwdenk printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n", 812c609719bSwdenk strlen(output_start), output_start); 813c609719bSwdenk #endif 814c609719bSwdenk } 815c609719bSwdenk 816c609719bSwdenk /**************************************************************************** 817c609719bSwdenk * returns: 818c609719bSwdenk * 1 - command executed, repeatable 819c609719bSwdenk * 0 - command executed but not repeatable, interrupted commands are 820c609719bSwdenk * always considered not repeatable 821c609719bSwdenk * -1 - not executed (unrecognized, bootd recursion or too many args) 822c609719bSwdenk * (If cmd is NULL or "" or longer than CFG_CBSIZE-1 it is 823c609719bSwdenk * considered unrecognized) 824c609719bSwdenk * 825c609719bSwdenk * WARNING: 826c609719bSwdenk * 827c609719bSwdenk * We must create a temporary copy of the command since the command we get 828c609719bSwdenk * may be the result from getenv(), which returns a pointer directly to 829c609719bSwdenk * the environment data, which may change magicly when the command we run 830c609719bSwdenk * creates or modifies environment variables (like "bootp" does). 831c609719bSwdenk */ 832c609719bSwdenk 833c609719bSwdenk int run_command (const char *cmd, int flag) 834c609719bSwdenk { 835c609719bSwdenk cmd_tbl_t *cmdtp; 836c609719bSwdenk char cmdbuf[CFG_CBSIZE]; /* working copy of cmd */ 837c609719bSwdenk char *token; /* start of token in cmdbuf */ 838c609719bSwdenk char *sep; /* end of token (separator) in cmdbuf */ 839c609719bSwdenk char finaltoken[CFG_CBSIZE]; 840c609719bSwdenk char *str = cmdbuf; 841c609719bSwdenk char *argv[CFG_MAXARGS + 1]; /* NULL terminated */ 842f07771ccSwdenk int argc, inquotes; 843c609719bSwdenk int repeatable = 1; 844f07771ccSwdenk int rc = 0; 845c609719bSwdenk 846c609719bSwdenk #ifdef DEBUG_PARSER 847c609719bSwdenk printf ("[RUN_COMMAND] cmd[%p]=\"", cmd); 848c609719bSwdenk puts (cmd ? cmd : "NULL"); /* use puts - string may be loooong */ 849c609719bSwdenk puts ("\"\n"); 850c609719bSwdenk #endif 851c609719bSwdenk 852c609719bSwdenk clear_ctrlc(); /* forget any previous Control C */ 853c609719bSwdenk 854c609719bSwdenk if (!cmd || !*cmd) { 855c609719bSwdenk return -1; /* empty command */ 856c609719bSwdenk } 857c609719bSwdenk 858c609719bSwdenk if (strlen(cmd) >= CFG_CBSIZE) { 859c609719bSwdenk puts ("## Command too long!\n"); 860c609719bSwdenk return -1; 861c609719bSwdenk } 862c609719bSwdenk 863c609719bSwdenk strcpy (cmdbuf, cmd); 864c609719bSwdenk 865c609719bSwdenk /* Process separators and check for invalid 866c609719bSwdenk * repeatable commands 867c609719bSwdenk */ 868c609719bSwdenk 869c609719bSwdenk #ifdef DEBUG_PARSER 870c609719bSwdenk printf ("[PROCESS_SEPARATORS] %s\n", cmd); 871c609719bSwdenk #endif 872c609719bSwdenk while (*str) { 873c609719bSwdenk 874c609719bSwdenk /* 875c609719bSwdenk * Find separator, or string end 876c609719bSwdenk * Allow simple escape of ';' by writing "\;" 877c609719bSwdenk */ 878a25f862bSwdenk for (inquotes = 0, sep = str; *sep; sep++) { 879a25f862bSwdenk if ((*sep=='\'') && 880a25f862bSwdenk (*(sep-1) != '\\')) 881a25f862bSwdenk inquotes=!inquotes; 882a25f862bSwdenk 883a25f862bSwdenk if (!inquotes && 884a25f862bSwdenk (*sep == ';') && /* separator */ 885c609719bSwdenk ( sep != str) && /* past string start */ 886c609719bSwdenk (*(sep-1) != '\\')) /* and NOT escaped */ 887c609719bSwdenk break; 888c609719bSwdenk } 889c609719bSwdenk 890c609719bSwdenk /* 891c609719bSwdenk * Limit the token to data between separators 892c609719bSwdenk */ 893c609719bSwdenk token = str; 894c609719bSwdenk if (*sep) { 895c609719bSwdenk str = sep + 1; /* start of command for next pass */ 896c609719bSwdenk *sep = '\0'; 897c609719bSwdenk } 898c609719bSwdenk else 899c609719bSwdenk str = sep; /* no more commands for next pass */ 900c609719bSwdenk #ifdef DEBUG_PARSER 901c609719bSwdenk printf ("token: \"%s\"\n", token); 902c609719bSwdenk #endif 903c609719bSwdenk 904c609719bSwdenk /* find macros in this token and replace them */ 905c609719bSwdenk process_macros (token, finaltoken); 906c609719bSwdenk 907c609719bSwdenk /* Extract arguments */ 908c609719bSwdenk argc = parse_line (finaltoken, argv); 909c609719bSwdenk 910c609719bSwdenk /* Look up command in command table */ 911c609719bSwdenk if ((cmdtp = find_cmd(argv[0])) == NULL) { 912c609719bSwdenk printf ("Unknown command '%s' - try 'help'\n", argv[0]); 913f07771ccSwdenk rc = -1; /* give up after bad command */ 914f07771ccSwdenk continue; 915c609719bSwdenk } 916c609719bSwdenk 917c609719bSwdenk /* found - check max args */ 918c609719bSwdenk if (argc > cmdtp->maxargs) { 919c609719bSwdenk printf ("Usage:\n%s\n", cmdtp->usage); 920f07771ccSwdenk rc = -1; 921f07771ccSwdenk continue; 922c609719bSwdenk } 923c609719bSwdenk 924c609719bSwdenk #if (CONFIG_COMMANDS & CFG_CMD_BOOTD) 925c609719bSwdenk /* avoid "bootd" recursion */ 926c609719bSwdenk if (cmdtp->cmd == do_bootd) { 927c609719bSwdenk #ifdef DEBUG_PARSER 928c609719bSwdenk printf ("[%s]\n", finaltoken); 929c609719bSwdenk #endif 930c609719bSwdenk if (flag & CMD_FLAG_BOOTD) { 9314b9206edSwdenk puts ("'bootd' recursion detected\n"); 932f07771ccSwdenk rc = -1; 933f07771ccSwdenk continue; 934c609719bSwdenk } 935c609719bSwdenk else 936c609719bSwdenk flag |= CMD_FLAG_BOOTD; 937c609719bSwdenk } 938c609719bSwdenk #endif /* CFG_CMD_BOOTD */ 939c609719bSwdenk 940c609719bSwdenk /* OK - call function to do the command */ 941c609719bSwdenk if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) { 942f07771ccSwdenk rc = -1; 943c609719bSwdenk } 944c609719bSwdenk 945c609719bSwdenk repeatable &= cmdtp->repeatable; 946c609719bSwdenk 947c609719bSwdenk /* Did the user stop this? */ 948c609719bSwdenk if (had_ctrlc ()) 949c609719bSwdenk return 0; /* if stopped then not repeatable */ 950c609719bSwdenk } 951c609719bSwdenk 952f07771ccSwdenk return rc ? rc : repeatable; 953c609719bSwdenk } 954c609719bSwdenk 955c609719bSwdenk /****************************************************************************/ 956c609719bSwdenk 957c609719bSwdenk #if (CONFIG_COMMANDS & CFG_CMD_RUN) 958c609719bSwdenk int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 959c609719bSwdenk { 960c609719bSwdenk int i; 961c609719bSwdenk 962c609719bSwdenk if (argc < 2) { 963c609719bSwdenk printf ("Usage:\n%s\n", cmdtp->usage); 964c609719bSwdenk return 1; 965c609719bSwdenk } 966c609719bSwdenk 967c609719bSwdenk for (i=1; i<argc; ++i) { 9683e38691eSwdenk char *arg; 9693e38691eSwdenk 9703e38691eSwdenk if ((arg = getenv (argv[i])) == NULL) { 9713e38691eSwdenk printf ("## Error: \"%s\" not defined\n", argv[i]); 9723e38691eSwdenk return 1; 9733e38691eSwdenk } 974c609719bSwdenk #ifndef CFG_HUSH_PARSER 9753e38691eSwdenk if (run_command (arg, flag) == -1) 9763e38691eSwdenk return 1; 977c609719bSwdenk #else 9783e38691eSwdenk if (parse_string_outer(arg, 9797aa78614Swdenk FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0) 9803e38691eSwdenk return 1; 981c609719bSwdenk #endif 982c609719bSwdenk } 9833e38691eSwdenk return 0; 984c609719bSwdenk } 9853e38691eSwdenk #endif /* CFG_CMD_RUN */ 986