This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
RedBoot - improve load command
- From: Gary Thomas <gary at chez-thomas dot org>
- To: eCos patches <ecos-patches at sources dot redhat dot com>
- Date: 01 Jul 2002 14:56:00 -0600
- Subject: RedBoot - improve load command
Index: redboot/current/ChangeLog
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/ChangeLog,v
retrieving revision 1.57
diff -u -5 -p -r1.57 ChangeLog
--- redboot/current/ChangeLog 31 May 2002 17:10:26 -0000 1.57
+++ redboot/current/ChangeLog 1 Jul 2002 15:22:37 -0000
@@ -1,5 +1,18 @@
+2002-07-01 Gary Thomas <gary@chez-thomas.org>
+
+ * src/net/tftp_client.c:
+ * src/net/http_client.c:
+ * src/fs/disk.c:
+ * src/xyzModem.h:
+ * src/xyzModem.c:
+ * src/load.c:
+ * include/net/tftp_support.h:
+ * include/net/http.h:
+ * include/redboot.h:
+ * cdl/redboot.cdl: Make 'load' command stream I/O table driven.
+
2002-05-31 Jesper Skov <jskov@redhat.com>
* doc/redboot_installing.sgml: Updated the remaining installation
instructions (well, the top mode details anyway).
Index: redboot/current/cdl/redboot.cdl
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/cdl/redboot.cdl,v
retrieving revision 1.37
diff -u -5 -p -r1.37 redboot.cdl
--- redboot/current/cdl/redboot.cdl 23 May 2002 23:08:25 -0000 1.37
+++ redboot/current/cdl/redboot.cdl 1 Jul 2002 19:59:46 -0000
@@ -7,10 +7,11 @@
# ====================================================================
#####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.
##
@@ -149,12 +150,12 @@ cdl_package CYGPKG_REDBOOT {
The image may require further relocation or symbol
stripping before being converted to a binary image.
This is handled by a rule in the target CDL."
compile main.c crc.c
- compile misc_funs.c io.c parse.c ticks.c xyzModem.c syscall.c alias.c
- compile -library=libextras.a load.c
+ compile misc_funs.c io.c parse.c ticks.c syscall.c alias.c
+ compile -library=libextras.a load.c xyzModem.c
make -priority 320 {
<PREFIX>/bin/redboot.elf : $(PREFIX)/lib/target.ld $(PREFIX)/lib/vectors.o $(PREFIX)/lib/libtarget.a $(PREFIX)/lib/libextras.a
@sh -c "mkdir -p $(dir $@)"
$(CC) -c $(INCLUDE_PATH) $(CFLAGS) -o $(PREFIX)/lib/version.o $(REPOSITORY)/$(PACKAGE)/src/version.c
@@ -167,12 +168,12 @@ cdl_package CYGPKG_REDBOOT {
flavor bool
active_if CYGPKG_IO_ETH_DRIVERS
default_value 1
compile net/bootp.c net/udp.c net/ip.c net/pktbuf.c net/cksum.c
compile net/enet.c net/icmp.c net/tcp.c net/timers.c net/arp.c
- compile net/tftp_client.c net/net_io.c net/inet_addr.c
- compile -library=libextras.a net/ping.c
+ compile net/net_io.c net/inet_addr.c
+ compile -library=libextras.a net/ping.c net/tftp_client.c
description "This option includes networking support in RedBoot."
define_proc {
puts $::cdl_system_header "#define CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS 1"
}
@@ -186,11 +187,11 @@ cdl_package CYGPKG_REDBOOT {
cdl_option CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD {
display "Support HTTP for download"
flavor bool
default_value 1
- compile net/http_client.c
+ compile -library=libextras.a net/http_client.c
description "
This option enables the use of the HTTP protocol for download"
}
cdl_component CYGDAT_REDBOOT_DEFAULT_IP_ADDR {
Index: redboot/current/include/redboot.h
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/include/redboot.h,v
retrieving revision 1.23
diff -u -5 -p -r1.23 redboot.h
--- redboot/current/include/redboot.h 23 May 2002 23:08:27 -0000 1.23
+++ redboot/current/include/redboot.h 1 Jul 2002 19:59:59 -0000
@@ -7,10 +7,11 @@
//==========================================================================
//####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.
//
@@ -62,11 +63,10 @@
#include <cyg/infra/diag.h>
#include <string.h>
#ifdef CYGPKG_REDBOOT_NETWORKING
#include <net/net.h>
-#include <net/tftp_support.h>
#include <net/bootp.h>
// Determine an IP address for this node, using BOOTP
extern int __bootp_find_local_ip(bootp_header_t *info);
#endif
@@ -147,13 +147,49 @@ unsigned long crc32(unsigned char *buf,
#ifdef CYGSEM_REDBOOT_FLASH_ALIASES
externC char *flash_lookup_alias(char *alias, char *alias_buf);
#endif
externC void expand_aliases(char *line, int len);
-typedef int (*getc_t)(void);
-typedef void (*terminate_t)(int method, getc_t get_c);
+//
+// Stream I/O support
+//
+
+typedef struct {
+ char *filename;
+ struct load_io_entry *mode;
+ int chan;
+#ifdef CYGPKG_REDBOOT_NETWORKING
+ struct sockaddr_in *server;
+#endif
+} connection_info_t;
+
+typedef struct {
+ int (*open)(connection_info_t *info, int *err);
+ void (*close)(int *err);
+ void (*terminate)(bool abort, int (*getc)(void));
+ int (*read)(char *buf, int size, int *err);
+ char *(*error)(int err);
+} getc_io_funcs_t;
+
+#define GETC_IO_FUNCS(_label_, _open_, _close_, _terminate_, _read_, _error_) \
+getc_io_funcs_t _label_ = { \
+ _open_, _close_, _terminate_, _read_, _error_ \
+};
+struct load_io_entry {
+ char *mode;
+ getc_io_funcs_t *funcs;
+ bool can_verbose;
+ bool need_filename;
+} CYG_HAL_TABLE_TYPE;
+#define _RedBoot_load(_mode_,_funcs_,_verbose_,_filename_) \
+struct load_io_entry _load_tab_##_funcs_##_mode_ \
+ CYG_HAL_TABLE_QUALIFIED_ENTRY(RedBoot_load,_funcs_##_mode) = \
+ { #_mode_, &_funcs_, _verbose_, _filename_ };
+#define RedBoot_load(_mode_,_funcs_,_verbose_,_filename_) \
+ _RedBoot_load(_mode_,_funcs_,_verbose_,_filename_)
+
#ifdef CYGPKG_COMPRESS_ZLIB
// Decompression support
typedef struct _pipe {
unsigned char* in_buf; // only changed by producer
int in_avail; // only changed by producer
@@ -229,11 +265,11 @@ struct idle_tab_entry _idle_tab_##_p_##_
#define RedBoot_idle(_f_,_p_) _RedBoot_idle(_f_,_p_)
// This function called when changing idle/not - mostly used by I/O
// to support idle when timeout, etc.
void do_idle(bool state);
-
+
// Option processing support
struct option_info {
char flag;
bool takes_arg;
@@ -253,16 +289,10 @@ externC struct cmd *parse(char **line, i
externC void init_opts(struct option_info *opts, char flag, bool takes_arg,
int arg_type, void **arg, bool *arg_set, char *name);
externC bool scan_opts(int argc, char *argv[], int first,
struct option_info *opts, int num_opts,
void **def_arg, int def_arg_type, char *def_descr);
-
-externC int redboot_getc(void);
-externC void redboot_getc_init(int (*fun)(char *, int, int *),
- int verbose, int decompress);
-externC void redboot_getc_rewind(void);
-externC void redboot_getc_close(void);
#ifdef CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS
#define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \
(CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS+CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS)
#else
Index: redboot/current/include/net/http.h
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/include/net/http.h,v
retrieving revision 1.1
diff -u -5 -p -r1.1 http.h
--- redboot/current/include/net/http.h 23 May 2002 23:08:29 -0000 1.1
+++ redboot/current/include/net/http.h 1 Jul 2002 20:00:11 -0000
@@ -7,10 +7,11 @@
//==========================================================================
//####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.
//
@@ -53,16 +54,17 @@
//==========================================================================
#ifndef _HTTP_H_
#define _HTTP_H_
-extern int http_stream_open(char *file, struct sockaddr_in *server, int *err);
+extern int http_stream_open(connection_info_t *info, int *err);
extern int http_stream_read(char *buf, int len, int *err);
-extern int http_stream_close(int *err);
+extern void http_stream_close(int *err);
extern char *http_error(int err);
#define HTTP_NOERR 0 // No error
#define HTTP_BADHDR 1 // Invalid HTTP header (response)
#define HTTP_OPEN 2 // Problems opening connection
#define HTTP_IO 3 // Misc I/O problems
+extern getc_io_funcs_t http_io;
#endif // _HTTP_H_
Index: redboot/current/include/net/tftp_support.h
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/include/net/tftp_support.h,v
retrieving revision 1.5
diff -u -5 -p -r1.5 tftp_support.h
--- redboot/current/include/net/tftp_support.h 23 May 2002 23:08:29 -0000 1.5
+++ redboot/current/include/net/tftp_support.h 1 Jul 2002 20:00:25 -0000
@@ -7,10 +7,11 @@
//==========================================================================
//####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.
//
@@ -81,19 +82,19 @@
/*
* Client support
*/
-extern int tftp_get(char *, struct sockaddr_in *, char *, int, int, int *);
-extern char *tftp_error(int err);
-
-extern int tftp_stream_open(char *file, struct sockaddr_in *server, int mode, int *err);
+extern int tftp_stream_open(connection_info_t *info, int *err);
extern int tftp_stream_read(char *buf, int len, int *err);
-extern int tftp_stream_close(int *err);
+extern void tftp_stream_close(int *err);
+extern char *tftp_error(int err);
#define TFTP_TIMEOUT_PERIOD 5
#define TFTP_TIMEOUT_MAX 15
#define TFTP_RETRIES_MAX 5
#define TFTP_PORT 69
+
+extern getc_io_funcs_t tftp_io;
#endif // _TFTP_SUPPORT_H_
Index: redboot/current/src/load.c
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/src/load.c,v
retrieving revision 1.24
diff -u -5 -p -r1.24 load.c
--- redboot/current/src/load.c 29 May 2002 18:28:34 -0000 1.24
+++ redboot/current/src/load.c 1 Jul 2002 20:00:38 -0000
@@ -7,10 +7,11 @@
//==========================================================================
//####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.
//
@@ -56,17 +57,47 @@
#include <xyzModem.h>
#include <elf.h>
#ifdef CYGPKG_REDBOOT_DISK
#include <fs/disk.h>
#endif
+#ifdef CYGPKG_REDBOOT_NETWORKING
+#include <net/tftp_support.h>
#ifdef CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD
#include <net/http.h>
#endif
+#endif
+
+static char usage[] = "[-r] [-v] "
+#ifdef CYGPKG_COMPRESS_ZLIB
+ "[-d] "
+#endif
+ "[-h <host>] [-m <varies>] "
+#if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1
+ "[-c <channel_number>] "
+#endif
+ "\n [-b <base_address>] <file_name>";
+
+// Exported CLI function
+RedBoot_cmd("load",
+ "Load a file",
+ usage,
+ do_load
+ );
+
+//
+// Stream I/O support
+//
+
+// Table describing the various I/O methods
+CYG_HAL_TABLE_BEGIN( __RedBoot_LOAD_TAB__, RedBoot_load );
+CYG_HAL_TABLE_END( __RedBoot_LOAD_TAB_END__, RedBoot_load );
+extern struct load_io_entry __RedBoot_LOAD_TAB__[], __RedBoot_LOAD_TAB_END__;
// Buffers, data used by redboot_getc
#define BUF_SIZE 256
struct {
+ getc_io_funcs_t *io;
int (*fun)(char *, int len, int *err);
unsigned char buf[BUF_SIZE];
unsigned char *bufp;
int avail, len, err;
int verbose, decompress, tick;
@@ -75,39 +106,156 @@ struct {
_pipe_t load_pipe;
unsigned char _buffer[CYGNUM_REDBOOT_LOAD_ZLIB_BUFFER];
#endif
} getc_info;
-static char usage[] = "[-r] [-v] "
+typedef int (*getc_t)(void);
+
+//
+// Read the next data byte from the stream.
+// Returns:
+// >= 0 - actual data
+// -1 - error or EOF, status in getc_info.err
+//
+static int
+redboot_getc(void)
+{
+ static char spin[] = "|/-\\|-";
+ if (getc_info.avail < 0) {
+ return -1;
+ }
+ if (getc_info.avail == 0) {
+ if (getc_info.verbose) {
+ diag_printf("%c\b", spin[getc_info.tick++]);
+ if (getc_info.tick >= sizeof(spin)) {
+ getc_info.tick = 0;
+ }
+ }
+ if (getc_info.len < BUF_SIZE) {
+ // No more data available
+ if (getc_info.verbose) diag_printf("\n");
+ return -1;
+ }
+ getc_info.bufp = getc_info.buf;
+ getc_info.len = (*getc_info.fun)(getc_info.bufp, BUF_SIZE, &getc_info.err);
+ if ((getc_info.avail = getc_info.len) <= 0) {
+ if (getc_info.verbose) diag_printf("\n");
+ return -1;
+ }
+ }
+ getc_info.avail--;
+ return *getc_info.bufp++;
+}
+
#ifdef CYGPKG_COMPRESS_ZLIB
- "[-d] "
-#endif
- "[-h <host>] [-m {TFTP "
-#ifdef CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD
- "| HTTP"
-#endif
-#ifdef xyzModem_zmodem
- "| {x|y|z}MODEM"
-#else
- "| {x|y}MODEM"
-#endif
-#ifdef CYGPKG_REDBOOT_DISK
- " | disk"
+//
+// Called to fetch a new chunk of data and decompress it
+//
+static int
+_decompress_stream(char *buf, int len, int *err)
+{
+ _pipe_t* p = &getc_info.load_pipe;
+ int res, total;
+
+ total = 0;
+ while (len > 0) {
+ if (p->in_avail == 0) {
+ p->in_buf = &getc_info._buffer[0];
+ res = (*getc_info.raw_fun)(p->in_buf, CYGNUM_REDBOOT_LOAD_ZLIB_BUFFER,
+ &getc_info.err);
+ if ((p->in_avail = res) <= 0) {
+ // No more data
+ return total;
+ }
+ }
+ p->out_buf = buf;
+ p->out_size = 0;
+ p->out_max = len;
+ res = (*_dc_inflate)(p);
+ if (res != 0) {
+ *err = res;
+ return total;
+ }
+ len -= p->out_size;
+ buf += p->out_size;
+ total += p->out_size;
+ }
+ return total;
+}
#endif
-#if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1
- " -c <channel_number>"
+
+static int
+redboot_getc_init(connection_info_t *info, getc_io_funcs_t *funcs,
+ int verbose, int decompress)
+{
+ int res;
+
+ res = (funcs->open)(info, &getc_info.err);
+ if (res < 0) {
+ diag_printf("Can't load '%s': %s\n", info->filename, (funcs->error)(getc_info.err));
+ return res;
+ }
+ getc_info.io = funcs;
+ getc_info.fun = funcs->read;
+ getc_info.avail = 0;
+ getc_info.len = BUF_SIZE;
+ getc_info.verbose = verbose;
+ getc_info.decompress = decompress;
+ getc_info.tick = 0;
+#ifdef CYGPKG_COMPRESS_ZLIB
+ if (decompress) {
+ _pipe_t* p = &getc_info.load_pipe;
+ p->out_buf = &getc_info.buf[0];
+ p->out_size = 0;
+ p->in_avail = 0;
+ getc_info.raw_fun = getc_info.fun;
+ getc_info.fun = _decompress_stream;
+ getc_info.err = (*_dc_init)(p);
+ if (0 != getc_info.err && p->msg) {
+ diag_printf("open decompression error: %s\n", p->msg);
+ }
+ }
#endif
- "}]\n [-b <base_address>] <file_name>";
+ return 0;
+}
-// Exported CLI function
-RedBoot_cmd("load",
- "Load a file",
- usage,
- do_load
- );
+static void
+redboot_getc_rewind(void)
+{
+ getc_info.bufp = getc_info.buf;
+ getc_info.avail = getc_info.len;
+}
+
+static void
+redboot_getc_terminate(bool abort)
+{
+ if (getc_info.io->terminate) {
+ (getc_info.io->terminate)(abort, redboot_getc);
+ }
+}
+
+static void
+redboot_getc_close(void)
+{
+ (getc_info.io->close)(&getc_info.err);
+#ifdef CYGPKG_COMPRESS_ZLIB
+ if (getc_info.decompress) {
+ _pipe_t* p = &getc_info.load_pipe;
+ int err = getc_info.err;
+ if (0 != err && p->msg) {
+ diag_printf("decompression error: %s\n", p->msg);
+ }
+ err = (*_dc_close)(p, getc_info.err);
+ }
+#endif
+}
#ifdef CYGSEM_REDBOOT_ELF
+//
+// Support function - used to read bytes into a buffer
+// Returns the number of bytes read (stops short on errors)
+//
static int
_read(int (*getc)(void), unsigned char *buf, int len)
{
int total = 0;
int ch;
@@ -122,12 +270,15 @@ _read(int (*getc)(void), unsigned char *
}
return total;
}
#endif
+//
+// Load an ELF [binary] image
+//
static unsigned long
-load_elf_image(getc_t getc, terminate_t terminate, unsigned long base)
+load_elf_image(getc_t getc, unsigned long base)
{
#ifdef CYGSEM_REDBOOT_ELF
Elf32_Ehdr ehdr;
#define MAX_PHDR 8
Elf32_Phdr phdr[MAX_PHDR];
@@ -216,20 +367,13 @@ load_elf_image(getc_t getc, terminate_t
}
// Copy data into memory
while (len-- > 0) {
#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
if ((addr < user_ram_start) || (addr > user_ram_end)) {
- // Only if there is no need to stop the download before printing
- // output can we ask confirmation questions.
- if (terminate) {
- (*terminate)(xyzModem_abort, getc);
- diag_printf("*** Warning! Attempt to load ELF data to address: %p\nRedBoot does not believe this is in RAM\nUse TFTP for a chance to override this.\n",(void*)addr);
- } else {
- if (!verify_action("Attempt to load ELF data to address: %p\n"
- "RedBoot does not believe this is in RAM", (void*)addr))
- return 0;
- }
+ redboot_getc_terminate(true);
+ diag_printf("*** Abort! Attempt to load ELF data to address: %p which is not in RAM\n", (void*)addr);
+ return 0;
}
#endif
if ((ch = (*getc)()) < 0) {
diag_printf(SHORT_DATA);
return 0;
@@ -292,13 +436,12 @@ _hex2(int (*getc)(void), int len, long *
// the first section of the data, so if there are non-contiguous
// pieces of data, they will end up relocated in the same fashion.
// Because of this, "base" probably only makes sense for a set of
// data which has only one section, e.g. a ROM image.
//
-#define MAX_LINE 80
static unsigned long
-load_srec_image(getc_t getc, terminate_t terminate, unsigned long base)
+load_srec_image(getc_t getc, unsigned long base)
{
int c;
long offset = 0, count, sum, val, cksum;
unsigned char *addr, *base_addr;
char type;
@@ -308,20 +451,20 @@ load_srec_image(getc_t getc, terminate_t
unsigned long lowest_address = 0xFFFFFFFF;
while ((c = (*getc)()) > 0) {
// Start of line
if (c != 'S') {
- if (terminate) (*terminate)(xyzModem_abort, getc);
+ redboot_getc_terminate(true);
diag_printf("Invalid S-record at offset %p, input: %c\n",
(void *)offset, c);
return 0;
}
type = (*getc)();
offset += 2;
sum = 0;
if ((count = _hex2(getc, 1, &sum)) < 0) {
- if (terminate) (*terminate)(xyzModem_abort, getc);
+ redboot_getc_terminate(true);
diag_printf("Bad S-record count at offset %p\n", (void *)offset);
return 0;
}
offset += 1;
switch (type) {
@@ -346,18 +489,13 @@ load_srec_image(getc_t getc, terminate_t
}
#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
if ((addr < user_ram_start) || (addr > user_ram_end)) {
// Only if there is no need to stop the download before printing
// output can we ask confirmation questions.
- if (terminate) {
- (*terminate)(xyzModem_abort, getc);
- diag_printf("*** Warning! Attempt to load S-record to address: %p\nRedBoot does not believe this is in RAM\nUse TFTP for a chance to override this.\n",(void*)addr);
- } else {
- if (!verify_action("Attempt to load S-record data to address: %p\n"
- "RedBoot does not believe this is in RAM", (void*)addr))
- return 0;
- }
+ redboot_getc_terminate(true);
+ diag_printf("*** Abort! Attempt to load S-record to address: %p, which is not in RAM\n",(void*)addr);
+ return 0;
}
#endif
count -= ((type-'1'+2)+1);
offset += count;
while (count-- > 0) {
@@ -367,11 +505,11 @@ load_srec_image(getc_t getc, terminate_t
cksum = _hex2(getc, 1, 0);
offset += 1;
sum = sum & 0xFF;
cksum = (~cksum & 0xFF);
if (cksum != sum) {
- if (terminate) (*terminate)(xyzModem_abort, getc);
+ redboot_getc_terminate(true);
diag_printf("*** Warning! Checksum failure - Addr: %lx, %02lX <> %02lX\n",
(unsigned long)base_addr, sum, cksum);
return 0;
}
if ((unsigned long)(addr-addr_offset) > highest_address) {
@@ -383,164 +521,45 @@ load_srec_image(getc_t getc, terminate_t
case '9':
addr = (unsigned char *)_hex2(getc, ('9'-type+2), &sum);
offset += ('9'-type+2);
// Save entry address
entry_address = (unsigned long)addr;
- if (terminate) (*terminate)(xyzModem_close, getc);
+ redboot_getc_terminate(false);
if (addr_offset) diag_printf("Address offset = %p\n", (void *)addr_offset);
diag_printf("Entry point: %p, address range: %p-%p\n",
(void*)entry_address, (void *)lowest_address, (void *)highest_address);
// Save load base/top
load_address = lowest_address;
load_address_end = highest_address;
return highest_address;
default:
- if (terminate) (*terminate)(xyzModem_abort, getc);
+ redboot_getc_terminate(true);
diag_printf("Invalid S-record at offset 0x%lx, type: %x\n",
(unsigned long)offset, type);
return 0;
}
while ((c = (*getc)()) != '\n') offset++;
}
return 0;
}
//
-// Stream I/O support
-//
-int
-redboot_getc(void)
-{
- static char spin[] = "|/-\\|-";
- if (getc_info.avail < 0) {
- return -1;
- }
- if (getc_info.avail == 0) {
- if (getc_info.verbose) {
- diag_printf("%c\b", spin[getc_info.tick++]);
- if (getc_info.tick >= sizeof(spin)) {
- getc_info.tick = 0;
- }
- }
- if (getc_info.len < BUF_SIZE) {
- // No more data available
- if (getc_info.verbose) diag_printf("\n");
- return -1;
- }
- getc_info.bufp = getc_info.buf;
- getc_info.len = (*getc_info.fun)(getc_info.bufp, BUF_SIZE, &getc_info.err);
- if ((getc_info.avail = getc_info.len) <= 0) {
- if (getc_info.verbose) diag_printf("\n");
- return -1;
- }
- }
- getc_info.avail--;
- return *getc_info.bufp++;
-}
-
+// 'load' CLI command processing
+// -b - specify a load [base] address
+// -m - specify an I/O stream/method
+// -c - Alternate serial I/O channel
#ifdef CYGPKG_COMPRESS_ZLIB
-// Called to fetch a new chunk of data and decompress it
-int
-_decompress_stream(char *buf, int len, int *err)
-{
- _pipe_t* p = &getc_info.load_pipe;
- int res, total;
-
- total = 0;
- while (len > 0) {
- if (p->in_avail == 0) {
- p->in_buf = &getc_info._buffer[0];
- res = (*getc_info.raw_fun)(p->in_buf, CYGNUM_REDBOOT_LOAD_ZLIB_BUFFER,
- &getc_info.err);
- if ((p->in_avail = res) <= 0) {
- // No more data
- return total;
- }
- }
- p->out_buf = buf;
- p->out_size = 0;
- p->out_max = len;
- res = (*_dc_inflate)(p);
- if (res != 0) {
- *err = res;
- return total;
- }
- len -= p->out_size;
- buf += p->out_size;
- total += p->out_size;
- }
- return total;
-}
-#endif
-
-void
-redboot_getc_init(int (*fun)(char *, int, int *),
- int verbose, int decompress)
-{
- getc_info.avail = 0;
- getc_info.len = BUF_SIZE;
- getc_info.fun = fun;
- getc_info.verbose = verbose;
- getc_info.decompress = decompress;
- getc_info.tick = 0;
-#ifdef CYGPKG_COMPRESS_ZLIB
- if (decompress) {
- _pipe_t* p = &getc_info.load_pipe;
- int err;
- p->out_buf = &getc_info.buf[0];
- p->out_size = 0;
- p->in_avail = 0;
- getc_info.fun = _decompress_stream;
- getc_info.raw_fun = fun;
- err = (*_dc_init)(p);
- if (0 != err && p->msg) {
- diag_printf("open decompression error: %s\n", p->msg);
- }
- }
+// -d - Decompress data [packed via 'zlib']
#endif
-}
-
-void
-redboot_getc_rewind(void)
-{
- getc_info.bufp = getc_info.buf;
- getc_info.avail = getc_info.len;
-}
-
-void
-redboot_getc_close(void)
-{
-#ifdef CYGPKG_COMPRESS_ZLIB
- if (getc_info.decompress) {
- _pipe_t* p = &getc_info.load_pipe;
- int err = getc_info.err;
- if (0 != err && p->msg) {
- diag_printf("decompression error: %s\n", p->msg);
- }
- err = (*_dc_close)(p, getc_info.err);
- }
-#endif
-}
-
-#define MODE_TFTP 0
-#define MODE_XMODEM xyzModem_xmodem // 1
-#define MODE_YMODEM xyzModem_ymodem // 2
-#ifdef xyzModem_zmodem
-#define MODE_ZMODEM xyzModem_zmodem // 3
-#endif
-#define MODE_DISK 4
-#ifdef CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD
-#define MODE_HTTP 5
-#endif
-
+//
void
do_load(int argc, char *argv[])
{
int res, num_options;
- int i, err, mode;
+ int i, err;
bool verbose, raw;
bool base_addr_set, mode_str_set;
char *mode_str;
#ifdef CYGPKG_REDBOOT_NETWORKING
struct sockaddr_in host;
@@ -555,24 +574,21 @@ do_load(int argc, char *argv[])
unsigned long base = 0;
unsigned long end = 0;
char type[4];
char *filename = 0;
struct option_info opts[7];
- terminate_t terminate = NULL;
+ connection_info_t info;
+ getc_io_funcs_t *io;
+ struct load_io_entry *io_tab;
#ifdef CYGPKG_REDBOOT_NETWORKING
memset((char *)&host, 0, sizeof(host));
host.sin_len = sizeof(host);
host.sin_family = AF_INET;
host.sin_addr = my_bootp_info.bp_siaddr;
host.sin_port = 0;
#endif
-#ifdef CYGPKG_REDBOOT_NETWORKING
- mode = MODE_TFTP;
-#else
- mode = MODE_YMODEM;
-#endif
init_opts(&opts[0], 'v', false, OPTION_ARG_TYPE_FLG,
(void **)&verbose, 0, "verbose");
init_opts(&opts[1], 'r', false, OPTION_ARG_TYPE_FLG,
(void **)&raw, 0, "load raw data");
@@ -614,81 +630,49 @@ do_load(int argc, char *argv[])
hostname, inet_ntoa((in_addr_t *)&host));
return;
}
}
#endif
+ if (chan >= CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS) {
+ diag_printf("Invalid I/O channel: %d\n", chan);
+ return;
+ }
if (mode_str_set) {
- if (strncasecmp(&mode_str[1], "modem", strlen(&mode_str[1])) == 0) {
- switch (_tolower(mode_str[0])) {
- case 'x':
- mode = MODE_XMODEM;
- break;
- case 'y':
- mode = MODE_YMODEM;
+ io = (getc_io_funcs_t *)NULL;
+ for (io_tab = __RedBoot_LOAD_TAB__;
+ io_tab != &__RedBoot_LOAD_TAB_END__; io_tab++) {
+ if (strncasecmp(&mode_str[0], io_tab->mode, strlen(&mode_str[0])) == 0) {
+ io = io_tab->funcs;
break;
-#ifdef xyzModem_zmodem
- case 'z':
- mode = MODE_ZMODEM;
- break;
-#endif
- default:
- diag_printf("Invalid 'mode': %s\n", mode_str);
- return;
- }
- // When using a serial download type, override verbose
- // setting: spinner interferes with the protocol.
- verbose = false;
-#ifdef CYGPKG_REDBOOT_DISK
- } else if (strcasecmp(mode_str, "disk") == 0) {
- mode = MODE_DISK;
-#endif
-#ifdef CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD
- } else if (strcasecmp(mode_str, "http") == 0) {
- mode = MODE_HTTP;
-#endif
-#ifdef CYGPKG_REDBOOT_NETWORKING
- } else if (strcasecmp(mode_str, "tftp") == 0) {
- mode = MODE_TFTP;
- if (!have_net) {
- diag_printf("TFTP mode requires a working network\n");
- return;
}
-#endif
- } else {
- diag_printf("Invalid 'mode': %s\n", mode_str);
- return;
}
- }
-#if defined(CYGPKG_REDBOOT_NETWORKING) || defined(CYGPKG_REDBOOT_DISK)
- if ((mode == MODE_TFTP || mode == MODE_DISK) && !filename) {
- diag_printf("File name missing\n");
- diag_printf("usage: load %s\n", usage);
- return;
- }
-#endif
-#if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1
- if (chan_set) {
- if ((mode != MODE_XMODEM) &&
-#ifdef MODE_ZMODEM
- (mode != MODE_ZMODEM) &&
-#endif
- (mode != MODE_YMODEM)) {
-#ifdef xyzModem_zmodem
- diag_printf("I/O channel can only be used with {xyz}Modem\n");
-#else
- diag_printf("I/O channel can only be used with {xy}Modem\n");
-#endif
+ if (!io) {
+ diag_printf("Invalid 'mode': %s. Valid modes are:", mode_str);
+ for (io_tab = __RedBoot_LOAD_TAB__;
+ io_tab != &__RedBoot_LOAD_TAB_END__; io_tab++) {
+ diag_printf(" %s", io_tab->mode);
+ }
+ diag_printf("\n");
+ }
+ if (!io) {
return;
}
- if (chan >= CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS) {
- diag_printf("Invalid I/O channel: %d\n", chan);
+ verbose &= io_tab->can_verbose;
+ if (io_tab->need_filename && !filename) {
+ diag_printf("File name required\n");
+ diag_printf("usage: load %s\n", usage);
return;
}
} else {
- chan = -1;
- }
+ io_tab = (struct load_io_entry *)NULL; // Default
+#ifdef CYGPKG_REDBOOT_NETWORKING
+ io = &tftp_io;
+#else
+ io = &xyzModem_io;
+ verbose = false;
#endif
+ }
#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
if (base_addr_set &&
((base < (unsigned long)user_ram_start) ||
(base > (unsigned long)user_ram_end))) {
if (!verify_action("Specified address (%p) is not believed to be in RAM", (void*)base))
@@ -697,78 +681,35 @@ do_load(int argc, char *argv[])
#endif
if (raw && !base_addr_set) {
diag_printf("Raw load requires a memory address\n");
return;
}
+ info.filename = filename;
+ info.chan = chan;
+ info.mode = io_tab;
#ifdef CYGPKG_REDBOOT_NETWORKING
- if (mode == MODE_TFTP) {
- res = tftp_stream_open(filename, &host, TFTP_OCTET, &err);
- if (res < 0) {
- diag_printf("Can't load '%s': %s\n", filename, tftp_error(err));
- return;
- }
- redboot_getc_init(tftp_stream_read, verbose, decompress);
- }
-#endif
-#ifdef CYGPKG_REDBOOT_DISK
- else if (mode == MODE_DISK) {
- res = disk_stream_open(filename, &err);
- if (res < 0) {
-
- diag_printf("Can't load '%s': %s\n", filename, disk_error(err));
- return;
- }
- redboot_getc_init(disk_stream_read, verbose, decompress);
- }
+ info.server = &host;
#endif
-#ifdef CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD
- else if (mode == MODE_HTTP) {
- res = http_stream_open(filename, &host, &err);
- if (res < 0) {
-
- diag_printf("Can't load '%s': %s\n", filename, http_error(err));
- return;
- }
- redboot_getc_init(http_stream_read, verbose, decompress);
- }
-#endif
- else {
- res = xyzModem_stream_open(filename, mode, chan, &err);
- if (res < 0) {
- diag_printf("Can't load '%s': %s\n", filename, xyzModem_error(err));
- return;
- }
- // Suppress verbosity when using xyz modem download
- redboot_getc_init(xyzModem_stream_read, 0 && verbose, decompress);
-
- terminate = xyzModem_stream_terminate;
+ res = redboot_getc_init(&info, io, verbose, decompress);
+ if (res < 0) {
+ return;
}
+ // Stream open, process the data
if (raw) {
- bool continue_load = false;
unsigned char *mp = (unsigned char *)base;
err = 0;
while ((res = redboot_getc()) >= 0) {
#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
- if (!continue_load && mp >= user_ram_end) {
+ if (mp >= user_ram_end) {
// Only if there is no need to stop the download
// before printing output can we ask confirmation
// questions.
- if (terminate) {
- (*terminate)(xyzModem_abort, redboot_getc);
- diag_printf("*** Warning! RAW data spills over limit of user RAM at %p\nRedBoot does not believe this is in RAM\nUse TFTP for a chance to override this.\n",(void*)mp);
- err = -1;
- break;
- } else {
- if (!verify_action("RAW data spills over limit of user RAM at %p\n"
- "Continuing may cause a hang or crash", (void*)mp)) {
- err = -1;
- break;
- }
- // Don't ask again
- continue_load = true;
- }
+ redboot_getc_terminate(true);
+ diag_printf("*** Abort! RAW data spills over limit of user RAM at %p\n",(void*)mp);
+ err = -1;
+ break;
}
#endif
*mp++ = res;
}
end = (unsigned long) mp;
@@ -776,10 +717,11 @@ do_load(int argc, char *argv[])
// Save load base/top
load_address = base;
load_address_end = end;
entry_address = base; // best guess
+ redboot_getc_terminate(false);
if (0 == err)
diag_printf("Raw file loaded %p-%p, assumed entry at %p\n",
(void *)base, (void *)end, (void*)base);
} else {
// Read initial header - to determine file [image] type
@@ -792,38 +734,18 @@ do_load(int argc, char *argv[])
}
if (res >= 0) {
redboot_getc_rewind(); // Restore header to stream
// Treat data as some sort of executable image
if (strncmp(&type[1], "ELF", 3) == 0) {
- end = load_elf_image(redboot_getc, terminate, base);
+ end = load_elf_image(redboot_getc, base);
} else if ((type[0] == 'S') &&
((type[1] >= '0') && (type[1] <= '9'))) {
- end = load_srec_image(redboot_getc, terminate, base);
+ end = load_srec_image(redboot_getc, base);
} else {
diag_printf("Unrecognized image type: 0x%lx\n", *(unsigned long *)type);
}
}
}
- switch (mode) {
-#ifdef CYGPKG_REDBOOT_DISK
- case MODE_DISK:
- disk_stream_close(&err);
- break;
-#endif
-#ifdef CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD
- case MODE_HTTP:
- http_stream_close(&err);
- break;
-#endif
-#ifdef CYGPKG_REDBOOT_NETWORKING
- case MODE_TFTP:
- tftp_stream_close(&err);
- break;
-#endif
- default:
- xyzModem_stream_close(&err);
- break;
- }
redboot_getc_close(); // Clean up
return;
}
Index: redboot/current/src/xyzModem.c
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/src/xyzModem.c,v
retrieving revision 1.14
diff -u -5 -p -r1.14 xyzModem.c
--- redboot/current/src/xyzModem.c 23 May 2002 23:08:32 -0000 1.14
+++ redboot/current/src/xyzModem.c 1 Jul 2002 20:01:05 -0000
@@ -7,10 +7,11 @@
//==========================================================================
//####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.
//
@@ -314,39 +315,39 @@ xyzModem_get_hdr(void)
// If we get here, the message passes [structural] muster
return 0;
}
int
-xyzModem_stream_open(char *filename, int mode, int chan, int *err)
+xyzModem_stream_open(connection_info_t *info, int *err)
{
int console_chan, stat;
int retries = xyzModem_MAX_RETRIES;
int crc_retries = xyzModem_MAX_RETRIES_WITH_CRC;
// ZM_DEBUG(zm_out = zm_out_start);
#ifdef xyzModem_zmodem
- if (mode == xyzModem_zmodem) {
+ if (info->mode == xyzModem_zmodem) {
*err = xyzModem_noZmodem;
return -1;
}
#endif
// 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 (chan >= 0) {
- CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);
+ 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);
xyz.len = 0;
xyz.crc_mode = true;
xyz.at_eof = false;
xyz.tx_ack = false;
- xyz.mode = mode;
+ xyz.mode = info->mode;
xyz.total_retries = 0;
xyz.total_SOH = 0;
xyz.total_STX = 0;
xyz.total_CAN = 0;
#ifdef USE_YMODEM_LENGTH
@@ -496,16 +497,15 @@ xyzModem_stream_close(int *err)
// ZM_DEBUG(zm_flush());
}
// Need to be able to clean out the input buffer, so have to take the
// getc
-void xyzModem_stream_terminate(int method, int (*getc)(void))
+void xyzModem_stream_terminate(bool abort, int (*getc)(void))
{
int c;
- switch (method) {
- case xyzModem_abort:
+ 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
@@ -527,11 +527,11 @@ void xyzModem_stream_terminate(int metho
case xyzModem_zmodem:
// Might support it some day I suppose.
#endif
break;
}
- default:
+ } 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.
@@ -540,11 +540,10 @@ void xyzModem_stream_terminate(int metho
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);
- break;
}
}
char *
xyzModem_error(int err)
@@ -577,5 +576,13 @@ xyzModem_error(int err)
default:
return "Unknown error";
break;
}
}
+
+//
+// RedBoot interface
+//
+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);
+RedBoot_load(ymodem, xyzModem_io, false, false);
Index: redboot/current/src/xyzModem.h
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/src/xyzModem.h,v
retrieving revision 1.6
diff -u -5 -p -r1.6 xyzModem.h
--- redboot/current/src/xyzModem.h 23 May 2002 23:08:33 -0000 1.6
+++ redboot/current/src/xyzModem.h 1 Jul 2002 20:01:15 -0000
@@ -7,10 +7,11 @@
//==========================================================================
//####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.
//
@@ -70,12 +71,14 @@
#define xyzModem_sequence -8
#define xyzModem_close 1
#define xyzModem_abort 2
-int xyzModem_stream_open(char *filename, int mode, int chan, int *err);
+int xyzModem_stream_open(connection_info_t *info, int *err);
void xyzModem_stream_close(int *err);
void xyzModem_stream_terminate(int method, int (*getc)(void));
int xyzModem_stream_read(char *buf, int size, int *err);
char *xyzModem_error(int err);
+
+extern getc_io_funcs_t xyzModem_io;
#endif // _XYZMODEM_H_
Index: redboot/current/src/fs/disk.c
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/src/fs/disk.c,v
retrieving revision 1.8
diff -u -5 -p -r1.8 disk.c
--- redboot/current/src/fs/disk.c 23 May 2002 23:08:33 -0000 1.8
+++ redboot/current/src/fs/disk.c 1 Jul 2002 20:01:31 -0000
@@ -7,10 +7,11 @@
//==========================================================================
//####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.
//
@@ -354,13 +355,14 @@ do_disks(int argc, char *argv[])
static void *fileptr;
static partition_t *file_part;
externC int
-disk_stream_open(char *filename, int *err)
+disk_stream_open(connection_info_t *info, int *err)
{
const char *filepath;
+ char *filename = info->filename;
// The filename is in <disk>:<path> format.
// Convert to a partition and path.
if (!disk_parse_filename(filename, &file_part, &filepath)) {
*err = diskerr_badname;
@@ -423,5 +425,11 @@ disk_error(int err)
return "Unknown error";
break;
}
}
+//
+// RedBoot interface
+//
+GETC_IO_FUNCS(disk_io, disk_stream_open, disk_stream_close,
+ 0, disk_stream_read, disk_error);
+RedBoot_load(disk, disk_io, true, true);
Index: redboot/current/src/net/http_client.c
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/src/net/http_client.c,v
retrieving revision 1.1
diff -u -5 -p -r1.1 http_client.c
--- redboot/current/src/net/http_client.c 23 May 2002 23:08:35 -0000 1.1
+++ redboot/current/src/net/http_client.c 1 Jul 2002 20:01:39 -0000
@@ -7,10 +7,11 @@
//==========================================================================
//####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.
//
@@ -77,40 +78,37 @@ min(int a, int b)
else
return b;
}
int
-http_stream_open(char *filename,
- struct sockaddr_in *server,
- int *err)
+http_stream_open(connection_info_t *info, int *err)
{
int res;
struct _stream *s = &http_stream;
- server->sin_port = 80; // HTTP port
- if ((res = __tcp_open(&s->sock, server, get_port++, 5000, err)) < 0) {
+ info->server->sin_port = 80; // HTTP port
+ if ((res = __tcp_open(&s->sock, info->server, get_port++, 5000, err)) < 0) {
*err = HTTP_OPEN;
return -1;
}
- diag_sprintf(s->data, "GET %s HTTP 1.0\r\n\r\n", filename);
+ diag_sprintf(s->data, "GET %s HTTP 1.0\r\n\r\n", info->filename);
__tcp_write_block(&s->sock, s->data, strlen(s->data));
s->avail = 0;
s->open = true;
s->pos = 0;
return 0;
}
-int
+void
http_stream_close(int *err)
{
struct _stream *s = &http_stream;
if (s->open) {
__tcp_close(&s->sock);
s->open = false;
}
- return 0;
}
int
http_stream_read(char *buf,
int len,
@@ -232,5 +230,12 @@ http_error(int err)
case HTTP_IO:
return "I/O error";
}
return errmsg;
}
+
+//
+// RedBoot interface
+//
+GETC_IO_FUNCS(http_io, http_stream_open, http_stream_close,
+ 0, http_stream_read, http_error);
+RedBoot_load(http, http_io, true, true);
Index: redboot/current/src/net/tftp_client.c
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/src/net/tftp_client.c,v
retrieving revision 1.9
diff -u -5 -p -r1.9 tftp_client.c
--- redboot/current/src/net/tftp_client.c 23 May 2002 23:08:36 -0000 1.9
+++ redboot/current/src/net/tftp_client.c 1 Jul 2002 20:01:47 -0000
@@ -7,10 +7,11 @@
//==========================================================================
//####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.
//
@@ -60,136 +61,10 @@
#include <net/tftp_support.h>
// So we remember which ports have been used
static int get_port = 7700;
-#if 0 // No longer used
-//
-// Read a file from a host into a local buffer. Returns the
-// number of bytes actually read, or (-1) if an error occurs.
-// On error, *err will hold the reason.
-//
-int
-tftp_get(char *filename,
- struct sockaddr_in *server,
- char *buf,
- int len,
- int mode,
- int *err)
-{
- int res = 0;
- int actual_len, data_len, recv_len;
- struct sockaddr_in local_addr, from_addr;
- char data[SEGSIZE+sizeof(struct tftphdr)];
- struct tftphdr *hdr = (struct tftphdr *)data;
- char *cp, *fp;
- struct timeval timeout;
- int last_good_block = 0;
- int total_timeouts = 0;
-
- *err = 0; // Just in case
-
- // Create initial request
- hdr->th_opcode = htons(RRQ); // Read file
- cp = (char *)&hdr->th_stuff;
- fp = filename;
- while (*fp) *cp++ = *fp++;
- *cp++ = '\0';
- if (mode == TFTP_NETASCII) {
- fp = "NETASCII";
- } else if (mode == TFTP_OCTET) {
- fp = "OCTET";
- } else {
- *err = TFTP_INVALID;
- return -1;
- }
- while (*fp) *cp++ = *fp++;
- *cp++ = '\0';
-
- memset((char *)&local_addr, 0, sizeof(local_addr));
- local_addr.sin_family = AF_INET;
- local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- local_addr.sin_port = htons(get_port++);
-
- if (server->sin_port == 0) {
- server->sin_port = htons(TFTP_PORT);
- }
-
- // Send request
- if (__udp_sendto(data, sizeof(data), server, &local_addr) < 0) {
- // Problem sending request
- *err = TFTP_NETERR;
- return -1;
- }
-
- // Read data
- fp = buf;
- while (true) {
- timeout.tv_sec = TFTP_TIMEOUT_PERIOD;
- timeout.tv_usec = 0;
- recv_len = sizeof(data);
- if ((data_len = __udp_recvfrom(&data[0], recv_len, &from_addr, &local_addr, &timeout)) < 0) {
- // No data, try again
- if ((++total_timeouts > TFTP_TIMEOUT_MAX) || (last_good_block == 0)) {
- // Timeout - no data received
- *err = TFTP_TIMEOUT;
- return -1;
- }
- // Try resending last ACK
- hdr->th_opcode = htons(ACK);
- hdr->th_block = htons(last_good_block);
- if (__udp_sendto(data, 4 /* FIXME */, &from_addr, &local_addr) < 0) {
- // Problem sending request
- *err = TFTP_NETERR;
- return -1;
- }
- } else {
- if (ntohs(hdr->th_opcode) == DATA) {
- actual_len = 0;
- if (ntohs(hdr->th_block) == (last_good_block+1)) {
- // Consume this data
- cp = hdr->th_data;
- data_len -= 4; /* Sizeof TFTP header */
- actual_len = data_len;
- res += actual_len;
- while (data_len-- > 0) {
- if (len-- > 0) {
- *fp++ = *cp++;
- } else {
- // Buffer overflow
- *err = TFTP_TOOLARGE;
- return -1;
- }
- }
- last_good_block++;
- }
- // Send out the ACK
- hdr->th_opcode = htons(ACK);
- hdr->th_block = htons(last_good_block);
- if (__udp_sendto(data, 4 /* FIXME */, &from_addr, &local_addr) < 0) {
- // Problem sending ACK
- *err = TFTP_NETERR;
- return -1;
- }
- if ((actual_len >= 0) && (actual_len < SEGSIZE)) {
- // End of data
- return res;
- }
- } else
- if (ntohs(hdr->th_opcode) == ERROR) {
- *err = ntohs(hdr->th_code);
- return -1;
- } else {
- // What kind of packet is this?
- *err = TFTP_PROTOCOL;
- return -1;
- }
- }
- }
-}
-#endif
-
static struct {
bool open;
int total_timeouts;
int last_good_block;
int avail, actual_len;
@@ -197,13 +72,11 @@ static struct {
char data[SEGSIZE+sizeof(struct tftphdr)];
char *bufp;
} tftp_stream;
int
-tftp_stream_open(char *filename,
- struct sockaddr_in *server,
- int mode,
+tftp_stream_open(connection_info_t *info,
int *err)
{
struct tftphdr *hdr = (struct tftphdr *)tftp_stream.data;
char *cp, *fp;
char test_buf;
@@ -214,38 +87,33 @@ tftp_stream_open(char *filename,
}
// Create initial request
hdr->th_opcode = htons(RRQ); // Read file
cp = (char *)&hdr->th_stuff;
- fp = filename;
+ fp = info->filename;
while (*fp) *cp++ = *fp++;
*cp++ = '\0';
- if (mode == TFTP_NETASCII) {
- fp = "NETASCII";
- } else if (mode == TFTP_OCTET) {
- fp = "OCTET";
- } else {
- *err = TFTP_INVALID;
- return -1;
- }
+ // Since this is used for downloading data, OCTET (binary) is the
+ // only mode that makes sense.
+ fp = "OCTET";
while (*fp) *cp++ = *fp++;
*cp++ = '\0';
memset((char *)&tftp_stream.local_addr, 0, sizeof(tftp_stream.local_addr));
tftp_stream.local_addr.sin_family = AF_INET;
tftp_stream.local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
tftp_stream.local_addr.sin_port = htons(get_port++);
- if (server->sin_port == 0) {
- server->sin_port = htons(TFTP_PORT);
+ if (info->server->sin_port == 0) {
+ info->server->sin_port = htons(TFTP_PORT);
}
// Send request - note: RFC 1350 (TFTP rev 2) indicates that this should be
// only as long as required to hold the request, with the nul terminator.
// Some servers silently go to lunch if the request is not the correct size.
if (__udp_sendto(tftp_stream.data, cp-(char *)hdr,
- server, &tftp_stream.local_addr) < 0) {
+ info->server, &tftp_stream.local_addr) < 0) {
// Problem sending request
*err = TFTP_NETERR;
return -1;
}
@@ -267,15 +135,14 @@ tftp_stream_open(char *filename,
tftp_stream.open = false;
return -1; // Couldn't read
}
}
-int
+void
tftp_stream_close(int *err)
{
tftp_stream.open = false;
- return 0;
}
int
tftp_stream_read(char *buf,
int len,
@@ -380,5 +247,13 @@ tftp_error(int err)
case TFTP_TOOLARGE:
return "file is larger than buffer";
}
return errmsg;
}
+
+//
+// RedBoot interface
+//
+GETC_IO_FUNCS(tftp_io, tftp_stream_open, tftp_stream_close,
+ 0, tftp_stream_read, tftp_error);
+RedBoot_load(tftp, tftp_io, true, true);
+