📄 cmd_load.c.l
字号:
406 #endif /* CFG_CMD_LOADS */407 408 409 #if (CONFIG_COMMANDS & CFG_CMD_LOADB) /* loadb command (load binary) included */410 411 #define XON_CHAR 17412 #define XOFF_CHAR 19413 #define START_CHAR 0x01414 #define ETX_CHAR 0x03415 #define END_CHAR 0x0D416 #define SPACE 0x20417 #define K_ESCAPE 0x23418 #define SEND_TYPE 'S'419 #define DATA_TYPE 'D'420 #define ACK_TYPE 'Y'421 #define NACK_TYPE 'N'422 #define BREAK_TYPE 'B'423 #define tochar(x) ((char) (((x) + SPACE) & 0xff))424 #define untochar(x) ((int) (((x) - SPACE) & 0xff))425 426 extern int os_data_count;427 extern int os_data_header[8];428 429 static void set_kerm_bin_mode(unsigned long *);430 static int k_recv(void);431 static ulong load_serial_bin (ulong offset);432 433 434 char his_eol; /* character he needs at end of packet */435 int his_pad_count; /* number of pad chars he needs */436 char his_pad_char; /* pad chars he needs */437 char his_quote; /* quote chars he'll use */438 439 int do_load_serial_bin (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])440 {441 ulong offset = 0;442 ulong addr;443 int load_baudrate, current_baudrate;444 int rcode = 0;445 char *s;446 447 /* pre-set offset from CFG_LOAD_ADDR */448 offset = CFG_LOAD_ADDR;449 450 /* pre-set offset from $loadaddr */451 if ((s = getenv("loadaddr")) != NULL) {452 offset = simple_strtoul(s, NULL, 16);453 }454 455 load_baudrate = current_baudrate = gd->baudrate;456 457 if (argc >= 2) {458 offset = simple_strtoul(argv[1], NULL, 16);459 }460 if (argc == 3) {461 load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);462 463 /* default to current baudrate */464 if (load_baudrate == 0)465 load_baudrate = current_baudrate;466 }467 468 if (load_baudrate != current_baudrate) {469 printf ("## Switch baudrate to %d bps and press ENTER ...\n",470 load_baudrate);471 udelay(50000);472 gd->baudrate = load_baudrate;473 serial_setbrg ();474 udelay(50000);475 for (;;) {476 if (getc() == '\r')477 break;478 }479 }480 481 /* support xmodem, www.arm9.net */482 if (strcmp(argv[0],"loadx")==0) {483 printf ("## Ready for binary (xmodem) download "484 "to 0x%08lX at %d bps...\n",485 offset,486 load_baudrate);487 488 addr = load_serial_xmodem (offset);489 490 } else if (strcmp(argv[0],"loady")==0) {491 printf ("## Ready for binary (ymodem) download "492 "to 0x%08lX at %d bps...\n",493 offset,494 load_baudrate);495 496 addr = load_serial_ymodem (offset);497 498 } else {499 500 printf ("## Ready for binary (kermit) download "501 "to 0x%08lX at %d bps...\n",502 offset,503 load_baudrate);504 addr = load_serial_bin (offset);505 506 if (addr == ~0) {507 load_addr = 0;508 printf ("## Binary (kermit) download aborted\n");509 rcode = 1;510 } else {511 printf ("## Start Addr = 0x%08lX\n", addr);512 load_addr = addr;513 }514 }515 if (load_baudrate != current_baudrate) {516 printf ("## Switch baudrate to %d bps and press ESC ...\n",517 current_baudrate);518 udelay (50000);519 gd->baudrate = current_baudrate;520 serial_setbrg ();521 udelay (50000);522 for (;;) {523 if (getc() == 0x1B) /* ESC */524 break;525 }526 }527 528 #ifdef CONFIG_AUTOSCRIPT529 if (load_addr) {530 char *s;531 532 if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {533 printf("Running autoscript at addr 0x%08lX ...\n", load_addr);534 rcode = autoscript (load_addr);535 }536 }537 #endif538 return rcode;539 }540 541 542 static ulong load_serial_bin (ulong offset)543 {544 int size, i;545 char buf[32];546 547 set_kerm_bin_mode ((ulong *) offset);548 size = k_recv ();549 550 /*551 * Gather any trailing characters (for instance, the ^D which552 * is sent by 'cu' after sending a file), and give the553 * box some time (100 * 1 ms)554 */555 for (i=0; i<100; ++i) {556 if (tstc()) {557 (void) getc();558 }559 udelay(1000);560 }561 562 flush_cache (offset, size);563 564 printf("## Total Size = 0x%08x = %d Bytes\n", size, size);565 sprintf(buf, "%X", size);566 setenv("filesize", buf);567 568 return offset;569 }570 571 void send_pad (void)572 {573 int count = his_pad_count;574 575 while (count-- > 0)576 putc (his_pad_char);577 }578 579 /* converts escaped kermit char to binary char */580 char ktrans (char in)581 {582 if ((in & 0x60) == 0x40) {583 return (char) (in & ~0x40);584 } else if ((in & 0x7f) == 0x3f) {585 return (char) (in | 0x40);586 } else587 return in;588 }589 590 int chk1 (char *buffer)591 {592 int total = 0;593 594 while (*buffer) {595 total += *buffer++;596 }597 return (int) ((total + ((total >> 6) & 0x03)) & 0x3f);598 }599 600 void s1_sendpacket (char *packet)601 {602 send_pad ();603 while (*packet) {604 putc (*packet++);605 }606 }607 608 static char a_b[24];609 void send_ack (int n)610 {611 a_b[0] = START_CHAR;612 a_b[1] = tochar (3);613 a_b[2] = tochar (n);614 a_b[3] = ACK_TYPE;615 a_b[4] = '\0';616 a_b[4] = tochar (chk1 (&a_b[1]));617 a_b[5] = his_eol;618 a_b[6] = '\0';619 s1_sendpacket (a_b);620 }621 622 void send_nack (int n)623 {624 a_b[0] = START_CHAR;625 a_b[1] = tochar (3);626 a_b[2] = tochar (n);627 a_b[3] = NACK_TYPE;628 a_b[4] = '\0';629 a_b[4] = tochar (chk1 (&a_b[1]));630 a_b[5] = his_eol;631 a_b[6] = '\0';632 s1_sendpacket (a_b);633 }634 635 636 /* os_data_* takes an OS Open image and puts it into memory, and637 puts the boot header in an array named os_data_header638 639 if image is binary, no header is stored in os_data_header.640 */641 void (*os_data_init) (void);642 void (*os_data_char) (char new_char);643 static int os_data_state, os_data_state_saved;644 int os_data_count;645 static int os_data_count_saved;646 static char *os_data_addr, *os_data_addr_saved;647 static char *bin_start_address;648 int os_data_header[8];649 static void bin_data_init (void)650 {651 os_data_state = 0;652 os_data_count = 0;653 os_data_addr = bin_start_address;654 }655 static void os_data_save (void)656 {657 os_data_state_saved = os_data_state;658 os_data_count_saved = os_data_count;659 os_data_addr_saved = os_data_addr;660 }661 static void os_data_restore (void)662 {663 os_data_state = os_data_state_saved;664 os_data_count = os_data_count_saved;665 os_data_addr = os_data_addr_saved;666 }667 static void bin_data_char (char new_char)668 {669 switch (os_data_state) {670 case 0: /* data */671 *os_data_addr++ = new_char;672 --os_data_count;673 break;674 }675 }676 static void set_kerm_bin_mode (unsigned long *addr)677 {678 bin_start_address = (char *) addr;679 os_data_init = bin_data_init;680 os_data_char = bin_data_char;681 }682 683 684 /* k_data_* simply handles the kermit escape translations */685 static int k_data_escape, k_data_escape_saved;686 void k_data_init (void)687 {688 k_data_escape = 0;689 os_data_init ();690 }691 void k_data_save (void)692 {693 k_data_escape_saved = k_data_escape;694 os_data_save ();695 }696 void k_data_restore (void)697 {698 k_data_escape = k_data_escape_saved;699 os_data_restore ();700 }701 void k_data_char (char new_char)702 {703 if (k_data_escape) {704 /* last char was escape - translate this character */705 os_data_char (ktrans (new_char));706 k_data_escape = 0;707 } else {708 if (new_char == his_quote) {709 /* this char is escape - remember */710 k_data_escape = 1;711 } else {712 /* otherwise send this char as-is */713 os_data_char (new_char);714 }715 }716 }717 718 #define SEND_DATA_SIZE 20719 char send_parms[SEND_DATA_SIZE];720 char *send_ptr;721 722 /* handle_send_packet interprits the protocol info and builds and723 sends an appropriate ack for what we can do */724 void handle_send_packet (int n)725 {726 int length = 3;727 int bytes;728 729 /* initialize some protocol parameters */730 his_eol = END_CHAR; /* default end of line character */731 his_pad_count = 0;732 his_pad_char = '\0';733 his_quote = K_ESCAPE;734 735 /* ignore last character if it filled the buffer */736 if (send_ptr == &send_parms[SEND_DATA_SIZE - 1])737 --send_ptr;738 bytes = send_ptr - send_parms; /* how many bytes we'll process */739 do {740 if (bytes-- <= 0)741 break;742 /* handle MAXL - max length */743 /* ignore what he says - most I'll take (here) is 94 */744 a_b[++length] = tochar (94);745 if (bytes-- <= 0)746 break;747 /* handle TIME - time you should wait for my packets */748 /* ignore what he says - don't wait for my ack longer than 1 second */749 a_b[++length] = tochar (1);750 if (bytes-- <= 0)751 break;752 /* handle NPAD - number of pad chars I need */753 /* remember what he says - I need none */754 his_pad_count = untochar (send_parms[2]);755 a_b[++length] = tochar (0);756 if (bytes-- <= 0)757 break;758 /* handle PADC - pad chars I need */759 /* remember what he says - I need none */760 his_pad_char = ktrans (send_parms[3]);761 a_b[++length] = 0x40; /* He should ignore this */762 if (bytes-- <= 0)763 break;764 /* handle EOL - end of line he needs */765 /* remember what he says - I need CR */766 his_eol = untochar (send_parms[4]);767 a_b[++length] = tochar (END_CHAR);768 if (bytes-- <= 0)769 break;770 /* handle QCTL - quote control char he'll use */771 /* remember what he says - I'll use '#' */772 his_quote = send_parms[5];773 a_b[++length] = '#';774 if (bytes-- <= 0)775 break;776 /* handle QBIN - 8-th bit prefixing */777 /* ignore what he says - I refuse */778 a_b[++length] = 'N';779 if (bytes-- <= 0)780 break;781 /* handle CHKT - the clock check type */782 /* ignore what he says - I do type 1 (for now) */783 a_b[++length] = '1';784 if (bytes-- <= 0)785 break;786 /* handle REPT - the repeat prefix */787 /* ignore what he says - I refuse (for now) */788 a_b[++length] = 'N';789 if (bytes-- <= 0)790 break;791 /* handle CAPAS - the capabilities mask */792 /* ignore what he says - I only do long packets - I don't do windows */793 a_b[++length] = tochar (2); /* only long packets */794 a_b[++length] = tochar (0); /* no windows */795 a_b[++length] = tochar (94); /* large packet msb */796 a_b[++length] = tochar (94); /* large packet lsb */797 } while (0);798 799 a_b[0] = START_CHAR;800 a_b[1] = tochar (length);801 a_b[2] = tochar (n);802 a_b[3] = ACK_TYPE;803 a_b[++length] = '\0';804 a_b[length] = tochar (chk1 (&a_b[1]));805 a_b[++length] = his_eol;806 a_b[++length] = '\0';807 s1_sendpacket (a_b);808 }809 810 /* k_recv receives a OS Open image file over kermit line */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -