#include <common.h>
#include <command.h>
#include <console.h>
+#include <cpu_func.h>
+#include <efi_loader.h>
#include <env.h>
-#include <s_record.h>
-#include <net.h>
#include <exports.h>
+#ifdef CONFIG_MTD_NOR_FLASH
+#include <flash.h>
+#endif
+#include <image.h>
+#include <lmb.h>
+#include <mapmem.h>
+#include <net.h>
+#include <s_record.h>
+#include <serial.h>
#include <xyzModem.h>
+#include <asm/cache.h>
+#include <asm/global_data.h>
+#include <linux/delay.h>
DECLARE_GLOBAL_DATA_PTR;
/* -------------------------------------------------------------------- */
#if defined(CONFIG_CMD_LOADS)
-static int do_load_serial(cmd_tbl_t *cmdtp, int flag, int argc,
- char * const argv[])
+static int do_load_serial(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
{
long offset = 0;
ulong addr;
offset = simple_strtol(argv[1], NULL, 16);
}
if (argc == 3) {
- load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
+ load_baudrate = (int)dectoul(argv[2], NULL);
/* default to current baudrate */
if (load_baudrate == 0)
printf("## Switch baudrate to %d bps and press ENTER ...\n",
load_baudrate);
udelay(50000);
+ flush();
gd->baudrate = load_baudrate;
serial_setbrg();
udelay(50000);
for (;;) {
- if (getc() == '\r')
+ if (getchar() == '\r')
break;
}
}
*/
for (i=0; i<100; ++i) {
if (tstc()) {
- (void) getc();
+ getchar();
}
udelay(1000);
}
rcode = 1;
} else {
printf("## Start Addr = 0x%08lX\n", addr);
- load_addr = addr;
+ image_load_addr = addr;
}
#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
printf("## Switch baudrate to %d bps and press ESC ...\n",
current_baudrate);
udelay(50000);
+ flush();
gd->baudrate = current_baudrate;
serial_setbrg();
udelay(50000);
for (;;) {
- if (getc() == 0x1B) /* ESC */
+ if (getchar() == 0x1B) /* ESC */
break;
}
}
static ulong load_serial(long offset)
{
+ struct lmb lmb;
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. */
ulong start_addr = ~0;
ulong end_addr = 0;
int line_count = 0;
+ long ret;
+
+ lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob);
while (read_record(record, SREC_MAXRECLEN + 1) >= 0) {
type = srec_decode(record, &binlen, &addr, binbuf);
} else
#endif
{
+ ret = lmb_reserve(&lmb, store_addr, binlen);
+ if (ret) {
+ printf("\nCannot overwrite reserved area (%08lx..%08lx)\n",
+ store_addr, store_addr + binlen);
+ return ret;
+ }
memcpy((char *)(store_addr), binbuf, binlen);
+ lmb_free(&lmb, store_addr, binlen);
}
if ((store_addr) < start_addr)
start_addr = store_addr;
--len; /* always leave room for terminating '\0' byte */
for (p=buf; p < buf+len; ++p) {
- c = getc(); /* read character */
+ c = getchar(); /* read character */
if (do_echo)
putc(c); /* ... and echo it */
*p = c;
}
- /* Check for the console hangup (if any different from serial) */
- if (gd->jt->getc != getc) {
- if (ctrlc()) {
- return (-1);
+ /* Check for the console hangup (if any different from serial) */
+ if (gd->jt->getc != getchar) {
+ if (ctrlc())
+ return (-1);
}
- }
}
/* line too long - truncate */
#if defined(CONFIG_CMD_SAVES)
-int do_save_serial (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_save_serial(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
{
ulong offset = 0;
ulong size = 0;
#endif
if (argc >= 2) {
- offset = simple_strtoul(argv[1], NULL, 16);
+ offset = hextoul(argv[1], NULL);
}
#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
if (argc >= 3) {
- size = simple_strtoul(argv[2], NULL, 16);
+ size = hextoul(argv[2], NULL);
}
if (argc == 4) {
- save_baudrate = (int)simple_strtoul(argv[3], NULL, 10);
+ save_baudrate = (int)dectoul(argv[3], NULL);
/* default to current baudrate */
if (save_baudrate == 0)
serial_setbrg();
udelay(50000);
for (;;) {
- if (getc() == '\r')
+ if (getchar() == '\r')
break;
}
}
#else /* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
if (argc == 3) {
- size = simple_strtoul(argv[2], NULL, 16);
+ size = hextoul(argv[2], NULL);
}
#endif /* CONFIG_SYS_LOADS_BAUD_CHANGE */
printf("## Ready for S-Record upload, press ENTER to proceed ...\n");
for (;;) {
- if (getc() == '\r')
+ if (getchar() == '\r')
break;
}
if (save_serial(offset, size)) {
printf("## Switch baudrate to %d bps and press ESC ...\n",
(int)current_baudrate);
udelay(50000);
+ flush();
gd->baudrate = current_baudrate;
serial_setbrg();
udelay(50000);
for (;;) {
- if (getc() == 0x1B) /* ESC */
+ if (getchar() == 0x1B) /* ESC */
break;
}
}
static char his_pad_char; /* pad chars he needs */
static char his_quote; /* quote chars he'll use */
-static int do_load_serial_bin(cmd_tbl_t *cmdtp, int flag, int argc,
- char * const argv[])
+static int do_load_serial_bin(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
{
ulong offset = 0;
ulong addr;
/* pre-set offset from $loadaddr */
s = env_get("loadaddr");
if (s)
- offset = simple_strtoul(s, NULL, 16);
+ offset = hextoul(s, NULL);
load_baudrate = current_baudrate = gd->baudrate;
if (argc >= 2) {
- offset = simple_strtoul(argv[1], NULL, 16);
+ offset = hextoul(argv[1], NULL);
}
if (argc == 3) {
- load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
+ load_baudrate = (int)dectoul(argv[2], NULL);
/* default to current baudrate */
if (load_baudrate == 0)
printf("## Switch baudrate to %d bps and press ENTER ...\n",
load_baudrate);
udelay(50000);
+ flush();
gd->baudrate = load_baudrate;
serial_setbrg();
udelay(50000);
for (;;) {
- if (getc() == '\r')
+ if (getchar() == '\r')
break;
}
}
addr = load_serial_ymodem(offset, xyzModem_ymodem);
+ if (addr == ~0) {
+ image_load_addr = 0;
+ printf("## Binary (ymodem) download aborted\n");
+ rcode = 1;
+ } else {
+ printf("## Start Addr = 0x%08lX\n", addr);
+ image_load_addr = addr;
+ }
} else if (strcmp(argv[0],"loadx")==0) {
printf("## Ready for binary (xmodem) download "
"to 0x%08lX at %d bps...\n",
addr = load_serial_ymodem(offset, xyzModem_xmodem);
+ if (addr == ~0) {
+ image_load_addr = 0;
+ printf("## Binary (xmodem) download aborted\n");
+ rcode = 1;
+ } else {
+ printf("## Start Addr = 0x%08lX\n", addr);
+ image_load_addr = addr;
+ }
} else {
printf("## Ready for binary (kermit) download "
addr = load_serial_bin(offset);
if (addr == ~0) {
- load_addr = 0;
+ image_load_addr = 0;
printf("## Binary (kermit) download aborted\n");
rcode = 1;
} else {
printf("## Start Addr = 0x%08lX\n", addr);
- load_addr = addr;
+ image_load_addr = addr;
}
}
if (load_baudrate != current_baudrate) {
printf("## Switch baudrate to %d bps and press ESC ...\n",
current_baudrate);
udelay(50000);
+ flush();
gd->baudrate = current_baudrate;
serial_setbrg();
udelay(50000);
for (;;) {
- if (getc() == 0x1B) /* ESC */
+ if (getchar() == 0x1B) /* ESC */
break;
}
}
*/
for (i=0; i<100; ++i) {
if (tstc()) {
- (void) getc();
+ getchar();
}
udelay(1000);
}
+ if (size == 0)
+ return ~0; /* Download aborted */
+
flush_cache(offset, size);
printf("## Total Size = 0x%08x = %d Bytes\n", size, size);
/* get a packet */
/* wait for the starting character or ^C */
for (;;) {
- switch (getc ()) {
+ switch (getchar()) {
case START_CHAR: /* start packet */
goto START;
case ETX_CHAR: /* ^C waiting for packet */
START:
/* get length of packet */
sum = 0;
- new_char = getc();
+ new_char = getchar();
if ((new_char & 0xE0) == 0)
goto packet_error;
sum += new_char & 0xff;
length = untochar(new_char);
/* get sequence number */
- new_char = getc();
+ new_char = getchar();
if ((new_char & 0xE0) == 0)
goto packet_error;
sum += new_char & 0xff;
/* END NEW CODE */
/* get packet type */
- new_char = getc();
+ new_char = getchar();
if ((new_char & 0xE0) == 0)
goto packet_error;
sum += new_char & 0xff;
if (length == -2) {
/* (length byte was 0, decremented twice) */
/* get the two length bytes */
- new_char = getc();
+ new_char = getchar();
if ((new_char & 0xE0) == 0)
goto packet_error;
sum += new_char & 0xff;
len_hi = untochar(new_char);
- new_char = getc();
+ new_char = getchar();
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();
+ new_char = getchar();
if ((new_char & 0xE0) == 0)
goto packet_error;
if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f))
}
/* bring in rest of packet */
while (length > 1) {
- new_char = getc();
+ new_char = getchar();
if ((new_char & 0xE0) == 0)
goto packet_error;
sum += new_char & 0xff;
}
}
/* get and validate checksum character */
- new_char = getc();
+ new_char = getchar();
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();
+ new_char = getchar();
if (new_char != END_CHAR) {
packet_error:
/* restore state machines */
static int getcxmodem(void) {
if (tstc())
- return (getc());
+ return (getchar());
return -1;
}
static ulong load_serial_ymodem(ulong offset, int mode)
res = xyzModem_stream_open(&info, &err);
if (!res) {
+ err = 0;
while ((res =
xyzModem_stream_read(ymodemBuf, 1024, &err)) > 0) {
store_addr = addr + offset;
rc = flash_write((char *) ymodemBuf,
store_addr, res);
if (rc != 0) {
- flash_perror (rc);
+ xyzModem_stream_terminate(true, &getcxmodem);
+ xyzModem_stream_close(&err);
+ printf("\n");
+ flash_perror(rc);
return (~0);
}
} else
}
}
+ if (err) {
+ xyzModem_stream_terminate((err == xyzModem_cancel) ? false : true, &getcxmodem);
+ xyzModem_stream_close(&err);
+ printf("\n%s\n", xyzModem_error(err));
+ return (~0); /* Download aborted */
+ }
+
+ if (IS_ENABLED(CONFIG_CMD_BOOTEFI))
+ efi_set_bootdev("Uart", "", "",
+ map_sysmem(offset, 0), size);
+
} else {
- printf("%s\n", xyzModem_error(err));
+ printf("\n%s\n", xyzModem_error(err));
+ return (~0); /* Download aborted */
}
- xyzModem_stream_close(&err);
xyzModem_stream_terminate(false, &getcxmodem);
+ xyzModem_stream_close(&err);
flush_cache(offset, ALIGN(size, ARCH_DMA_MINALIGN));
#endif
+#if defined(CONFIG_CMD_LOADM)
+static int do_load_memory_bin(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr, dest, size;
+ void *src, *dst;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ addr = simple_strtoul(argv[1], NULL, 16);
+
+ dest = simple_strtoul(argv[2], NULL, 16);
+
+ size = simple_strtoul(argv[3], NULL, 16);
+
+ if (!size) {
+ printf("loadm: can not load zero bytes\n");
+ return 1;
+ }
+
+ src = map_sysmem(addr, size);
+ dst = map_sysmem(dest, size);
+
+ memcpy(dst, src, size);
+
+ unmap_sysmem(src);
+ unmap_sysmem(dst);
+
+ if (IS_ENABLED(CONFIG_CMD_BOOTEFI))
+ efi_set_bootdev("Mem", "", "", map_sysmem(dest, 0), size);
+
+ printf("loaded bin to memory: size: %lu\n", size);
+
+ return 0;
+}
+#endif
+
/* -------------------------------------------------------------------- */
#if defined(CONFIG_CMD_LOADS)
U_BOOT_CMD(
loadb, 3, 0, do_load_serial_bin,
"load binary file over serial line (kermit mode)",
- "[ off ] [ baud ]\n"
+ "[ addr [ baud ] ]\n"
" - load binary file over serial line"
- " with offset 'off' and baudrate 'baud'"
+ " at address 'addr' with baudrate 'baud'"
);
U_BOOT_CMD(
loadx, 3, 0, do_load_serial_bin,
"load binary file over serial line (xmodem mode)",
- "[ off ] [ baud ]\n"
+ "[ addr [ baud ] ]\n"
" - load binary file over serial line"
- " with offset 'off' and baudrate 'baud'"
+ " at address 'addr' with baudrate 'baud'"
);
U_BOOT_CMD(
loady, 3, 0, do_load_serial_bin,
"load binary file over serial line (ymodem mode)",
- "[ off ] [ baud ]\n"
+ "[ addr [ baud ] ]\n"
" - load binary file over serial line"
- " with offset 'off' and baudrate 'baud'"
+ " at address 'addr' with baudrate 'baud'"
);
#endif /* CONFIG_CMD_LOADB */
+
+#if defined(CONFIG_CMD_LOADM)
+U_BOOT_CMD(
+ loadm, 4, 0, do_load_memory_bin,
+ "load binary blob from source address to destination address",
+ "[src_addr] [dst_addr] [size]\n"
+ " - load a binary blob from one memory location to other"
+ " from src_addr to dst_addr by size bytes"
+);
+#endif /* CONFIG_CMD_LOADM */