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 36804a85b3bSwdenk #ifdef CONFIG_AUTO_COMPLETE 36904a85b3bSwdenk install_auto_complete(); 37004a85b3bSwdenk #endif 37104a85b3bSwdenk 372c609719bSwdenk #ifdef CONFIG_PREBOOT 373c609719bSwdenk if ((p = getenv ("preboot")) != NULL) { 374c609719bSwdenk # ifdef CONFIG_AUTOBOOT_KEYED 375c609719bSwdenk int prev = disable_ctrlc(1); /* disable Control C checking */ 376c609719bSwdenk # endif 377c609719bSwdenk 378c609719bSwdenk # ifndef CFG_HUSH_PARSER 379c609719bSwdenk run_command (p, 0); 380c609719bSwdenk # else 381c609719bSwdenk parse_string_outer(p, FLAG_PARSE_SEMICOLON | 382c609719bSwdenk FLAG_EXIT_FROM_LOOP); 383c609719bSwdenk # endif 384c609719bSwdenk 385c609719bSwdenk # ifdef CONFIG_AUTOBOOT_KEYED 386c609719bSwdenk disable_ctrlc(prev); /* restore Control C checking */ 387c609719bSwdenk # endif 388c609719bSwdenk } 389c609719bSwdenk #endif /* CONFIG_PREBOOT */ 390c609719bSwdenk 391c609719bSwdenk #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) 392c609719bSwdenk s = getenv ("bootdelay"); 393c609719bSwdenk bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; 394c609719bSwdenk 395a6c7ad2fSwdenk debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay); 396c609719bSwdenk 397c609719bSwdenk # ifdef CONFIG_BOOT_RETRY_TIME 3986dd652faSwdenk init_cmd_timeout (); 399c609719bSwdenk # endif /* CONFIG_BOOT_RETRY_TIME */ 400c609719bSwdenk 401bdccc4feSwdenk #ifdef CONFIG_BOOTCOUNT_LIMIT 402bdccc4feSwdenk if (bootlimit && (bootcount > bootlimit)) { 403bdccc4feSwdenk printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n", 404bdccc4feSwdenk (unsigned)bootlimit); 405bdccc4feSwdenk s = getenv ("altbootcmd"); 406bdccc4feSwdenk } 407bdccc4feSwdenk else 408bdccc4feSwdenk #endif /* CONFIG_BOOTCOUNT_LIMIT */ 409c609719bSwdenk s = getenv ("bootcmd"); 410a6c7ad2fSwdenk 411a6c7ad2fSwdenk debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>"); 412a6c7ad2fSwdenk 413c609719bSwdenk if (bootdelay >= 0 && s && !abortboot (bootdelay)) { 414c609719bSwdenk # ifdef CONFIG_AUTOBOOT_KEYED 415c609719bSwdenk int prev = disable_ctrlc(1); /* disable Control C checking */ 416c609719bSwdenk # endif 417c609719bSwdenk 418c609719bSwdenk # ifndef CFG_HUSH_PARSER 419c609719bSwdenk run_command (s, 0); 420c609719bSwdenk # else 421c609719bSwdenk parse_string_outer(s, FLAG_PARSE_SEMICOLON | 422c609719bSwdenk FLAG_EXIT_FROM_LOOP); 423c609719bSwdenk # endif 424c609719bSwdenk 425c609719bSwdenk # ifdef CONFIG_AUTOBOOT_KEYED 426c609719bSwdenk disable_ctrlc(prev); /* restore Control C checking */ 427c609719bSwdenk # endif 428c609719bSwdenk } 429c7de829cSwdenk 430c7de829cSwdenk # ifdef CONFIG_MENUKEY 431a6c7ad2fSwdenk if (menukey == CONFIG_MENUKEY) { 432c7de829cSwdenk s = getenv("menucmd"); 433a6c7ad2fSwdenk if (s) { 434c7de829cSwdenk # ifndef CFG_HUSH_PARSER 435c7de829cSwdenk run_command (s, bd, 0); 436c7de829cSwdenk # else 437c7de829cSwdenk parse_string_outer(s, FLAG_PARSE_SEMICOLON | 438c7de829cSwdenk FLAG_EXIT_FROM_LOOP); 439c7de829cSwdenk # endif 440c7de829cSwdenk } 441c7de829cSwdenk } 442c7de829cSwdenk #endif /* CONFIG_MENUKEY */ 443c609719bSwdenk #endif /* CONFIG_BOOTDELAY */ 444c609719bSwdenk 445c7de829cSwdenk #ifdef CONFIG_AMIGAONEG3SE 446c7de829cSwdenk { 447c7de829cSwdenk extern void video_banner(void); 448c7de829cSwdenk video_banner(); 449c7de829cSwdenk } 450c7de829cSwdenk #endif 451c7de829cSwdenk 452c609719bSwdenk /* 453c609719bSwdenk * Main Loop for Monitor Command Processing 454c609719bSwdenk */ 455c609719bSwdenk #ifdef CFG_HUSH_PARSER 456c609719bSwdenk parse_file_outer(); 457c609719bSwdenk /* This point is never reached */ 458c609719bSwdenk for (;;); 459c609719bSwdenk #else 460c609719bSwdenk for (;;) { 461c609719bSwdenk #ifdef CONFIG_BOOT_RETRY_TIME 462c609719bSwdenk if (rc >= 0) { 463c609719bSwdenk /* Saw enough of a valid command to 464c609719bSwdenk * restart the timeout. 465c609719bSwdenk */ 466c609719bSwdenk reset_cmd_timeout(); 467c609719bSwdenk } 468c609719bSwdenk #endif 469c609719bSwdenk len = readline (CFG_PROMPT); 470c609719bSwdenk 471c609719bSwdenk flag = 0; /* assume no special flags for now */ 472c609719bSwdenk if (len > 0) 473c609719bSwdenk strcpy (lastcommand, console_buffer); 474c609719bSwdenk else if (len == 0) 475c609719bSwdenk flag |= CMD_FLAG_REPEAT; 476c609719bSwdenk #ifdef CONFIG_BOOT_RETRY_TIME 477c609719bSwdenk else if (len == -2) { 478c609719bSwdenk /* -2 means timed out, retry autoboot 479c609719bSwdenk */ 4804b9206edSwdenk puts ("\nTimed out waiting for command\n"); 481c609719bSwdenk # ifdef CONFIG_RESET_TO_RETRY 482c609719bSwdenk /* Reinit board to run initialization code again */ 483c609719bSwdenk do_reset (NULL, 0, 0, NULL); 484c609719bSwdenk # else 485c609719bSwdenk return; /* retry autoboot */ 486c609719bSwdenk # endif 487c609719bSwdenk } 488c609719bSwdenk #endif 489c609719bSwdenk 490c609719bSwdenk if (len == -1) 4914b9206edSwdenk puts ("<INTERRUPT>\n"); 492c609719bSwdenk else 493c609719bSwdenk rc = run_command (lastcommand, flag); 494c609719bSwdenk 495c609719bSwdenk if (rc <= 0) { 496c609719bSwdenk /* invalid command or not repeatable, forget it */ 497c609719bSwdenk lastcommand[0] = 0; 498c609719bSwdenk } 499c609719bSwdenk } 500c609719bSwdenk #endif /*CFG_HUSH_PARSER*/ 501c609719bSwdenk } 502c609719bSwdenk 5036dd652faSwdenk #ifdef CONFIG_BOOT_RETRY_TIME 5046dd652faSwdenk /*************************************************************************** 5056dd652faSwdenk * initialise command line timeout 5066dd652faSwdenk */ 5076dd652faSwdenk void init_cmd_timeout(void) 5086dd652faSwdenk { 5096dd652faSwdenk char *s = getenv ("bootretry"); 5106dd652faSwdenk 5116dd652faSwdenk if (s != NULL) 512b028f715Swdenk retry_time = (int)simple_strtol(s, NULL, 10); 5136dd652faSwdenk else 5146dd652faSwdenk retry_time = CONFIG_BOOT_RETRY_TIME; 5156dd652faSwdenk 5166dd652faSwdenk if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN) 5176dd652faSwdenk retry_time = CONFIG_BOOT_RETRY_MIN; 5186dd652faSwdenk } 5196dd652faSwdenk 520c609719bSwdenk /*************************************************************************** 521c609719bSwdenk * reset command line timeout to retry_time seconds 522c609719bSwdenk */ 523c609719bSwdenk void reset_cmd_timeout(void) 524c609719bSwdenk { 525c609719bSwdenk endtime = endtick(retry_time); 526c609719bSwdenk } 527c609719bSwdenk #endif 528c609719bSwdenk 529c609719bSwdenk /****************************************************************************/ 530c609719bSwdenk 531c609719bSwdenk /* 532c609719bSwdenk * Prompt for input and read a line. 533c609719bSwdenk * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0, 534c609719bSwdenk * time out when time goes past endtime (timebase time in ticks). 535c609719bSwdenk * Return: number of read characters 536c609719bSwdenk * -1 if break 537c609719bSwdenk * -2 if timed out 538c609719bSwdenk */ 539c609719bSwdenk int readline (const char *const prompt) 540c609719bSwdenk { 541c609719bSwdenk char *p = console_buffer; 542c609719bSwdenk int n = 0; /* buffer index */ 543c609719bSwdenk int plen = 0; /* prompt length */ 544c609719bSwdenk int col; /* output column cnt */ 545c609719bSwdenk char c; 546c609719bSwdenk 547c609719bSwdenk /* print prompt */ 548c609719bSwdenk if (prompt) { 549c609719bSwdenk plen = strlen (prompt); 550c609719bSwdenk puts (prompt); 551c609719bSwdenk } 552c609719bSwdenk col = plen; 553c609719bSwdenk 554c609719bSwdenk for (;;) { 555c609719bSwdenk #ifdef CONFIG_BOOT_RETRY_TIME 556c609719bSwdenk while (!tstc()) { /* while no incoming data */ 557c609719bSwdenk if (retry_time >= 0 && get_ticks() > endtime) 558c609719bSwdenk return (-2); /* timed out */ 559c609719bSwdenk } 560c609719bSwdenk #endif 561c609719bSwdenk WATCHDOG_RESET(); /* Trigger watchdog, if needed */ 562c609719bSwdenk 563c609719bSwdenk #ifdef CONFIG_SHOW_ACTIVITY 564c609719bSwdenk while (!tstc()) { 565c609719bSwdenk extern void show_activity(int arg); 566c609719bSwdenk show_activity(0); 567c609719bSwdenk } 568c609719bSwdenk #endif 569c609719bSwdenk c = getc(); 570c609719bSwdenk 571c609719bSwdenk /* 572c609719bSwdenk * Special character handling 573c609719bSwdenk */ 574c609719bSwdenk switch (c) { 575c609719bSwdenk case '\r': /* Enter */ 576c609719bSwdenk case '\n': 577c609719bSwdenk *p = '\0'; 578c609719bSwdenk puts ("\r\n"); 579c609719bSwdenk return (p - console_buffer); 580c609719bSwdenk 58127aa8186Swdenk case '\0': /* nul */ 58227aa8186Swdenk continue; 58327aa8186Swdenk 584c609719bSwdenk case 0x03: /* ^C - break */ 585c609719bSwdenk console_buffer[0] = '\0'; /* discard input */ 586c609719bSwdenk return (-1); 587c609719bSwdenk 588c609719bSwdenk case 0x15: /* ^U - erase line */ 589c609719bSwdenk while (col > plen) { 590c609719bSwdenk puts (erase_seq); 591c609719bSwdenk --col; 592c609719bSwdenk } 593c609719bSwdenk p = console_buffer; 594c609719bSwdenk n = 0; 595c609719bSwdenk continue; 596c609719bSwdenk 597c609719bSwdenk case 0x17: /* ^W - erase word */ 598c609719bSwdenk p=delete_char(console_buffer, p, &col, &n, plen); 599c609719bSwdenk while ((n > 0) && (*p != ' ')) { 600c609719bSwdenk p=delete_char(console_buffer, p, &col, &n, plen); 601c609719bSwdenk } 602c609719bSwdenk continue; 603c609719bSwdenk 604c609719bSwdenk case 0x08: /* ^H - backspace */ 605c609719bSwdenk case 0x7F: /* DEL - backspace */ 606c609719bSwdenk p=delete_char(console_buffer, p, &col, &n, plen); 607c609719bSwdenk continue; 608c609719bSwdenk 609c609719bSwdenk default: 610c609719bSwdenk /* 611c609719bSwdenk * Must be a normal character then 612c609719bSwdenk */ 613c609719bSwdenk if (n < CFG_CBSIZE-2) { 614c609719bSwdenk if (c == '\t') { /* expand TABs */ 61504a85b3bSwdenk #ifdef CONFIG_AUTO_COMPLETE 61604a85b3bSwdenk /* if auto completion triggered just continue */ 61704a85b3bSwdenk *p = '\0'; 61804a85b3bSwdenk if (cmd_auto_complete(prompt, console_buffer, &n, &col)) { 61904a85b3bSwdenk p = console_buffer + n; /* reset */ 62004a85b3bSwdenk continue; 62104a85b3bSwdenk } 62204a85b3bSwdenk #endif 623c609719bSwdenk puts (tab_seq+(col&07)); 624c609719bSwdenk col += 8 - (col&07); 625c609719bSwdenk } else { 626c609719bSwdenk ++col; /* echo input */ 627c609719bSwdenk putc (c); 628c609719bSwdenk } 629c609719bSwdenk *p++ = c; 630c609719bSwdenk ++n; 631c609719bSwdenk } else { /* Buffer full */ 632c609719bSwdenk putc ('\a'); 633c609719bSwdenk } 634c609719bSwdenk } 635c609719bSwdenk } 636c609719bSwdenk } 637c609719bSwdenk 638c609719bSwdenk /****************************************************************************/ 639c609719bSwdenk 640c609719bSwdenk static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen) 641c609719bSwdenk { 642c609719bSwdenk char *s; 643c609719bSwdenk 644c609719bSwdenk if (*np == 0) { 645c609719bSwdenk return (p); 646c609719bSwdenk } 647c609719bSwdenk 648c609719bSwdenk if (*(--p) == '\t') { /* will retype the whole line */ 649c609719bSwdenk while (*colp > plen) { 650c609719bSwdenk puts (erase_seq); 651c609719bSwdenk (*colp)--; 652c609719bSwdenk } 653c609719bSwdenk for (s=buffer; s<p; ++s) { 654c609719bSwdenk if (*s == '\t') { 655c609719bSwdenk puts (tab_seq+((*colp) & 07)); 656c609719bSwdenk *colp += 8 - ((*colp) & 07); 657c609719bSwdenk } else { 658c609719bSwdenk ++(*colp); 659c609719bSwdenk putc (*s); 660c609719bSwdenk } 661c609719bSwdenk } 662c609719bSwdenk } else { 663c609719bSwdenk puts (erase_seq); 664c609719bSwdenk (*colp)--; 665c609719bSwdenk } 666c609719bSwdenk (*np)--; 667c609719bSwdenk return (p); 668c609719bSwdenk } 669c609719bSwdenk 670c609719bSwdenk /****************************************************************************/ 671c609719bSwdenk 672c609719bSwdenk int parse_line (char *line, char *argv[]) 673c609719bSwdenk { 674c609719bSwdenk int nargs = 0; 675c609719bSwdenk 676c609719bSwdenk #ifdef DEBUG_PARSER 677c609719bSwdenk printf ("parse_line: \"%s\"\n", line); 678c609719bSwdenk #endif 679c609719bSwdenk while (nargs < CFG_MAXARGS) { 680c609719bSwdenk 681c609719bSwdenk /* skip any white space */ 682c609719bSwdenk while ((*line == ' ') || (*line == '\t')) { 683c609719bSwdenk ++line; 684c609719bSwdenk } 685c609719bSwdenk 686c609719bSwdenk if (*line == '\0') { /* end of line, no more args */ 687c609719bSwdenk argv[nargs] = NULL; 688c609719bSwdenk #ifdef DEBUG_PARSER 689c609719bSwdenk printf ("parse_line: nargs=%d\n", nargs); 690c609719bSwdenk #endif 691c609719bSwdenk return (nargs); 692c609719bSwdenk } 693c609719bSwdenk 694c609719bSwdenk argv[nargs++] = line; /* begin of argument string */ 695c609719bSwdenk 696c609719bSwdenk /* find end of string */ 697c609719bSwdenk while (*line && (*line != ' ') && (*line != '\t')) { 698c609719bSwdenk ++line; 699c609719bSwdenk } 700c609719bSwdenk 701c609719bSwdenk if (*line == '\0') { /* end of line, no more args */ 702c609719bSwdenk argv[nargs] = NULL; 703c609719bSwdenk #ifdef DEBUG_PARSER 704c609719bSwdenk printf ("parse_line: nargs=%d\n", nargs); 705c609719bSwdenk #endif 706c609719bSwdenk return (nargs); 707c609719bSwdenk } 708c609719bSwdenk 709c609719bSwdenk *line++ = '\0'; /* terminate current arg */ 710c609719bSwdenk } 711c609719bSwdenk 712c609719bSwdenk printf ("** Too many args (max. %d) **\n", CFG_MAXARGS); 713c609719bSwdenk 714c609719bSwdenk #ifdef DEBUG_PARSER 715c609719bSwdenk printf ("parse_line: nargs=%d\n", nargs); 716c609719bSwdenk #endif 717c609719bSwdenk return (nargs); 718c609719bSwdenk } 719c609719bSwdenk 720c609719bSwdenk /****************************************************************************/ 721c609719bSwdenk 722c609719bSwdenk static void process_macros (const char *input, char *output) 723c609719bSwdenk { 724c609719bSwdenk char c, prev; 725c609719bSwdenk const char *varname_start = NULL; 726c609719bSwdenk int inputcnt = strlen (input); 727c609719bSwdenk int outputcnt = CFG_CBSIZE; 728c609719bSwdenk int state = 0; /* 0 = waiting for '$' */ 729*5cf91d6bSwdenk /* 1 = waiting for '(' or '{' */ 730*5cf91d6bSwdenk /* 2 = waiting for ')' or '}' */ 731a25f862bSwdenk /* 3 = waiting for ''' */ 732c609719bSwdenk #ifdef DEBUG_PARSER 733c609719bSwdenk char *output_start = output; 734c609719bSwdenk 735c609719bSwdenk printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(input), input); 736c609719bSwdenk #endif 737c609719bSwdenk 738c609719bSwdenk prev = '\0'; /* previous character */ 739c609719bSwdenk 740c609719bSwdenk while (inputcnt && outputcnt) { 741c609719bSwdenk c = *input++; 742c609719bSwdenk inputcnt--; 743c609719bSwdenk 744a25f862bSwdenk if (state!=3) { 745c609719bSwdenk /* remove one level of escape characters */ 746c609719bSwdenk if ((c == '\\') && (prev != '\\')) { 747c609719bSwdenk if (inputcnt-- == 0) 748c609719bSwdenk break; 749c609719bSwdenk prev = c; 750c609719bSwdenk c = *input++; 751c609719bSwdenk } 752a25f862bSwdenk } 753c609719bSwdenk 754c609719bSwdenk switch (state) { 755c609719bSwdenk case 0: /* Waiting for (unescaped) $ */ 756a25f862bSwdenk if ((c == '\'') && (prev != '\\')) { 757a25f862bSwdenk state = 3; 758a25f862bSwdenk break; 759a25f862bSwdenk } 760c609719bSwdenk if ((c == '$') && (prev != '\\')) { 761c609719bSwdenk state++; 762c609719bSwdenk } else { 763c609719bSwdenk *(output++) = c; 764c609719bSwdenk outputcnt--; 765c609719bSwdenk } 766c609719bSwdenk break; 767c609719bSwdenk case 1: /* Waiting for ( */ 768*5cf91d6bSwdenk if (c == '(' || c == '{') { 769c609719bSwdenk state++; 770c609719bSwdenk varname_start = input; 771c609719bSwdenk } else { 772c609719bSwdenk state = 0; 773c609719bSwdenk *(output++) = '$'; 774c609719bSwdenk outputcnt--; 775c609719bSwdenk 776c609719bSwdenk if (outputcnt) { 777c609719bSwdenk *(output++) = c; 778c609719bSwdenk outputcnt--; 779c609719bSwdenk } 780c609719bSwdenk } 781c609719bSwdenk break; 782c609719bSwdenk case 2: /* Waiting for ) */ 783*5cf91d6bSwdenk if (c == ')' || c == '}') { 784c609719bSwdenk int i; 785c609719bSwdenk char envname[CFG_CBSIZE], *envval; 786c609719bSwdenk int envcnt = input-varname_start-1; /* Varname # of chars */ 787c609719bSwdenk 788c609719bSwdenk /* Get the varname */ 789c609719bSwdenk for (i = 0; i < envcnt; i++) { 790c609719bSwdenk envname[i] = varname_start[i]; 791c609719bSwdenk } 792c609719bSwdenk envname[i] = 0; 793c609719bSwdenk 794c609719bSwdenk /* Get its value */ 795c609719bSwdenk envval = getenv (envname); 796c609719bSwdenk 797c609719bSwdenk /* Copy into the line if it exists */ 798c609719bSwdenk if (envval != NULL) 799c609719bSwdenk while ((*envval) && outputcnt) { 800c609719bSwdenk *(output++) = *(envval++); 801c609719bSwdenk outputcnt--; 802c609719bSwdenk } 803c609719bSwdenk /* Look for another '$' */ 804c609719bSwdenk state = 0; 805c609719bSwdenk } 806c609719bSwdenk break; 807a25f862bSwdenk case 3: /* Waiting for ' */ 808a25f862bSwdenk if ((c == '\'') && (prev != '\\')) { 809a25f862bSwdenk state = 0; 810a25f862bSwdenk } else { 811a25f862bSwdenk *(output++) = c; 812a25f862bSwdenk outputcnt--; 813c609719bSwdenk } 814a25f862bSwdenk break; 815a25f862bSwdenk } 816c609719bSwdenk prev = c; 817c609719bSwdenk } 818c609719bSwdenk 819c609719bSwdenk if (outputcnt) 820c609719bSwdenk *output = 0; 821c609719bSwdenk 822c609719bSwdenk #ifdef DEBUG_PARSER 823c609719bSwdenk printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n", 824c609719bSwdenk strlen(output_start), output_start); 825c609719bSwdenk #endif 826c609719bSwdenk } 827c609719bSwdenk 828c609719bSwdenk /**************************************************************************** 829c609719bSwdenk * returns: 830c609719bSwdenk * 1 - command executed, repeatable 831c609719bSwdenk * 0 - command executed but not repeatable, interrupted commands are 832c609719bSwdenk * always considered not repeatable 833c609719bSwdenk * -1 - not executed (unrecognized, bootd recursion or too many args) 834c609719bSwdenk * (If cmd is NULL or "" or longer than CFG_CBSIZE-1 it is 835c609719bSwdenk * considered unrecognized) 836c609719bSwdenk * 837c609719bSwdenk * WARNING: 838c609719bSwdenk * 839c609719bSwdenk * We must create a temporary copy of the command since the command we get 840c609719bSwdenk * may be the result from getenv(), which returns a pointer directly to 841c609719bSwdenk * the environment data, which may change magicly when the command we run 842c609719bSwdenk * creates or modifies environment variables (like "bootp" does). 843c609719bSwdenk */ 844c609719bSwdenk 845c609719bSwdenk int run_command (const char *cmd, int flag) 846c609719bSwdenk { 847c609719bSwdenk cmd_tbl_t *cmdtp; 848c609719bSwdenk char cmdbuf[CFG_CBSIZE]; /* working copy of cmd */ 849c609719bSwdenk char *token; /* start of token in cmdbuf */ 850c609719bSwdenk char *sep; /* end of token (separator) in cmdbuf */ 851c609719bSwdenk char finaltoken[CFG_CBSIZE]; 852c609719bSwdenk char *str = cmdbuf; 853c609719bSwdenk char *argv[CFG_MAXARGS + 1]; /* NULL terminated */ 854f07771ccSwdenk int argc, inquotes; 855c609719bSwdenk int repeatable = 1; 856f07771ccSwdenk int rc = 0; 857c609719bSwdenk 858c609719bSwdenk #ifdef DEBUG_PARSER 859c609719bSwdenk printf ("[RUN_COMMAND] cmd[%p]=\"", cmd); 860c609719bSwdenk puts (cmd ? cmd : "NULL"); /* use puts - string may be loooong */ 861c609719bSwdenk puts ("\"\n"); 862c609719bSwdenk #endif 863c609719bSwdenk 864c609719bSwdenk clear_ctrlc(); /* forget any previous Control C */ 865c609719bSwdenk 866c609719bSwdenk if (!cmd || !*cmd) { 867c609719bSwdenk return -1; /* empty command */ 868c609719bSwdenk } 869c609719bSwdenk 870c609719bSwdenk if (strlen(cmd) >= CFG_CBSIZE) { 871c609719bSwdenk puts ("## Command too long!\n"); 872c609719bSwdenk return -1; 873c609719bSwdenk } 874c609719bSwdenk 875c609719bSwdenk strcpy (cmdbuf, cmd); 876c609719bSwdenk 877c609719bSwdenk /* Process separators and check for invalid 878c609719bSwdenk * repeatable commands 879c609719bSwdenk */ 880c609719bSwdenk 881c609719bSwdenk #ifdef DEBUG_PARSER 882c609719bSwdenk printf ("[PROCESS_SEPARATORS] %s\n", cmd); 883c609719bSwdenk #endif 884c609719bSwdenk while (*str) { 885c609719bSwdenk 886c609719bSwdenk /* 887c609719bSwdenk * Find separator, or string end 888c609719bSwdenk * Allow simple escape of ';' by writing "\;" 889c609719bSwdenk */ 890a25f862bSwdenk for (inquotes = 0, sep = str; *sep; sep++) { 891a25f862bSwdenk if ((*sep=='\'') && 892a25f862bSwdenk (*(sep-1) != '\\')) 893a25f862bSwdenk inquotes=!inquotes; 894a25f862bSwdenk 895a25f862bSwdenk if (!inquotes && 896a25f862bSwdenk (*sep == ';') && /* separator */ 897c609719bSwdenk ( sep != str) && /* past string start */ 898c609719bSwdenk (*(sep-1) != '\\')) /* and NOT escaped */ 899c609719bSwdenk break; 900c609719bSwdenk } 901c609719bSwdenk 902c609719bSwdenk /* 903c609719bSwdenk * Limit the token to data between separators 904c609719bSwdenk */ 905c609719bSwdenk token = str; 906c609719bSwdenk if (*sep) { 907c609719bSwdenk str = sep + 1; /* start of command for next pass */ 908c609719bSwdenk *sep = '\0'; 909c609719bSwdenk } 910c609719bSwdenk else 911c609719bSwdenk str = sep; /* no more commands for next pass */ 912c609719bSwdenk #ifdef DEBUG_PARSER 913c609719bSwdenk printf ("token: \"%s\"\n", token); 914c609719bSwdenk #endif 915c609719bSwdenk 916c609719bSwdenk /* find macros in this token and replace them */ 917c609719bSwdenk process_macros (token, finaltoken); 918c609719bSwdenk 919c609719bSwdenk /* Extract arguments */ 920c609719bSwdenk argc = parse_line (finaltoken, argv); 921c609719bSwdenk 922c609719bSwdenk /* Look up command in command table */ 923c609719bSwdenk if ((cmdtp = find_cmd(argv[0])) == NULL) { 924c609719bSwdenk printf ("Unknown command '%s' - try 'help'\n", argv[0]); 925f07771ccSwdenk rc = -1; /* give up after bad command */ 926f07771ccSwdenk continue; 927c609719bSwdenk } 928c609719bSwdenk 929c609719bSwdenk /* found - check max args */ 930c609719bSwdenk if (argc > cmdtp->maxargs) { 931c609719bSwdenk printf ("Usage:\n%s\n", cmdtp->usage); 932f07771ccSwdenk rc = -1; 933f07771ccSwdenk continue; 934c609719bSwdenk } 935c609719bSwdenk 936c609719bSwdenk #if (CONFIG_COMMANDS & CFG_CMD_BOOTD) 937c609719bSwdenk /* avoid "bootd" recursion */ 938c609719bSwdenk if (cmdtp->cmd == do_bootd) { 939c609719bSwdenk #ifdef DEBUG_PARSER 940c609719bSwdenk printf ("[%s]\n", finaltoken); 941c609719bSwdenk #endif 942c609719bSwdenk if (flag & CMD_FLAG_BOOTD) { 9434b9206edSwdenk puts ("'bootd' recursion detected\n"); 944f07771ccSwdenk rc = -1; 945f07771ccSwdenk continue; 946c609719bSwdenk } 947c609719bSwdenk else 948c609719bSwdenk flag |= CMD_FLAG_BOOTD; 949c609719bSwdenk } 950c609719bSwdenk #endif /* CFG_CMD_BOOTD */ 951c609719bSwdenk 952c609719bSwdenk /* OK - call function to do the command */ 953c609719bSwdenk if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) { 954f07771ccSwdenk rc = -1; 955c609719bSwdenk } 956c609719bSwdenk 957c609719bSwdenk repeatable &= cmdtp->repeatable; 958c609719bSwdenk 959c609719bSwdenk /* Did the user stop this? */ 960c609719bSwdenk if (had_ctrlc ()) 961c609719bSwdenk return 0; /* if stopped then not repeatable */ 962c609719bSwdenk } 963c609719bSwdenk 964f07771ccSwdenk return rc ? rc : repeatable; 965c609719bSwdenk } 966c609719bSwdenk 967c609719bSwdenk /****************************************************************************/ 968c609719bSwdenk 969c609719bSwdenk #if (CONFIG_COMMANDS & CFG_CMD_RUN) 970c609719bSwdenk int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 971c609719bSwdenk { 972c609719bSwdenk int i; 973c609719bSwdenk 974c609719bSwdenk if (argc < 2) { 975c609719bSwdenk printf ("Usage:\n%s\n", cmdtp->usage); 976c609719bSwdenk return 1; 977c609719bSwdenk } 978c609719bSwdenk 979c609719bSwdenk for (i=1; i<argc; ++i) { 9803e38691eSwdenk char *arg; 9813e38691eSwdenk 9823e38691eSwdenk if ((arg = getenv (argv[i])) == NULL) { 9833e38691eSwdenk printf ("## Error: \"%s\" not defined\n", argv[i]); 9843e38691eSwdenk return 1; 9853e38691eSwdenk } 986c609719bSwdenk #ifndef CFG_HUSH_PARSER 9873e38691eSwdenk if (run_command (arg, flag) == -1) 9883e38691eSwdenk return 1; 989c609719bSwdenk #else 9903e38691eSwdenk if (parse_string_outer(arg, 9917aa78614Swdenk FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0) 9923e38691eSwdenk return 1; 993c609719bSwdenk #endif 994c609719bSwdenk } 9953e38691eSwdenk return 0; 996c609719bSwdenk } 9973e38691eSwdenk #endif /* CFG_CMD_RUN */ 998