diff options
author | Robert Jarzmik <robert.jarzmik@free.fr> | 2012-11-08 22:16:40 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2012-11-12 09:35:53 +0100 |
commit | 2a38aa83f78d54e81f887bddc1eb77451628f830 (patch) | |
tree | b48be1c2bd2c01497f1b1a65d340260513b32ece /commands | |
parent | 06bc2e706c8546bbcd98e0416e6d32a96a0f07ca (diff) | |
download | barebox-2a38aa83f78d54e81f887bddc1eb77451628f830.tar.gz barebox-2a38aa83f78d54e81f887bddc1eb77451628f830.tar.xz |
commands: change Y-Modem implementation
The current Y-Modem implementation has some limitations:
- Y-Modem/G protocol is not supported
- Multiple files (aka. batch) transfers are not supported
- Transfer speed over fast lines (USB console) is slow
- Code is not trivial to maintain (personnal opinion)
This implementation tries to address all these points by
introducing loady2 command.
The effects are :
- transfer speed for Y-Modem over USB jumps from 2kBytes/s
to 180kBytes/s
- transfer speed for Y-Modem/G jumps to 200kBytes/s
- multiple file transfers are possible
This command was tested on a USB console and UART 9600bps
serial line :
- NAKs (and retransmissions) were tested for faulty
serial lines
- multiple file transfers were tested
- Y-Modem, Y-Modem/G and X-Modem transfers were tested
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
Tested-by: Antony Pavlov <antonynpavlov@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'commands')
-rw-r--r-- | commands/Kconfig | 1 | ||||
-rw-r--r-- | commands/Makefile | 2 | ||||
-rw-r--r-- | commands/loadxy.c | 238 |
3 files changed, 240 insertions, 1 deletions
diff --git a/commands/Kconfig b/commands/Kconfig index 16706d36c3..ce04bb2835 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -261,6 +261,7 @@ config CMD_LOADB config CMD_LOADY select CRC16 + select XYMODEM tristate prompt "loady" diff --git a/commands/Makefile b/commands/Makefile index 610be55c6a..2be5f9cf99 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -3,7 +3,7 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o obj-$(CONFIG_CMD_UIMAGE) += uimage.o obj-$(CONFIG_CMD_LINUX16) += linux16.o obj-$(CONFIG_CMD_LOADB) += loadb.o xyzModem.o -obj-$(CONFIG_CMD_LOADY) += loadb.o xyzModem.o +obj-$(CONFIG_CMD_LOADY) += loadb.o xyzModem.o loadxy.o obj-$(CONFIG_CMD_LOADS) += loads.o obj-$(CONFIG_CMD_ECHO) += echo.o obj-$(CONFIG_CMD_MEMORY) += mem.o diff --git a/commands/loadxy.c b/commands/loadxy.c new file mode 100644 index 0000000000..141bd7bf9e --- /dev/null +++ b/commands/loadxy.c @@ -0,0 +1,238 @@ +/** + * @file + * @brief loady and loadx support. + * + * Provides loadx (over X-Modem) and loady(over Y-Modem) support to download + * images. + * + * FileName: commands/loadxy.c + */ +/* + * (C) Copyright 2012 Robert Jarzmik <robert.jarzmik@free.fr> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program 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 of + * the License, or (at your option) any later version. + * + * This program 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. + * + */ + +/* + * Serial up- and download support + */ +#include <common.h> +#include <command.h> +#include <console.h> +#include <xymodem.h> +#include <errno.h> +#include <getopt.h> +#include <fcntl.h> +#include <fs.h> +#include <malloc.h> + +#define DEF_FILE "image.bin" + +/** + * @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; +} + +static int console_change_speed(struct console_device *cdev, int baudrate) +{ + int current_baudrate; + + current_baudrate = + (int)simple_strtoul(dev_get_param(&cdev->class_dev, + "baudrate"), NULL, 10); + if (baudrate && baudrate != current_baudrate) { + printf("## Switch baudrate from %d to %d bps and press ENTER ...\n", + current_baudrate, baudrate); + mdelay(50); + cdev->setbrg(cdev, baudrate); + mdelay(50); + } + return current_baudrate; +} + +/** + * @brief provide the loady(Y-Modem or Y-Modem/G) support + * + * @param argc number of arguments + * @param argv arguments of loady command + * + * @return success or failure + */ +static int do_loady(int argc, char *argv[]) +{ + int is_ymodemg = 0, rc = 0, opt, rcode = 0; + int load_baudrate = 0, current_baudrate; + struct console_device *cdev = NULL; + + while ((opt = getopt(argc, argv, "b:g")) > 0) { + switch (opt) { + case 'b': + load_baudrate = (int)simple_strtoul(optarg, NULL, 10); + break; + case 'g': + is_ymodemg = 1; + break; + default: + perror(argv[0]); + return 1; + } + } + + cdev = get_current_console(); + if (NULL == cdev) { + printf("%s:No console device with STDIN and STDOUT\n", argv[0]); + return -ENODEV; + } + + current_baudrate = console_change_speed(cdev, load_baudrate); + printf("## Ready for binary (ymodem) download at %d bps...\n", + load_baudrate ? load_baudrate : current_baudrate); + + if (is_ymodemg) + rc = do_load_serial_ymodemg(cdev); + else + rc = do_load_serial_ymodem(cdev); + + if (rc < 0) { + printf("## Binary (ymodem) download aborted (%d)\n", rc); + rcode = 1; + } + + console_change_speed(cdev, current_baudrate); + + return rcode; +} + +/** + * @brief provide the loadx(X-Modem) support + * + * @param argc number of arguments + * @param argv arguments of loadx command + * + * @return success or failure + */ +static int do_loadx(int argc, char *argv[]) +{ + ulong offset = 0; + int load_baudrate = 0, current_baudrate, ofd, opt, rcode = 0; + int open_mode = O_WRONLY; + char *output_file = NULL; + struct console_device *cdev = NULL; + + while ((opt = getopt(argc, argv, "f:b:o:c")) > 0) { + switch (opt) { + case 'f': + output_file = optarg; + break; + case 'b': + load_baudrate = (int)simple_strtoul(optarg, NULL, 10); + break; + case 'o': + offset = (int)simple_strtoul(optarg, NULL, 10); + break; + case 'c': + open_mode |= O_CREAT; + break; + default: + perror(argv[0]); + return 1; + } + } + + cdev = get_current_console(); + if (NULL == cdev) { + printf("%s:No console device with STDIN and STDOUT\n", argv[0]); + return -ENODEV; + } + + /* Load Defaults */ + if (NULL == output_file) + output_file = DEF_FILE; + + /* File should exist */ + ofd = open(output_file, open_mode); + if (ofd < 0) { + perror(argv[0]); + return 3; + } + /* Seek to the right offset */ + if (offset) { + int seek = lseek(ofd, offset, SEEK_SET); + if (seek != offset) { + close(ofd); + ofd = 0; + perror(argv[0]); + return 4; + } + } + + current_baudrate = console_change_speed(cdev, load_baudrate); + printf("## Ready for binary (X-Modem) download " + "to 0x%08lX offset on %s device at %d bps...\n", offset, + output_file, load_baudrate); + rcode = do_load_serial_ymodem(cdev); + if (rcode < 0) { + printf("## Binary (kermit) download aborted (%d)\n", rcode); + rcode = 1; + } + console_change_speed(cdev, current_baudrate); + + return rcode; +} + +static const __maybe_unused char cmd_loadx_help[] = + "[OPTIONS]\n" + " -f file - where to download to - defaults to " DEF_FILE "\n" + " -o offset - what offset to download - defaults to 0\n" + " -b baud - baudrate at which to download - defaults to " + "console baudrate\n" + " -c - Create file if it is not present - default disabled"; + +#ifdef CONFIG_CMD_LOADB +BAREBOX_CMD_START(loadx) + .cmd = do_loadx, + .usage = "Load binary file over serial line (X-Modem)", +BAREBOX_CMD_HELP(cmd_loadx_help) +BAREBOX_CMD_END +#endif + +static const __maybe_unused char cmd_loady_help[] = + "[OPTIONS]\n" + " -y - use Y-Modem/G (only for lossless tty as USB)\n" + " -b baud - baudrate at which to download - defaults to " + "console baudrate\n"; + +#ifdef CONFIG_CMD_LOADY +BAREBOX_CMD_START(loady2) + .cmd = do_loady, + .usage = "Load binary file over serial line (Y-Modem or Y-Modem/G)", +BAREBOX_CMD_HELP(cmd_loady_help) +BAREBOX_CMD_END +#endif |