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