📄 cmd_load.c
字号:
#endif /* CFG_CMD_LOADS */#if (CONFIG_COMMANDS & CFG_CMD_LOADB) /* loadb command (load binary) included */#define XON_CHAR 17#define XOFF_CHAR 19#define START_CHAR 0x01#define ETX_CHAR 0x03#define END_CHAR 0x0D#define SPACE 0x20#define K_ESCAPE 0x23#define SEND_TYPE 'S'#define DATA_TYPE 'D'#define ACK_TYPE 'Y'#define NACK_TYPE 'N'#define BREAK_TYPE 'B'#define tochar(x) ((char) (((x) + SPACE) & 0xff))#define untochar(x) ((int) (((x) - SPACE) & 0xff))extern int os_data_count;extern int os_data_header[8];static void set_kerm_bin_mode(unsigned long *);static int k_recv(void);static ulong load_serial_bin (ulong offset);char his_eol; /* character he needs at end of packet */int his_pad_count; /* number of pad chars he needs */char his_pad_char; /* pad chars he needs */char his_quote; /* quote chars he'll use */int do_load_serial_bin (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ ulong offset = 0; ulong addr; int load_baudrate, current_baudrate; int rcode = 0; char *s; /* pre-set offset from CFG_LOAD_ADDR */ offset = CFG_LOAD_ADDR; /* pre-set offset from $loadaddr */ if ((s = getenv("loadaddr")) != NULL) { offset = simple_strtoul(s, NULL, 16); } load_baudrate = current_baudrate = gd->baudrate; if (argc >= 2) { offset = simple_strtoul(argv[1], NULL, 16); } if (argc == 3) { load_baudrate = (int)simple_strtoul(argv[2], NULL, 10); /* default to current baudrate */ if (load_baudrate == 0) load_baudrate = current_baudrate; } if (load_baudrate != current_baudrate) { printf ("## Switch baudrate to %d bps and press ENTER ...\n", load_baudrate); udelay(50000); gd->baudrate = load_baudrate; serial_setbrg (); udelay(50000); for (;;) { if (getc() == '\r') break; } } /* support xmodem, www.arm9.net */ if (strcmp(argv[0],"loadx")==0) { printf ("## Ready for binary (xmodem) download " "to 0x%08lX at %d bps...\n", offset, load_baudrate); addr = load_serial_xmodem (offset); } else if (strcmp(argv[0],"loady")==0) { printf ("## Ready for binary (ymodem) download " "to 0x%08lX at %d bps...\n", offset, load_baudrate); addr = load_serial_ymodem (offset); } else { printf ("## Ready for binary (kermit) download " "to 0x%08lX at %d bps...\n", offset, load_baudrate); addr = load_serial_bin (offset); if (addr == ~0) { load_addr = 0; printf ("## Binary (kermit) download aborted\n"); rcode = 1; } else { printf ("## Start Addr = 0x%08lX\n", addr); load_addr = addr; } } if (load_baudrate != current_baudrate) { printf ("## Switch baudrate to %d bps and press ESC ...\n", current_baudrate); udelay (50000); gd->baudrate = current_baudrate; serial_setbrg (); udelay (50000); for (;;) { if (getc() == 0x1B) /* ESC */ break; } }#ifdef CONFIG_AUTOSCRIPT if (load_addr) { char *s; if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) { printf("Running autoscript at addr 0x%08lX ...\n", load_addr); rcode = autoscript (load_addr); } }#endif return rcode;}static ulong load_serial_bin (ulong offset){ int size, i; char buf[32]; set_kerm_bin_mode ((ulong *) offset); size = k_recv (); /* * Gather any trailing characters (for instance, the ^D which * is sent by 'cu' after sending a file), and give the * box some time (100 * 1 ms) */ for (i=0; i<100; ++i) { if (tstc()) { (void) getc(); } udelay(1000); } flush_cache (offset, size); printf("## Total Size = 0x%08x = %d Bytes\n", size, size); sprintf(buf, "%X", size); setenv("filesize", buf); return offset;}void send_pad (void){ int count = his_pad_count; while (count-- > 0) putc (his_pad_char);}/* converts escaped kermit char to binary char */char ktrans (char in){ if ((in & 0x60) == 0x40) { return (char) (in & ~0x40); } else if ((in & 0x7f) == 0x3f) { return (char) (in | 0x40); } else return in;}int chk1 (char *buffer){ int total = 0; while (*buffer) { total += *buffer++; } return (int) ((total + ((total >> 6) & 0x03)) & 0x3f);}void s1_sendpacket (char *packet){ send_pad (); while (*packet) { putc (*packet++); }}static char a_b[24];void send_ack (int n){ a_b[0] = START_CHAR; a_b[1] = tochar (3); a_b[2] = tochar (n); a_b[3] = ACK_TYPE; a_b[4] = '\0'; a_b[4] = tochar (chk1 (&a_b[1])); a_b[5] = his_eol; a_b[6] = '\0'; s1_sendpacket (a_b);}void send_nack (int n){ a_b[0] = START_CHAR; a_b[1] = tochar (3); a_b[2] = tochar (n); a_b[3] = NACK_TYPE; a_b[4] = '\0'; a_b[4] = tochar (chk1 (&a_b[1])); a_b[5] = his_eol; a_b[6] = '\0'; s1_sendpacket (a_b);}/* os_data_* takes an OS Open image and puts it into memory, and puts the boot header in an array named os_data_header if image is binary, no header is stored in os_data_header.*/void (*os_data_init) (void);void (*os_data_char) (char new_char);static int os_data_state, os_data_state_saved;int os_data_count;static int os_data_count_saved;static char *os_data_addr, *os_data_addr_saved;static char *bin_start_address;int os_data_header[8];static void bin_data_init (void){ os_data_state = 0; os_data_count = 0; os_data_addr = bin_start_address;}static void os_data_save (void){ os_data_state_saved = os_data_state; os_data_count_saved = os_data_count; os_data_addr_saved = os_data_addr;}static void os_data_restore (void){ os_data_state = os_data_state_saved; os_data_count = os_data_count_saved; os_data_addr = os_data_addr_saved;}static void bin_data_char (char new_char){ switch (os_data_state) { case 0: /* data */ *os_data_addr++ = new_char; --os_data_count; break; }}static void set_kerm_bin_mode (unsigned long *addr){ bin_start_address = (char *) addr; os_data_init = bin_data_init; os_data_char = bin_data_char;}/* k_data_* simply handles the kermit escape translations */static int k_data_escape, k_data_escape_saved;void k_data_init (void){ k_data_escape = 0; os_data_init ();}void k_data_save (void){ k_data_escape_saved = k_data_escape; os_data_save ();}void k_data_restore (void){ k_data_escape = k_data_escape_saved; os_data_restore ();}void k_data_char (char new_char){ if (k_data_escape) { /* last char was escape - translate this character */ os_data_char (ktrans (new_char)); k_data_escape = 0; } else { if (new_char == his_quote) { /* this char is escape - remember */ k_data_escape = 1; } else { /* otherwise send this char as-is */ os_data_char (new_char); } }}#define SEND_DATA_SIZE 20char send_parms[SEND_DATA_SIZE];char *send_ptr;/* handle_send_packet interprits the protocol info and builds and sends an appropriate ack for what we can do */void handle_send_packet (int n){ int length = 3; int bytes; /* initialize some protocol parameters */ his_eol = END_CHAR; /* default end of line character */ his_pad_count = 0; his_pad_char = '\0'; his_quote = K_ESCAPE; /* ignore last character if it filled the buffer */ if (send_ptr == &send_parms[SEND_DATA_SIZE - 1]) --send_ptr; bytes = send_ptr - send_parms; /* how many bytes we'll process */ do { if (bytes-- <= 0) break; /* handle MAXL - max length */ /* ignore what he says - most I'll take (here) is 94 */ a_b[++length] = tochar (94); if (bytes-- <= 0) break; /* handle TIME - time you should wait for my packets */ /* ignore what he says - don't wait for my ack longer than 1 second */ a_b[++length] = tochar (1); if (bytes-- <= 0) break; /* handle NPAD - number of pad chars I need */ /* remember what he says - I need none */ his_pad_count = untochar (send_parms[2]); a_b[++length] = tochar (0); if (bytes-- <= 0) break; /* handle PADC - pad chars I need */ /* remember what he says - I need none */ his_pad_char = ktrans (send_parms[3]); a_b[++length] = 0x40; /* He should ignore this */ if (bytes-- <= 0) break; /* handle EOL - end of line he needs */ /* remember what he says - I need CR */ his_eol = untochar (send_parms[4]); a_b[++length] = tochar (END_CHAR); if (bytes-- <= 0) break; /* handle QCTL - quote control char he'll use */ /* remember what he says - I'll use '#' */ his_quote = send_parms[5]; a_b[++length] = '#'; if (bytes-- <= 0) break; /* handle QBIN - 8-th bit prefixing */ /* ignore what he says - I refuse */ a_b[++length] = 'N'; if (bytes-- <= 0) break; /* handle CHKT - the clock check type */ /* ignore what he says - I do type 1 (for now) */ a_b[++length] = '1'; if (bytes-- <= 0) break; /* handle REPT - the repeat prefix */ /* ignore what he says - I refuse (for now) */ a_b[++length] = 'N'; if (bytes-- <= 0) break; /* handle CAPAS - the capabilities mask */ /* ignore what he says - I only do long packets - I don't do windows */ a_b[++length] = tochar (2); /* only long packets */ a_b[++length] = tochar (0); /* no windows */ a_b[++length] = tochar (94); /* large packet msb */ a_b[++length] = tochar (94); /* large packet lsb */ } while (0); a_b[0] = START_CHAR; a_b[1] = tochar (length); a_b[2] = tochar (n); a_b[3] = ACK_TYPE; a_b[++length] = '\0'; a_b[length] = tochar (chk1 (&a_b[1])); a_b[++length] = his_eol; a_b[++length] = '\0'; s1_sendpacket (a_b);}/* k_recv receives a OS Open image file over kermit line */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -