This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
TFTP fixes
- From: Gary Thomas <gary at mlbassoc dot com>
- To: eCos patches <ecos-patches at ecos dot sourceware dot org>
- Date: Fri, 09 Sep 2005 07:27:43 -0600
- Subject: TFTP fixes
- Organization: MLB Associates
Very old patch from Andrew Dyer, recently tested and applied.
--
------------------------------------------------------------
Gary Thomas | Consulting for the
MLB Associates | Embedded world
------------------------------------------------------------
Index: redboot/current/ChangeLog
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/ChangeLog,v
retrieving revision 1.234
diff -u -5 -p -r1.234 ChangeLog
--- redboot/current/ChangeLog 8 Sep 2005 12:14:28 -0000 1.234
+++ redboot/current/ChangeLog 9 Sep 2005 13:24:40 -0000
@@ -1,5 +1,18 @@
+2005-09-09 Andrew Dyer <adyer@righthandtech.com>
+
+ * src/load.c: add calls to redboot_getc_terminate before exiting
+ load_elf_image() in various error scenarios, change the final call
+ to redboot_getc_terminate to have the error flag set. This will
+ cause a tftp nak and close down the connection since for ELF files
+ we don't read the whole content but end the connection when the
+ runnable parts are in.
+
+ * src/net/tftp_client.c: add tftp_error() to send an error back to
+ the server. define tftp_stream_terminate() and pass it into the
+ redboot interface.
+
2005-09-08 Gary Thomas <gary@mlbassoc.com>
* src/io.c:
* include/redboot.h:
* doc/redboot.sgml:
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.6
diff -u -5 -p -r1.6 tftp_support.h
--- redboot/current/include/net/tftp_support.h 1 Jul 2002 20:55:28 -0000 1.6
+++ redboot/current/include/net/tftp_support.h 9 Sep 2005 13:23:59 -0000
@@ -85,10 +85,11 @@
*/
extern int tftp_stream_open(connection_info_t *info, int *err);
extern int tftp_stream_read(char *buf, int len, int *err);
extern void tftp_stream_close(int *err);
+extern void tftp_stream_terminate(bool abort, int (*getc)(void));
extern char *tftp_error(int err);
#define TFTP_TIMEOUT_PERIOD 5
#define TFTP_TIMEOUT_MAX 15
#define TFTP_RETRIES_MAX 5
Index: redboot/current/src/load.c
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/src/load.c,v
retrieving revision 1.44
diff -u -5 -p -r1.44 load.c
--- redboot/current/src/load.c 19 Sep 2004 13:01:54 -0000 1.44
+++ redboot/current/src/load.c 9 Sep 2005 13:23:59 -0000
@@ -305,10 +305,11 @@ load_elf_image(getc_t getc, unsigned lon
unsigned char *SHORT_DATA = "Short data reading ELF file\n";
// Read the header
if (_read(getc, (unsigned char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
diag_printf("Can't read ELF header\n");
+ redboot_getc_terminate(true);
return 0;
}
offset += sizeof(ehdr);
#if 0 // DEBUG
diag_printf("Type: %d, Machine: %d, Version: %d, Entry: %p, PHoff: %p/%d/%d, SHoff: %p/%d/%d\n",
@@ -316,26 +317,30 @@ load_elf_image(getc_t getc, unsigned lon
ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_phnum,
ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shnum);
#endif
if (ehdr.e_type != ET_EXEC) {
diag_printf("Only absolute ELF images supported\n");
+ redboot_getc_terminate(true);
return 0;
}
if (ehdr.e_phnum > MAX_PHDR) {
diag_printf("Too many program headers\n");
+ redboot_getc_terminate(true);
return 0;
}
while (offset < ehdr.e_phoff) {
if ((*getc)() < 0) {
diag_printf(SHORT_DATA);
+ redboot_getc_terminate(true);
return 0;
}
offset++;
}
for (phx = 0; phx < ehdr.e_phnum; phx++) {
if (_read(getc, (unsigned char *)&phdr[phx], sizeof(phdr[0])) != sizeof(phdr[0])) {
diag_printf("Can't read ELF program header\n");
+ redboot_getc_terminate(true);
return 0;
}
#if 0 // DEBUG
diag_printf("Program header: type: %d, off: %p, va: %p, pa: %p, len: %d/%d, flags: %d\n",
phdr[phx].p_type, phdr[phx].p_offset, phdr[phx].p_vaddr, phdr[phx].p_paddr,
@@ -374,17 +379,19 @@ load_elf_image(getc_t getc, unsigned lon
}
addr += addr_offset;
if (offset > phdr[phx].p_offset) {
if ((phdr[phx].p_offset + len) < offset) {
diag_printf("Can't load ELF file - program headers out of order\n");
+ redboot_getc_terminate(true);
return 0;
}
addr += offset - phdr[phx].p_offset;
} else {
while (offset < phdr[phx].p_offset) {
if ((*getc)() < 0) {
diag_printf(SHORT_DATA);
+ redboot_getc_terminate(true);
return 0;
}
offset++;
}
}
@@ -398,10 +405,11 @@ load_elf_image(getc_t getc, unsigned lon
return 0;
}
#endif
if ((ch = (*getc)()) < 0) {
diag_printf(SHORT_DATA);
+ redboot_getc_terminate(true);
return 0;
}
*addr++ = ch;
offset++;
if ((unsigned long)(addr-addr_offset) > highest_address) {
@@ -420,11 +428,14 @@ load_elf_image(getc_t getc, unsigned lon
load_address = lowest_address;
load_address_end = highest_address;
entry_address = ehdr.e_entry;
}
- redboot_getc_terminate(false);
+ // nak everything to stop the transfer, since redboot
+ // usually doesn't read all the way to the end of the
+ // elf files.
+ redboot_getc_terminate(true);
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 *)load_address, (void *)load_address_end);
return 1;
#else // CYGSEM_REDBOOT_ELF
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.16
diff -u -5 -p -r1.16 tftp_client.c
--- redboot/current/src/net/tftp_client.c 23 Apr 2004 20:38:18 -0000 1.16
+++ redboot/current/src/net/tftp_client.c 9 Sep 2005 13:23:59 -0000
@@ -156,14 +156,53 @@ tftp_ack(int *err)
}
}
return 0;
}
+static int
+tftp_error_ack(int *err, short code, char *msg)
+{
+ struct tftphdr *hdr = (struct tftphdr *)tftp_stream.data;
+
+ if (strlen(msg) > (SEGSIZE-1)) {
+ *(msg + SEGSIZE) = NULL;
+ }
+
+ if (tftp_stream.packets_received > 0) {
+ hdr->th_opcode = htons(ERROR);
+ hdr->th_code = code;
+ strcpy(&hdr->th_data, msg);
+ if (__udp_sendto(tftp_stream.data, (5 + strlen(msg)),
+ &tftp_stream.from_addr, &tftp_stream.local_addr) < 0) {
+ // Problem sending ACK
+ *err = TFTP_NETERR;
+ return -1;
+ }
+ }
+ return 0;
+}
+
void
tftp_stream_close(int *err)
{
- tftp_ack(err);
+ if (tftp_stream.open == true) {
+ tftp_ack(err);
+ tftp_stream.open = false;
+ }
+}
+
+void
+tftp_stream_terminate(bool abort,
+ int (*getc)(void))
+{
+ int err;
+
+ if (abort)
+ tftp_error_ack(&err, EUNDEF, "redboot tftp_stream_terminate");
+ else
+ tftp_ack(&err);
+
tftp_stream.open = false;
}
int
tftp_stream_read(char *buf,
@@ -272,8 +311,8 @@ tftp_error(int err)
//
// RedBoot interface
//
GETC_IO_FUNCS(tftp_io, tftp_stream_open, tftp_stream_close,
- 0, tftp_stream_read, tftp_error);
+ tftp_stream_terminate, tftp_stream_read, tftp_error);
RedBoot_load(tftp, tftp_io, true, true, 0);