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