
On Wed, May 21, 2008 at 11:28:12AM -0500, Menon, Nishanth wrote:
This patch provides support for loadb and loady and enables the broken feature. xyzModem.c is brought in from U-Boot V1, Lindent, checkpatch and sparse cleaned :).
Signed-off-by: Nishanth Menonx0nishan@ti.com
commands/Kconfig | 14 commands/Makefile | 1 commands/loadb.c | 182 ++++++++--- commands/xyzModem.c | 792 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/Makefile | 1 5 files changed, 932 insertions(+), 58 deletions(-)
Index: u-boot-v2.git/commands/Kconfig
--- u-boot-v2.git.orig/commands/Kconfig 2008-05-20 17:53:55.000000000 -0500 +++ u-boot-v2.git/commands/Kconfig 2008-05-20 17:54:18.000000000 -0500 @@ -121,13 +121,23 @@ endmenu
menu "memory " +config LOAD_ADDR
- depends on CMD_LOADB
- hex
- prompt "default load address"
- help
Provide the default load address for the platform
config CMD_LOADB
- depends on BROKEN select CRC16
- tristate
- bool prompt "loadb"
Is there a reason why loadb does not work as module? othwerwise you should leave this to tristate.
+config CMD_LOADY
- select CRC16
- bool
- prompt "loady"
config CMD_LOADS depends on BROKEN tristate Index: u-boot-v2.git/commands/Makefile =================================================================== --- u-boot-v2.git.orig/commands/Makefile 2008-05-20 17:53:55.000000000 -0500 +++ u-boot-v2.git/commands/Makefile 2008-05-20 17:54:18.000000000 -0500 @@ -1,5 +1,6 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o obj-$(CONFIG_CMD_LOADB) += loadb.o xyzModem.o +obj-$(CONFIG_CMD_LOADY) += loadb.o xyzModem.o obj-$(CONFIG_CMD_LOADS) += loads.o obj-$(CONFIG_CMD_ECHO) += echo.o obj-$(CONFIG_CMD_MEMORY) += mem.o Index: u-boot-v2.git/commands/loadb.c =================================================================== --- u-boot-v2.git.orig/commands/loadb.c 2008-05-20 17:53:55.000000000 -0500 +++ u-boot-v2.git/commands/loadb.c 2008-05-20 17:58:05.000000000 -0500 @@ -1,3 +1,12 @@ +/**
- @file
- @brief LoadB and LoadY support.
- Provides loadb (over Kermit) and LoadY(over Y modem) support to download
- images.
- FileName: commands/loadb.c
- */
/*
- (C) Copyright 2000-2004
- Wolfgang Denk, DENX Software Engineering, wd@denx.de.
@@ -26,14 +35,16 @@ */ #include <common.h> #include <command.h> -#include <s_record.h> -#include <net.h> -#include <exports.h> #include <xyzModem.h> +#include <console.h> +#include <errno.h> +#include <environment.h> +#include <cache.h>
-DECLARE_GLOBAL_DATA_PTR;
+#ifdef CONFIG_CMD_LOADY static ulong load_serial_ymodem (ulong offset); +#endif
#define XON_CHAR 17 #define XOFF_CHAR 19 @@ -50,36 +61,70 @@ #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 */ +static char his_eol; /* character he needs at end of packet */ +static int his_pad_count; /* number of pad chars he needs */ +static char his_pad_char; /* pad chars he needs */ +static char his_quote; /* quote chars he'll use */
-int do_load_serial_bin (cmd_tbl_t *cmdtp, int argc, char *argv[]) +/**
- @brief returns current used console device
- @return console device which is registered with CONSOLE_STDIN and
- CONSOLE_STDOUT
- */
+static struct console_device *get_current_console(void) +{
- struct console_device *cdev;
- /*
* Assumption to have BOTH CONSOLE_STDIN AND STDOUT in the
* same output console
*/
- for_each_console(cdev) {
if ((cdev->f_active & (CONSOLE_STDIN | CONSOLE_STDOUT)))
return cdev;
- }
- return NULL;
+}
+/**
- @brief provide the loadb(Kermit) or loadY mode support
- @param cmdtp
- @param argc
- @param argv
- @return success or failure
- */
+static int do_load_serial_bin(cmd_tbl_t *cmdtp, int argc, char *argv[]) { ulong offset = 0; ulong addr; int load_baudrate, current_baudrate; int rcode = 0; char *s;
- struct console_device *cdev = get_current_console();
- if (NULL == cdev) {
printf("No device with STDIN and STDOUT\n");
return -ENODEV;
- }
- /* pre-set offset from CFG_LOAD_ADDR */
- offset = CFG_LOAD_ADDR;
/* pre-set offset from CONFIG_LOAD_ADDR */
offset = CONFIG_LOAD_ADDR;
/* pre-set offset from $loadaddr */
- if ((s = getenv("loadaddr")) != NULL) {
- s = (char *) getenv("loadaddr");
- if (s != NULL) offset = simple_strtoul(s, NULL, 16);
Parameters to commands should go via command line arguments and not environment variables. The use of environment variables makes it necessary to read the documentation (if it's there ;) or the source to make it clear which commands use which variables. Command line options on the other hand are self explaining via the -h option.
Normally commands like tftp work on a file and not on a plain memory address. The serial commands should behave the same.
}
load_baudrate = current_baudrate = gd->baudrate;
load_baudrate = current_baudrate =
simple_strtoul(cdev->baudrate_string, NULL, 10);
if (argc >= 2) { offset = simple_strtoul(argv[1], NULL, 16);
@@ -96,15 +141,14 @@ 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; } }cdev->setbrg(cdev, load_baudrate);
+#ifdef CONFIG_CMD_LOADY if (strcmp(argv[0],"loady")==0) { printf ("## Ready for binary (ymodem) download " "to 0x%08lX at %d bps...\n", @@ -113,7 +157,10 @@
addr = load_serial_ymodem (offset);
- } else {
- }
+#endif +#ifdef CONFIG_CMD_LOADB
if (strcmp(argv[0],"loadb")==0) {
printf ("## Ready for binary (kermit) download " "to 0x%08lX at %d bps...\n",
@@ -122,20 +169,18 @@ addr = load_serial_bin (offset);
if (addr == ~0) {
} else { printf ("## Start Addr = 0x%08lX\n", addr);load_addr = 0; printf ("## Binary (kermit) download aborted\n"); rcode = 1;
} }load_addr = addr;
+#endif 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 */cdev->setbrg(cdev, current_baudrate);
@@ -147,6 +192,14 @@ }
+#ifdef CONFIG_CMD_LOADB +/**
- @brief loadb Support over kermit protocol
- @param offset where to download to
- @return downloaded address
- */
static ulong load_serial_bin (ulong offset) { int size, i; @@ -175,17 +228,18 @@
return offset; } +#endif
-void send_pad (void) +static void send_pad (void) { int count = his_pad_count;
while (count-- > 0)
putc (his_pad_char);
console_putc (CONSOLE_STDOUT, his_pad_char);
}
/* converts escaped kermit char to binary char */ -char ktrans (char in) +static char ktrans(char in) { if ((in & 0x60) == 0x40) { return (char) (in & ~0x40); @@ -195,7 +249,7 @@ return in; }
-int chk1 (char *buffer) +static int chk1 (char *buffer) { int total = 0;
@@ -205,16 +259,16 @@ return (int) ((total + ((total >> 6) & 0x03)) & 0x3f); }
-void s1_sendpacket (char *packet) +static void s1_sendpacket (char *packet) { send_pad (); while (*packet) {
putc (*packet++);
}console_putc (CONSOLE_STDOUT, *packet++);
}
static char a_b[24]; -void send_ack (int n) +static void send_ack (int n) { a_b[0] = START_CHAR; a_b[1] = tochar (3); @@ -227,7 +281,7 @@ s1_sendpacket (a_b); }
-void send_nack (int n) +static void send_nack (int n) { a_b[0] = START_CHAR; a_b[1] = tochar (3); @@ -246,14 +300,15 @@
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 void (*os_data_init) (void); +static 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; 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]; +/* FIXME: carry over feature to use this. commented for sparse warning +static int os_data_header[8]; */ static void bin_data_init (void) { os_data_state = 0; @@ -291,22 +346,22 @@
/* k_data_* simply handles the kermit escape translations */ static int k_data_escape, k_data_escape_saved; -void k_data_init (void) +static void k_data_init(void) { k_data_escape = 0; os_data_init (); } -void k_data_save (void) +static void k_data_save(void) { k_data_escape_saved = k_data_escape; os_data_save (); } -void k_data_restore (void) +static void k_data_restore(void) { k_data_escape = k_data_escape_saved; os_data_restore (); } -void k_data_char (char new_char) +static void k_data_char(char new_char) { if (k_data_escape) { /* last char was escape - translate this character */ @@ -324,12 +379,12 @@ }
#define SEND_DATA_SIZE 20 -char send_parms[SEND_DATA_SIZE]; -char *send_ptr; +static char send_parms[SEND_DATA_SIZE]; +static 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) +static void handle_send_packet(int n) { int length = 3; int bytes; @@ -588,11 +643,19 @@ return ((ulong) os_data_addr - (ulong) bin_start_address); }
+#ifdef CONFIG_CMD_LOADY static int getcxmodem(void) { if (tstc()) return (getc()); return -1; } +/**
- @brief LoadY over ymodem protocol
- @param offset address to download to
- @return address downloaded
- */
static ulong load_serial_ymodem (ulong offset) { int size; @@ -633,19 +696,26 @@
return offset; } +#endif
-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"
-);
-U_BOOT_CMD(
- loady, 3, 0, do_load_serial_bin,
- "loady - load binary file over serial line (ymodem mode)\n",
+static const __maybe_unused char cmd_loadb_help[] = "[ off ] [ baud ]\n" " - load binary file over serial line"
- " with offset 'off' and baudrate 'baud'\n"
-);
- " with offset 'off' and baudrate 'baud'\n";
+#ifdef CONFIG_CMD_LOADB +U_BOOT_CMD_START(loadb)
- .maxargs = 3,
- .cmd = do_load_serial_bin,
- .usage = "load binary file over serial line (kermit mode)",
- U_BOOT_CMD_HELP(cmd_loadb_help)
+U_BOOT_CMD_END +#endif
+#ifdef CONFIG_CMD_LOADY +U_BOOT_CMD_START(loady)
- .maxargs = 3,
- .cmd = do_load_serial_bin,
- .usage = "load binary file over serial line (ymodem mode)",
- U_BOOT_CMD_HELP(cmd_loadb_help)
+U_BOOT_CMD_END +#endif Index: u-boot-v2.git/commands/xyzModem.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ u-boot-v2.git/commands/xyzModem.c 2008-05-20 17:54:18.000000000 -0500 @@ -0,0 +1,792 @@ +/**
- @file
- @brief RedBoot stream handler for xyzModem protocol
- FileName: commands/xyzModem.c
- Originally from U-Boot V1 xyzModem.c
- */
+/*
- 2008 - Nishanth Menon x0nishan@ti.com
- Modified for sparse and checkpatch.pl compliance
- */
+/*
- *==========================================================================
xyzModem.c
RedBoot stream handler for xyzModem protocol
- *==========================================================================
- *####ECOSGPLCOPYRIGHTBEGIN####
- This file is part of eCos, the Embedded Configurable Operating System.
- Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
- Copyright (C) 2002 Gary Thomas
- eCos is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 2 or (at your option) any later version.
- eCos is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
- You should have received a copy of the GNU General Public License along
- with eCos; if not, write to the Free Software Foundation, Inc.,
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- As a special exception, if other files instantiate templates or use macros
- or inline functions from this file, or you compile this file and link it
- with other works to produce a work based on this file, this file does not
- by itself cause the resulting work to be covered by the GNU General Public
- License. However the source code for this file must still be made available
- in accordance with section (3) of the GNU General Public License.
- This exception does not invalidate any other reasons why a work based on
- this file might be covered by the GNU General Public License.
- Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
- at http: *sources.redhat.com/ecos/ecos-license/
- *####ECOSGPLCOPYRIGHTEND####
- *==========================================================================
- *#####DESCRIPTIONBEGIN####
- Author(s): gthomas
- Contributors: gthomas, tsmith, Yoshinori Sato
- Date: 2000-07-14
- Purpose:
- Description:
- This code is part of RedBoot (tm).
- *####DESCRIPTIONEND####
- *==========================================================================
- */
+#include <common.h> +#include <xyzModem.h> +#include <stdarg.h> +#include <stdio.h> +#include <console.h> +#include <crc.h>
+/* Assumption - run xyzModem protocol over the console port */
+/* Values magic to the protocol */ +#define SOH 0x01 +#define STX 0x02 +#define EOT 0x04 +#define ACK 0x06 +#define BSP 0x08 +#define NAK 0x15 +#define CAN 0x18 +#define EOF 0x1A /* ^Z for DOS officionados */
+#define USE_YMODEM_LENGTH
+/* Data & state local to the protocol */ +static struct { +#ifdef REDBOOT
- hal_virtual_comm_table_t *__chan;
+#else
- int *__chan;
+#endif
- unsigned char pkt[1024], *bufp;
- unsigned char blk, cblk, crc1, crc2;
- unsigned char next_blk; /* Expected block */
- int len, mode, total_retries;
- int total_SOH, total_STX, total_CAN;
- bool crc_mode, at_eof, tx_ack;
+#ifdef USE_YMODEM_LENGTH
- unsigned long file_length, read_length;
+#endif +} xyz;
+#define xyzModem_CHAR_TIMEOUT 2000 /* 2 seconds */ +#define xyzModem_MAX_RETRIES 20 +#define xyzModem_MAX_RETRIES_WITH_CRC 10 +/* Wait for 3 CAN before quitting */ +#define xyzModem_CAN_COUNT 3
+#ifndef REDBOOT /*SB */ +typedef int cyg_int32; +static int CYGACC_COMM_IF_GETC_TIMEOUT(char chan, char *c) +{ +#define DELAY 20
- unsigned long counter = 0;
- while (!tstc() && (counter < xyzModem_CHAR_TIMEOUT * 1000 / DELAY)) {
udelay(DELAY);
counter++;
- }
- if (tstc()) {
*c = getc();
return 1;
- }
- return 0;
+}
+static void CYGACC_COMM_IF_PUTC(char x, char y) +{
- console_putc(CONSOLE_STDOUT, y);
+}
+/* Validate a hex character */ +static inline bool _is_hex(char c) +{
- return (((c >= '0') && (c <= '9')) ||
((c >= 'A') && (c <= 'F')) || ((c >= 'a') && (c <= 'f')));
+}
+/* Convert a single hex nibble */ +static inline int _from_hex(char c) +{
- int ret = 0;
- if ((c >= '0') && (c <= '9'))
ret = (c - '0');
- else if ((c >= 'a') && (c <= 'f'))
ret = (c - 'a' + 0x0a);
- else if ((c >= 'A') && (c <= 'F'))
ret = (c - 'A' + 0x0A);
- return ret;
+}
+/* Convert a character to lower case */ +static inline char _tolower(char c) +{
- if ((c >= 'A') && (c <= 'Z'))
c = (c - 'A') + 'a';
- return c;
+}
We already have a tolower function in include/linux/ctype.h
+/* Parse (scan) a number */ +static bool parse_num(char *s, unsigned long *val, char **es, char *delim) +{
- bool first = true;
- int radix = 10;
- char c;
- unsigned long result = 0;
- int digit;
- while (*s == ' ')
s++;
- while (*s) {
if (first && (s[0] == '0') && (_tolower(s[1]) == 'x')) {
radix = 16;
s += 2;
}
first = false;
c = *s++;
if (_is_hex(c))
digit = _from_hex(c);
if (_is_hex(c) && (digit < radix)) {
/* Valid digit */
+#ifdef CYGPKG_HAL_MIPS
/* FIXME: tx49 compiler generates 0x2539018 for
* MUL which isn't any good. */
if (16 == radix)
result = result << 4;
else
result = 10 * result;
result += digit;
+#else
result = (result * radix) + digit;
+#endif
} else {
if (delim != (char *)0) {
/* See if this character is one of the
* delimiters */
char *dp = delim;
while (*dp && (c != *dp))
dp++;
if (*dp)
break; /* Found a good delimiter */
}
return false; /* Malformatted number */
}
- }
- *val = result;
- if (es != (char **)0)
*es = s;
- return true;
+}
+#endif
+#define USE_SPRINTF +#ifdef DEBUG +#ifndef USE_SPRINTF +/*
- Note: this debug setup only works if the target platform has two serial ports
- available so that the other one (currently only port 1) can be used for debug
- messages.
- */
+static int zm_dprintf(char *fmt, ...) +{
- int cur_console;
- va_list args;
- va_start(args, fmt);
+#ifdef REDBOOT
- cur_console =
CYGACC_CALL_IF_SET_CONSOLE_COMM
(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
- CYGACC_CALL_IF_SET_CONSOLE_COMM(1);
+#endif
- diag_vprintf(fmt, args);
+#ifdef REDBOOT
- CYGACC_CALL_IF_SET_CONSOLE_COMM(cur_console);
+#endif +}
+static void zm_flush(void) +{ +}
+#else +/*
- Note: this debug setup works by storing the strings in a fixed buffer
- */
+#define FINAL +#ifdef FINAL +static char *zm_out = (char *)0x00380000; +static char *zm_out_start = (char *)0x00380000; +#else +static char zm_buf[8192]; +static char *zm_out = zm_buf; +static char *zm_out_start = zm_buf;
+#endif +static int zm_dprintf(char *fmt, ...) +{
- int len;
- va_list args;
- va_start(args, fmt);
- len = diag_vsprintf(zm_out, fmt, args);
- zm_out += len;
- return len;
+}
+static void zm_flush(void) +{ +#ifdef REDBOOT
- char *p = zm_out_start;
- while (*p)
mon_write_char(*p++);
+#endif
- zm_out = zm_out_start;
+} +#endif
+static void zm_dump_buf(void *buf, int len) +{ +#ifdef REDBOOT
- diag_vdump_buf_with_offset(zm_dprintf, buf, len, 0);
+#else
+#endif +}
+static unsigned char zm_buf[2048]; +static unsigned char *zm_bp;
+static void zm_new(void) +{
- zm_bp = zm_buf;
+}
+static void zm_save(unsigned char c) +{
- *zm_bp++ = c;
+}
+static void zm_dump(int line) +{
- zm_dprintf("Packet at line: %d\n", line);
- zm_dump_buf(zm_buf, zm_bp - zm_buf);
+}
+#define ZM_DEBUG(x) x +#else +#define ZM_DEBUG(x) +#endif
+/* Wait for the line to go idle */ +static void xyzModem_flush(void) +{
- int res;
- char c;
- while (true) {
res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &c);
if (!res)
return;
- }
+}
+static int xyzModem_get_hdr(void) +{
- char c;
- int res;
- bool hdr_found = false;
- int i, can_total, hdr_chars;
- unsigned short cksum;
- ZM_DEBUG(zm_new());
- /* Find the start of a header */
- can_total = 0;
- hdr_chars = 0;
- if (xyz.tx_ack) {
CYGACC_COMM_IF_PUTC(*xyz.__chan, ACK);
xyz.tx_ack = false;
- }
- while (!hdr_found) {
res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &c);
ZM_DEBUG(zm_save(c));
if (res) {
hdr_chars++;
switch (c) {
case SOH:
xyz.total_SOH++;
case STX:
if (c == STX)
xyz.total_STX++;
hdr_found = true;
break;
case CAN:
xyz.total_CAN++;
ZM_DEBUG(zm_dump(__LINE__));
if (++can_total == xyzModem_CAN_COUNT) {
return xyzModem_cancel;
} else {
/* Wait for multiple CAN to avoid
* early quits */
break;
}
case EOT:
/* EOT only supported if no noise */
if (hdr_chars == 1) {
CYGACC_COMM_IF_PUTC(*xyz.__chan, ACK);
ZM_DEBUG(zm_dprintf
("ACK on EOT #%d\n",
__LINE__));
ZM_DEBUG(zm_dump(__LINE__));
return xyzModem_eof;
}
default:
/* Ignore, waiting for start of header */
;
}
} else {
/* Data stream timed out */
xyzModem_flush(); /* Toss any current input */
ZM_DEBUG(zm_dump(__LINE__));
CYGACC_CALL_IF_DELAY_US((cyg_int32) 250000);
return xyzModem_timeout;
}
- }
- /* Header found, now read the data */
- res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, (char *)&xyz.blk);
- ZM_DEBUG(zm_save(xyz.blk));
- if (!res) {
ZM_DEBUG(zm_dump(__LINE__));
return xyzModem_timeout;
- }
- res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, (char *)&xyz.cblk);
- ZM_DEBUG(zm_save(xyz.cblk));
- if (!res) {
ZM_DEBUG(zm_dump(__LINE__));
return xyzModem_timeout;
- }
- xyz.len = (c == SOH) ? 128 : 1024;
- xyz.bufp = xyz.pkt;
- for (i = 0; i < xyz.len; i++) {
res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &c);
ZM_DEBUG(zm_save(c));
if (res) {
xyz.pkt[i] = c;
} else {
ZM_DEBUG(zm_dump(__LINE__));
return xyzModem_timeout;
}
- }
- res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, (char *)&xyz.crc1);
- ZM_DEBUG(zm_save(xyz.crc1));
- if (!res) {
ZM_DEBUG(zm_dump(__LINE__));
return xyzModem_timeout;
- }
- if (xyz.crc_mode) {
res =
CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, (char *)&xyz.crc2);
ZM_DEBUG(zm_save(xyz.crc2));
if (!res) {
ZM_DEBUG(zm_dump(__LINE__));
return xyzModem_timeout;
}
- }
- ZM_DEBUG(zm_dump(__LINE__));
- /* Validate the message */
- if ((xyz.blk ^ xyz.cblk) != (unsigned char)0xFF) {
ZM_DEBUG(zm_dprintf
("Framing error - blk: %x/%x/%x\n", xyz.blk, xyz.cblk,
(xyz.blk ^ xyz.cblk)));
ZM_DEBUG(zm_dump_buf(xyz.pkt, xyz.len));
xyzModem_flush();
return xyzModem_frame;
- }
- /* Verify checksum/CRC */
- if (xyz.crc_mode) {
cksum = cyg_crc16(xyz.pkt, xyz.len);
if (cksum != ((xyz.crc1 << 8) | xyz.crc2)) {
ZM_DEBUG(zm_dprintf
("CRC error - recvd: %02x%02x, computed: %x\n",
xyz.crc1, xyz.crc2, cksum & 0xFFFF));
return xyzModem_cksum;
}
- } else {
cksum = 0;
for (i = 0; i < xyz.len; i++)
cksum += xyz.pkt[i];
if (xyz.crc1 != (cksum & 0xFF)) {
ZM_DEBUG(zm_dprintf
("Checksum error - recvd: %x, computed: %x\n",
xyz.crc1, cksum & 0xFF));
return xyzModem_cksum;
}
- }
- /* If we get here, the message passes [structural] muster */
- return 0;
+}
+int xyzModem_stream_open(connection_info_t *info, int *err) +{ +#ifdef REDBOOT
- int console_chan;
+#endif
- int stat = 0;
- int retries = xyzModem_MAX_RETRIES;
- int crc_retries = xyzModem_MAX_RETRIES_WITH_CRC;
+/* ZM_DEBUG(zm_out = zm_out_start); */ +#ifdef xyzModem_zmodem
- if (info->mode == xyzModem_zmodem) {
*err = xyzModem_noZmodem;
return -1;
- }
+#endif
+#ifdef REDBOOT
- /* Set up the I/O channel. Note: this allows for using a different
* port in the future */
- console_chan =
CYGACC_CALL_IF_SET_CONSOLE_COMM
(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
- if (info->chan >= 0)
CYGACC_CALL_IF_SET_CONSOLE_COMM(info->chan);
- else
CYGACC_CALL_IF_SET_CONSOLE_COMM(console_chan);
- xyz.__chan = CYGACC_CALL_IF_CONSOLE_PROCS();
- CYGACC_CALL_IF_SET_CONSOLE_COMM(console_chan);
- CYGACC_COMM_IF_CONTROL(*xyz.__chan, __COMMCTL_SET_TIMEOUT,
xyzModem_CHAR_TIMEOUT);
+#else +/* TODO: CHECK ! */
- int dummy;
- xyz.__chan = &dummy;
+#endif
- xyz.len = 0;
- xyz.crc_mode = true;
- xyz.at_eof = false;
- xyz.tx_ack = false;
- xyz.mode = info->mode;
- xyz.total_retries = 0;
- xyz.total_SOH = 0;
- xyz.total_STX = 0;
- xyz.total_CAN = 0;
+#ifdef USE_YMODEM_LENGTH
- xyz.read_length = 0;
- xyz.file_length = 0;
+#endif
- CYGACC_COMM_IF_PUTC(*xyz.__chan, (xyz.crc_mode ? 'C' : NAK));
- if (xyz.mode == xyzModem_xmodem) {
/* X-modem doesn't have an information header - exit here */
xyz.next_blk = 1;
return 0;
- }
- while (retries-- > 0) {
stat = xyzModem_get_hdr();
if (stat == 0) {
/* Y-modem file information header */
if (xyz.blk == 0) {
+#ifdef USE_YMODEM_LENGTH
/* skip filename */
while (*xyz.bufp++) ;
/* get the length */
parse_num((char *)xyz.bufp, &xyz.file_length,
NULL, " ");
+#endif
/* The rest of the file name data block
* quietly discarded
*/
xyz.tx_ack = true;
}
xyz.next_blk = 1;
xyz.len = 0;
return 0;
} else if (stat == xyzModem_timeout) {
if (--crc_retries <= 0)
xyz.crc_mode = false;
/* Extra delay for startup */
CYGACC_CALL_IF_DELAY_US(5 * 100000);
CYGACC_COMM_IF_PUTC(*xyz.__chan,
(xyz.crc_mode ? 'C' : NAK));
xyz.total_retries++;
ZM_DEBUG(zm_dprintf("NAK (%d)\n", __LINE__));
}
if (stat == xyzModem_cancel)
break;
- }
- *err = stat;
- ZM_DEBUG(zm_flush());
- return -1;
+}
+int xyzModem_stream_read(char *buf, int size, int *err) +{
- int stat, total, len;
- int retries;
- total = 0;
- stat = xyzModem_cancel;
- /* Try and get 'size' bytes into the buffer */
- while (!xyz.at_eof && (size > 0)) {
if (xyz.len == 0) {
retries = xyzModem_MAX_RETRIES;
while (retries-- > 0) {
stat = xyzModem_get_hdr();
if (stat == 0) {
if (xyz.blk == xyz.next_blk) {
xyz.tx_ack = true;
ZM_DEBUG(zm_dprintf
("ACK block %d (%d)\n",
xyz.blk, __LINE__));
xyz.next_blk =
(xyz.next_blk + 1) & 0xFF;
+#if defined(xyzModem_zmodem) || defined(USE_YMODEM_LENGTH)
if (xyz.mode == xyzModem_xmodem
|| xyz.file_length == 0) {
+#else
if (1) {
+#endif
/* WARNING - Leaving formatting aside for code
* clarity */
/* Data blocks can be padded with ^Z (EOF) characters */
/* This code tries to detect and remove them */
if ((xyz.bufp[xyz.len - 1] == EOF)
&& (xyz.bufp[xyz.len - 2] == EOF)
&& (xyz.bufp[xyz.len - 3] == EOF)) {
while (xyz.len &&
(xyz.bufp[xyz.len - 1] == EOF))
xyz.len--;
}
}
+#ifdef USE_YMODEM_LENGTH
/* WARNING - Leaving formatting aside for code
* clarity */
/*
* See if accumulated length exceeds that of the file.
* If so, reduce size (i.e., cut out pad bytes)
* Only do this for Y-modem (and Z-modem should it ever
* be supported since it can fall back to Y-modem mode).
*/
if (xyz.mode != xyzModem_xmodem
&& 0 != xyz.file_length) {
xyz.read_length += xyz.len;
if (xyz.read_length > xyz.file_length)
xyz.len -= (xyz.read_length -
xyz.file_length);
}
+#endif
break;
} else if (xyz.blk ==
((xyz.next_blk - 1) &
0xFF)) {
/* Just re-ACK this so sender
* will get on with it */
CYGACC_COMM_IF_PUTC(*xyz.__chan,
ACK);
/* Need new header */
continue;
} else
stat = xyzModem_sequence;
}
if (stat == xyzModem_cancel)
break;
if (stat == xyzModem_eof) {
CYGACC_COMM_IF_PUTC(*xyz.__chan, ACK);
ZM_DEBUG(zm_dprintf
("ACK (%d)\n", __LINE__));
if (xyz.mode == xyzModem_ymodem) {
CYGACC_COMM_IF_PUTC(*xyz.__chan,
(xyz.
crc_mode ?
'C' :
NAK));
xyz.total_retries++;
ZM_DEBUG(zm_dprintf
("Reading Final Header\n"));
stat = xyzModem_get_hdr();
CYGACC_COMM_IF_PUTC(*xyz.__chan,
ACK);
ZM_DEBUG(zm_dprintf
("FINAL ACK (%d)\n",
__LINE__));
}
xyz.at_eof = true;
break;
}
CYGACC_COMM_IF_PUTC(*xyz.__chan,
(xyz.crc_mode ? 'C' : NAK));
xyz.total_retries++;
ZM_DEBUG(zm_dprintf("NAK (%d)\n", __LINE__));
}
if (stat < 0) {
*err = stat;
xyz.len = -1;
return total;
}
}
/* Don't "read" data from the EOF protocol package */
if (!xyz.at_eof) {
len = xyz.len;
if (size < len)
len = size;
memcpy(buf, xyz.bufp, len);
size -= len;
buf += len;
total += len;
xyz.len -= len;
xyz.bufp += len;
}
- }
- return total;
+}
+void xyzModem_stream_close(int *err) +{
- diag_printf
("xyzModem - %s mode, %d(SOH)/%d(STX)/%d(CAN) packets,"
" %d retries\n",
xyz.crc_mode ? "CRC" : "Cksum", xyz.total_SOH, xyz.total_STX,
xyz.total_CAN, xyz.total_retries);
- ZM_DEBUG(zm_flush());
+}
+/* Need to be able to clean out the input buffer, so have to take the */ +/* getc */ +void xyzModem_stream_terminate(bool abort, int (*getc) (void)) +{
- int c;
- if (abort) {
ZM_DEBUG(zm_dprintf("!!!! TRANSFER ABORT !!!!\n"));
switch (xyz.mode) {
case xyzModem_xmodem:
case xyzModem_ymodem:
/* The X/YMODEM Spec seems to suggest that multiple CAN
* followed by an equal number of Backspaces is a
* friendly way to get the other end to abort. */
CYGACC_COMM_IF_PUTC(*xyz.__chan, CAN);
CYGACC_COMM_IF_PUTC(*xyz.__chan, CAN);
CYGACC_COMM_IF_PUTC(*xyz.__chan, CAN);
CYGACC_COMM_IF_PUTC(*xyz.__chan, CAN);
CYGACC_COMM_IF_PUTC(*xyz.__chan, BSP);
CYGACC_COMM_IF_PUTC(*xyz.__chan, BSP);
CYGACC_COMM_IF_PUTC(*xyz.__chan, BSP);
CYGACC_COMM_IF_PUTC(*xyz.__chan, BSP);
/* Now consume the rest of what's waiting on the line.*/
ZM_DEBUG(zm_dprintf("Flushing serial line.\n"));
xyzModem_flush();
xyz.at_eof = true;
break;
+#ifdef xyzModem_zmodem
case xyzModem_zmodem:
/* Might support it some day I suppose. */
+#endif
break;
}
- } else {
ZM_DEBUG(zm_dprintf("Engaging cleanup mode...\n"));
/*
* Consume any trailing crap left in the inbuffer from
* previous recieved blocks. Since very few files are an
* exact multiple of the transfer block size, there will
* almost always be some gunk here.
* If we don't eat it now, RedBoot will think the user typed it.
*/
ZM_DEBUG(zm_dprintf("Trailing gunk:\n"));
while ((c = (*getc) ()) > -1) ;
ZM_DEBUG(zm_dprintf("\n"));
/*
* Make a small delay to give terminal programs like minicom
* time to get control again after their file transfer program
* exits.
*/
CYGACC_CALL_IF_DELAY_US((cyg_int32) 250000);
- }
+}
+char *xyzModem_error(int err) +{
- switch (err) {
- case xyzModem_access:
return "Can't access file";
break;
- case xyzModem_noZmodem:
return "Sorry, zModem not available yet";
break;
- case xyzModem_timeout:
return "Timed out";
break;
- case xyzModem_eof:
return "End of file";
break;
- case xyzModem_cancel:
return "Cancelled";
break;
- case xyzModem_frame:
return "Invalid framing";
break;
- case xyzModem_cksum:
return "CRC/checksum error";
break;
- case xyzModem_sequence:
return "Block sequence error";
break;
- default:
return "Unknown error";
break;
- }
+}
+/*
- RedBoot interface
- */
+#if 0 /* SB */ +GETC_IO_FUNCS(xyzModem_io, xyzModem_stream_open, xyzModem_stream_close,
xyzModem_stream_terminate, xyzModem_stream_read, xyzModem_error);
+RedBoot_load(xmodem, xyzModem_io, false, false, xyzModem_xmodem); +RedBoot_load(ymodem, xyzModem_io, false, false, xyzModem_ymodem); +#endif Index: u-boot-v2.git/lib/Makefile =================================================================== --- u-boot-v2.git.orig/lib/Makefile 2008-05-20 17:53:55.000000000 -0500 +++ u-boot-v2.git/lib/Makefile 2008-05-20 17:54:18.000000000 -0500 @@ -19,6 +19,7 @@ obj-$(CONFIG_BZLIB) += bzlib.o bzlib_crctable.o bzlib_decompress.o bzlib_huffman.o bzlib_randtable.o obj-$(CONFIG_ZLIB) += zlib.o gunzip.o obj-$(CONFIG_CRC32) += crc32.o +obj-$(CONFIG_CRC16) += crc16.o obj-$(CONFIG_CMDLINE_EDITING) += readline.o obj-$(CONFIG_SIMPLE_READLINE) += readline_simple.o obj-$(CONFIG_GLOB) += fnmatch.o