? redboot/current/src/test_load.c Index: redboot/current/ChangeLog =================================================================== RCS file: /cvs/ecos/ecos/packages/redboot/current/ChangeLog,v retrieving revision 1.187 diff -u -5 -r1.187 ChangeLog --- redboot/current/ChangeLog 28 Feb 2004 16:51:08 -0000 1.187 +++ redboot/current/ChangeLog 9 Mar 2004 16:00:55 -0000 @@ -1,5 +1,24 @@ +2004-03-08 Andrew Dyer + + * 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. + +2004-03-02 Andrew Dyer + + * src/load.c: add -p option to help string and only print it and -h if + CYGPKG_REDBOOT_NETWORKING is enabled. Add a CR to the end of the + SHORT_DATA message string + 2004-02-27 Jani Monoses * src/net/http_client.c: Close connection with abort instead of friendly close since for ELF files we don't read the whole content but end the connection when the runnable parts are in. The server Index: redboot/current/include/net/tftp_support.h =================================================================== RCS file: /cvs/ecos/ecos/packages/redboot/current/include/net/tftp_support.h,v retrieving revision 1.6 diff -u -5 -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 Mar 2004 16:00:56 -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: /cvs/ecos/ecos/packages/redboot/current/src/load.c,v retrieving revision 1.40 diff -u -5 -r1.40 load.c --- redboot/current/src/load.c 26 Feb 2004 11:12:10 -0000 1.40 +++ redboot/current/src/load.c 9 Mar 2004 16:00:56 -0000 @@ -75,11 +75,14 @@ static char usage[] = "[-r] [-v] " #ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB "[-d] " #endif - "[-h ] [-m ] " +#ifdef CYGPKG_REDBOOT_NETWORKING + "[-h ] [-p ]" +#endif + "[-m ] " #if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1 "[-c ] " #endif "\n [-b ] "; @@ -296,15 +299,16 @@ int phx, len, ch; unsigned char *addr; unsigned long addr_offset = 0; unsigned long highest_address = 0; unsigned long lowest_address = 0xFFFFFFFF; - unsigned char *SHORT_DATA = "Short data reading ELF file"; + 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", @@ -312,26 +316,30 @@ 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, @@ -361,17 +369,19 @@ } 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++; } } @@ -384,10 +394,11 @@ 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) { @@ -405,11 +416,14 @@ 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: /cvs/ecos/ecos/packages/redboot/current/src/net/tftp_client.c,v retrieving revision 1.15 diff -u -5 -r1.15 tftp_client.c --- redboot/current/src/net/tftp_client.c 19 Sep 2003 17:11:34 -0000 1.15 +++ redboot/current/src/net/tftp_client.c 9 Mar 2004 16:00:57 -0000 @@ -154,15 +154,54 @@ } } 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) { + 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, int len, @@ -182,11 +221,11 @@ buf += size; tftp_stream.bufp += size; tftp_stream.avail -= size; total_bytes += size; } else { - if (tftp_ack(err) < 0) { + if (tftp_ack(err) < 0) { return -1; } if ((tftp_stream.actual_len >= 0) && (tftp_stream.actual_len < SEGSIZE)) { // Out of data break; @@ -270,8 +309,8 @@ // // 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);