Newer
Older
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* Serial up- and download support
*/
#include <common.h>
#include <command.h>
#include <exports.h>
#include <xyzModem.h>
DECLARE_GLOBAL_DATA_PTR;
#if defined(CONFIG_CMD_LOADB)
static ulong load_serial_ymodem(ulong offset, int mode);
#if defined(CONFIG_CMD_LOADS)
static ulong load_serial(long offset);
static int read_record(char *buf, ulong len);
# if defined(CONFIG_CMD_SAVES)
static int save_serial(ulong offset, ulong size);
static int write_record(char *buf);
/* -------------------------------------------------------------------- */
#if defined(CONFIG_CMD_LOADS)
static int do_load_serial(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
ulong addr;
int i;
char *env_echo;
int rcode = 0;
#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
int load_baudrate, current_baudrate;
load_baudrate = current_baudrate = gd->baudrate;
#endif
if (((env_echo = getenv("loads_echo")) != NULL) && (*env_echo == '1')) {
do_echo = 1;
} else {
do_echo = 0;
}
#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
offset = simple_strtol(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;
udelay(50000);
for (;;) {
if (getc() == '\r')
break;
}
}
#else /* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
offset = simple_strtol(argv[1], NULL, 16);
#endif /* CONFIG_SYS_LOADS_BAUD_CHANGE */
printf("## Ready for S-Record download ...\n");
/*
* 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();
#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
printf("## Switch baudrate to %d bps and press ESC ...\n",
for (;;) {
if (getc() == 0x1B) /* ESC */
break;
}
}
#endif
return rcode;
}
{
char record[SREC_MAXRECLEN + 1]; /* buffer for one S-Record */
char binbuf[SREC_MAXBINLEN]; /* buffer for binary data */
int binlen; /* no. of data bytes in S-Rec. */
int type; /* return code for record type */
ulong addr; /* load address from S-Record */
ulong size; /* number of bytes transferred */
ulong store_addr;
ulong start_addr = ~0;
ulong end_addr = 0;
int line_count = 0;
while (read_record(record, SREC_MAXRECLEN + 1) >= 0) {
type = srec_decode(record, &binlen, &addr, binbuf);
if (type < 0) {
return (~0); /* Invalid S-Record */
}
switch (type) {
case SREC_DATA2:
case SREC_DATA3:
case SREC_DATA4:
store_addr = addr + offset;
#ifndef CONFIG_SYS_NO_FLASH
memcpy((char *)(store_addr), binbuf, binlen);
}
if ((store_addr) < start_addr)
start_addr = store_addr;
if ((store_addr + binlen - 1) > end_addr)
end_addr = store_addr + binlen - 1;
break;
case SREC_END2:
case SREC_END3:
case SREC_END4:
"## First Load Addr = 0x%08lX\n"
"## Last Load Addr = 0x%08lX\n"
"## Total Size = 0x%08lX = %ld Bytes\n",
start_addr, end_addr, size, size
);
return (addr);
case SREC_START:
break;
default:
break;
}
if (!do_echo) { /* print a '.' every 100 lines */
if ((++line_count % 100) == 0)
}
}
return (~0); /* Download aborted */
}
Loading
Loading full blame...