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