📄 cmd_load.c
字号:
static int k_recv (void){ char new_char; char k_state, k_state_saved; int sum; int done; int length; int n, last_n; int z = 0; int len_lo, len_hi; /* 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; /* initialize the k_recv and k_data state machine */ done = 0; k_state = 0; k_data_init (); k_state_saved = k_state; k_data_save (); n = 0; /* just to get rid of a warning */ last_n = -1; /* expect this "type" sequence (but don't check): S: send initiate F: file header D: data (multiple) Z: end of file B: break transmission */ /* enter main loop */ while (!done) { /* set the send packet pointer to begining of send packet parms */ send_ptr = send_parms; /* With each packet, start summing the bytes starting with the length. Save the current sequence number. Note the type of the packet. If a character less than SPACE (0x20) is received - error. */#if 0 /* OLD CODE, Prior to checking sequence numbers */ /* first have all state machines save current states */ k_state_saved = k_state; k_data_save ();#endif /* get a packet */ /* wait for the starting character or ^C */ for (;;) { switch (getc ()) { case START_CHAR: /* start packet */ goto START; case ETX_CHAR: /* ^C waiting for packet */ return (0); default: ; } }START: /* get length of packet */ sum = 0; new_char = getc (); if ((new_char & 0xE0) == 0) goto packet_error; sum += new_char & 0xff; length = untochar (new_char); /* get sequence number */ new_char = getc (); if ((new_char & 0xE0) == 0) goto packet_error; sum += new_char & 0xff; n = untochar (new_char); --length; /* NEW CODE - check sequence numbers for retried packets */ /* Note - this new code assumes that the sequence number is correctly * received. Handling an invalid sequence number adds another layer * of complexity that may not be needed - yet! At this time, I'm hoping * that I don't need to buffer the incoming data packets and can write * the data into memory in real time. */ if (n == last_n) { /* same sequence number, restore the previous state */ k_state = k_state_saved; k_data_restore (); } else { /* new sequence number, checkpoint the download */ last_n = n; k_state_saved = k_state; k_data_save (); } /* END NEW CODE */ /* get packet type */ new_char = getc (); if ((new_char & 0xE0) == 0) goto packet_error; sum += new_char & 0xff; k_state = new_char; --length; /* check for extended length */ if (length == -2) { /* (length byte was 0, decremented twice) */ /* get the two length bytes */ new_char = getc (); if ((new_char & 0xE0) == 0) goto packet_error; sum += new_char & 0xff; len_hi = untochar (new_char); new_char = getc (); if ((new_char & 0xE0) == 0) goto packet_error; sum += new_char & 0xff; len_lo = untochar (new_char); length = len_hi * 95 + len_lo; /* check header checksum */ new_char = getc (); if ((new_char & 0xE0) == 0) goto packet_error; if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f)) goto packet_error; sum += new_char & 0xff;/* --length; */ /* new length includes only data and block check to come */ } /* bring in rest of packet */ while (length > 1) { new_char = getc (); if ((new_char & 0xE0) == 0) goto packet_error; sum += new_char & 0xff; --length; if (k_state == DATA_TYPE) { /* pass on the data if this is a data packet */ k_data_char (new_char); } else if (k_state == SEND_TYPE) { /* save send pack in buffer as is */ *send_ptr++ = new_char; /* if too much data, back off the pointer */ if (send_ptr >= &send_parms[SEND_DATA_SIZE]) --send_ptr; } } /* get and validate checksum character */ new_char = getc (); if ((new_char & 0xE0) == 0) goto packet_error; if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f)) goto packet_error; /* get END_CHAR */ new_char = getc (); if (new_char != END_CHAR) { packet_error: /* restore state machines */ k_state = k_state_saved; k_data_restore (); /* send a negative acknowledge packet in */ send_nack (n); } else if (k_state == SEND_TYPE) { /* crack the protocol parms, build an appropriate ack packet */ handle_send_packet (n); } else { /* send simple acknowledge packet in */ send_ack (n); /* quit if end of transmission */ if (k_state == BREAK_TYPE) done = 1; } ++z; } return ((ulong) os_data_addr - (ulong) bin_start_address);}static int getcxmodem(void) { if (tstc()) return (getc()); return -1;}/* support xmodem, www.arm9.net */static ulong load_serial_xmodem (ulong offset){ int size; char buf[32]; int err; int res; connection_info_t info; char xmodemBuf[1024]; ulong store_addr = ~0; ulong addr = 0; size = 0; info.mode = xyzModem_xmodem; res = xyzModem_stream_open (&info, &err); if (!res) { while ((res = xyzModem_stream_read (xmodemBuf, 1024, &err)) > 0) { store_addr = addr + offset; size += res; addr += res;#ifndef CFG_NO_FLASH if (addr2info (store_addr)) { int rc; rc = flash_write ((char *) xmodemBuf, store_addr, res); if (rc != 0) { flash_perror (rc); return (~0); } } else#endif { memcpy ((char *) (store_addr), xmodemBuf, res); } } } else { printf ("%s\n", xyzModem_error (err)); } xyzModem_stream_close (&err); xyzModem_stream_terminate (false, &getcxmodem); flush_cache (offset, size); printf ("## Total Size = 0x%08x = %d Bytes\n", size, size); sprintf (buf, "%X", size); setenv ("filesize", buf); return offset;}static ulong load_serial_ymodem (ulong offset){ int size; char buf[32]; int err; int res; connection_info_t info; char ymodemBuf[1024]; ulong store_addr = ~0; ulong addr = 0; size = 0; info.mode = xyzModem_ymodem; res = xyzModem_stream_open (&info, &err); if (!res) { while ((res = xyzModem_stream_read (ymodemBuf, 1024, &err)) > 0) { store_addr = addr + offset; size += res; addr += res;#ifndef CFG_NO_FLASH if (addr2info (store_addr)) { int rc; rc = flash_write ((char *) ymodemBuf, store_addr, res); if (rc != 0) { flash_perror (rc); return (~0); } } else#endif { memcpy ((char *) (store_addr), ymodemBuf, res); } } } else { printf ("%s\n", xyzModem_error (err)); } xyzModem_stream_close (&err); xyzModem_stream_terminate (false, &getcxmodem); flush_cache (offset, size); printf ("## Total Size = 0x%08x = %d Bytes\n", size, size); sprintf (buf, "%X", size); setenv ("filesize", buf); return offset;}#endif /* CFG_CMD_LOADB *//* -------------------------------------------------------------------- */#if (CONFIG_COMMANDS & CFG_CMD_LOADS)#ifdef CFG_LOADS_BAUD_CHANGEU_BOOT_CMD( loads, 3, 0, do_load_serial, "loads - load S-Record file over serial line\n", "[ off ] [ baud ]\n" " - load S-Record file over serial line" " with offset 'off' and baudrate 'baud'\n");#else /* ! CFG_LOADS_BAUD_CHANGE */U_BOOT_CMD( loads, 2, 0, do_load_serial, "loads - load S-Record file over serial line\n", "[ off ]\n" " - load S-Record file over serial line with offset 'off'\n");#endif /* CFG_LOADS_BAUD_CHANGE *//* * SAVES always requires LOADS support, but not vice versa */#if (CONFIG_COMMANDS & CFG_CMD_SAVES)#ifdef CFG_LOADS_BAUD_CHANGEU_BOOT_CMD( saves, 4, 0, do_save_serial, "saves - save S-Record file over serial line\n", "[ off ] [size] [ baud ]\n" " - save S-Record file over serial line" " with offset 'off', size 'size' and baudrate 'baud'\n");#else /* ! CFG_LOADS_BAUD_CHANGE */U_BOOT_CMD( saves, 3, 0, do_save_serial, "saves - save S-Record file over serial line\n", "[ off ] [size]\n" " - save S-Record file over serial line with offset 'off' and size 'size'\n");#endif /* CFG_LOADS_BAUD_CHANGE */#endif /* CFG_CMD_SAVES */#endif /* CFG_CMD_LOADS */#if (CONFIG_COMMANDS & CFG_CMD_LOADB)U_BOOT_CMD( loadb, 3, 0, do_load_serial_bin, "loadb - load binary file over serial line (kermit mode)\n", "[ off ] [ baud ]\n" " - load binary file over serial line" " with offset 'off' and baudrate 'baud'\n");/* support xmodem, www.arm9.net */U_BOOT_CMD( loadx, 3, 0, do_load_serial_bin, "loadx - load binary file over serial line (xmodem mode)\n", "[ off ] [ baud ]\n" " - load binary file over serial line" " with offset 'off' and baudrate 'baud'\n");U_BOOT_CMD( loady, 3, 0, do_load_serial_bin, "loady - load binary file over serial line (ymodem mode)\n", "[ off ] [ baud ]\n" " - load binary file over serial line" " with offset 'off' and baudrate 'baud'\n");#endif /* CFG_CMD_LOADB *//* -------------------------------------------------------------------- */#if (CONFIG_COMMANDS & CFG_CMD_HWFLOW)int do_hwflow (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ extern int hwflow_onoff(int); if (argc == 2) { if (strcmp(argv[1], "off") == 0) hwflow_onoff(-1); else if (strcmp(argv[1], "on") == 0) hwflow_onoff(1); else printf("Usage: %s\n", cmdtp->usage); } printf("RTS/CTS hardware flow control: %s\n", hwflow_onoff(0) ? "on" : "off"); return 0;}/* -------------------------------------------------------------------- */U_BOOT_CMD( hwflow, 2, 0, do_hwflow, "hwflow - turn the harwdare flow control on/off\n", "[on|off]\n - change RTS/CTS hardware flow control over serial line\n");#endif /* CFG_CMD_HWFLOW */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -