"Das U-Boot" Source Tree
at master 1190 lines 28 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2000-2004 4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 5 */ 6 7/* 8 * Serial up- and download support 9 */ 10#include <command.h> 11#include <console.h> 12#include <cpu_func.h> 13#include <efi_loader.h> 14#include <env.h> 15#include <exports.h> 16#ifdef CONFIG_MTD_NOR_FLASH 17#include <flash.h> 18#endif 19#include <image.h> 20#include <lmb.h> 21#include <mapmem.h> 22#include <net.h> 23#include <s_record.h> 24#include <serial.h> 25#include <xyzModem.h> 26#include <asm/cache.h> 27#include <asm/global_data.h> 28#include <linux/delay.h> 29 30DECLARE_GLOBAL_DATA_PTR; 31 32#if defined(CONFIG_CMD_LOADB) 33static ulong load_serial_ymodem(ulong offset, int mode); 34#endif 35 36#if defined(CONFIG_CMD_LOADS) 37static ulong load_serial(long offset); 38static int read_record(char *buf, ulong len); 39# if defined(CONFIG_CMD_SAVES) 40static int save_serial(ulong offset, ulong size); 41static int write_record(char *buf); 42#endif 43 44static int do_echo = 1; 45#endif 46 47/* -------------------------------------------------------------------- */ 48 49#if defined(CONFIG_CMD_LOADS) 50static int do_load_serial(struct cmd_tbl *cmdtp, int flag, int argc, 51 char *const argv[]) 52{ 53 long offset = 0; 54 ulong addr; 55 int i; 56 char *env_echo; 57 int rcode = 0; 58#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE 59 int load_baudrate, current_baudrate; 60 61 load_baudrate = current_baudrate = gd->baudrate; 62#endif 63 64 env_echo = env_get("loads_echo"); 65 if (env_echo && *env_echo == '1') 66 do_echo = 1; 67 else 68 do_echo = 0; 69 70#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE 71 if (argc >= 2) { 72 offset = simple_strtol(argv[1], NULL, 16); 73 } 74 if (argc == 3) { 75 load_baudrate = (int)dectoul(argv[2], NULL); 76 77 /* default to current baudrate */ 78 if (load_baudrate == 0) 79 load_baudrate = current_baudrate; 80 } 81 if (load_baudrate != current_baudrate) { 82 printf("## Switch baudrate to %d bps and press ENTER ...\n", 83 load_baudrate); 84 udelay(50000); 85 flush(); 86 gd->baudrate = load_baudrate; 87 serial_setbrg(); 88 udelay(50000); 89 for (;;) { 90 if (getchar() == '\r') 91 break; 92 } 93 } 94#else /* ! CONFIG_SYS_LOADS_BAUD_CHANGE */ 95 if (argc == 2) { 96 offset = simple_strtol(argv[1], NULL, 16); 97 } 98#endif /* CONFIG_SYS_LOADS_BAUD_CHANGE */ 99 100 printf("## Ready for S-Record download ...\n"); 101 102 addr = load_serial(offset); 103 104 /* 105 * Gather any trailing characters (for instance, the ^D which 106 * is sent by 'cu' after sending a file), and give the 107 * box some time (100 * 1 ms) 108 */ 109 for (i=0; i<100; ++i) { 110 if (tstc()) { 111 getchar(); 112 } 113 udelay(1000); 114 } 115 116 if (addr == ~0) { 117 printf("## S-Record download aborted\n"); 118 rcode = 1; 119 } else { 120 printf("## Start Addr = 0x%08lX\n", addr); 121 image_load_addr = addr; 122 } 123 124#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE 125 if (load_baudrate != current_baudrate) { 126 printf("## Switch baudrate to %d bps and press ESC ...\n", 127 current_baudrate); 128 udelay(50000); 129 flush(); 130 gd->baudrate = current_baudrate; 131 serial_setbrg(); 132 udelay(50000); 133 for (;;) { 134 if (getchar() == 0x1B) /* ESC */ 135 break; 136 } 137 } 138#endif 139 return rcode; 140} 141 142static ulong load_serial(long offset) 143{ 144 char record[SREC_MAXRECLEN + 1]; /* buffer for one S-Record */ 145 char binbuf[SREC_MAXBINLEN]; /* buffer for binary data */ 146 int binlen; /* no. of data bytes in S-Rec. */ 147 int type; /* return code for record type */ 148 ulong addr; /* load address from S-Record */ 149 ulong size; /* number of bytes transferred */ 150 ulong store_addr; 151 ulong start_addr = ~0; 152 ulong end_addr = 0; 153 int line_count = 0; 154 long ret; 155 156 while (read_record(record, SREC_MAXRECLEN + 1) >= 0) { 157 type = srec_decode(record, &binlen, &addr, binbuf); 158 159 if (type < 0) { 160 return (~0); /* Invalid S-Record */ 161 } 162 163 switch (type) { 164 case SREC_DATA2: 165 case SREC_DATA3: 166 case SREC_DATA4: 167 store_addr = addr + offset; 168#ifdef CONFIG_MTD_NOR_FLASH 169 if (addr2info(store_addr)) { 170 int rc; 171 172 rc = flash_write((char *)binbuf,store_addr,binlen); 173 if (rc != 0) { 174 flash_perror(rc); 175 return (~0); 176 } 177 } else 178#endif 179 { 180 void *dst; 181 182 ret = lmb_reserve(store_addr, binlen, LMB_NONE); 183 if (ret) { 184 printf("\nCannot overwrite reserved area (%08lx..%08lx)\n", 185 store_addr, store_addr + binlen); 186 return ret; 187 } 188 dst = map_sysmem(store_addr, binlen); 189 memcpy(dst, binbuf, binlen); 190 unmap_sysmem(dst); 191 lmb_free(store_addr, binlen); 192 } 193 if ((store_addr) < start_addr) 194 start_addr = store_addr; 195 if ((store_addr + binlen - 1) > end_addr) 196 end_addr = store_addr + binlen - 1; 197 break; 198 case SREC_END2: 199 case SREC_END3: 200 case SREC_END4: 201 udelay(10000); 202 size = end_addr - start_addr + 1; 203 printf("\n" 204 "## First Load Addr = 0x%08lX\n" 205 "## Last Load Addr = 0x%08lX\n" 206 "## Total Size = 0x%08lX = %ld Bytes\n", 207 start_addr, end_addr, size, size 208 ); 209 flush_cache(start_addr, size); 210 env_set_hex("filesize", size); 211 return (addr); 212 case SREC_START: 213 break; 214 default: 215 break; 216 } 217 if (!do_echo) { /* print a '.' every 100 lines */ 218 if ((++line_count % 100) == 0) 219 putc('.'); 220 } 221 } 222 223 return (~0); /* Download aborted */ 224} 225 226static int read_record(char *buf, ulong len) 227{ 228 char *p; 229 int c; 230 231 --len; /* always leave room for terminating '\0' byte */ 232 233 for (p=buf; p < buf+len; ++p) { 234 c = getchar(); /* read character */ 235 if (do_echo) 236 putc(c); /* ... and echo it */ 237 238 switch (c) { 239 case '\r': 240 case '\n': 241 *p = '\0'; 242 return (p - buf); 243 case '\0': 244 case 0x03: /* ^C - Control C */ 245 return (-1); 246 default: 247 *p = c; 248 } 249 250 /* Check for the console hangup (if any different from serial) */ 251 if (gd->jt->getc != getchar) { 252 if (ctrlc()) 253 return (-1); 254 } 255 } 256 257 /* line too long - truncate */ 258 *p = '\0'; 259 return (p - buf); 260} 261 262#if defined(CONFIG_CMD_SAVES) 263 264int do_save_serial(struct cmd_tbl *cmdtp, int flag, int argc, 265 char *const argv[]) 266{ 267 ulong offset = 0; 268 ulong size = 0; 269#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE 270 int save_baudrate, current_baudrate; 271 272 save_baudrate = current_baudrate = gd->baudrate; 273#endif 274 275 if (argc >= 2) { 276 offset = hextoul(argv[1], NULL); 277 } 278#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE 279 if (argc >= 3) { 280 size = hextoul(argv[2], NULL); 281 } 282 if (argc == 4) { 283 save_baudrate = (int)dectoul(argv[3], NULL); 284 285 /* default to current baudrate */ 286 if (save_baudrate == 0) 287 save_baudrate = current_baudrate; 288 } 289 if (save_baudrate != current_baudrate) { 290 printf("## Switch baudrate to %d bps and press ENTER ...\n", 291 save_baudrate); 292 udelay(50000); 293 gd->baudrate = save_baudrate; 294 serial_setbrg(); 295 udelay(50000); 296 for (;;) { 297 if (getchar() == '\r') 298 break; 299 } 300 } 301#else /* ! CONFIG_SYS_LOADS_BAUD_CHANGE */ 302 if (argc == 3) { 303 size = hextoul(argv[2], NULL); 304 } 305#endif /* CONFIG_SYS_LOADS_BAUD_CHANGE */ 306 307 printf("## Ready for S-Record upload, press ENTER to proceed ...\n"); 308 for (;;) { 309 if (getchar() == '\r') 310 break; 311 } 312 if (save_serial(offset, size)) { 313 printf("## S-Record upload aborted\n"); 314 } else { 315 printf("## S-Record upload complete\n"); 316 } 317#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE 318 if (save_baudrate != current_baudrate) { 319 printf("## Switch baudrate to %d bps and press ESC ...\n", 320 (int)current_baudrate); 321 udelay(50000); 322 flush(); 323 gd->baudrate = current_baudrate; 324 serial_setbrg(); 325 udelay(50000); 326 for (;;) { 327 if (getchar() == 0x1B) /* ESC */ 328 break; 329 } 330 } 331#endif 332 return 0; 333} 334 335#define SREC3_START "S0030000FC\n" 336#define SREC3_FORMAT "S3%02X%08lX%s%02X\n" 337#define SREC3_END "S70500000000FA\n" 338#define SREC_BYTES_PER_RECORD 16 339 340static int save_serial(ulong address, ulong count) 341{ 342 int i, c, reclen, checksum, length; 343 char *hex = "0123456789ABCDEF"; 344 char record[2*SREC_BYTES_PER_RECORD+16]; /* buffer for one S-Record */ 345 char data[2*SREC_BYTES_PER_RECORD+1]; /* buffer for hex data */ 346 347 reclen = 0; 348 checksum = 0; 349 350 if(write_record(SREC3_START)) /* write the header */ 351 return (-1); 352 do { 353 volatile uchar *src; 354 355 src = map_sysmem(address, count); 356 if (count) { /* collect hex data in the buffer */ 357 c = src[reclen]; /* get one byte */ 358 checksum += c; /* accumulate checksum */ 359 data[2*reclen] = hex[(c>>4)&0x0f]; 360 data[2*reclen+1] = hex[c & 0x0f]; 361 data[2*reclen+2] = '\0'; 362 ++reclen; 363 --count; 364 } 365 unmap_sysmem((void *)src); 366 if(reclen == SREC_BYTES_PER_RECORD || count == 0) { 367 /* enough data collected for one record: dump it */ 368 if(reclen) { /* build & write a data record: */ 369 /* address + data + checksum */ 370 length = 4 + reclen + 1; 371 372 /* accumulate length bytes into checksum */ 373 for(i = 0; i < 2; i++) 374 checksum += (length >> (8*i)) & 0xff; 375 376 /* accumulate address bytes into checksum: */ 377 for(i = 0; i < 4; i++) 378 checksum += (address >> (8*i)) & 0xff; 379 380 /* make proper checksum byte: */ 381 checksum = ~checksum & 0xff; 382 383 /* output one record: */ 384 sprintf(record, SREC3_FORMAT, length, address, data, checksum); 385 if(write_record(record)) 386 return (-1); 387 } 388 address += reclen; /* increment address */ 389 checksum = 0; 390 reclen = 0; 391 } 392 } 393 while(count); 394 if(write_record(SREC3_END)) /* write the final record */ 395 return (-1); 396 return(0); 397} 398 399static int write_record(char *buf) 400{ 401 char c; 402 403 while((c = *buf++)) 404 putc(c); 405 406 /* Check for the console hangup (if any different from serial) */ 407 408 if (ctrlc()) { 409 return (-1); 410 } 411 return (0); 412} 413# endif 414 415#endif 416 417#if defined(CONFIG_CMD_LOADB) 418/* 419 * loadb command (load binary) included 420 */ 421#define XON_CHAR 17 422#define XOFF_CHAR 19 423#define START_CHAR 0x01 424#define ETX_CHAR 0x03 425#define END_CHAR 0x0D 426#define SPACE 0x20 427#define K_ESCAPE 0x23 428#define SEND_TYPE 'S' 429#define DATA_TYPE 'D' 430#define ACK_TYPE 'Y' 431#define NACK_TYPE 'N' 432#define BREAK_TYPE 'B' 433#define tochar(x) ((char) (((x) + SPACE) & 0xff)) 434#define untochar(x) ((int) (((x) - SPACE) & 0xff)) 435 436static void set_kerm_bin_mode(unsigned long *); 437static int k_recv(void); 438static ulong load_serial_bin(ulong offset); 439 440static char his_eol; /* character he needs at end of packet */ 441static int his_pad_count; /* number of pad chars he needs */ 442static char his_pad_char; /* pad chars he needs */ 443static char his_quote; /* quote chars he'll use */ 444 445static int do_load_serial_bin(struct cmd_tbl *cmdtp, int flag, int argc, 446 char *const argv[]) 447{ 448 ulong offset = 0; 449 ulong addr; 450 int load_baudrate, current_baudrate; 451 int rcode = 0; 452 char *s; 453 454 /* pre-set offset from CONFIG_SYS_LOAD_ADDR */ 455 offset = CONFIG_SYS_LOAD_ADDR; 456 457 /* pre-set offset from $loadaddr */ 458 s = env_get("loadaddr"); 459 if (s) 460 offset = hextoul(s, NULL); 461 462 load_baudrate = current_baudrate = gd->baudrate; 463 464 if (argc >= 2) { 465 offset = hextoul(argv[1], NULL); 466 } 467 if (argc == 3) { 468 load_baudrate = (int)dectoul(argv[2], NULL); 469 470 /* default to current baudrate */ 471 if (load_baudrate == 0) 472 load_baudrate = current_baudrate; 473 } 474 475 if (load_baudrate != current_baudrate) { 476 printf("## Switch baudrate to %d bps and press ENTER ...\n", 477 load_baudrate); 478 udelay(50000); 479 flush(); 480 gd->baudrate = load_baudrate; 481 serial_setbrg(); 482 udelay(50000); 483 for (;;) { 484 if (getchar() == '\r') 485 break; 486 } 487 } 488 489 if (strcmp(argv[0],"loady")==0) { 490 printf("## Ready for binary (ymodem) download " 491 "to 0x%08lX at %d bps...\n", 492 offset, 493 load_baudrate); 494 495 addr = load_serial_ymodem(offset, xyzModem_ymodem); 496 497 if (addr == ~0) { 498 image_load_addr = 0; 499 printf("## Binary (ymodem) download aborted\n"); 500 rcode = 1; 501 } else { 502 printf("## Start Addr = 0x%08lX\n", addr); 503 image_load_addr = addr; 504 } 505 } else if (strcmp(argv[0],"loadx")==0) { 506 printf("## Ready for binary (xmodem) download " 507 "to 0x%08lX at %d bps...\n", 508 offset, 509 load_baudrate); 510 511 addr = load_serial_ymodem(offset, xyzModem_xmodem); 512 513 if (addr == ~0) { 514 image_load_addr = 0; 515 printf("## Binary (xmodem) download aborted\n"); 516 rcode = 1; 517 } else { 518 printf("## Start Addr = 0x%08lX\n", addr); 519 image_load_addr = addr; 520 } 521 } else { 522 523 printf("## Ready for binary (kermit) download " 524 "to 0x%08lX at %d bps...\n", 525 offset, 526 load_baudrate); 527 addr = load_serial_bin(offset); 528 529 if (addr == ~0) { 530 image_load_addr = 0; 531 printf("## Binary (kermit) download aborted\n"); 532 rcode = 1; 533 } else { 534 printf("## Start Addr = 0x%08lX\n", addr); 535 image_load_addr = addr; 536 } 537 } 538 if (load_baudrate != current_baudrate) { 539 printf("## Switch baudrate to %d bps and press ESC ...\n", 540 current_baudrate); 541 udelay(50000); 542 flush(); 543 gd->baudrate = current_baudrate; 544 serial_setbrg(); 545 udelay(50000); 546 for (;;) { 547 if (getchar() == 0x1B) /* ESC */ 548 break; 549 } 550 } 551 552 return rcode; 553} 554 555static ulong load_serial_bin(ulong offset) 556{ 557 int size, i; 558 559 set_kerm_bin_mode((ulong *) offset); 560 size = k_recv(); 561 562 /* 563 * Gather any trailing characters (for instance, the ^D which 564 * is sent by 'cu' after sending a file), and give the 565 * box some time (100 * 1 ms) 566 */ 567 for (i=0; i<100; ++i) { 568 if (tstc()) { 569 getchar(); 570 } 571 udelay(1000); 572 } 573 574 if (size == 0) 575 return ~0; /* Download aborted */ 576 577 flush_cache(offset, size); 578 579 printf("## Total Size = 0x%08x = %d Bytes\n", size, size); 580 env_set_hex("filesize", size); 581 582 return offset; 583} 584 585static void send_pad(void) 586{ 587 int count = his_pad_count; 588 589 while (count-- > 0) 590 putc(his_pad_char); 591} 592 593/* converts escaped kermit char to binary char */ 594static char ktrans(char in) 595{ 596 if ((in & 0x60) == 0x40) { 597 return (char) (in & ~0x40); 598 } else if ((in & 0x7f) == 0x3f) { 599 return (char) (in | 0x40); 600 } else 601 return in; 602} 603 604static int chk1(char *buffer) 605{ 606 int total = 0; 607 608 while (*buffer) { 609 total += *buffer++; 610 } 611 return (int) ((total + ((total >> 6) & 0x03)) & 0x3f); 612} 613 614static void s1_sendpacket(char *packet) 615{ 616 send_pad(); 617 while (*packet) { 618 putc(*packet++); 619 } 620} 621 622static char a_b[24]; 623static void send_ack(int n) 624{ 625 a_b[0] = START_CHAR; 626 a_b[1] = tochar(3); 627 a_b[2] = tochar(n); 628 a_b[3] = ACK_TYPE; 629 a_b[4] = '\0'; 630 a_b[4] = tochar(chk1(&a_b[1])); 631 a_b[5] = his_eol; 632 a_b[6] = '\0'; 633 s1_sendpacket(a_b); 634} 635 636static void send_nack(int n) 637{ 638 a_b[0] = START_CHAR; 639 a_b[1] = tochar(3); 640 a_b[2] = tochar(n); 641 a_b[3] = NACK_TYPE; 642 a_b[4] = '\0'; 643 a_b[4] = tochar(chk1(&a_b[1])); 644 a_b[5] = his_eol; 645 a_b[6] = '\0'; 646 s1_sendpacket(a_b); 647} 648 649static void (*os_data_init)(void); 650static void (*os_data_char)(char new_char); 651static int os_data_state, os_data_state_saved; 652static char *os_data_addr, *os_data_addr_saved; 653static char *bin_start_address; 654 655static void bin_data_init(void) 656{ 657 os_data_state = 0; 658 os_data_addr = bin_start_address; 659} 660 661static void os_data_save(void) 662{ 663 os_data_state_saved = os_data_state; 664 os_data_addr_saved = os_data_addr; 665} 666 667static void os_data_restore(void) 668{ 669 os_data_state = os_data_state_saved; 670 os_data_addr = os_data_addr_saved; 671} 672 673static void bin_data_char(char new_char) 674{ 675 switch (os_data_state) { 676 case 0: /* data */ 677 *os_data_addr++ = new_char; 678 break; 679 } 680} 681 682static void set_kerm_bin_mode(unsigned long *addr) 683{ 684 bin_start_address = (char *) addr; 685 os_data_init = bin_data_init; 686 os_data_char = bin_data_char; 687} 688 689/* k_data_* simply handles the kermit escape translations */ 690static int k_data_escape, k_data_escape_saved; 691static void k_data_init(void) 692{ 693 k_data_escape = 0; 694 os_data_init(); 695} 696 697static void k_data_save(void) 698{ 699 k_data_escape_saved = k_data_escape; 700 os_data_save(); 701} 702 703static void k_data_restore(void) 704{ 705 k_data_escape = k_data_escape_saved; 706 os_data_restore(); 707} 708 709static void k_data_char(char new_char) 710{ 711 if (k_data_escape) { 712 /* last char was escape - translate this character */ 713 os_data_char(ktrans(new_char)); 714 k_data_escape = 0; 715 } else { 716 if (new_char == his_quote) { 717 /* this char is escape - remember */ 718 k_data_escape = 1; 719 } else { 720 /* otherwise send this char as-is */ 721 os_data_char(new_char); 722 } 723 } 724} 725 726#define SEND_DATA_SIZE 20 727static char send_parms[SEND_DATA_SIZE]; 728static char *send_ptr; 729 730/* handle_send_packet interprits the protocol info and builds and 731 sends an appropriate ack for what we can do */ 732static void handle_send_packet(int n) 733{ 734 int length = 3; 735 int bytes; 736 737 /* initialize some protocol parameters */ 738 his_eol = END_CHAR; /* default end of line character */ 739 his_pad_count = 0; 740 his_pad_char = '\0'; 741 his_quote = K_ESCAPE; 742 743 /* ignore last character if it filled the buffer */ 744 if (send_ptr == &send_parms[SEND_DATA_SIZE - 1]) 745 --send_ptr; 746 bytes = send_ptr - send_parms; /* how many bytes we'll process */ 747 do { 748 if (bytes-- <= 0) 749 break; 750 /* handle MAXL - max length */ 751 /* ignore what he says - most I'll take (here) is 94 */ 752 a_b[++length] = tochar(94); 753 if (bytes-- <= 0) 754 break; 755 /* handle TIME - time you should wait for my packets */ 756 /* ignore what he says - don't wait for my ack longer than 1 second */ 757 a_b[++length] = tochar(1); 758 if (bytes-- <= 0) 759 break; 760 /* handle NPAD - number of pad chars I need */ 761 /* remember what he says - I need none */ 762 his_pad_count = untochar(send_parms[2]); 763 a_b[++length] = tochar(0); 764 if (bytes-- <= 0) 765 break; 766 /* handle PADC - pad chars I need */ 767 /* remember what he says - I need none */ 768 his_pad_char = ktrans(send_parms[3]); 769 a_b[++length] = 0x40; /* He should ignore this */ 770 if (bytes-- <= 0) 771 break; 772 /* handle EOL - end of line he needs */ 773 /* remember what he says - I need CR */ 774 his_eol = untochar(send_parms[4]); 775 a_b[++length] = tochar(END_CHAR); 776 if (bytes-- <= 0) 777 break; 778 /* handle QCTL - quote control char he'll use */ 779 /* remember what he says - I'll use '#' */ 780 his_quote = send_parms[5]; 781 a_b[++length] = '#'; 782 if (bytes-- <= 0) 783 break; 784 /* handle QBIN - 8-th bit prefixing */ 785 /* ignore what he says - I refuse */ 786 a_b[++length] = 'N'; 787 if (bytes-- <= 0) 788 break; 789 /* handle CHKT - the clock check type */ 790 /* ignore what he says - I do type 1 (for now) */ 791 a_b[++length] = '1'; 792 if (bytes-- <= 0) 793 break; 794 /* handle REPT - the repeat prefix */ 795 /* ignore what he says - I refuse (for now) */ 796 a_b[++length] = 'N'; 797 if (bytes-- <= 0) 798 break; 799 /* handle CAPAS - the capabilities mask */ 800 /* ignore what he says - I only do long packets - I don't do windows */ 801 a_b[++length] = tochar(2); /* only long packets */ 802 a_b[++length] = tochar(0); /* no windows */ 803 a_b[++length] = tochar(94); /* large packet msb */ 804 a_b[++length] = tochar(94); /* large packet lsb */ 805 } while (0); 806 807 a_b[0] = START_CHAR; 808 a_b[1] = tochar(length); 809 a_b[2] = tochar(n); 810 a_b[3] = ACK_TYPE; 811 a_b[++length] = '\0'; 812 a_b[length] = tochar(chk1(&a_b[1])); 813 a_b[++length] = his_eol; 814 a_b[++length] = '\0'; 815 s1_sendpacket(a_b); 816} 817 818/* k_recv receives a OS Open image file over kermit line */ 819static int k_recv(void) 820{ 821 int new_char; 822 char k_state, k_state_saved; 823 int sum; 824 int done; 825 int length; 826 int n, last_n; 827 int len_lo, len_hi; 828 829 /* initialize some protocol parameters */ 830 his_eol = END_CHAR; /* default end of line character */ 831 his_pad_count = 0; 832 his_pad_char = '\0'; 833 his_quote = K_ESCAPE; 834 835 /* initialize the k_recv and k_data state machine */ 836 done = 0; 837 k_state = 0; 838 k_data_init(); 839 k_state_saved = k_state; 840 k_data_save(); 841 n = 0; /* just to get rid of a warning */ 842 last_n = -1; 843 844 /* expect this "type" sequence (but don't check): 845 S: send initiate 846 F: file header 847 D: data (multiple) 848 Z: end of file 849 B: break transmission 850 */ 851 852 /* enter main loop */ 853 while (!done) { 854 /* set the send packet pointer to begining of send packet parms */ 855 send_ptr = send_parms; 856 857 /* With each packet, start summing the bytes starting with the length. 858 Save the current sequence number. 859 Note the type of the packet. 860 If a character less than SPACE (0x20) is received - error. 861 */ 862 863#if 0 864 /* OLD CODE, Prior to checking sequence numbers */ 865 /* first have all state machines save current states */ 866 k_state_saved = k_state; 867 k_data_save (); 868#endif 869 870 /* get a packet */ 871 /* wait for the starting character or ^C */ 872 for (;;) { 873 switch (getchar()) { 874 case START_CHAR: /* start packet */ 875 goto START; 876 case ETX_CHAR: /* ^C waiting for packet */ 877 return (0); 878 default: 879 ; 880 } 881 } 882START: 883 /* get length of packet */ 884 sum = 0; 885 new_char = getchar(); 886 if ((new_char & 0xE0) == 0) 887 goto packet_error; 888 sum += new_char & 0xff; 889 length = untochar(new_char); 890 /* get sequence number */ 891 new_char = getchar(); 892 if ((new_char & 0xE0) == 0) 893 goto packet_error; 894 sum += new_char & 0xff; 895 n = untochar(new_char); 896 --length; 897 898 /* NEW CODE - check sequence numbers for retried packets */ 899 /* Note - this new code assumes that the sequence number is correctly 900 * received. Handling an invalid sequence number adds another layer 901 * of complexity that may not be needed - yet! At this time, I'm hoping 902 * that I don't need to buffer the incoming data packets and can write 903 * the data into memory in real time. 904 */ 905 if (n == last_n) { 906 /* same sequence number, restore the previous state */ 907 k_state = k_state_saved; 908 k_data_restore(); 909 } else { 910 /* new sequence number, checkpoint the download */ 911 last_n = n; 912 k_state_saved = k_state; 913 k_data_save(); 914 } 915 /* END NEW CODE */ 916 917 /* get packet type */ 918 new_char = getchar(); 919 if ((new_char & 0xE0) == 0) 920 goto packet_error; 921 sum += new_char & 0xff; 922 k_state = new_char; 923 --length; 924 /* check for extended length */ 925 if (length == -2) { 926 /* (length byte was 0, decremented twice) */ 927 /* get the two length bytes */ 928 new_char = getchar(); 929 if ((new_char & 0xE0) == 0) 930 goto packet_error; 931 sum += new_char & 0xff; 932 len_hi = untochar(new_char); 933 new_char = getchar(); 934 if ((new_char & 0xE0) == 0) 935 goto packet_error; 936 sum += new_char & 0xff; 937 len_lo = untochar(new_char); 938 length = len_hi * 95 + len_lo; 939 /* check header checksum */ 940 new_char = getchar(); 941 if ((new_char & 0xE0) == 0) 942 goto packet_error; 943 if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f)) 944 goto packet_error; 945 sum += new_char & 0xff; 946/* --length; */ /* new length includes only data and block check to come */ 947 } 948 /* bring in rest of packet */ 949 while (length > 1) { 950 new_char = getchar(); 951 if ((new_char & 0xE0) == 0) 952 goto packet_error; 953 sum += new_char & 0xff; 954 --length; 955 if (k_state == DATA_TYPE) { 956 /* pass on the data if this is a data packet */ 957 k_data_char (new_char); 958 } else if (k_state == SEND_TYPE) { 959 /* save send pack in buffer as is */ 960 *send_ptr++ = new_char; 961 /* if too much data, back off the pointer */ 962 if (send_ptr >= &send_parms[SEND_DATA_SIZE]) 963 --send_ptr; 964 } 965 } 966 /* get and validate checksum character */ 967 new_char = getchar(); 968 if ((new_char & 0xE0) == 0) 969 goto packet_error; 970 if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f)) 971 goto packet_error; 972 /* get END_CHAR */ 973 new_char = getchar(); 974 if (new_char != END_CHAR) { 975 packet_error: 976 /* restore state machines */ 977 k_state = k_state_saved; 978 k_data_restore(); 979 /* send a negative acknowledge packet in */ 980 send_nack(n); 981 } else if (k_state == SEND_TYPE) { 982 /* crack the protocol parms, build an appropriate ack packet */ 983 handle_send_packet(n); 984 } else { 985 /* send simple acknowledge packet in */ 986 send_ack(n); 987 /* quit if end of transmission */ 988 if (k_state == BREAK_TYPE) 989 done = 1; 990 } 991 } 992 return ((ulong) os_data_addr - (ulong) bin_start_address); 993} 994 995static int getcxmodem(void) { 996 if (tstc()) 997 return (getchar()); 998 return -1; 999} 1000static ulong load_serial_ymodem(ulong offset, int mode) 1001{ 1002 int size; 1003 int err; 1004 int res; 1005 connection_info_t info; 1006 char ymodemBuf[1024]; 1007 ulong store_addr = ~0; 1008 ulong addr = 0; 1009 1010 size = 0; 1011 info.mode = mode; 1012 res = xyzModem_stream_open(&info, &err); 1013 if (!res) { 1014 1015 err = 0; 1016 while ((res = 1017 xyzModem_stream_read(ymodemBuf, 1024, &err)) > 0) { 1018 store_addr = addr + offset; 1019 size += res; 1020 addr += res; 1021#ifdef CONFIG_MTD_NOR_FLASH 1022 if (addr2info(store_addr)) { 1023 int rc; 1024 1025 rc = flash_write((char *) ymodemBuf, 1026 store_addr, res); 1027 if (rc != 0) { 1028 xyzModem_stream_terminate(true, &getcxmodem); 1029 xyzModem_stream_close(&err); 1030 printf("\n"); 1031 flash_perror(rc); 1032 return (~0); 1033 } 1034 } else 1035#endif 1036 { 1037 memcpy((char *)(store_addr), ymodemBuf, 1038 res); 1039 } 1040 1041 } 1042 if (err) { 1043 xyzModem_stream_terminate((err == xyzModem_cancel) ? false : true, &getcxmodem); 1044 xyzModem_stream_close(&err); 1045 printf("\n%s\n", xyzModem_error(err)); 1046 return (~0); /* Download aborted */ 1047 } 1048 1049 if (IS_ENABLED(CONFIG_CMD_BOOTEFI)) 1050 efi_set_bootdev("Uart", "", "", 1051 map_sysmem(offset, 0), size); 1052 1053 } else { 1054 printf("\n%s\n", xyzModem_error(err)); 1055 return (~0); /* Download aborted */ 1056 } 1057 1058 xyzModem_stream_terminate(false, &getcxmodem); 1059 xyzModem_stream_close(&err); 1060 1061 flush_cache(offset, ALIGN(size, ARCH_DMA_MINALIGN)); 1062 1063 printf("## Total Size = 0x%08x = %d Bytes\n", size, size); 1064 env_set_hex("filesize", size); 1065 1066 return offset; 1067} 1068 1069#endif 1070 1071#if defined(CONFIG_CMD_LOADM) 1072static int do_load_memory_bin(struct cmd_tbl *cmdtp, int flag, int argc, 1073 char *const argv[]) 1074{ 1075 ulong addr, dest, size; 1076 void *src, *dst; 1077 1078 if (argc != 4) 1079 return CMD_RET_USAGE; 1080 1081 addr = simple_strtoul(argv[1], NULL, 16); 1082 1083 dest = simple_strtoul(argv[2], NULL, 16); 1084 1085 size = simple_strtoul(argv[3], NULL, 16); 1086 1087 if (!size) { 1088 printf("loadm: can not load zero bytes\n"); 1089 return 1; 1090 } 1091 1092 src = map_sysmem(addr, size); 1093 dst = map_sysmem(dest, size); 1094 1095 memcpy(dst, src, size); 1096 1097 unmap_sysmem(src); 1098 unmap_sysmem(dst); 1099 1100 if (IS_ENABLED(CONFIG_CMD_BOOTEFI)) 1101 efi_set_bootdev("Mem", "", "", map_sysmem(dest, 0), size); 1102 1103 printf("loaded bin to memory: size: %lu\n", size); 1104 1105 return 0; 1106} 1107#endif 1108 1109/* -------------------------------------------------------------------- */ 1110 1111#if defined(CONFIG_CMD_LOADS) 1112 1113#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE 1114U_BOOT_CMD( 1115 loads, 3, 0, do_load_serial, 1116 "load S-Record file over serial line", 1117 "[ off ] [ baud ]\n" 1118 " - load S-Record file over serial line" 1119 " with offset 'off' and baudrate 'baud'" 1120); 1121 1122#else /* ! CONFIG_SYS_LOADS_BAUD_CHANGE */ 1123U_BOOT_CMD( 1124 loads, 2, 0, do_load_serial, 1125 "load S-Record file over serial line", 1126 "[ off ]\n" 1127 " - load S-Record file over serial line with offset 'off'" 1128); 1129#endif /* CONFIG_SYS_LOADS_BAUD_CHANGE */ 1130 1131/* 1132 * SAVES always requires LOADS support, but not vice versa 1133 */ 1134 1135#if defined(CONFIG_CMD_SAVES) 1136#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE 1137U_BOOT_CMD( 1138 saves, 4, 0, do_save_serial, 1139 "save S-Record file over serial line", 1140 "[ off ] [size] [ baud ]\n" 1141 " - save S-Record file over serial line" 1142 " with offset 'off', size 'size' and baudrate 'baud'" 1143); 1144#else /* ! CONFIG_SYS_LOADS_BAUD_CHANGE */ 1145U_BOOT_CMD( 1146 saves, 3, 0, do_save_serial, 1147 "save S-Record file over serial line", 1148 "[ off ] [size]\n" 1149 " - save S-Record file over serial line with offset 'off' and size 'size'" 1150); 1151#endif /* CONFIG_SYS_LOADS_BAUD_CHANGE */ 1152#endif /* CONFIG_CMD_SAVES */ 1153#endif /* CONFIG_CMD_LOADS */ 1154 1155#if defined(CONFIG_CMD_LOADB) 1156U_BOOT_CMD( 1157 loadb, 3, 0, do_load_serial_bin, 1158 "load binary file over serial line (kermit mode)", 1159 "[ addr [ baud ] ]\n" 1160 " - load binary file over serial line" 1161 " at address 'addr' with baudrate 'baud'" 1162); 1163 1164U_BOOT_CMD( 1165 loadx, 3, 0, do_load_serial_bin, 1166 "load binary file over serial line (xmodem mode)", 1167 "[ addr [ baud ] ]\n" 1168 " - load binary file over serial line" 1169 " at address 'addr' with baudrate 'baud'" 1170); 1171 1172U_BOOT_CMD( 1173 loady, 3, 0, do_load_serial_bin, 1174 "load binary file over serial line (ymodem mode)", 1175 "[ addr [ baud ] ]\n" 1176 " - load binary file over serial line" 1177 " at address 'addr' with baudrate 'baud'" 1178); 1179 1180#endif /* CONFIG_CMD_LOADB */ 1181 1182#if defined(CONFIG_CMD_LOADM) 1183U_BOOT_CMD( 1184 loadm, 4, 0, do_load_memory_bin, 1185 "load binary blob from source address to destination address", 1186 "[src_addr] [dst_addr] [size]\n" 1187 " - load a binary blob from one memory location to other" 1188 " from src_addr to dst_addr by size bytes" 1189); 1190#endif /* CONFIG_CMD_LOADM */