Index: /ar5315_microredboot/microredboot/CHANGELOG =================================================================== --- /ar5315_microredboot/microredboot/CHANGELOG (revision 12345) +++ /ar5315_microredboot/microredboot/CHANGELOG (revision 12368) @@ -1,2 +1,12 @@ +24.6.09 + * added wiligear firmware format for tftp recovery (the whole code is rewritten to be readable and small) +23.6.09 + * added ubnt firmware format for tftp recovery (format taken from fwsplit) + * added tftp recovery code (code was provided by wiligear) + - if reset button is keep pushed the tftp server will start, redboot will then accept tftp transfers in the common dd-wrt webflash format + - i will add wiligear GEOS format and ubnt format in future versions ,the provided code need to be rewritten first +22.6.09 + * we invert the usage for resetbutton_enable here, so it will only boot redboot per default if the resetbutton feature is disabled from dd-wrt + otherwise, use trigger reset button to enter it 21.6.09 * implement dynamic uart clock for ap51/ap61 redboot (required for clean uart output with overclocked cpu's) Index: /ar5315_microredboot/microredboot/ecos/packages/templates/redboot/current.ect =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/templates/redboot/current.ect (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/templates/redboot/current.ect (revision 12368) @@ -16,4 +16,5 @@ package CYGPKG_ISOINFRA current ; package CYGPKG_LIBC_STRING current ; + package CYGPKG_CRC current ; }; Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/cdl/redboot.cdl =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/cdl/redboot.cdl (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/cdl/redboot.cdl (revision 12368) @@ -335,4 +335,22 @@ This option enables the use of the TFTP protocol for download" } + + cdl_option CYGSEM_REDBOOT_NET_TFTP_SERVER { + display "Support TFTP server with WILIBOX fwupdate support" + flavor bool + default_value 1 + compile -library=libextras.a net/tftp_server.c net/fwupgrade.c net/fwupgrade_ubnt.c net/fwupgrade_wili.c + description " + This option enables the use of the TFTP server" + } + + cdl_option CYGSEM_REDBOOT_RESCUE_MODE { + display "Support rescue mode" + flavor bool + default_value 1 + requires CYGSEM_REDBOOT_NET_TFTP_SERVER + description " + This option enables the rescue mode (start tftp server)" + } cdl_option CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD { Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/timers.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/timers.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/timers.c (revision 12368) @@ -57,79 +57,74 @@ static timer_t *tmr_list; - /* * Set a timer. Caller is responsible for providing the timer_t struct. */ void -__timer_set(timer_t *t, unsigned long delay, +__timer_set(timer_t * t, unsigned long delay, tmr_handler_t handler, void *user_data) { - timer_t *p; + timer_t *p; - t->delay = delay; - t->start = MS_TICKS(); - t->handler = handler; - t->user_data = user_data; + t->delay = delay; + t->start = MS_TICKS(); + t->handler = handler; + t->user_data = user_data; - for (p = tmr_list; p; p = p->next) - if (p == t) { - return; - } + for (p = tmr_list; p; p = p->next) + if (p == t) { + return; + } - t->next = tmr_list; - tmr_list = t; + t->next = tmr_list; + tmr_list = t; } - /* * Remove a given timer from timer list. */ -void -__timer_cancel(timer_t *t) +void __timer_cancel(timer_t * t) { - timer_t *prev, *p; + timer_t *prev, *p; - for (prev = NULL, p = tmr_list; p; prev = p, p = p->next) - if (p == t) { - if (prev) - prev->next = p->next; - else - tmr_list = p->next; - return; - } + for (prev = NULL, p = tmr_list; p; prev = p, p = p->next) + if (p == t) { + if (prev) + prev->next = p->next; + else + tmr_list = p->next; + return; + } } - /* * Poll timer list for timer expirations. */ -void -__timer_poll(void) +void __timer_poll(void) { - timer_t *prev, *t; + timer_t *prev, *t; - prev = NULL; - t = tmr_list; - while (t) { - if ((MS_TICKS_DELAY() - t->start) >= t->delay) { + prev = NULL; + t = tmr_list; + while (t) { + if ((MS_TICKS_DELAY() - t->start) >= t->delay) { - /* remove it before calling handler */ - if (prev) - prev->next = t->next; - else - tmr_list = t->next; - /* now, call the handler */ - t->handler(t->user_data); - - /* - * handler may be time consuming, so start - * from beginning of list. - */ - prev = NULL; - t = tmr_list; - } else { - prev = t; - t = t->next; + /* remove it before calling handler */ + if (prev) + prev->next = t->next; + else + tmr_list = t->next; + /* now, call the handler */ + t->handler(t->user_data); + + /* + * handler may be time consuming, so start + * from beginning of list. + */ + prev = NULL; + t = tmr_list; + } else { + prev = t; + t = t->next; + } } - } } Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/tftp_server.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/tftp_server.c (revision 12368) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/tftp_server.c (revision 12368) @@ -0,0 +1,370 @@ +//========================================================================== +// +// net/tftp_server.c +// +// Stand-alone TFTP server support for RedBoot +// + +#include // have_net +#include +#include +#include +#include +#include "fwupgrade.h" + +#define IPPORT_TFTPD 69 +#define FIRMWARE_PASSWORD "flash_update" + +#define TFTP_HEADER_SIZE 4 +#define SEGSIZE 512 + +/* from main.c */ +extern void do_reset(int argc, char *argv[]); + +/* global variables for tftpd */ +static ip_route_t wrq_route = { ip_addr:{0, 0, 0, 0} }; + +static word wrq_port = 0; +static char tftpd_buffer[SEGSIZE + TFTP_HEADER_SIZE]; + +unsigned long tftpd_base = 0; + +static char usage[] = ""; + +// Exported CLI function +RedBoot_cmd("tftpd", + "Start tftp server and wait for firmware update", usage, do_tftpd); + +static void +tftpd_error(int error_code, char *error_msg, ip_route_t * src_route, + word src_port) +{ + struct tftphdr *tp; + int len; + + diag_printf("TFTPD: Error %d: %s\n", error_code, error_msg); + + tp = (struct tftphdr *)tftpd_buffer; + tp->th_opcode = htons((unsigned short)ERROR); + tp->th_code = htons((unsigned short)error_code); + strcpy(tp->th_msg, error_msg); + len = strlen(error_msg); + tp->th_msg[len] = '\0'; + len += (TFTP_HEADER_SIZE + 1); + + __udp_send((char *)tftpd_buffer, len, src_route, src_port, + IPPORT_TFTPD); +} + +static void +tftpd_send(int opcode, int block, ip_route_t * src_route, word src_port) +{ + struct tftphdr *tp; + +#if 0 + diag_printf("tftpd_send\n"); +#endif + + tp = (struct tftphdr *)tftpd_buffer; + tp->th_opcode = htons((unsigned short)opcode); + tp->th_block = htons((unsigned short)block); + + __udp_send((char *)tftpd_buffer, TFTP_HEADER_SIZE, src_route, src_port, + IPPORT_TFTPD); +} + +#if 0 +/* jM -- set status led green or red */ +#define STATUS_LED_GPIO 2 +static void set_status_led(int status) +{ + HAL_GPIO_OUTPUT_ENABLE(STATUS_LED_GPIO); + + if (status == 0) + HAL_GPIO_OUTPUT_CLEAR(STATUS_LED_GPIO); + else + HAL_GPIO_OUTPUT_SET(STATUS_LED_GPIO); +} +#endif + +#include "../ramconfig.h" + +extern int page_programming_supported; +extern int page_gpio; + +static void pagesetup(void) +{ +#if defined(CYGPKG_HAL_MIPS_AR2316) +#if FISTYPE == 1 + *(volatile unsigned *)0xB1000090 |= 1; /*set GPIO0 to 1 to spi flash CS normal state */ + *(volatile unsigned *)0xB1000098 |= 1; /*set GPIO0 to be output */ + page_programming_supported = 1; + page_gpio = 0; +#endif + +#if FISTYPE == 2 + *(volatile unsigned *)0xB1000090 |= 1 << 3; /*set GPIO0 to 1 to spi flash CS normal state */ + *(volatile unsigned *)0xB1000098 |= 1 << 3; /*set GPIO0 to be output */ + page_programming_supported = 1; + page_gpio = 3; +#endif + +#if FISTYPE == 0 + page_programming_supported = 0; + page_gpio = 0; +#endif +#endif + +} + +static void flashresult(int rc) +{ + if (rc) + diag_printf("Flash update failed!\n"); + else + diag_printf("Flash update complete.\n"); + /* clean da memory */ + do_reset(0, NULL); + +} + +void do_flash_update_ddwrt(unsigned long base_addr, unsigned long len) +{ + int rc; + pagesetup(); + /* do_flash = 1, write to flash */ + rc = fw_check_image_ddwrt((char *)base_addr, len, 1); + memset((unsigned char *)base_addr, 0, len); + flashresult(rc); +} + +void do_flash_update_ubnt(unsigned long base_addr, unsigned long len) +{ + int rc; + pagesetup(); + /* do_flash = 1, write to flash */ + rc = fw_check_image_ubnt((char *)base_addr, len, 1); + + memset((unsigned char *)base_addr, 0, len); + flashresult(rc); +} + +void do_flash_update_wili(unsigned long base_addr, unsigned long len) +{ + int rc; + pagesetup(); + /* do_flash = 1, write to flash */ + rc = fw_check_image_wili((char *)base_addr, len, 1); + + memset((unsigned char *)base_addr, 0, len); + flashresult(rc); +} + +void +tftpd_fsm(struct tftphdr *tp, int len, ip_route_t * src_route, word src_port) +{ + char *mode, *password; + static unsigned int last_sync_block; + unsigned int block; + static int bytes_received = 0; + static unsigned long ptr = 0L; + +#if 0 + diag_printf("got packet from %d.%d.%d.%d port %d\n", + src_route->ip_addr[0], + src_route->ip_addr[1], + src_route->ip_addr[2], src_route->ip_addr[3], src_port); + + diag_printf("packet len is %d, TFTP opcode is %d\n", + len, tp->th_opcode); +#endif + + switch (tp->th_opcode) { + case WRQ: /* write request */ + password = tp->th_stuff; + mode = &password[strlen(password) + 1]; + diag_printf("TFTPD: Connect from %d.%d.%d.%d port %d\n", + src_route->ip_addr[0], + src_route->ip_addr[1], + src_route->ip_addr[2], + src_route->ip_addr[3], src_port); + //if (strcmp(password, FIRMWARE_PASSWORD)) { + // tftpd_error(EACCESS, "Access violation (invalid password)", src_route, src_port); + // break; + //} + if (strcmp(mode, "octet")) { + tftpd_error(EACCESS, + "Access violation (use binary mode)", + src_route, src_port); + break; + } + + /* we are ready for data */ + tftpd_send(ACK, 0, src_route, src_port); + + last_sync_block = 0; + memmove(&wrq_route.ip_addr, &src_route->ip_addr, + sizeof(ip_addr_t)); + wrq_port = src_port; + + break; + + case DATA: /* received data */ + if (*(int *)(wrq_route.ip_addr) != *(int *)(src_route->ip_addr)) + tftpd_error(EACCESS, + "Access violation (unknown address)", + src_route, src_port); + + block = ntohs(tp->th_block); + len -= TFTP_HEADER_SIZE; + + if (block == 1) { + bytes_received = 0; + ptr = BASE_ADDR; /* rewind pointer */ + + } + bytes_received += len; +#if 0 + if (!(bytes_received % (1024 * 16))) + diag_printf("ptr = %08X\n", ptr); +#endif + if (bytes_received >= MAX_IMAGE_SIZE) { + tftpd_error(EACCESS, "Image size too big.", src_route, + src_port); + break; + } + if (block == last_sync_block + 1) { + last_sync_block = block; + + memmove((char *)ptr, &tp->th_data, len); + ptr += len; + + } else { + /* out of sync */ + diag_printf("Blocks out of sync (prev %d, curr %d)", + last_sync_block, block); + break; + } + + if (len < SEGSIZE) { + diag_printf("TFTPD: Upload completed (got %d bytes).\n", + ptr - BASE_ADDR); + + // CRC CHECK + diag_printf("Checking uploaded file...\n"); + + int isddwrt = 0; + int isubnt = 0; + int iswili = 0; + isddwrt = fw_check_image_ddwrt((char *)BASE_ADDR, + ptr - BASE_ADDR, 0) == 0; + if (!isddwrt) + isubnt = + fw_check_image_ubnt((char *)BASE_ADDR, + ptr - BASE_ADDR, + 0) == 0; + + if (!isubnt && !isddwrt) + iswili = + fw_check_image_wili((char *)BASE_ADDR, + ptr - BASE_ADDR, + 0) == 0; + + if (isddwrt || isubnt || iswili) /* third parameter 0 - do not write to flash */ + tftpd_send(ACK, block, src_route, src_port); // crc ok + else { + tftpd_error(EACCESS, "CRC error", src_route, + src_port); + break; + } + + // write to flash +#if 1 + if (isddwrt) { + diag_printf + ("DD-WRT firmware format detected\n"); + do_flash_update_ddwrt(BASE_ADDR, + ptr - BASE_ADDR); + } + if (isubnt) { + diag_printf("UBNT firmware format detected\n"); + do_flash_update_ubnt(BASE_ADDR, + ptr - BASE_ADDR); + } + if (iswili) { + diag_printf + ("WILIGEAR firmware format detected\n"); + do_flash_update_wili(BASE_ADDR, + ptr - BASE_ADDR); + } +#else + diag_printf("Not writing to flash.\n"); +#endif + + } else { + /* send ACK to last block in sequence */ + tftpd_send(ACK, block, src_route, src_port); + } + break; + default: + tftpd_error(EBADOP, "Illegal TFTP operation", src_route, + src_port); + break; + } +} + +void +tftpd_handler(udp_socket_t * skt, char *buf, int len, + ip_route_t * src_route, word src_port) +{ + struct tftphdr *tp; + +#if 0 + diag_printf("tftpd handler called!\n"); +#endif + + tp = (struct tftphdr *)buf; + tp->th_opcode = ntohs(tp->th_opcode); + tftpd_fsm(tp, len, src_route, src_port); + +} + +void do_tftpd(int argc, char *argv[]) +{ + udp_socket_t udp_skt; + + /* First, fwupdate.bin will be loaded to BASE_ADDR. + * Then before writing to flash each partition (kernel, ramdisk) + * will be moved to FW_TEMP_BASE (thus this address will be in FIS mem entry + */ + FW_TEMP_BASE = + ((CYG_ADDRWORD) mem_segments[0].start + 0x03ff) & ~0x03ff; + /* note: memory addresses from 80700000 are reserved ? anyway, do not use them */ +// BASE_ADDR = ((CYG_ADDRWORD)mem_segments[0].end & ~0x03ff) - MAX_IMAGE_SIZE; + BASE_ADDR = + (((CYG_ADDRWORD) mem_segments[0].start + 0x03ff) & ~0x03ff) + + MAX_PART_SIZE; + if ((BASE_ADDR + MAX_IMAGE_SIZE) >= 0x80730000) + diag_printf + ("Warning: memory buffer for uploaded file may be on reserved RAM area.\n"); + +#if 1 + /* hack: on ar531x, elf image should always be at 0x80002000 base, so adjust if possible */ + if ((FW_TEMP_BASE < 0x80002000) + && (FW_TEMP_BASE + MAX_PART_SIZE <= BASE_ADDR)) + FW_TEMP_BASE = 0x80002000; +#endif + + diag_printf + ("TFTPD is running (using memory ranges: %p - %p, %p - %p).\n", + FW_TEMP_BASE, BASE_ADDR, BASE_ADDR, BASE_ADDR + MAX_IMAGE_SIZE); + + __udp_install_listener(&udp_skt, IPPORT_TFTPD, tftpd_handler); + + while (!_rb_break(0)) { + __enet_poll(); // wait for packet ? + } + + __udp_remove_listener(IPPORT_TFTPD); + diag_printf("TFTPD terminated.\n"); +} Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade_wili.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade_wili.c (revision 12368) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade_wili.c (revision 12368) @@ -0,0 +1,275 @@ +/* +firmware upgrade code for DD-WRT webflash images +*/ + +#include +#include +#include +#include +#include "fwupgrade_wili.h" + +/* some variables from flash.c */ +extern void *flash_start, *flash_end; +extern int flash_block_size, flash_num_blocks; +#ifdef CYGOPT_REDBOOT_FIS +extern void *fis_work_block; +extern void *fis_addr; +extern int fisdir_size; // Size of FIS directory. +#endif +//extern void _show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat); +extern void fis_update_directory(void); + +//#define TRACE diag_printf("DBG: %s:%d\n", __FUNCTION__, __LINE__) + +#define TRACE + +/* + * check if update file is valid + * - magic signatures + * - crc + * - data size (must match partition sizes) + * setup miniroot environment + * - copy libc & fwupdate to /var (new root) + * - create /dev/ entries in miniroot + * - use pivot_root to switch root, old root will be available at /oldroot + * - restart fwupdate from miniroot (with -f switch) + * update flash memory (check if fwupdate is started from miniroot) + * - write images to flash + * - reboot + */ + +/* update file structure: + * + * header + * part1 + * part2 + * signature + * + * header: + * magic1 [4 bytes] GEOS + * version [128 bytes] + * reserved [128 bytes] + * crc [4 bytes] for [0..reserved] range + * crypto [4 bytes] for [0..crc] range + * + * part: + * magic2 [4 bytes] PART + * name [32 bytes] "kernel", "cramfs", "etc", "cfg", "RedBoot" (as in /proc/mtd) + * partition nr [4 bytes] 0, 1, 2... - will be appended to /dev/mtdblock + * flags1 [4 bytes] 0x0001 - image is compressed, 0x0000 - raw + * flags2 [4 bytes] + * length [4 bytes] should be less than partition size + * part_len [4bytes] partition size + * data [length bytes] + * crc [4 bytes] from part start till data field (incl.) + * crypto [4 bytes] from part start till crc field (incl.) + * + * signature: + * magic3 [4 bytes] END. + * crc [4 bytes] from the start of file till signature's magic3 field (including) + * crypto [4 bytes] from the start of file till signature's crc field (including) + */ +/* fwupdate.bin size */ +#define MAX_IMAGE_SIZE 0x7E0000 /* 4mb - 64k */ + +/* max size for single partition - typicaly this is cramfs size */ +#define MAX_PART_SIZE 0x800000 /* 3mb - valid only for ar531x */ + +#define MAGIC_HEADER "GEOS" +#define MAGIC_PART "PART" +#define MAGIC_END "END." + +#define MAGIC_LENGTH 4 + +typedef unsigned int u_int32_t; + +typedef struct header { + char magic[MAGIC_LENGTH]; + char version[256]; + u_int32_t crc; + u_int32_t pad; +} __attribute__((packed)) header_t; + +typedef struct part { + char magic[MAGIC_LENGTH]; + char name[32]; + u_int32_t part_nr; + u_int32_t flags1; + u_int32_t flags2; + u_int32_t data_size; + u_int32_t part_size; +} __attribute__((packed)) part_t; + +typedef struct part_crc { + u_int32_t crc; + u_int32_t pad; +} __attribute__((packed)) part_crc_t; + +typedef struct signature { + char magic[MAGIC_LENGTH]; + u_int32_t crc; + u_int32_t pad; +} __attribute__((packed)) signature_t; + +#define MAX_PARTS 8 + +typedef struct fw_part { + part_t *header; + unsigned char *data; + u_int32_t data_size; + part_crc_t *signature; +} fw_part_t; + +typedef struct fw { + u_int32_t size; + char version[256]; + fw_part_t parts[MAX_PARTS]; + int part_count; +} fw_t; + +#define crc32 cyg_ether_crc32_accumulate + +extern void fis_init(int argc, char *argv[], int force); + +int fw_check_image_wili(unsigned char *addr, unsigned long maxlen, int do_flash) +{ + header_t *header = (header_t *) addr; + fw_t fw; + int len = sizeof(header_t) - 2 * sizeof(u_int32_t); + unsigned int crc = crc32(0L, (unsigned char *)header, len); + signature_t *sig; + fw.size = maxlen; + if (strncmp(header->magic, MAGIC_HEADER, 4)) { + return -1; + } + if (htonl(crc) != header->crc) { + diag_printf("WILI_FW: header crc failed\n"); + return -1; + } + memcpy(fw.version, header->version, sizeof(fw.version)); + if (do_flash) + diag_printf("WILI_FW: Firmware version: '%s'\n", + header->version); + part_t *p; + p = (part_t *) (addr + sizeof(header_t)); + int i = 0; + while (strncmp(p->magic, MAGIC_END, MAGIC_LENGTH) != 0) { + if (do_flash) { + diag_printf("Partition: %s\n", p->name); + diag_printf("Partition size: 0x%X\n", + ntohl(p->part_size)); + diag_printf("Data size: %u\n", ntohl(p->data_size)); + } + if ((strncmp(p->magic, MAGIC_PART, MAGIC_LENGTH) == 0) + && (i < MAX_PARTS)) { + fw_part_t *fwp = &fw.parts[i]; + + fwp->header = p; + fwp->data = (unsigned char *)p + sizeof(part_t); + fwp->data_size = ntohl(p->data_size); + fwp->signature = + (part_crc_t *) (fwp->data + fwp->data_size); + crc = + htonl(crc32 + (0L, (unsigned char *)p, + fwp->data_size + sizeof(part_t))); + if (crc != fwp->signature->crc) { + diag_printf + ("WILI_FW: Invalid '%s' CRC (claims: %u, but is %u)\n", + fwp->header->name, fwp->signature->crc, + crc); + return -1; + } + int index; + struct fis_image_desc *img = + fis_lookup(fwp->header->name, &index); + if (!img) { + diag_printf + ("WILI_FW: cannot find partition %s, not flashable!\n"); + return -1; + } + ++i; + } + + p = (part_t *) ((unsigned char *)p + sizeof(part_t) + + ntohl(p->data_size) + sizeof(part_crc_t)); + + /* check bounds */ + if (((unsigned char *)p - addr) >= maxlen) { + return -3; + } + } + + fw.part_count = i; + + sig = (signature_t *) p; + if (strncmp(sig->magic, MAGIC_END, MAGIC_LENGTH) != 0) { + diag_printf("WILI_FW: Bad firmware signature\n"); + return -4; + } + + crc = htonl(crc32(0L, addr, (unsigned char *)sig - addr)); + if (crc != sig->crc) { + diag_printf + ("WILI_FW: Invalid signature CRC (claims: %u, but is %u)\n", + sig->crc, crc); + return -5; + } + + if (do_flash) { + char *arg[] = { "fis", "init" }; + fis_init(2, arg, 1); + void *err_addr; + flash_read(fis_addr, fis_work_block, fisdir_size, + (void **)&err_addr); + struct fis_image_desc *img = fis_lookup("RedBoot", &i); + if (i != 0) { + diag_printf + ("WILI_FW: RedBoot partition is not the first partition\n"); + return -1; + } + for (i = 0; i < fw.part_count; ++i) { + fw_part_t *fwp = &fw.parts[i]; + if (!strncmp(fwp->header->name, "RedBoot", 7) + && ntohl(fwp->header->part_size) > 0x10000) { + diag_printf("ignore %s\n", fwp->header->name); + continue; + } + diag_printf("WILI_FW: Flashing: %s\n", + fwp->header->name); + int stat; + int index; + img = fis_lookup(fwp->header->name, &index); + if (!img) { + diag_printf + ("WILI_FW: cannot find partition %s, not flashable. break\n"); + return -1; + } + if ((stat = + flash_erase((void *)img->flash_base, + ntohl(fwp->header->part_size), + (void **)&err_addr)) != 0) { + diag_printf + ("WILI_FW: Can't erase region at %p: %s\n", + err_addr, flash_errmsg(stat)); + return -1; + } + if ((stat = flash_program((void *)img->flash_base, + (void *)fwp->data, + ntohl(fwp->data_size), + (void **)&err_addr)) != 0) { + diag_printf + ("WILI_FW: Can't program region at %p: %s\n", + err_addr, flash_errmsg(stat)); + return -1; + } + img->size = ntohl(fwp->header->part_size); + img->data_length = ntohl(fwp->header->data_size); + + } + fis_update_directory(); + diag_printf("WILI_FW: flashing done\n"); + } + + return 0; +} Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/ip.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/ip.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/ip.c (revision 12368) @@ -67,4 +67,5 @@ ip_addr_t __local_ip_addr = { CYGDAT_REDBOOT_DEFAULT_IP_ADDR }; + #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY ip_addr_t __local_ip_mask = { CYGDAT_REDBOOT_DEFAULT_IP_ADDR_MASK }; @@ -78,12 +79,10 @@ * See if an address is on the local network */ -int -__ip_addr_local(ip_addr_t *addr) -{ - return !( - ((__local_ip_addr[0] ^ (*addr)[0]) & __local_ip_mask[0]) | - ((__local_ip_addr[1] ^ (*addr)[1]) & __local_ip_mask[1]) | - ((__local_ip_addr[2] ^ (*addr)[2]) & __local_ip_mask[2]) | - ((__local_ip_addr[3] ^ (*addr)[3]) & __local_ip_mask[3])); +int __ip_addr_local(ip_addr_t * addr) +{ + return !(((__local_ip_addr[0] ^ (*addr)[0]) & __local_ip_mask[0]) | + ((__local_ip_addr[1] ^ (*addr)[1]) & __local_ip_mask[1]) | + ((__local_ip_addr[2] ^ (*addr)[2]) & __local_ip_mask[2]) | + ((__local_ip_addr[3] ^ (*addr)[3]) & __local_ip_mask[3])); } #endif @@ -93,25 +92,24 @@ * Check for broadcast matches as well. */ -static int -ip_addr_match(ip_addr_t addr) -{ - if (addr[0] == 255 && addr[1] == 255 && addr[2] == 255 && addr[3] == 255) - return 1; - - if (!memcmp(addr, __local_ip_addr, sizeof(ip_addr_t))) - return 1; - - /* - * Consider it an address match if we haven't gotten our IP address yet. - * Some DHCP servers will address IP packets to the assigned address - * instead of a IP broadcast address. - */ - if (__local_ip_addr[0] == 0 && __local_ip_addr[1] == 0 && - __local_ip_addr[2] == 0 && __local_ip_addr[3] == 0) - return 1; - - return 0; -} - +static int ip_addr_match(ip_addr_t addr) +{ + if (addr[0] == 255 && addr[1] == 255 && addr[2] == 255 + && addr[3] == 255) + return 1; + + if (!memcmp(addr, __local_ip_addr, sizeof(ip_addr_t))) + return 1; + + /* + * Consider it an address match if we haven't gotten our IP address yet. + * Some DHCP servers will address IP packets to the assigned address + * instead of a IP broadcast address. + */ + if (__local_ip_addr[0] == 0 && __local_ip_addr[1] == 0 && + __local_ip_addr[2] == 0 && __local_ip_addr[3] == 0) + return 1; + + return 0; +} extern void __tcp_handler(pktbuf_t *, ip_route_t *); @@ -120,53 +118,51 @@ * Handle IP packets coming from the polled ethernet interface. */ -void -__ip_handler(pktbuf_t *pkt, enet_addr_t *src_enet_addr) -{ - ip_header_t *ip = pkt->ip_hdr; - ip_route_t r; - int hdr_bytes; - - /* first make sure its ours and has a good checksum. */ - if (!ip_addr_match(ip->destination) || - __sum((word *)ip, ip->hdr_len << 2, 0) != 0) { - __pktbuf_free(pkt); - return; - } - - memcpy(r.ip_addr, ip->source, sizeof(ip_addr_t)); - memcpy(r.enet_addr, src_enet_addr, sizeof(enet_addr_t)); - - hdr_bytes = ip->hdr_len << 2; - pkt->pkt_bytes = ntohs(ip->length) - hdr_bytes; - - switch (ip->protocol) { +void __ip_handler(pktbuf_t * pkt, enet_addr_t * src_enet_addr) +{ + ip_header_t *ip = pkt->ip_hdr; + ip_route_t r; + int hdr_bytes; + + /* first make sure its ours and has a good checksum. */ + if (!ip_addr_match(ip->destination) || + __sum((word *) ip, ip->hdr_len << 2, 0) != 0) { + __pktbuf_free(pkt); + return; + } + + memcpy(r.ip_addr, ip->source, sizeof(ip_addr_t)); + memcpy(r.enet_addr, src_enet_addr, sizeof(enet_addr_t)); + + hdr_bytes = ip->hdr_len << 2; + pkt->pkt_bytes = ntohs(ip->length) - hdr_bytes; + + switch (ip->protocol) { #if NET_SUPPORT_ICMP - case IP_PROTO_ICMP: - pkt->icmp_hdr = (icmp_header_t *)(((char *)ip) + hdr_bytes); - __icmp_handler(pkt, &r); - break; + case IP_PROTO_ICMP: + pkt->icmp_hdr = (icmp_header_t *) (((char *)ip) + hdr_bytes); + __icmp_handler(pkt, &r); + break; #endif #if NET_SUPPORT_TCP - case IP_PROTO_TCP: - pkt->tcp_hdr = (tcp_header_t *)(((char *)ip) + hdr_bytes); - __tcp_handler(pkt, &r); - break; + case IP_PROTO_TCP: + pkt->tcp_hdr = (tcp_header_t *) (((char *)ip) + hdr_bytes); + __tcp_handler(pkt, &r); + break; #endif #if NET_SUPPORT_UDP - case IP_PROTO_UDP: - pkt->udp_hdr = (udp_header_t *)(((char *)ip) + hdr_bytes); - __udp_handler(pkt, &r); - break; -#endif - - default: - __pktbuf_free(pkt); - break; - } -} - + case IP_PROTO_UDP: + pkt->udp_hdr = (udp_header_t *) (((char *)ip) + hdr_bytes); + __udp_handler(pkt, &r); + break; +#endif + + default: + __pktbuf_free(pkt); + break; + } +} /* @@ -178,39 +174,36 @@ * options field. */ -int -__ip_send(pktbuf_t *pkt, int protocol, ip_route_t *dest) -{ - ip_header_t *ip = pkt->ip_hdr; - int hdr_bytes; - unsigned short cksum; - - /* - * Figure out header length. The use udp_hdr is - * somewhat arbitrary, but works because it is - * a union with other IP protocol headers. - */ - hdr_bytes = (((char *)pkt->udp_hdr) - ((char *)ip)); - - pkt->pkt_bytes += hdr_bytes; - - ip->version = 4; - ip->hdr_len = hdr_bytes >> 2; - ip->tos = 0; - ip->length = htons(pkt->pkt_bytes); - ip->ident = htons(ip_ident); - ip_ident++; - ip->fragment = 0; - ip->ttl = 255; - ip->ttl = 64; - ip->protocol = protocol; - ip->checksum = 0; - memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t)); - memcpy(ip->destination, dest->ip_addr, sizeof(ip_addr_t)); - cksum = __sum((word *)ip, hdr_bytes, 0); - ip->checksum = htons(cksum); - - __enet_send(pkt, &dest->enet_addr, ETH_TYPE_IP); - return 0; -} - - +int __ip_send(pktbuf_t * pkt, int protocol, ip_route_t * dest) +{ + ip_header_t *ip = pkt->ip_hdr; + int hdr_bytes; + unsigned short cksum; + + /* + * Figure out header length. The use udp_hdr is + * somewhat arbitrary, but works because it is + * a union with other IP protocol headers. + */ + hdr_bytes = (((char *)pkt->udp_hdr) - ((char *)ip)); + + pkt->pkt_bytes += hdr_bytes; + + ip->version = 4; + ip->hdr_len = hdr_bytes >> 2; + ip->tos = 0; + ip->length = htons(pkt->pkt_bytes); + ip->ident = htons(ip_ident); + ip_ident++; + ip->fragment = 0; + ip->ttl = 255; + ip->ttl = 64; + ip->protocol = protocol; + ip->checksum = 0; + memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t)); + memcpy(ip->destination, dest->ip_addr, sizeof(ip_addr_t)); + cksum = __sum((word *) ip, hdr_bytes, 0); + ip->checksum = htons(cksum); + + __enet_send(pkt, &dest->enet_addr, ETH_TYPE_IP); + return 0; +} Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/tftp_client.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/tftp_client.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/tftp_client.c (revision 12368) @@ -56,5 +56,5 @@ // TFTP client support -#include // have_net +#include // have_net #include #include @@ -65,208 +65,218 @@ static struct { - bool open; - int total_timeouts, packets_received; - unsigned long last_good_block; - int avail, actual_len; - struct sockaddr_in local_addr, from_addr; - char data[SEGSIZE+sizeof(struct tftphdr)]; - char *bufp; + bool open; + int total_timeouts, packets_received; + unsigned long last_good_block; + int avail, actual_len; + struct sockaddr_in local_addr, from_addr; + char data[SEGSIZE + sizeof(struct tftphdr)]; + char *bufp; } tftp_stream; -int -tftp_stream_open(connection_info_t *info, - int *err) -{ - struct tftphdr *hdr = (struct tftphdr *)tftp_stream.data; - char *cp, *fp; - char test_buf; - - if (!have_net || tftp_stream.open) { - *err = TFTP_INVALID; // Already open - return -1; - } - - // Create initial request - hdr->th_opcode = htons(RRQ); // Read file - cp = (char *)&hdr->th_stuff; - fp = info->filename; - while (*fp) *cp++ = *fp++; - *cp++ = '\0'; - // 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 (info->server->sin_port == 0) { - info->server->sin_port = htons(TFTP_PORT); - } else { - info->server->sin_port = htons(info->server->sin_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, - info->server, &tftp_stream.local_addr) < 0) { - // Problem sending request - *err = TFTP_NETERR; - return -1; - } - - tftp_stream.open = true; - tftp_stream.avail = 0; - tftp_stream.actual_len = -1; - tftp_stream.last_good_block = 0; - tftp_stream.total_timeouts = 0; - tftp_stream.from_addr.sin_port = 0; - tftp_stream.packets_received = 0; - - // Try and read the first byte [block] since no errors are - // reported until then. - if (tftp_stream_read(&test_buf, 1, err) == 1) { - // Back up [rewind] over this datum - tftp_stream.bufp--; - tftp_stream.avail++; - return 0; // Open and first read successful - } else { - tftp_stream.open = false; - return -1; // Couldn't read - } -} - -static int -tftp_ack(int *err) -{ - struct tftphdr *hdr = (struct tftphdr *)tftp_stream.data; - // ACK last packet so server can shut down - if (tftp_stream.packets_received > 0) { - hdr->th_opcode = htons(ACK); - hdr->th_block = htons((cyg_uint16)tftp_stream.last_good_block & 0xFFFF); - if (__udp_sendto(tftp_stream.data, 4 /* FIXME */, - &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); - tftp_stream.open = false; -} - -int -tftp_stream_read(char *buf, - int len, - int *err) -{ - int total_bytes = 0; - int size, recv_len, data_len; - struct timeval timeout; - struct tftphdr *hdr = (struct tftphdr *)tftp_stream.data; - - while (total_bytes < len) { - // Move any bytes which we've already read/buffered - if (tftp_stream.avail > 0) { - size = tftp_stream.avail; - if (size > (len - total_bytes)) size = len - total_bytes; - memcpy(buf, tftp_stream.bufp, size); - buf += size; - tftp_stream.bufp += size; - tftp_stream.avail -= size; - total_bytes += size; - } else { - if (tftp_ack(err) < 0) { - return -1; - } - if ((tftp_stream.actual_len >= 0) && (tftp_stream.actual_len < SEGSIZE)) { - // Out of data - break; - } - timeout.tv_sec = (tftp_stream.last_good_block == 0) ? 10*TFTP_TIMEOUT_PERIOD : TFTP_TIMEOUT_PERIOD; - timeout.tv_usec = 0; - recv_len = sizeof(tftp_stream.data); - if ((data_len = __udp_recvfrom(&tftp_stream.data[0], recv_len, &tftp_stream.from_addr, - &tftp_stream.local_addr, &timeout)) < 0) { - // No data, try again - diag_printf("TFTP timed out %d/%d\n", tftp_stream.total_timeouts+1, TFTP_TIMEOUT_MAX); - if ((++tftp_stream.total_timeouts > TFTP_TIMEOUT_MAX) || - (tftp_stream.last_good_block == 0)) { - // Timeout - no data received - *err = TFTP_TIMEOUT; - return -1; - } - // Send out the ACK for the last block - maybe server will retry - if (tftp_ack(err) < 0) { - return -1; - } - } else { - tftp_stream.packets_received++; - if (ntohs(hdr->th_opcode) == DATA) { - if (ntohs(hdr->th_block) == (cyg_uint16)((tftp_stream.last_good_block+1) & 0xFFFF)) { - // Consume this data - data_len -= 4; /* Sizeof TFTP header */ - tftp_stream.avail = tftp_stream.actual_len = data_len; - tftp_stream.bufp = hdr->th_data; - tftp_stream.last_good_block++; - } - } 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; - } - } - } - } - } - return total_bytes; -} - -char * -tftp_error(int err) -{ - char *errmsg = "Unknown error"; - - switch (err) { - case TFTP_ENOTFOUND: - return "file not found"; - case TFTP_EACCESS: - return "access violation"; - case TFTP_ENOSPACE: - return "disk full or allocation exceeded"; - case TFTP_EBADOP: - return "illegal TFTP operation"; - case TFTP_EBADID: - return "unknown transfer ID"; - case TFTP_EEXISTS: - return "file already exists"; - case TFTP_ENOUSER: - return "no such user"; - case TFTP_TIMEOUT: - return "operation timed out"; - case TFTP_NETERR: - return "some sort of network error"; - case TFTP_INVALID: - return "invalid parameter"; - case TFTP_PROTOCOL: - return "protocol violation"; - case TFTP_TOOLARGE: - return "file is larger than buffer"; - } - return errmsg; +int tftp_stream_open(connection_info_t * info, int *err) +{ + struct tftphdr *hdr = (struct tftphdr *)tftp_stream.data; + char *cp, *fp; + char test_buf; + + if (!have_net || tftp_stream.open) { + *err = TFTP_INVALID; // Already open + return -1; + } + // Create initial request + hdr->th_opcode = htons(RRQ); // Read file + cp = (char *)&hdr->th_stuff; + fp = info->filename; + while (*fp) + *cp++ = *fp++; + *cp++ = '\0'; + // 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 (info->server->sin_port == 0) { + info->server->sin_port = htons(TFTP_PORT); + } else { + info->server->sin_port = htons(info->server->sin_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, + info->server, &tftp_stream.local_addr) < 0) { + // Problem sending request + *err = TFTP_NETERR; + return -1; + } + + tftp_stream.open = true; + tftp_stream.avail = 0; + tftp_stream.actual_len = -1; + tftp_stream.last_good_block = 0; + tftp_stream.total_timeouts = 0; + tftp_stream.from_addr.sin_port = 0; + tftp_stream.packets_received = 0; + + // Try and read the first byte [block] since no errors are + // reported until then. + if (tftp_stream_read(&test_buf, 1, err) == 1) { + // Back up [rewind] over this datum + tftp_stream.bufp--; + tftp_stream.avail++; + return 0; // Open and first read successful + } else { + tftp_stream.open = false; + return -1; // Couldn't read + } +} + +static int tftp_ack(int *err) +{ + struct tftphdr *hdr = (struct tftphdr *)tftp_stream.data; + // ACK last packet so server can shut down + if (tftp_stream.packets_received > 0) { + hdr->th_opcode = htons(ACK); + hdr->th_block = + htons((cyg_uint16) tftp_stream.last_good_block & 0xFFFF); + if (__udp_sendto(tftp_stream.data, 4 /* FIXME */ , + &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); + tftp_stream.open = false; +} + +int tftp_stream_read(char *buf, int len, int *err) +{ + int total_bytes = 0; + int size, recv_len, data_len; + struct timeval timeout; + struct tftphdr *hdr = (struct tftphdr *)tftp_stream.data; + + while (total_bytes < len) { + // Move any bytes which we've already read/buffered + if (tftp_stream.avail > 0) { + size = tftp_stream.avail; + if (size > (len - total_bytes)) + size = len - total_bytes; + memcpy(buf, tftp_stream.bufp, size); + buf += size; + tftp_stream.bufp += size; + tftp_stream.avail -= size; + total_bytes += size; + } else { + if (tftp_ack(err) < 0) { + return -1; + } + if ((tftp_stream.actual_len >= 0) + && (tftp_stream.actual_len < SEGSIZE)) { + // Out of data + break; + } + timeout.tv_sec = + (tftp_stream.last_good_block == + 0) ? 10 * + TFTP_TIMEOUT_PERIOD : TFTP_TIMEOUT_PERIOD; + timeout.tv_usec = 0; + recv_len = sizeof(tftp_stream.data); + if ((data_len = + __udp_recvfrom(&tftp_stream.data[0], recv_len, + &tftp_stream.from_addr, + &tftp_stream.local_addr, + &timeout)) < 0) { + // No data, try again + diag_printf("TFTP timed out %d/%d\n", + tftp_stream.total_timeouts + 1, + TFTP_TIMEOUT_MAX); + if ((++tftp_stream.total_timeouts > + TFTP_TIMEOUT_MAX) + || (tftp_stream.last_good_block == 0)) { + // Timeout - no data received + *err = TFTP_TIMEOUT; + return -1; + } + // Send out the ACK for the last block - maybe server will retry + if (tftp_ack(err) < 0) { + return -1; + } + } else { + tftp_stream.packets_received++; + if (ntohs(hdr->th_opcode) == DATA) { + if (ntohs(hdr->th_block) == + (cyg_uint16) ((tftp_stream.last_good_block + 1) & 0xFFFF)) { + // Consume this data + data_len -= 4; /* Sizeof TFTP header */ + tftp_stream.avail = + tftp_stream.actual_len = + data_len; + tftp_stream.bufp = hdr->th_data; + tftp_stream.last_good_block++; + } + } 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; + } + } + } + } + } + return total_bytes; +} + +char *tftp_error(int err) +{ + char *errmsg = "Unknown error"; + + switch (err) { + case TFTP_ENOTFOUND: + return "file not found"; + case TFTP_EACCESS: + return "access violation"; + case TFTP_ENOSPACE: + return "disk full or allocation exceeded"; + case TFTP_EBADOP: + return "illegal TFTP operation"; + case TFTP_EBADID: + return "unknown transfer ID"; + case TFTP_EEXISTS: + return "file already exists"; + case TFTP_ENOUSER: + return "no such user"; + case TFTP_TIMEOUT: + return "operation timed out"; + case TFTP_NETERR: + return "some sort of network error"; + case TFTP_INVALID: + return "invalid parameter"; + case TFTP_PROTOCOL: + return "protocol violation"; + case TFTP_TOOLARGE: + return "file is larger than buffer"; + } + return errmsg; } @@ -275,5 +285,4 @@ // GETC_IO_FUNCS(tftp_io, tftp_stream_open, tftp_stream_close, - 0, tftp_stream_read, tftp_error); + 0, tftp_stream_read, tftp_error); RedBoot_load(tftp, tftp_io, true, true, 0); - Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade_ubnt.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade_ubnt.c (revision 12368) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade_ubnt.c (revision 12368) @@ -0,0 +1,199 @@ +/* +firmware upgrade code for UBNT images +huge parts are taken from ubnt fwsplit utility + +2009, Sebastian Gottschall +*/ + +#include +#include +#include +#include +#include "fwupgrade_ubnt.h" + +/* some variables from flash.c */ +extern void *flash_start, *flash_end; +extern int flash_block_size, flash_num_blocks; +#ifdef CYGOPT_REDBOOT_FIS +extern void *fis_work_block; +extern void *fis_addr; +extern int fisdir_size; // Size of FIS directory. +#endif +//extern void _show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat); +extern void fis_update_directory(void); + +//#define TRACE diag_printf("DBG: %s:%d\n", __FUNCTION__, __LINE__) + +#define TRACE + +#define MAX_PARTS 8 + +typedef struct fw_part { + part_t *header; + unsigned char *data; + u_int32_t data_size; + part_crc_t *signature; +} fw_part_t; + +typedef struct fw { + u_int32_t size; + char version[256]; + fw_part_t parts[MAX_PARTS]; + int part_count; +} fw_t; + +#define crc32 cyg_ether_crc32_accumulate + +extern void fis_init(int argc, char *argv[], int force); + +int fw_check_image_ubnt(unsigned char *addr, unsigned long maxlen, int do_flash) +{ + header_t *header = (header_t *) addr; + fw_t fw; + int len = sizeof(header_t) - (2 * sizeof(u_int32_t)); + unsigned int crc = crc32(0L, (unsigned char *)header, len); + signature_t *sig; + fw.size = maxlen; + if (htonl(crc) != header->crc) { + diag_printf("UBNT_FW: header crc failed\n"); + return -1; + } + memcpy(fw.version, header->version, sizeof(fw.version)); + if (do_flash) + diag_printf("UBNT_FW: Firmware version: '%s'\n", + header->version); + part_t *p; + p = (part_t *) (addr + sizeof(header_t)); + int i = 0; + while (strncmp(p->magic, MAGIC_END, MAGIC_LENGTH) != 0) { + if (do_flash) { + diag_printf("Partition: %s [%u]\n", p->name, + ntohl(p->index)); + diag_printf("Partition size: 0x%X\n", + ntohl(p->part_size)); + diag_printf("Data size: %u\n", ntohl(p->data_size)); + } + if ((strncmp(p->magic, MAGIC_PART, MAGIC_LENGTH) == 0) + && (i < MAX_PARTS)) { + fw_part_t *fwp = &fw.parts[i]; + + fwp->header = p; + fwp->data = (unsigned char *)p + sizeof(part_t); + fwp->data_size = ntohl(p->data_size); + fwp->signature = + (part_crc_t *) (fwp->data + fwp->data_size); + crc = + htonl(crc32 + (0L, (unsigned char *)p, + fwp->data_size + sizeof(part_t))); + if (crc != fwp->signature->crc) { + diag_printf + ("UBNT_FW: Invalid '%s' CRC (claims: %u, but is %u)\n", + fwp->header->name, fwp->signature->crc, + crc); + return -1; + } + ++i; + } + + p = (part_t *) ((unsigned char *)p + sizeof(part_t) + + ntohl(p->data_size) + sizeof(part_crc_t)); + + /* check bounds */ + if (((unsigned char *)p - addr) >= maxlen) { + return -3; + } + } + + fw.part_count = i; + + sig = (signature_t *) p; + if (strncmp(sig->magic, MAGIC_END, MAGIC_LENGTH) != 0) { + diag_printf("UBNT_FW: Bad firmware signature\n"); + return -4; + } + + crc = htonl(crc32(0L, addr, (unsigned char *)sig - addr)); + if (crc != sig->crc) { + diag_printf + ("UBNT_FW: Invalid signature CRC (claims: %u, but is %u)\n", + sig->crc, crc); + return -5; + } + + if (do_flash) { + char *arg[] = { "fis", "init" }; + fis_init(2, arg, 1); + void *err_addr; + flash_read(fis_addr, fis_work_block, fisdir_size, + (void **)&err_addr); + struct fis_image_desc *img = fis_lookup("RedBoot", &i); + if (i != 0) { + diag_printf + ("UBNT_FW: RedBoot partition is not the first partition\n"); + return -1; + } + for (i = 0; i < fw.part_count; ++i) { + fw_part_t *fwp = &fw.parts[i]; + /* do not flash bootloaders bigger than 64kb, since it makes no sense to step back */ + if (!strncmp(fwp->header->name, "RedBoot", 7) + && ntohl(fwp->header->part_size) > 0x10000) { + diag_printf("ignore %s\n", fwp->header->name); + continue; + } + diag_printf("UBNT_FW: Flashing: %s\n", + fwp->header->name); + int stat; + + unsigned int base = ntohl(fwp->header->baseaddr); + /* convert flash mappings to fit to the current bootloader flash mapping which might be incompatible */ + if ((base & 0xbfc00000) == 0xbfc00000) { + base ^= 0xbfc00000; + } else if ((base & 0xbe00000) == 0xbe00000) { + base ^= 0xbe00000; + } else if ((base & 0xa800000) == 0xa800000) { + base ^= 0xa800000; + } + base |= CYGNUM_FLASH_BASE; + if ((stat = + flash_erase((void *)base, + ntohl(fwp->header->part_size), + (void **)&err_addr)) != 0) { + diag_printf + ("UBNT_FW: Can't erase region at %p: %s\n", + err_addr, flash_errmsg(stat)); + return -1; + } + if ((stat = + flash_program((void *)base, + (void *)fwp->data, + ntohl(fwp->data_size), + (void **)&err_addr)) != 0) { + diag_printf + ("UBNT_FW: Can't program region at %p: %s\n", + err_addr, flash_errmsg(stat)); + return -1; + } + int index; + img = (struct fis_image_desc *)fis_work_block; + for (index = 0; + index < fisdir_size / sizeof(*img); + index++, img++) { + if (img->name[0] == (unsigned char)0xFF) { + break; + } + } + strcpy(img->name, fwp->header->name); + img->flash_base = base; + img->mem_base = ntohl(fwp->header->memaddr); + img->entry_point = ntohl(fwp->header->entryaddr); // Hope it's been set + img->size = ntohl(fwp->header->part_size); + img->data_length = ntohl(fwp->header->data_size); + + } + fis_update_directory(); + diag_printf("UBNT_FW: flashing done\n"); + } + + return 0; +} Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade_wili.h =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade_wili.h (revision 12368) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade_wili.h (revision 12368) @@ -0,0 +1,15 @@ + +#ifndef __wili_fw__ +#define __wili_fw__ + +extern int fw_check_image_wili(unsigned char *addr, unsigned long maxlen, + int do_flash); + +/***********************************************************************************/ + +/* these variables will be initialized in do_tftpd() */ +CYG_ADDRWORD BASE_ADDR; +CYG_ADDRWORD FW_TEMP_BASE; +/***********************************************************************************/ + +#endif /* __wilibox_fw__ */ Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/http_client.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/http_client.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/http_client.c (revision 12368) @@ -56,5 +56,5 @@ // HTTP client support -#include // have_net +#include // have_net #include #include @@ -63,187 +63,197 @@ static int get_port = 7800; -static struct _stream{ - bool open; - int avail, actual_len, pos, filelen; - char data[4096]; - char *bufp; - tcp_socket_t sock; +static struct _stream { + bool open; + int avail, actual_len, pos, filelen; + char data[4096]; + char *bufp; + tcp_socket_t sock; } http_stream; -static __inline__ int -min(int a, int b) -{ - if (a < b) - return a; - else - return b; -} - -int -http_stream_open(connection_info_t *info, int *err) -{ - int res; - struct _stream *s = &http_stream; - - if (!info->server->sin_port) - 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", info->filename); - __tcp_write_block(&s->sock, s->data, strlen(s->data)); - s->avail = 0; - s->open = true; - s->pos = 0; - return 0; -} - -void -http_stream_close(int *err) -{ - struct _stream *s = &http_stream; - - if (s->open) { - __tcp_abort(&s->sock,1); - s->open = false; - } -} - -int -http_stream_read(char *buf, - int len, - int *err) -{ - struct _stream *s = &http_stream; - int total = 0; - int cnt, code; - - if (!s->open) { - return -1; // Shouldn't happen, but... - } - while (len) { - while (s->avail == 0) { - // Need to wait for some data to arrive - __tcp_poll(); - if (s->sock.state != _ESTABLISHED) { - if (s->sock.state == _CLOSE_WAIT) { - // This connection is breaking - if (s->sock.data_bytes == 0 && s->sock.rxcnt == 0) { - __tcp_close(&s->sock); - return total; - } - } else if (s->sock.state == _CLOSED) { - // The connection is gone - s->open = false; - return -1; - } else { - *err = HTTP_IO; - return -1; +static __inline__ int min(int a, int b) +{ + if (a < b) + return a; + else + return b; +} + +int http_stream_open(connection_info_t * info, int *err) +{ + int res; + struct _stream *s = &http_stream; + + if (!info->server->sin_port) + 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", info->filename); + __tcp_write_block(&s->sock, s->data, strlen(s->data)); + s->avail = 0; + s->open = true; + s->pos = 0; + return 0; +} + +void http_stream_close(int *err) +{ + struct _stream *s = &http_stream; + + if (s->open) { + __tcp_abort(&s->sock, 1); + s->open = false; + } +} + +int http_stream_read(char *buf, int len, int *err) +{ + struct _stream *s = &http_stream; + int total = 0; + int cnt, code; + + if (!s->open) { + return -1; // Shouldn't happen, but... + } + while (len) { + while (s->avail == 0) { + // Need to wait for some data to arrive + __tcp_poll(); + if (s->sock.state != _ESTABLISHED) { + if (s->sock.state == _CLOSE_WAIT) { + // This connection is breaking + if (s->sock.data_bytes == 0 + && s->sock.rxcnt == 0) { + __tcp_close(&s->sock); + return total; + } + } else if (s->sock.state == _CLOSED) { + // The connection is gone + s->open = false; + return -1; + } else { + *err = HTTP_IO; + return -1; + } + } + s->actual_len = + __tcp_read(&s->sock, s->data, sizeof(s->data)); + if (s->actual_len > 0) { + s->bufp = s->data; + s->avail = s->actual_len; + if (s->pos == 0) { + // First data - need to scan HTTP response header + if (strncmp(s->bufp, "HTTP/", 5) == 0) { + // Should look like "HTTP/1.1 200 OK" + s->bufp += 5; + s->avail -= 5; + // Find first space + while ((s->avail > 0) + && (*s->bufp != ' ')) { + s->bufp++; + s->avail--; + } + // Now the integer response + code = 0; + while ((s->avail > 0) + && (*s->bufp == ' ')) { + s->bufp++; + s->avail--; + } + while ((s->avail > 0) + && isdigit(*s->bufp)) { + code = + (code * 10) + + (*s->bufp - '0'); + s->bufp++; + s->avail--; + } + // Make sure it says OK + while ((s->avail > 0) + && (*s->bufp == ' ')) { + s->bufp++; + s->avail--; + } + if (strncmp(s->bufp, "OK", 2)) { + switch (code) { + case 400: + *err = + HTTP_BADREQ; + break; + case 404: + *err = + HTTP_NOFILE; + break; + default: + *err = + HTTP_BADHDR; + break; + } + return -1; + } + // Find \r\n\r\n - end of HTTP preamble + while (s->avail >= 4) { + // This could be done faster, but not simpler + if (strncmp + (s->bufp, + "\r\n\r\n", + 4) == 0) { + s->bufp += 4; + s->avail -= 4; +#if 0 // DEBUG - show header + *(s->bufp - 2) = + '\0'; + diag_printf + (s->data); +#endif + break; + } + s->avail--; + s->bufp++; + } + s->pos++; + } else { + // Unrecognized response + *err = HTTP_BADHDR; + return -1; + } + } + } else if (s->actual_len < 0) { + *err = HTTP_IO; + return -1; + } } - } - s->actual_len = __tcp_read(&s->sock, s->data, sizeof(s->data)); - if (s->actual_len > 0) { - s->bufp = s->data; - s->avail = s->actual_len; - if (s->pos == 0) { - // First data - need to scan HTTP response header - if (strncmp(s->bufp, "HTTP/", 5) == 0) { - // Should look like "HTTP/1.1 200 OK" - s->bufp += 5; - s->avail -= 5; - // Find first space - while ((s->avail > 0) && (*s->bufp != ' ')) { - s->bufp++; - s->avail--; - } - // Now the integer response - code = 0; - while ((s->avail > 0) && (*s->bufp == ' ')) { - s->bufp++; - s->avail--; - } - while ((s->avail > 0) && isdigit(*s->bufp)) { - code = (code * 10) + (*s->bufp - '0'); - s->bufp++; - s->avail--; - } - // Make sure it says OK - while ((s->avail > 0) && (*s->bufp == ' ')) { - s->bufp++; - s->avail--; - } - if (strncmp(s->bufp, "OK", 2)) { - switch (code) { - case 400: - *err = HTTP_BADREQ; - break; - case 404: - *err = HTTP_NOFILE; - break; - default: - *err = HTTP_BADHDR; - break; - } - return -1; - } - // Find \r\n\r\n - end of HTTP preamble - while (s->avail >= 4) { - // This could be done faster, but not simpler - if (strncmp(s->bufp, "\r\n\r\n", 4) == 0) { - s->bufp += 4; - s->avail -= 4; -#if 0 // DEBUG - show header - *(s->bufp-2) = '\0'; - diag_printf(s->data); -#endif - break; - } - s->avail--; - s->bufp++; - } - s->pos++; - } else { - // Unrecognized response - *err = HTTP_BADHDR; - return -1; - } - } - } else if (s->actual_len < 0) { - *err = HTTP_IO; - return -1; - } - } - cnt = min(len, s->avail); - memcpy(buf, s->bufp, cnt); - s->avail -= cnt; - s->bufp += cnt; - buf += cnt; - total += cnt; - len -= cnt; - } - return total; -} - -char * -http_error(int err) -{ - char *errmsg = "Unknown error"; - - switch (err) { - case HTTP_NOERR: - return ""; - case HTTP_BADHDR: - return "Unrecognized HTTP response"; - case HTTP_BADREQ: - return "Bad HTTP request (check file name)"; - case HTTP_NOFILE: - return "No such file"; - case HTTP_OPEN: - return "Can't connect to host"; - case HTTP_IO: - return "I/O error"; - } - return errmsg; + cnt = min(len, s->avail); + memcpy(buf, s->bufp, cnt); + s->avail -= cnt; + s->bufp += cnt; + buf += cnt; + total += cnt; + len -= cnt; + } + return total; +} + +char *http_error(int err) +{ + char *errmsg = "Unknown error"; + + switch (err) { + case HTTP_NOERR: + return ""; + case HTTP_BADHDR: + return "Unrecognized HTTP response"; + case HTTP_BADREQ: + return "Bad HTTP request (check file name)"; + case HTTP_NOFILE: + return "No such file"; + case HTTP_OPEN: + return "Can't connect to host"; + case HTTP_IO: + return "I/O error"; + } + return errmsg; } @@ -252,4 +262,4 @@ // GETC_IO_FUNCS(http_io, http_stream_open, http_stream_close, - 0, http_stream_read, http_error); + 0, http_stream_read, http_error); RedBoot_load(http, http_io, true, true, 0); Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/net_io.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/net_io.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/net_io.c (revision 12368) @@ -56,9 +56,9 @@ #include #include -#include // Helper functions -#include // HAL I/O interfaces +#include // Helper functions +#include // HAL I/O interfaces #include #include -#include // assertion macros +#include // assertion macros #ifdef CYGSEM_REDBOOT_FLASH_CONFIG @@ -66,9 +66,7 @@ RedBoot_config_option("GDB connection port", - gdb_port, - ALWAYS_ENABLED, true, - CONFIG_INT, - CYGNUM_REDBOOT_NETWORKING_TCP_PORT - ); + gdb_port, + ALWAYS_ENABLED, true, + CONFIG_INT, CYGNUM_REDBOOT_NETWORKING_TCP_PORT); //RedBoot_config_option("Network debug at boot time", // net_debug, @@ -78,10 +76,6 @@ // ); #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1) -RedBoot_config_option("Default network device", - net_device, - ALWAYS_ENABLED, true, - CONFIG_NETPORT, - "" - ); +RedBoot_config_option("Default network device", + net_device, ALWAYS_ENABLED, true, CONFIG_NETPORT, ""); #endif // Note: the following options are related. If 'bootp' is false, then @@ -97,49 +91,25 @@ #endif RedBoot_config_option("Use BOOTP for network configuration", - bootp, - ALWAYS_ENABLED, true, - CONFIG_BOOL, - !CYGSEM_REDBOOT_DEFAULT_NO_BOOTP - ); + bootp, + ALWAYS_ENABLED, true, + CONFIG_BOOL, !CYGSEM_REDBOOT_DEFAULT_NO_BOOTP); RedBoot_config_option("Local IP address", - bootp_my_ip, - "bootp", false, - CONFIG_IP, - 0 - ); + bootp_my_ip, "bootp", false, CONFIG_IP, 0); #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY RedBoot_config_option("Local IP address mask", - bootp_my_ip_mask, - "bootp", false, - CONFIG_IP, - 0 - ); + bootp_my_ip_mask, "bootp", false, CONFIG_IP, 0); RedBoot_config_option("Gateway IP address", - bootp_my_gateway_ip, - "bootp", false, - CONFIG_IP, - 0 - ); + bootp_my_gateway_ip, "bootp", false, CONFIG_IP, 0); #endif RedBoot_config_option("Default server IP address", - bootp_server_ip, - ALWAYS_ENABLED, true, - CONFIG_IP, - 0 - ); + bootp_server_ip, ALWAYS_ENABLED, true, CONFIG_IP, 0); // Note: the following options are related too. RedBoot_config_option("Force console for special debug messages", - info_console_force, - ALWAYS_ENABLED, true, - CONFIG_BOOL, - false - ); + info_console_force, + ALWAYS_ENABLED, true, CONFIG_BOOL, false); RedBoot_config_option("Console number for special debug messages", - info_console_number, - "info_console_force", true, - CONFIG_INT, - 0 - ); + info_console_number, + "info_console_force", true, CONFIG_INT, 0); #endif @@ -148,5 +118,5 @@ #ifdef DEBUG_TCP int show_tcp = 0; -#endif +#endif static tcp_socket_t tcp_sock; @@ -166,405 +136,408 @@ static void net_io_flush(void); static void net_io_revert_console(void); -static void net_io_putc(void*, cyg_uint8); +static void net_io_putc(void *, cyg_uint8); // Special characters used by Telnet - must be interpretted here -#define TELNET_IAC 0xFF // Interpret as command (escape) -#define TELNET_IP 0xF4 // Interrupt process -#define TELNET_WONT 0xFC // I Won't do it -#define TELNET_DO 0xFD // Will you XXX -#define TELNET_TM 0x06 // Time marker (special DO/WONT after IP) - -static cyg_bool -_net_io_getc_nonblock(void* __ch_data, cyg_uint8* ch) -{ - if (in_buflen == 0) { - __tcp_poll(); - if (tcp_sock.state == _CLOSE_WAIT) { - // This connection is breaking - if (tcp_sock.data_bytes == 0 && tcp_sock.rxcnt == 0) { - __tcp_close(&tcp_sock); - return false; - } - } - if (tcp_sock.state == _CLOSED) { - // The connection is gone - net_io_revert_console(); - *ch = '\n'; - return true; - } - in_buflen = __tcp_read(&tcp_sock, in_buf, sizeof(in_buf)); - in_bufp = in_buf; +#define TELNET_IAC 0xFF // Interpret as command (escape) +#define TELNET_IP 0xF4 // Interrupt process +#define TELNET_WONT 0xFC // I Won't do it +#define TELNET_DO 0xFD // Will you XXX +#define TELNET_TM 0x06 // Time marker (special DO/WONT after IP) + +static cyg_bool _net_io_getc_nonblock(void *__ch_data, cyg_uint8 * ch) +{ + if (in_buflen == 0) { + __tcp_poll(); + if (tcp_sock.state == _CLOSE_WAIT) { + // This connection is breaking + if (tcp_sock.data_bytes == 0 && tcp_sock.rxcnt == 0) { + __tcp_close(&tcp_sock); + return false; + } + } + if (tcp_sock.state == _CLOSED) { + // The connection is gone + net_io_revert_console(); + *ch = '\n'; + return true; + } + in_buflen = __tcp_read(&tcp_sock, in_buf, sizeof(in_buf)); + in_bufp = in_buf; #ifdef DEBUG_TCP - if (show_tcp && (in_buflen > 0)) { - int old_console; - old_console = start_console(); - diag_printf("%s:%d\n", __FUNCTION__, __LINE__); - diag_dump_buf(in_buf, in_buflen); - end_console(old_console); - } -#endif // DEBUG_TCP - } - if (in_buflen) { - *ch = *in_bufp++; - in_buflen--; - return true; - } else { - return false; - } -} - -static cyg_bool -net_io_getc_nonblock(void* __ch_data, cyg_uint8* ch) -{ - cyg_uint8 esc; - - if (!_net_io_getc_nonblock(__ch_data, ch)) - return false; - - if (gdb_active || *ch != TELNET_IAC) - return true; - - // Telnet escape - need to read/handle more - while (!_net_io_getc_nonblock(__ch_data, &esc)) ; - - switch (esc) { - case TELNET_IAC: - // The other special case - escaped escape - return true; - case TELNET_IP: - // Special case for ^C == Interrupt Process - *ch = 0x03; - // Just in case the other end needs synchronizing - net_io_putc(__ch_data, TELNET_IAC); - net_io_putc(__ch_data, TELNET_WONT); - net_io_putc(__ch_data, TELNET_TM); - net_io_flush(); - return true; - case TELNET_DO: - // Telnet DO option - while (!_net_io_getc_nonblock(__ch_data, &esc)) ; - // Respond with WONT option - net_io_putc(__ch_data, TELNET_IAC); - net_io_putc(__ch_data, TELNET_WONT); - net_io_putc(__ch_data, esc); - return false; // Ignore this whole thing! - default: - return false; - } -} - -static cyg_uint8 -net_io_getc(void* __ch_data) -{ - cyg_uint8 ch; - int idle_timeout = 10; // 10ms - - CYGARC_HAL_SAVE_GP(); - while (true) { - if (net_io_getc_nonblock(__ch_data, &ch)) break; - if (--idle_timeout == 0) { - net_io_flush(); - idle_timeout = 10; - } - } - CYGARC_HAL_RESTORE_GP(); - return ch; + if (show_tcp && (in_buflen > 0)) { + int old_console; + old_console = start_console(); + diag_printf("%s:%d\n", __FUNCTION__, __LINE__); + diag_dump_buf(in_buf, in_buflen); + end_console(old_console); + } +#endif // DEBUG_TCP + } + if (in_buflen) { + *ch = *in_bufp++; + in_buflen--; + return true; + } else { + return false; + } +} + +static cyg_bool net_io_getc_nonblock(void *__ch_data, cyg_uint8 * ch) +{ + cyg_uint8 esc; + + if (!_net_io_getc_nonblock(__ch_data, ch)) + return false; + + if (gdb_active || *ch != TELNET_IAC) + return true; + + // Telnet escape - need to read/handle more + while (!_net_io_getc_nonblock(__ch_data, &esc)) ; + + switch (esc) { + case TELNET_IAC: + // The other special case - escaped escape + return true; + case TELNET_IP: + // Special case for ^C == Interrupt Process + *ch = 0x03; + // Just in case the other end needs synchronizing + net_io_putc(__ch_data, TELNET_IAC); + net_io_putc(__ch_data, TELNET_WONT); + net_io_putc(__ch_data, TELNET_TM); + net_io_flush(); + return true; + case TELNET_DO: + // Telnet DO option + while (!_net_io_getc_nonblock(__ch_data, &esc)) ; + // Respond with WONT option + net_io_putc(__ch_data, TELNET_IAC); + net_io_putc(__ch_data, TELNET_WONT); + net_io_putc(__ch_data, esc); + return false; // Ignore this whole thing! + default: + return false; + } +} + +static cyg_uint8 net_io_getc(void *__ch_data) +{ + cyg_uint8 ch; + int idle_timeout = 10; // 10ms + + CYGARC_HAL_SAVE_GP(); + while (true) { + if (net_io_getc_nonblock(__ch_data, &ch)) + break; + if (--idle_timeout == 0) { + net_io_flush(); + idle_timeout = 10; + } + } + CYGARC_HAL_RESTORE_GP(); + return ch; +} + +static void net_io_flush(void) +{ + int n; + char *bp = out_buf; + +#ifdef DEBUG_TCP + if (show_tcp) { + int old_console; + old_console = start_console(); + diag_printf("%s.%d\n", __FUNCTION__, __LINE__); + diag_dump_buf(out_buf, out_buflen); + end_console(old_console); + } +#endif // SHOW_TCP + n = __tcp_write_block(&tcp_sock, bp, out_buflen); + if (n < 0) { + // The connection is gone! + net_io_revert_console(); + } else { + out_buflen -= n; + bp += n; + } + out_bufp = out_buf; + out_buflen = 0; + // Check interrupt flag + if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) { + CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0); + cyg_hal_user_break(0); + } +} + +static void net_io_putc(void *__ch_data, cyg_uint8 c) +{ + static bool have_dollar, have_hash; + static int hash_count; + + CYGARC_HAL_SAVE_GP(); + *out_bufp++ = c; + if (c == '$') + have_dollar = true; + if (have_dollar && (c == '#')) { + have_hash = true; + hash_count = 0; + } + if ((++out_buflen == sizeof(out_buf)) || + (flush_output_lines && c == '\n') || + (have_hash && (++hash_count == 3))) { + net_io_flush(); + have_dollar = false; + } + CYGARC_HAL_RESTORE_GP(); } static void -net_io_flush(void) -{ - int n; - char *bp = out_buf; - +net_io_write(void *__ch_data, const cyg_uint8 * __buf, cyg_uint32 __len) +{ + int old_console; + + old_console = start_console(); + diag_printf("%s.%d\n", __FUNCTION__, __LINE__); + end_console(old_console); +#if 0 + CYGARC_HAL_SAVE_GP(); + + while (__len-- > 0) + net_io_putc(__ch_data, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +#endif +} + +static void net_io_read(void *__ch_data, cyg_uint8 * __buf, cyg_uint32 __len) +{ + int old_console; + + old_console = start_console(); + diag_printf("%s.%d\n", __FUNCTION__, __LINE__); + end_console(old_console); +#if 0 + CYGARC_HAL_SAVE_GP(); + + while (__len-- > 0) + *__buf++ = net_io_getc(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +#endif +} + +static cyg_bool net_io_getc_timeout(void *__ch_data, cyg_uint8 * ch) +{ + int delay_count; + cyg_bool res; + + CYGARC_HAL_SAVE_GP(); + net_io_flush(); // Make sure any output has been sent + delay_count = _timeout; + + for (;;) { + res = net_io_getc_nonblock(__ch_data, ch); + if (res || 0 == delay_count--) + break; + } + + CYGARC_HAL_RESTORE_GP(); + + return res; +} + +static int net_io_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + static int vector = 0; + int ret = 0; + static int irq_state = 0; + + CYGARC_HAL_SAVE_GP(); + + switch (__func) { + case __COMMCTL_IRQ_ENABLE: + irq_state = 1; + if (vector == 0) { + vector = eth_drv_int_vector(); + } + HAL_INTERRUPT_UNMASK(vector); + break; + case __COMMCTL_IRQ_DISABLE: + ret = irq_state; + irq_state = 0; + if (vector == 0) { + vector = eth_drv_int_vector(); + } + HAL_INTERRUPT_MASK(vector); + break; + case __COMMCTL_DBG_ISR_VECTOR: + ret = vector; + break; + case __COMMCTL_SET_TIMEOUT: + { + va_list ap; + + va_start(ap, __func); + + ret = _timeout; + _timeout = va_arg(ap, cyg_uint32); + + va_end(ap); + break; + } + case __COMMCTL_FLUSH_OUTPUT: + net_io_flush(); + break; + case __COMMCTL_ENABLE_LINE_FLUSH: + flush_output_lines = true; + break; + case __COMMCTL_DISABLE_LINE_FLUSH: + flush_output_lines = false; + break; + default: + break; + } + CYGARC_HAL_RESTORE_GP(); + return ret; +} + +static int +net_io_isr(void *__ch_data, int *__ctrlc, + CYG_ADDRWORD __vector, CYG_ADDRWORD __data) +{ + char ch; + + CYGARC_HAL_SAVE_GP(); + *__ctrlc = 0; + if (net_io_getc_nonblock(__ch_data, &ch)) { + if (ch == 0x03) { + *__ctrlc = 1; + } + } + CYGARC_HAL_RESTORE_GP(); + return CYG_ISR_HANDLED; +} + +// TEMP + +int start_console(void) +{ + int cur_console = + CYGACC_CALL_IF_SET_CONSOLE_COMM + (CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + +#ifdef CYGSEM_REDBOOT_FLASH_CONFIG + int i = 0; + if (flash_get_config("info_console_force", &i, CONFIG_BOOL)) + if (i) + if (!flash_get_config + ("info_console_number", &i, CONFIG_INT)) + i = 0; // the default, if that call failed. + if (i) + CYGACC_CALL_IF_SET_CONSOLE_COMM(i); + else +#endif + CYGACC_CALL_IF_SET_CONSOLE_COMM(0); + + return cur_console; +} + +void end_console(int old_console) +{ + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM(old_console); +} + +// TEMP + +static void net_io_revert_console(void) +{ +#ifdef CYGPKG_REDBOOT_ANY_CONSOLE + console_selected = false; +#endif + CYGACC_CALL_IF_SET_CONSOLE_COMM(orig_console); + CYGACC_CALL_IF_SET_DEBUG_COMM(orig_debug); + console_echo = true; +} + +static void net_io_assume_console(void) +{ +#ifdef CYGPKG_REDBOOT_ANY_CONSOLE + console_selected = true; +#endif + console_echo = false; + orig_console = + CYGACC_CALL_IF_SET_CONSOLE_COMM + (CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL); + orig_debug = + CYGACC_CALL_IF_SET_DEBUG_COMM + (CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + CYGACC_CALL_IF_SET_DEBUG_COMM(TCP_CHANNEL); +} + +static void net_io_init(void) +{ + static int init = 0; + if (!init) { + hal_virtual_comm_table_t *comm; + int cur = + CYGACC_CALL_IF_SET_CONSOLE_COMM + (CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Setup procs in the vector table + CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + //CYGACC_COMM_IF_CH_DATA_SET(*comm, chan); + CYGACC_COMM_IF_WRITE_SET(*comm, net_io_write); + CYGACC_COMM_IF_READ_SET(*comm, net_io_read); + CYGACC_COMM_IF_PUTC_SET(*comm, net_io_putc); + CYGACC_COMM_IF_GETC_SET(*comm, net_io_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, net_io_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, net_io_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, net_io_getc_timeout); + + // Disable interrupts via this interface to set static + // state into correct state. + net_io_control(comm, __COMMCTL_IRQ_DISABLE); + + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); + + init = 1; + gdb_active = false; + } + __tcp_listen(&tcp_sock, gdb_port); + state = tcp_sock.state; #ifdef DEBUG_TCP - if (show_tcp) { - int old_console; - old_console = start_console(); - diag_printf("%s.%d\n", __FUNCTION__, __LINE__); - diag_dump_buf(out_buf, out_buflen); - end_console(old_console); - } -#endif // SHOW_TCP - n = __tcp_write_block(&tcp_sock, bp, out_buflen); - if (n < 0) { - // The connection is gone! - net_io_revert_console(); - } else { - out_buflen -= n; - bp += n; - } - out_bufp = out_buf; out_buflen = 0; - // Check interrupt flag - if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) { - CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0); - cyg_hal_user_break(0); - } -} - -static void -net_io_putc(void* __ch_data, cyg_uint8 c) -{ - static bool have_dollar, have_hash; - static int hash_count; - - CYGARC_HAL_SAVE_GP(); - *out_bufp++ = c; - if (c == '$') have_dollar = true; - if (have_dollar && (c == '#')) { - have_hash = true; - hash_count = 0; - } - if ((++out_buflen == sizeof(out_buf)) || - (flush_output_lines && c == '\n') || - (have_hash && (++hash_count == 3))) { - net_io_flush(); - have_dollar = false; - } - CYGARC_HAL_RESTORE_GP(); -} - -static void -net_io_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len) -{ - int old_console; - - old_console = start_console(); - diag_printf("%s.%d\n", __FUNCTION__, __LINE__); - end_console(old_console); -#if 0 - CYGARC_HAL_SAVE_GP(); - - while(__len-- > 0) - net_io_putc(__ch_data, *__buf++); - - CYGARC_HAL_RESTORE_GP(); -#endif -} - -static void -net_io_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) -{ - int old_console; - - old_console = start_console(); - diag_printf("%s.%d\n", __FUNCTION__, __LINE__); - end_console(old_console); -#if 0 - CYGARC_HAL_SAVE_GP(); - - while(__len-- > 0) - *__buf++ = net_io_getc(__ch_data); - - CYGARC_HAL_RESTORE_GP(); -#endif -} - -static cyg_bool -net_io_getc_timeout(void* __ch_data, cyg_uint8* ch) -{ - int delay_count; - cyg_bool res; - - CYGARC_HAL_SAVE_GP(); - net_io_flush(); // Make sure any output has been sent - delay_count = _timeout; - - for(;;) { - res = net_io_getc_nonblock(__ch_data, ch); - if (res || 0 == delay_count--) - break; - } - - CYGARC_HAL_RESTORE_GP(); - - return res; -} - -static int -net_io_control(void *__ch_data, __comm_control_cmd_t __func, ...) -{ - static int vector = 0; - int ret = 0; - static int irq_state = 0; - - CYGARC_HAL_SAVE_GP(); - - switch (__func) { - case __COMMCTL_IRQ_ENABLE: - irq_state = 1; - if (vector == 0) { - vector = eth_drv_int_vector(); - } - HAL_INTERRUPT_UNMASK(vector); - break; - case __COMMCTL_IRQ_DISABLE: - ret = irq_state; - irq_state = 0; - if (vector == 0) { - vector = eth_drv_int_vector(); - } - HAL_INTERRUPT_MASK(vector); - break; - case __COMMCTL_DBG_ISR_VECTOR: - ret = vector; - break; - case __COMMCTL_SET_TIMEOUT: - { - va_list ap; - - va_start(ap, __func); - - ret = _timeout; - _timeout = va_arg(ap, cyg_uint32); - - va_end(ap); - break; - } - case __COMMCTL_FLUSH_OUTPUT: - net_io_flush(); - break; - case __COMMCTL_ENABLE_LINE_FLUSH: - flush_output_lines = true; - break; - case __COMMCTL_DISABLE_LINE_FLUSH: - flush_output_lines = false; - break; - default: - break; - } - CYGARC_HAL_RESTORE_GP(); - return ret; -} - -static int -net_io_isr(void *__ch_data, int* __ctrlc, - CYG_ADDRWORD __vector, CYG_ADDRWORD __data) -{ - char ch; - - CYGARC_HAL_SAVE_GP(); - *__ctrlc = 0; - if (net_io_getc_nonblock(__ch_data, &ch)) { - if (ch == 0x03) { - *__ctrlc = 1; - } - } - CYGARC_HAL_RESTORE_GP(); - return CYG_ISR_HANDLED; -} - -// TEMP - -int -start_console(void) -{ - int cur_console = - CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); - -#ifdef CYGSEM_REDBOOT_FLASH_CONFIG - int i = 0; - if ( flash_get_config( "info_console_force", &i, CONFIG_BOOL) ) - if ( i ) - if ( ! flash_get_config( "info_console_number", &i, CONFIG_INT) ) - i = 0; // the default, if that call failed. - if ( i ) - CYGACC_CALL_IF_SET_CONSOLE_COMM(i); - else -#endif - CYGACC_CALL_IF_SET_CONSOLE_COMM(0); - - return cur_console; -} - -void -end_console(int old_console) -{ - // Restore original console - CYGACC_CALL_IF_SET_CONSOLE_COMM(old_console); -} -// TEMP - -static void -net_io_revert_console(void) -{ -#ifdef CYGPKG_REDBOOT_ANY_CONSOLE - console_selected = false; -#endif - CYGACC_CALL_IF_SET_CONSOLE_COMM(orig_console); - CYGACC_CALL_IF_SET_DEBUG_COMM(orig_debug); - console_echo = true; -} - -static void -net_io_assume_console(void) -{ -#ifdef CYGPKG_REDBOOT_ANY_CONSOLE - console_selected = true; -#endif - console_echo = false; - orig_console = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); - CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL); - orig_debug = CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); - CYGACC_CALL_IF_SET_DEBUG_COMM(TCP_CHANNEL); -} - -static void -net_io_init(void) -{ - static int init = 0; - if (!init) { - hal_virtual_comm_table_t* comm; - int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); - - // Setup procs in the vector table - CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL); - comm = CYGACC_CALL_IF_CONSOLE_PROCS(); - //CYGACC_COMM_IF_CH_DATA_SET(*comm, chan); - CYGACC_COMM_IF_WRITE_SET(*comm, net_io_write); - CYGACC_COMM_IF_READ_SET(*comm, net_io_read); - CYGACC_COMM_IF_PUTC_SET(*comm, net_io_putc); - CYGACC_COMM_IF_GETC_SET(*comm, net_io_getc); - CYGACC_COMM_IF_CONTROL_SET(*comm, net_io_control); - CYGACC_COMM_IF_DBG_ISR_SET(*comm, net_io_isr); - CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, net_io_getc_timeout); - - // Disable interrupts via this interface to set static - // state into correct state. - net_io_control( comm, __COMMCTL_IRQ_DISABLE ); - - // Restore original console - CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); - - init = 1; - gdb_active = false; - } - __tcp_listen(&tcp_sock, gdb_port); - state = tcp_sock.state; -#ifdef DEBUG_TCP - diag_printf("show tcp = %p\n", (void *)&show_tcp); + diag_printf("show tcp = %p\n", (void *)&show_tcp); #endif } // Check for incoming TCP debug connection -void -net_io_test(bool is_idle) -{ - if (!is_idle) return; // Only care about idle case - if (!have_net) return; - __tcp_poll(); - if (state != tcp_sock.state) { - // Something has changed - if (tcp_sock.state == _ESTABLISHED) { - // A new connection has arrived - net_io_assume_console(); - in_bufp = in_buf; in_buflen = 1; *in_bufp = '\r'; - out_bufp = out_buf; out_buflen = 0; - } - if (tcp_sock.state == _CLOSED) { - net_io_init(); // Get ready for another connection - } - } - state = tcp_sock.state; +void net_io_test(bool is_idle) +{ + if (!is_idle) + return; // Only care about idle case + if (!have_net) + return; + __tcp_poll(); + if (state != tcp_sock.state) { + // Something has changed + if (tcp_sock.state == _ESTABLISHED) { + // A new connection has arrived + net_io_assume_console(); + in_bufp = in_buf; + in_buflen = 1; + *in_bufp = '\r'; + out_bufp = out_buf; + out_buflen = 0; + } + if (tcp_sock.state == _CLOSED) { + net_io_init(); // Get ready for another connection + } + } + state = tcp_sock.state; } @@ -582,178 +555,171 @@ // Define table boundaries -CYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev ); -CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev ); +CYG_HAL_TABLE_BEGIN(__NETDEVTAB__, netdev); +CYG_HAL_TABLE_END(__NETDEVTAB_END__, netdev); RedBoot_init(net_init, RedBoot_INIT_LAST); -static void -show_addrs(void) -{ - diag_printf("IP: %s", inet_ntoa((in_addr_t *)&__local_ip_addr)); +static void show_addrs(void) +{ + diag_printf("IP: %s", inet_ntoa((in_addr_t *) & __local_ip_addr)); #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY - diag_printf("/%s", inet_ntoa((in_addr_t *)&__local_ip_mask)); - diag_printf(", Gateway: %s\n", inet_ntoa((in_addr_t *)&__local_ip_gate)); + diag_printf("/%s", inet_ntoa((in_addr_t *) & __local_ip_mask)); + diag_printf(", Gateway: %s\n", + inet_ntoa((in_addr_t *) & __local_ip_gate)); #else - diag_printf(", "); -#endif - diag_printf("Default server: %s", inet_ntoa(&my_bootp_info.bp_siaddr)); + diag_printf(", "); +#endif + diag_printf("Default server: %s", inet_ntoa(&my_bootp_info.bp_siaddr)); #ifdef CYGPKG_REDBOOT_NETWORKING_DNS - show_dns(); -#endif - diag_printf("\n"); + show_dns(); +#endif + diag_printf("\n"); } #ifdef CYGSEM_REDBOOT_FLASH_CONFIG -static void -flash_get_IP(char *id, ip_addr_t *val) -{ - ip_addr_t my_ip; - int i; - - if (flash_get_config(id, &my_ip, CONFIG_IP)) { - if (my_ip[0] != 0 || my_ip[1] != 0 || - my_ip[2] != 0 || my_ip[3] != 0) { - // 'id' is set to something so let it override any static IP - for (i=0; i<4; i++) - (*val)[i] = my_ip[i]; - } - } -} -#endif - -static cyg_netdevtab_entry_t * -net_devtab_entry(unsigned index) -{ - cyg_netdevtab_entry_t *t = &__NETDEVTAB__[index]; - - if (t < &__NETDEVTAB__[0] || t >= &__NETDEVTAB_END__) +static void flash_get_IP(char *id, ip_addr_t * val) +{ + ip_addr_t my_ip; + int i; + + if (flash_get_config(id, &my_ip, CONFIG_IP)) { + if (my_ip[0] != 0 || my_ip[1] != 0 || + my_ip[2] != 0 || my_ip[3] != 0) { + // 'id' is set to something so let it override any static IP + for (i = 0; i < 4; i++) + (*val)[i] = my_ip[i]; + } + } +} +#endif + +static cyg_netdevtab_entry_t *net_devtab_entry(unsigned index) +{ + cyg_netdevtab_entry_t *t = &__NETDEVTAB__[index]; + + if (t < &__NETDEVTAB__[0] || t >= &__NETDEVTAB_END__) + return NULL; + + return t; +} + +const char *net_devname(unsigned index) +{ + cyg_netdevtab_entry_t *t = net_devtab_entry(index); + if (t) + return t->name; return NULL; - - return t; -} - -const char * -net_devname(unsigned index) -{ - cyg_netdevtab_entry_t *t = net_devtab_entry(index); - if (t) - return t->name; - return NULL; -} - -int -net_devindex(char *name) -{ - const char *devname; - int index; - - for (index = 0; (devname = net_devname(index)) != NULL; index++) - if (!strcmp(name, devname)) - return index; - return -1; -} - -static void -show_eth_info(void) -{ - diag_printf("Ethernet %s: MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", - __local_enet_sc->dev_name, - __local_enet_addr[0], - __local_enet_addr[1], - __local_enet_addr[2], - __local_enet_addr[3], - __local_enet_addr[4], - __local_enet_addr[5]); -} - -void -net_init(void) -{ - cyg_netdevtab_entry_t *t; - unsigned index; - struct eth_drv_sc *primary_net = (struct eth_drv_sc *)0; +} + +int net_devindex(char *name) +{ + const char *devname; + int index; + + for (index = 0; (devname = net_devname(index)) != NULL; index++) + if (!strcmp(name, devname)) + return index; + return -1; +} + +static void show_eth_info(void) +{ + diag_printf("Ethernet %s: MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", + __local_enet_sc->dev_name, + __local_enet_addr[0], + __local_enet_addr[1], + __local_enet_addr[2], + __local_enet_addr[3], + __local_enet_addr[4], __local_enet_addr[5]); +} + +void net_init(void) +{ + cyg_netdevtab_entry_t *t; + unsigned index; + struct eth_drv_sc *primary_net = (struct eth_drv_sc *)0; #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1) - char *default_devname; - int default_index; + char *default_devname; + int default_index; #endif #ifdef CYGDAT_REDBOOT_DEFAULT_BOOTP_SERVER_IP_ADDR - char ip_addr[16]; -#endif - - // Set defaults as appropriate + char ip_addr[16]; +#endif + + // Set defaults as appropriate #ifdef CYGSEM_REDBOOT_DEFAULT_NO_BOOTP - use_bootp = false; + use_bootp = false; #else - use_bootp = true; + use_bootp = true; #endif #ifdef CYGDBG_REDBOOT_NET_DEBUG - net_debug = true; + net_debug = true; #else - net_debug = false; -#endif - gdb_port = CYGNUM_REDBOOT_NETWORKING_TCP_PORT; + net_debug = false; +#endif + gdb_port = CYGNUM_REDBOOT_NETWORKING_TCP_PORT; #ifdef CYGSEM_REDBOOT_FLASH_CONFIG - // Fetch values from saved config data, if available + // Fetch values from saved config data, if available #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1) - flash_get_config("net_device", &default_devname, CONFIG_NETPORT); + flash_get_config("net_device", &default_devname, CONFIG_NETPORT); #endif // flash_get_config("net_debug", &net_debug, CONFIG_BOOL); - flash_get_config("gdb_port", &gdb_port, CONFIG_INT); - flash_get_config("bootp", &use_bootp, CONFIG_BOOL); - if (!use_bootp) { - flash_get_IP("bootp_my_ip", &__local_ip_addr); + flash_get_config("gdb_port", &gdb_port, CONFIG_INT); + flash_get_config("bootp", &use_bootp, CONFIG_BOOL); + if (!use_bootp) { + flash_get_IP("bootp_my_ip", &__local_ip_addr); #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY - flash_get_IP("bootp_my_ip_mask", &__local_ip_mask); - flash_get_IP("bootp_my_gateway_ip", &__local_ip_gate); -#endif - } + flash_get_IP("bootp_my_ip_mask", &__local_ip_mask); + flash_get_IP("bootp_my_gateway_ip", &__local_ip_gate); +#endif + } #endif # ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG - // Don't override if the user has deliberately set something more - // verbose. - if (0 == cyg_io_eth_net_debug) - cyg_io_eth_net_debug = net_debug; + // Don't override if the user has deliberately set something more + // verbose. + if (0 == cyg_io_eth_net_debug) + cyg_io_eth_net_debug = net_debug; # endif - have_net = false; - // Make sure the recv buffers are set up - eth_drv_buffers_init(); - __pktbuf_init(); - - // Initialize network device(s). + have_net = false; + // Make sure the recv buffers are set up + eth_drv_buffers_init(); + __pktbuf_init(); + + // Initialize network device(s). #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1) - default_index = net_devindex(default_devname); - if (default_index < 0) - default_index = 0; + default_index = net_devindex(default_devname); + if (default_index < 0) + default_index = 0; #ifdef CYGSEM_REDBOOT_NETWORK_INIT_ONE_DEVICE - if ((t = net_devtab_entry(default_index)) != NULL && t->init(t)) { - t->status = CYG_NETDEVTAB_STATUS_AVAIL; - primary_net = __local_enet_sc; - } else -#endif -#endif - for (index = 0; (t = net_devtab_entry(index)) != NULL; index++) { + if ((t = net_devtab_entry(default_index)) != NULL && t->init(t)) { + t->status = CYG_NETDEVTAB_STATUS_AVAIL; + primary_net = __local_enet_sc; + } else +#endif +#endif + for (index = 0; (t = net_devtab_entry(index)) != NULL; index++) { #ifdef CYGSEM_REDBOOT_NETWORK_INIT_ONE_DEVICE - if (index == default_index) - continue; -#endif - if (t->init(t)) { - t->status = CYG_NETDEVTAB_STATUS_AVAIL; - if (primary_net == (struct eth_drv_sc *)0) { - primary_net = __local_enet_sc; - } + if (index == default_index) + continue; +#endif + if (t->init(t)) { + t->status = CYG_NETDEVTAB_STATUS_AVAIL; + if (primary_net == (struct eth_drv_sc *)0) { + primary_net = __local_enet_sc; + } #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1) - if (index == default_index) { - primary_net = __local_enet_sc; - } -#endif - } - } - __local_enet_sc = primary_net; - - if (!__local_enet_sc) { - diag_printf("No network interfaces found\n"); - return; - } - // Initialize the network [if present] + if (index == default_index) { + primary_net = __local_enet_sc; + } +#endif + } + } + __local_enet_sc = primary_net; + + if (!__local_enet_sc) { + diag_printf("No network interfaces found\n"); + return; + } + // Initialize the network [if present] /* if (use_bootp) { if (__bootp_find_local_ip(&my_bootp_info) == 0) { @@ -772,126 +738,129 @@ } else { */ - if (__local_ip_addr[0] == 0 && __local_ip_addr[1] == 0 && - __local_ip_addr[2] == 0 && __local_ip_addr[3] == 0) { - __local_ip_addr[0]=192; - __local_ip_addr[1]=168; - __local_ip_addr[2]=1; - __local_ip_addr[3]=1; + if (__local_ip_addr[0] == 0 && __local_ip_addr[1] == 0 && + __local_ip_addr[2] == 0 && __local_ip_addr[3] == 0) { + __local_ip_addr[0] = 192; + __local_ip_addr[1] = 168; + __local_ip_addr[2] = 1; + __local_ip_addr[3] = 1; // __local_ip_mask[0]=255; // __local_ip_mask[1]=255; // __local_ip_mask[2]=0; // __local_ip_mask[3]=0; - } - - { - - - enet_addr_t enet_addr; - have_net = true; // Assume values in FLASH were OK - // Tell the world that we are using this fixed IP address - if (__arp_request((ip_addr_t *)__local_ip_addr, &enet_addr, 1) >= 0) { - diag_printf("Warning: IP address %s in use\n", inet_ntoa((in_addr_t *)&__local_ip_addr)); - } - } + } + + { + + enet_addr_t enet_addr; + have_net = true; // Assume values in FLASH were OK + // Tell the world that we are using this fixed IP address + if (__arp_request((ip_addr_t *) __local_ip_addr, &enet_addr, 1) + >= 0) { + diag_printf("Warning: IP address %s in use\n", + inet_ntoa((in_addr_t *) & __local_ip_addr)); + } + } // } - if (have_net) { - show_eth_info(); + if (have_net) { + show_eth_info(); #ifdef CYGDAT_REDBOOT_DEFAULT_BOOTP_SERVER_IP_ADDR - diag_sprintf(ip_addr, "%d.%d.%d.%d", - CYGDAT_REDBOOT_DEFAULT_BOOTP_SERVER_IP_ADDR); - inet_aton(ip_addr, &my_bootp_info.bp_siaddr); + diag_sprintf(ip_addr, "%d.%d.%d.%d", + CYGDAT_REDBOOT_DEFAULT_BOOTP_SERVER_IP_ADDR); + inet_aton(ip_addr, &my_bootp_info.bp_siaddr); #endif #ifdef CYGSEM_REDBOOT_FLASH_CONFIG - flash_get_IP("bootp_server_ip", (ip_addr_t *)&my_bootp_info.bp_siaddr); + flash_get_IP("bootp_server_ip", + (ip_addr_t *) & my_bootp_info.bp_siaddr); #endif #ifdef CYGPKG_REDBOOT_NETWORKING_DNS - redboot_dns_res_init(); -#endif - show_addrs(); - net_io_init(); - } -} - -static char usage[] = "[-l [/]] [-h ]"; + redboot_dns_res_init(); +#endif + show_addrs(); + net_io_init(); + } +} + +static char usage[] = + "[-l [/]] [-h ]"; // Exported CLI function static void do_ip_addr(int argc, char *argv[]); -RedBoot_cmd("ip_address", - "Set/change IP addresses", - usage, - do_ip_addr - ); - -void -do_ip_addr(int argc, char *argv[]) -{ - struct option_info opts[3]; - char *ip_addr, *host_addr; - bool ip_addr_set, host_addr_set; - struct sockaddr_in host; +RedBoot_cmd("ip_address", "Set/change IP addresses", usage, do_ip_addr); + +void do_ip_addr(int argc, char *argv[]) +{ + struct option_info opts[3]; + char *ip_addr, *host_addr; + bool ip_addr_set, host_addr_set; + struct sockaddr_in host; #ifdef CYGPKG_REDBOOT_NETWORKING_DNS - char *dns_addr; - bool dns_addr_set; -#endif - int num_opts; - - init_opts(&opts[0], 'l', true, OPTION_ARG_TYPE_STR, - (void *)&ip_addr, (bool *)&ip_addr_set, "local IP address"); - init_opts(&opts[1], 'h', true, OPTION_ARG_TYPE_STR, - (void *)&host_addr, (bool *)&host_addr_set, "default server address"); - num_opts = 2; + char *dns_addr; + bool dns_addr_set; +#endif + int num_opts; + + init_opts(&opts[0], 'l', true, OPTION_ARG_TYPE_STR, + (void *)&ip_addr, (bool *) & ip_addr_set, "local IP address"); + init_opts(&opts[1], 'h', true, OPTION_ARG_TYPE_STR, + (void *)&host_addr, (bool *) & host_addr_set, + "default server address"); + num_opts = 2; #ifdef CYGPKG_REDBOOT_NETWORKING_DNS - init_opts(&opts[2], 'd', true, OPTION_ARG_TYPE_STR, - (void *)&dns_addr, (bool *)&dns_addr_set, "DNS server address"); - num_opts++; -#endif - - CYG_ASSERT(num_opts <= NUM_ELEMS(opts), "Too many options"); - - if (!scan_opts(argc, argv, 1, opts, num_opts, 0, 0, "")) { - return; - } - if (ip_addr_set) { + init_opts(&opts[2], 'd', true, OPTION_ARG_TYPE_STR, + (void *)&dns_addr, (bool *) & dns_addr_set, + "DNS server address"); + num_opts++; +#endif + + CYG_ASSERT(num_opts <= NUM_ELEMS(opts), "Too many options"); + + if (!scan_opts(argc, argv, 1, opts, num_opts, 0, 0, "")) { + return; + } + if (ip_addr_set) { #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY - char *slash_pos; - /* see if the (optional) mask length was given */ - if( (slash_pos = strchr(ip_addr, '/')) ) { - int mask_len; - unsigned long mask; - *slash_pos = '\0'; - slash_pos++; - if( !parse_num(slash_pos, (unsigned long *)&mask_len, 0, 0) || - mask_len <= 0 || mask_len > 32 ) { - diag_printf("Invalid mask length: %s\n", slash_pos); - return; - } - mask = htonl((0xffffffff << (32-mask_len))&0xffffffff); - memcpy(&__local_ip_mask, &mask, 4); - } -#endif - if (!_gethostbyname(ip_addr, (in_addr_t *)&host)) { - diag_printf("Invalid local IP address: %s\n", ip_addr); - return; - } - // Of course, each address goes in its own place :-) - memcpy(&__local_ip_addr, &host.sin_addr, sizeof(host.sin_addr)); - } - if (host_addr_set) { - if (!_gethostbyname(host_addr, (in_addr_t *)&host)) { - diag_printf("Invalid server address: %s\n", host_addr); - return; - } - my_bootp_info.bp_siaddr = host.sin_addr; - } + char *slash_pos; + /* see if the (optional) mask length was given */ + if ((slash_pos = strchr(ip_addr, '/'))) { + int mask_len; + unsigned long mask; + *slash_pos = '\0'; + slash_pos++; + if (!parse_num + (slash_pos, (unsigned long *)&mask_len, 0, 0) + || mask_len <= 0 || mask_len > 32) { + diag_printf("Invalid mask length: %s\n", + slash_pos); + return; + } + mask = + htonl((0xffffffff << (32 - mask_len)) & 0xffffffff); + memcpy(&__local_ip_mask, &mask, 4); + } +#endif + if (!_gethostbyname(ip_addr, (in_addr_t *) & host)) { + diag_printf("Invalid local IP address: %s\n", ip_addr); + return; + } + // Of course, each address goes in its own place :-) + memcpy(&__local_ip_addr, &host.sin_addr, sizeof(host.sin_addr)); + } + if (host_addr_set) { + if (!_gethostbyname(host_addr, (in_addr_t *) & host)) { + diag_printf("Invalid server address: %s\n", host_addr); + return; + } + my_bootp_info.bp_siaddr = host.sin_addr; + } #ifdef CYGPKG_REDBOOT_NETWORKING_DNS - if (dns_addr_set) { - set_dns(dns_addr); - } -#endif - show_addrs(); - if (!have_net) { - have_net = true; - net_io_init(); - } + if (dns_addr_set) { + set_dns(dns_addr); + } +#endif + show_addrs(); + if (!have_net) { + have_net = true; + net_io_init(); + } } Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade_ubnt.h =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade_ubnt.h (revision 12368) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade_ubnt.h (revision 12368) @@ -0,0 +1,59 @@ + +#ifndef __ubnt_fw__ +#define __ubnt_fw__ + +#define MAGIC_HEADER "OPEN" +#define MAGIC_PART "PART" +#define MAGIC_END "END." + +#define MAGIC_LENGTH 4 + +typedef unsigned int u_int32_t; + +typedef struct header { + char magic[MAGIC_LENGTH]; + char version[256]; + u_int32_t crc; + u_int32_t pad; +} __attribute__((packed)) header_t; + +typedef struct part { + char magic[MAGIC_LENGTH]; + char name[16]; + char pad[12]; + u_int32_t memaddr; + u_int32_t index; + u_int32_t baseaddr; + u_int32_t entryaddr; + u_int32_t data_size; + u_int32_t part_size; +} __attribute__((packed)) part_t; + +typedef struct part_crc { + u_int32_t crc; + u_int32_t pad; +} __attribute__((packed)) part_crc_t; + +typedef struct signature { + char magic[MAGIC_LENGTH]; + u_int32_t crc; + u_int32_t pad; +} __attribute__((packed)) signature_t; + +extern int fw_check_image_ubnt(unsigned char *addr, unsigned long maxlen, + int do_flash); + +/***********************************************************************************/ + +/* fwupdate.bin size */ +#define MAX_IMAGE_SIZE 0x7E0000 /* 4mb - 64k */ + +/* max size for single partition - typicaly this is cramfs size */ +#define MAX_PART_SIZE 0x800000 /* 3mb - valid only for ar531x */ + +/* these variables will be initialized in do_tftpd() */ +CYG_ADDRWORD BASE_ADDR; +CYG_ADDRWORD FW_TEMP_BASE; +/***********************************************************************************/ + +#endif /* __wilibox_fw__ */ Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/arp.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/arp.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/arp.c (revision 12368) @@ -57,7 +57,7 @@ static struct { - int waiting; - char *eth; - char *ip; + int waiting; + char *eth; + char *ip; } arp_req; @@ -65,45 +65,48 @@ * Handle incoming ARP packets. */ -void -__arp_handler(pktbuf_t *pkt) +void __arp_handler(pktbuf_t * pkt) { - arp_header_t *arp = pkt->arp_hdr; - int hw_type, protocol; - - /* - * Only handle ethernet hardware and IP protocol. - */ - protocol = ntohs(arp->protocol); - hw_type = ntohs(arp->hw_type); - if ((hw_type == ARP_HW_ETHER) && (protocol == ETH_TYPE_IP)) { + arp_header_t *arp = pkt->arp_hdr; + int hw_type, protocol; + /* - * Handle requests for our ethernet address. + * Only handle ethernet hardware and IP protocol. */ - if (!memcmp(arp->target_ip, __local_ip_addr, 4)) { - if (ntohs(arp->opcode) == ARP_REQUEST) { - /* format response. */ - arp->opcode = htons(ARP_REPLY); - memcpy(arp->target_ip, arp->sender_ip, - sizeof(ip_addr_t)); - memcpy(arp->target_enet, arp->sender_enet, - sizeof(enet_addr_t)); - memcpy(arp->sender_ip, __local_ip_addr, - sizeof(ip_addr_t)); - memcpy(arp->sender_enet, __local_enet_addr, - sizeof(enet_addr_t)); - pkt->pkt_bytes = sizeof(arp_header_t); - __enet_send(pkt, &arp->target_enet, ETH_TYPE_ARP); - - } else if (ntohs(arp->opcode) == ARP_REPLY && arp_req.waiting) { - if (!memcmp(arp_req.ip, arp->sender_ip, sizeof(ip_addr_t))) { - memcpy(arp_req.eth, arp->sender_enet, sizeof(enet_addr_t)); - arp_req.waiting = 0; - } - } - } - } - __pktbuf_free(pkt); + protocol = ntohs(arp->protocol); + hw_type = ntohs(arp->hw_type); + if ((hw_type == ARP_HW_ETHER) && (protocol == ETH_TYPE_IP)) { + /* + * Handle requests for our ethernet address. + */ + if (!memcmp(arp->target_ip, __local_ip_addr, 4)) { + if (ntohs(arp->opcode) == ARP_REQUEST) { + /* format response. */ + arp->opcode = htons(ARP_REPLY); + memcpy(arp->target_ip, arp->sender_ip, + sizeof(ip_addr_t)); + memcpy(arp->target_enet, arp->sender_enet, + sizeof(enet_addr_t)); + memcpy(arp->sender_ip, __local_ip_addr, + sizeof(ip_addr_t)); + memcpy(arp->sender_enet, __local_enet_addr, + sizeof(enet_addr_t)); + pkt->pkt_bytes = sizeof(arp_header_t); + __enet_send(pkt, &arp->target_enet, + ETH_TYPE_ARP); + + } else if (ntohs(arp->opcode) == ARP_REPLY + && arp_req.waiting) { + if (!memcmp + (arp_req.ip, arp->sender_ip, + sizeof(ip_addr_t))) { + memcpy(arp_req.eth, arp->sender_enet, + sizeof(enet_addr_t)); + arp_req.waiting = 0; + } + } + } + } + __pktbuf_free(pkt); } - /* @@ -113,65 +116,65 @@ * -1 if unsuccessful. */ -int -__arp_request(ip_addr_t *ip_addr, enet_addr_t *eth_addr, int allow_self) +int __arp_request(ip_addr_t * ip_addr, enet_addr_t * eth_addr, int allow_self) { - pktbuf_t *pkt; - arp_header_t *arp; - unsigned long retry_start; - enet_addr_t bcast_addr; - int retry; - - if (!allow_self) { - // Special case request for self - if (!memcmp(ip_addr, __local_ip_addr, 4)) { - memcpy(eth_addr, __local_enet_addr, sizeof(enet_addr_t)); - return 0; - } - } - - /* just fail if can't get a buffer */ - if ((pkt = __pktbuf_alloc(ARP_PKT_SIZE)) == NULL) + pktbuf_t *pkt; + arp_header_t *arp; + unsigned long retry_start; + enet_addr_t bcast_addr; + int retry; + + if (!allow_self) { + // Special case request for self + if (!memcmp(ip_addr, __local_ip_addr, 4)) { + memcpy(eth_addr, __local_enet_addr, + sizeof(enet_addr_t)); + return 0; + } + } + + /* just fail if can't get a buffer */ + if ((pkt = __pktbuf_alloc(ARP_PKT_SIZE)) == NULL) + return -1; + + arp = pkt->arp_hdr; + arp->opcode = htons(ARP_REQUEST); + arp->hw_type = htons(ARP_HW_ETHER); + arp->protocol = htons(0x800); + arp->hw_len = sizeof(enet_addr_t); + arp->proto_len = sizeof(ip_addr_t); + + memcpy(arp->sender_ip, __local_ip_addr, sizeof(ip_addr_t)); + memcpy(arp->sender_enet, __local_enet_addr, sizeof(enet_addr_t)); + memcpy(arp->target_ip, ip_addr, sizeof(ip_addr_t)); + + bcast_addr[0] = 255; + bcast_addr[1] = 255; + bcast_addr[2] = 255; + bcast_addr[3] = 255; + bcast_addr[4] = 255; + bcast_addr[5] = 255; + + arp_req.eth = (char *)eth_addr; + arp_req.ip = (char *)ip_addr; + arp_req.waiting = 1; + + retry = 8; + while (retry-- > 0) { + + /* send the packet */ + pkt->pkt_bytes = sizeof(arp_header_t); + __enet_send(pkt, &bcast_addr, ETH_TYPE_ARP); + + retry_start = MS_TICKS(); + while ((MS_TICKS_DELAY() - retry_start) < 250) { + __enet_poll(); + if (!arp_req.waiting) { + __pktbuf_free(pkt); + return 0; + } + } + } + __pktbuf_free(pkt); return -1; - - arp = pkt->arp_hdr; - arp->opcode = htons(ARP_REQUEST); - arp->hw_type = htons(ARP_HW_ETHER); - arp->protocol = htons(0x800); - arp->hw_len = sizeof(enet_addr_t); - arp->proto_len = sizeof(ip_addr_t); - - memcpy(arp->sender_ip, __local_ip_addr, sizeof(ip_addr_t)); - memcpy(arp->sender_enet, __local_enet_addr, sizeof(enet_addr_t)); - memcpy(arp->target_ip, ip_addr, sizeof(ip_addr_t)); - - bcast_addr[0] = 255; - bcast_addr[1] = 255; - bcast_addr[2] = 255; - bcast_addr[3] = 255; - bcast_addr[4] = 255; - bcast_addr[5] = 255; - - arp_req.eth = (char *)eth_addr; - arp_req.ip = (char *)ip_addr; - arp_req.waiting = 1; - - retry = 8; - while (retry-- > 0) { - - /* send the packet */ - pkt->pkt_bytes = sizeof(arp_header_t); - __enet_send(pkt, &bcast_addr, ETH_TYPE_ARP); - - retry_start = MS_TICKS(); - while ((MS_TICKS_DELAY() - retry_start) < 250) { - __enet_poll(); - if (!arp_req.waiting) { - __pktbuf_free(pkt); - return 0; - } - } - } - __pktbuf_free(pkt); - return -1; } @@ -179,34 +182,34 @@ static ip_route_t routes[NUM_ARP]; -int -__arp_lookup(ip_addr_t *host, ip_route_t *rt) +int __arp_lookup(ip_addr_t * host, ip_route_t * rt) { - int i; - static int next_arp = 0; - - for (i = 0; i < NUM_ARP; i++) { - if (memcmp(host, &routes[i].ip_addr, sizeof(*host)) == 0) { - // This is a known host - memcpy(rt, &routes[i], sizeof(*rt)); - return 0; - } - } - memcpy(&rt->ip_addr, host, sizeof(*host)); - if (((*host)[0] == 0xFF) && ((*host)[1] == 0xFF) && ((*host)[2] == 0xFF)) { - memset(&rt->enet_addr, 0xFF, sizeof(&rt->enet_addr)); - return 0; + int i; + static int next_arp = 0; + + for (i = 0; i < NUM_ARP; i++) { + if (memcmp(host, &routes[i].ip_addr, sizeof(*host)) == 0) { + // This is a known host + memcpy(rt, &routes[i], sizeof(*rt)); + return 0; + } + } + memcpy(&rt->ip_addr, host, sizeof(*host)); + if (((*host)[0] == 0xFF) && ((*host)[1] == 0xFF) + && ((*host)[2] == 0xFF)) { + memset(&rt->enet_addr, 0xFF, sizeof(&rt->enet_addr)); + return 0; #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY - } else if (!__ip_addr_local(host)) { - // non-local IP address -- look up Gateway's Ethernet address - host = &__local_ip_gate; + } else if (!__ip_addr_local(host)) { + // non-local IP address -- look up Gateway's Ethernet address + host = &__local_ip_gate; #endif - } - if (__arp_request(host, &rt->enet_addr, 0) < 0) { - return -1; - } else { - memcpy(&routes[next_arp], rt, sizeof(*rt)); - if (++next_arp == NUM_ARP) next_arp = 0; - return 0; - } + } + if (__arp_request(host, &rt->enet_addr, 0) < 0) { + return -1; + } else { + memcpy(&routes[next_arp], rt, sizeof(*rt)); + if (++next_arp == NUM_ARP) + next_arp = 0; + return 0; + } } - Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/cksum.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/cksum.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/cksum.c (revision 12368) @@ -60,65 +60,62 @@ * The returned checksum is in network byte order. */ -unsigned short -__sum(word *w, int len, int init_sum) +unsigned short __sum(word * w, int len, int init_sum) { - int sum = init_sum; + int sum = init_sum; - union { - volatile unsigned char c[2]; - volatile unsigned short s; - } su; + union { + volatile unsigned char c[2]; + volatile unsigned short s; + } su; - union { - volatile unsigned short s[2]; - volatile int i; - } iu; + union { + volatile unsigned short s[2]; + volatile int i; + } iu; - while ((len -= 2) >= 0) - sum += *w++; + while ((len -= 2) >= 0) + sum += *w++; - if (len == -1) { - su.c[0] = *(char *)w; - su.c[1] = 0; - sum += su.s; - } + if (len == -1) { + su.c[0] = *(char *)w; + su.c[1] = 0; + sum += su.s; + } - iu.i = sum; - sum = iu.s[0] + iu.s[1]; - if (sum > 65535) - sum -= 65535; + iu.i = sum; + sum = iu.s[0] + iu.s[1]; + if (sum > 65535) + sum -= 65535; - su.s = ~sum; + su.s = ~sum; - return (su.c[0] << 8) | su.c[1]; + return (su.c[0] << 8) | su.c[1]; } - /* * Compute a partial checksum for the UDP/TCP pseudo header. */ -int -__pseudo_sum(ip_header_t *ip) +int __pseudo_sum(ip_header_t * ip) { - int sum; - word *p; + int sum; + word *p; - union { - volatile unsigned char c[2]; - volatile unsigned short s; - } su; - - p = (word *)ip->source; - sum = *p++; - sum += *p++; - sum += *p++; - sum += *p++; - - su.c[0] = 0; - su.c[1] = ip->protocol; - sum += su.s; + union { + volatile unsigned char c[2]; + volatile unsigned short s; + } su; - sum += ip->length; - - return sum; + p = (word *) ip->source; + sum = *p++; + sum += *p++; + sum += *p++; + sum += *p++; + + su.c[0] = 0; + su.c[1] = ip->protocol; + sum += su.s; + + sum += ip->length; + + return sum; } Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/bootp.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/bootp.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/bootp.c (revision 12368) @@ -65,96 +65,96 @@ static bootp_header_t *bp_info; - -#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP -static const unsigned char dhcpCookie[] = {99,130,83,99}; -static const unsigned char dhcpEnd[] = {255}; -static const unsigned char dhcpDiscover[] = {53,1,1}; -static const unsigned char dhcpRequest[] = {53,1,3}; -static const unsigned char dhcpRequestIP[] = {50,4}; -static const unsigned char dhcpParamRequestList[] = {55,3,1,3,6}; + +#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP +static const unsigned char dhcpCookie[] = { 99, 130, 83, 99 }; +static const unsigned char dhcpEnd[] = { 255 }; +static const unsigned char dhcpDiscover[] = { 53, 1, 1 }; +static const unsigned char dhcpRequest[] = { 53, 1, 3 }; +static const unsigned char dhcpRequestIP[] = { 50, 4 }; +static const unsigned char dhcpParamRequestList[] = { 55, 3, 1, 3, 6 }; + static enum { - DHCP_NONE = 0, - DHCP_DISCOVER, - DHCP_OFFER, - DHCP_REQUEST, - DHCP_ACK + DHCP_NONE = 0, + DHCP_DISCOVER, + DHCP_OFFER, + DHCP_REQUEST, + DHCP_ACK } dhcpState; #endif static void -bootp_handler(udp_socket_t *skt, char *buf, int len, - ip_route_t *src_route, word src_port) +bootp_handler(udp_socket_t * skt, char *buf, int len, + ip_route_t * src_route, word src_port) { - bootp_header_t *b; -#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP - unsigned char *p, expected = 0; -#endif - - b = (bootp_header_t *)buf; - if (bp_info) { - memset(bp_info,0,sizeof *bp_info); - if (len > sizeof *bp_info) - len = sizeof *bp_info; - memcpy(bp_info, b, len); - } - - // Only accept pure REPLY responses - if (b->bp_op != BOOTREPLY) - return; - - // Must be sent to me, as well! - if (memcmp(b->bp_chaddr, __local_enet_addr, 6)) - return; - -#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP - p = b->bp_vend; - if (memcmp(p, dhcpCookie, sizeof(dhcpCookie))) - return; - p += 4; - - // Find the DHCP Message Type tag - while (*p != TAG_DHCP_MESS_TYPE) { - p += p[1] + 2; - if (p >= (unsigned char*)b + sizeof(*bp_info)) - return; - } - - p += 2; - - switch (dhcpState) { - case DHCP_DISCOVER: - // The discover message has been sent, only accept an offer reply - if (*p == DHCP_MESS_TYPE_OFFER) { - dhcpState = DHCP_OFFER; - return; - } else { - expected = DHCP_MESS_TYPE_OFFER; - } - break; - case DHCP_REQUEST: - // The request message has been sent, only accept an ack reply - if (*p == DHCP_MESS_TYPE_ACK) { - dhcpState = DHCP_ACK; - return; - } else { - expected = DHCP_MESS_TYPE_ACK; - } - break; - case DHCP_NONE: - case DHCP_OFFER: - case DHCP_ACK: - // Quitely ignore these - they indicate repeated message from server - return; - } - // See if we've been NAK'd - if so, give up and try again - if (*p == DHCP_MESS_TYPE_NAK) { - dhcpState = DHCP_NONE; - return; - } - diag_printf("DHCP reply: %d, not %d\n", (int)*p, (int)expected); - return; + bootp_header_t *b; +#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP + unsigned char *p, expected = 0; +#endif + + b = (bootp_header_t *) buf; + if (bp_info) { + memset(bp_info, 0, sizeof *bp_info); + if (len > sizeof *bp_info) + len = sizeof *bp_info; + memcpy(bp_info, b, len); + } + // Only accept pure REPLY responses + if (b->bp_op != BOOTREPLY) + return; + + // Must be sent to me, as well! + if (memcmp(b->bp_chaddr, __local_enet_addr, 6)) + return; + +#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP + p = b->bp_vend; + if (memcmp(p, dhcpCookie, sizeof(dhcpCookie))) + return; + p += 4; + + // Find the DHCP Message Type tag + while (*p != TAG_DHCP_MESS_TYPE) { + p += p[1] + 2; + if (p >= (unsigned char *)b + sizeof(*bp_info)) + return; + } + + p += 2; + + switch (dhcpState) { + case DHCP_DISCOVER: + // The discover message has been sent, only accept an offer reply + if (*p == DHCP_MESS_TYPE_OFFER) { + dhcpState = DHCP_OFFER; + return; + } else { + expected = DHCP_MESS_TYPE_OFFER; + } + break; + case DHCP_REQUEST: + // The request message has been sent, only accept an ack reply + if (*p == DHCP_MESS_TYPE_ACK) { + dhcpState = DHCP_ACK; + return; + } else { + expected = DHCP_MESS_TYPE_ACK; + } + break; + case DHCP_NONE: + case DHCP_OFFER: + case DHCP_ACK: + // Quitely ignore these - they indicate repeated message from server + return; + } + // See if we've been NAK'd - if so, give up and try again + if (*p == DHCP_MESS_TYPE_NAK) { + dhcpState = DHCP_NONE; + return; + } + diag_printf("DHCP reply: %d, not %d\n", (int)*p, (int)expected); + return; #else - // Simple BOOTP - this is all there is! - memcpy(__local_ip_addr, &b->bp_yiaddr, 4); + // Simple BOOTP - this is all there is! + memcpy(__local_ip_addr, &b->bp_yiaddr, 4); #endif } @@ -166,180 +166,191 @@ * Return zero if successful, -1 if not. */ -int -__bootp_find_local_ip(bootp_header_t *info) +int __bootp_find_local_ip(bootp_header_t * info) { - udp_socket_t udp_skt; - bootp_header_t b; - ip_route_t r; - int retry; - unsigned long start; - ip_addr_t saved_ip_addr; -#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP - unsigned char *p; - int oldState; -#endif - int txSize; - bool abort = false; - static int xid = SHOULD_BE_RANDOM; - -#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP - dhcpState = DHCP_NONE; -#endif - - // Where we want the results saved - bp_info = info; - // Preserve any IP address we currently have, just in case - memcpy(saved_ip_addr, __local_ip_addr, sizeof(__local_ip_addr)); - - // fill out route for a broadcast - r.ip_addr[0] = 255; - r.ip_addr[1] = 255; - r.ip_addr[2] = 255; - r.ip_addr[3] = 255; - r.enet_addr[0] = 255; - r.enet_addr[1] = 255; - r.enet_addr[2] = 255; - r.enet_addr[3] = 255; - r.enet_addr[4] = 255; - r.enet_addr[5] = 255; - - // setup a socket listener for bootp replies - __udp_install_listener(&udp_skt, IPPORT_BOOTPC, bootp_handler); - - retry = MAX_RETRIES; - while (!abort && (retry-- > 0)) { - start = MS_TICKS(); - - // Build up the BOOTP/DHCP request - memset(&b, 0, sizeof(b)); - b.bp_op = BOOTREQUEST; - b.bp_htype = HTYPE_ETHERNET; - b.bp_hlen = 6; - b.bp_xid = xid++; - memcpy(b.bp_chaddr, __local_enet_addr, 6); - memset(__local_ip_addr, 0, sizeof(__local_ip_addr)); - -#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP - p = b.bp_vend; - switch (dhcpState) { - case DHCP_NONE: - case DHCP_DISCOVER: - AddOption(p,dhcpCookie); - AddOption(p,dhcpDiscover); - AddOption(p,dhcpParamRequestList); - AddOption(p,dhcpEnd); - dhcpState = DHCP_DISCOVER; - break; - case DHCP_OFFER: - retry = MAX_RETRIES; - case DHCP_REQUEST: - b.bp_xid = bp_info->bp_xid; // Match what server sent - AddOption(p,dhcpCookie); - AddOption(p,dhcpRequest); - AddOption(p,dhcpRequestIP); - memcpy(p, &bp_info->bp_yiaddr, 4); p += 4; // Ask for the address just given - AddOption(p,dhcpParamRequestList); - AddOption(p,dhcpEnd); - dhcpState = DHCP_REQUEST; - memset(&b.bp_yiaddr, 0xFF, 4); - memset(&b.bp_siaddr, 0xFF, 4); - memset(&b.bp_yiaddr, 0x00, 4); - memset(&b.bp_siaddr, 0x00, 4); - break; - case DHCP_ACK: - // Ignore these states (they won't happen) - break; - } - - // Some servers insist on a minimum amount of "vendor" data - if (p < &b.bp_vend[BP_MIN_VEND_SIZE]) p = &b.bp_vend[BP_MIN_VEND_SIZE]; - txSize = p - (unsigned char*)&b; - oldState = dhcpState; + udp_socket_t udp_skt; + bootp_header_t b; + ip_route_t r; + int retry; + unsigned long start; + ip_addr_t saved_ip_addr; +#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP + unsigned char *p; + int oldState; +#endif + int txSize; + bool abort = false; + static int xid = SHOULD_BE_RANDOM; + +#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP + dhcpState = DHCP_NONE; +#endif + + // Where we want the results saved + bp_info = info; + // Preserve any IP address we currently have, just in case + memcpy(saved_ip_addr, __local_ip_addr, sizeof(__local_ip_addr)); + + // fill out route for a broadcast + r.ip_addr[0] = 255; + r.ip_addr[1] = 255; + r.ip_addr[2] = 255; + r.ip_addr[3] = 255; + r.enet_addr[0] = 255; + r.enet_addr[1] = 255; + r.enet_addr[2] = 255; + r.enet_addr[3] = 255; + r.enet_addr[4] = 255; + r.enet_addr[5] = 255; + + // setup a socket listener for bootp replies + __udp_install_listener(&udp_skt, IPPORT_BOOTPC, bootp_handler); + + retry = MAX_RETRIES; + while (!abort && (retry-- > 0)) { + start = MS_TICKS(); + + // Build up the BOOTP/DHCP request + memset(&b, 0, sizeof(b)); + b.bp_op = BOOTREQUEST; + b.bp_htype = HTYPE_ETHERNET; + b.bp_hlen = 6; + b.bp_xid = xid++; + memcpy(b.bp_chaddr, __local_enet_addr, 6); + memset(__local_ip_addr, 0, sizeof(__local_ip_addr)); + +#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP + p = b.bp_vend; + switch (dhcpState) { + case DHCP_NONE: + case DHCP_DISCOVER: + AddOption(p, dhcpCookie); + AddOption(p, dhcpDiscover); + AddOption(p, dhcpParamRequestList); + AddOption(p, dhcpEnd); + dhcpState = DHCP_DISCOVER; + break; + case DHCP_OFFER: + retry = MAX_RETRIES; + case DHCP_REQUEST: + b.bp_xid = bp_info->bp_xid; // Match what server sent + AddOption(p, dhcpCookie); + AddOption(p, dhcpRequest); + AddOption(p, dhcpRequestIP); + memcpy(p, &bp_info->bp_yiaddr, 4); + p += 4; // Ask for the address just given + AddOption(p, dhcpParamRequestList); + AddOption(p, dhcpEnd); + dhcpState = DHCP_REQUEST; + memset(&b.bp_yiaddr, 0xFF, 4); + memset(&b.bp_siaddr, 0xFF, 4); + memset(&b.bp_yiaddr, 0x00, 4); + memset(&b.bp_siaddr, 0x00, 4); + break; + case DHCP_ACK: + // Ignore these states (they won't happen) + break; + } + + // Some servers insist on a minimum amount of "vendor" data + if (p < &b.bp_vend[BP_MIN_VEND_SIZE]) + p = &b.bp_vend[BP_MIN_VEND_SIZE]; + txSize = p - (unsigned char *)&b; + oldState = dhcpState; #else - txSize = sizeof(b); -#endif - - __udp_send((char *)&b, txSize, &r, IPPORT_BOOTPS, IPPORT_BOOTPC); - - do { - __enet_poll(); -#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP - if (dhcpState != oldState) { - if (dhcpState == DHCP_ACK) { - unsigned char *end; - int optlen; - // Address information has now arrived! - memcpy(__local_ip_addr, &bp_info->bp_yiaddr, 4); + txSize = sizeof(b); +#endif + + __udp_send((char *)&b, txSize, &r, IPPORT_BOOTPS, + IPPORT_BOOTPC); + + do { + __enet_poll(); +#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP + if (dhcpState != oldState) { + if (dhcpState == DHCP_ACK) { + unsigned char *end; + int optlen; + // Address information has now arrived! + memcpy(__local_ip_addr, + &bp_info->bp_yiaddr, 4); #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY - memcpy(__local_ip_gate, &bp_info->bp_giaddr, 4); -#endif - p = bp_info->bp_vend+4; - end = (unsigned char *)bp_info+sizeof(*bp_info); - while (p < end) { - unsigned char tag = *p; - if (tag == TAG_END) - break; - if (tag == TAG_PAD) - optlen = 1; - else { - optlen = p[1]; - p += 2; - switch (tag) { + memcpy(__local_ip_gate, + &bp_info->bp_giaddr, 4); +#endif + p = bp_info->bp_vend + 4; + end = + (unsigned char *)bp_info + + sizeof(*bp_info); + while (p < end) { + unsigned char tag = *p; + if (tag == TAG_END) + break; + if (tag == TAG_PAD) + optlen = 1; + else { + optlen = p[1]; + p += 2; + switch (tag) { #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY - case TAG_SUBNET_MASK: // subnet mask - memcpy(__local_ip_mask,p,4); - break; - case TAG_GATEWAY: // router - memcpy(__local_ip_gate,p,4); - break; + case TAG_SUBNET_MASK: // subnet mask + memcpy + (__local_ip_mask, + p, 4); + break; + case TAG_GATEWAY: // router + memcpy + (__local_ip_gate, + p, 4); + break; #endif #ifdef CYGPKG_REDBOOT_NETWORKING_DNS - case TAG_DOMAIN_SERVER: -// diag_printf(" DNS server found!\n"); - memcpy(&__bootp_dns_addr, p, 4); - __bootp_dns_set = 1; + case TAG_DOMAIN_SERVER: +// diag_printf(" DNS server found!\n"); + memcpy + (&__bootp_dns_addr, + p, 4); + __bootp_dns_set + = 1; + break; +#endif + default: + break; + } + } + p += optlen; + } + __udp_remove_listener(IPPORT_BOOTPC); + return 0; + } else { + break; // State changed, handle it + } + } +#else + // All done, if address response has arrived + if (__local_ip_addr[0] || __local_ip_addr[1] || + __local_ip_addr[2] || __local_ip_addr[3]) { + /* success */ + __udp_remove_listener(IPPORT_BOOTPC); + return 0; + } +#endif + if (_rb_break(1)) { + // The user typed ^C on the console + abort = true; break; -#endif - default: - break; - } - } - p += optlen; - } - __udp_remove_listener(IPPORT_BOOTPC); - return 0; - } else { - break; // State changed, handle it - } - } -#else - // All done, if address response has arrived - if (__local_ip_addr[0] || __local_ip_addr[1] || - __local_ip_addr[2] || __local_ip_addr[3]) { - /* success */ - __udp_remove_listener(IPPORT_BOOTPC); - return 0; - } -#endif - if (_rb_break(1)) { - // The user typed ^C on the console - abort = true; - break; - } - MS_TICKS_DELAY(); // Count for ^C test - } while ((MS_TICKS_DELAY() - start) < RETRY_TIME); - - // Warn the user that we're polling for BOOTP info - if (retry == (MAX_RETRIES-1)) { - diag_printf("... waiting for BOOTP information\n"); - } - } - - // timed out - __udp_remove_listener(IPPORT_BOOTPC); - // Restore any previous IP address - memcpy(__local_ip_addr, saved_ip_addr, sizeof(__local_ip_addr)); - return -1; + } + MS_TICKS_DELAY(); // Count for ^C test + } while ((MS_TICKS_DELAY() - start) < RETRY_TIME); + + // Warn the user that we're polling for BOOTP info + if (retry == (MAX_RETRIES - 1)) { + diag_printf("... waiting for BOOTP information\n"); + } + } + + // timed out + __udp_remove_listener(IPPORT_BOOTPC); + // Restore any previous IP address + memcpy(__local_ip_addr, saved_ip_addr, sizeof(__local_ip_addr)); + return -1; } - - Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/dns.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/dns.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/dns.c (revision 12368) @@ -58,5 +58,5 @@ #include #include -#include /* Tracing support */ +#include /* Tracing support */ #include @@ -69,9 +69,5 @@ RedBoot_config_option("DNS server IP address", - dns_ip, - ALWAYS_ENABLED, true, - CONFIG_IP, - 0 - ); + dns_ip, ALWAYS_ENABLED, true, CONFIG_IP, 0); #endif @@ -92,5 +88,5 @@ /* static buffers so we can make do without malloc */ static struct hostent _hent; -static char* _h_addr_list[2]; +static char *_h_addr_list[2]; static struct in_addr _h_addr_list0; static int _hent_alloc = 0; @@ -102,79 +98,74 @@ /* as in dns.c proper */ -static short id = 0; /* ID of the last query */ -static int s = -1; /* Socket to the DNS server */ -static cyg_drv_mutex_t dns_mutex; /* Mutex to stop multiple queries as once */ -static char * domainname=NULL; /* Domain name used for queries */ - +static short id = 0; /* ID of the last query */ +static int s = -1; /* Socket to the DNS server */ +static cyg_drv_mutex_t dns_mutex; /* Mutex to stop multiple queries as once */ +static char *domainname = NULL; /* Domain name used for queries */ /* Allocate space for string of length (len). Return NULL on failure. */ -static char* -alloc_string(int len) -{ - int i; - - if (len > _STRING_LENGTH) - return NULL; - - for (i = 0; i < _STRING_COUNT; i++) { - if (_strings_alloc & (1 << i)) continue; - _strings_alloc |= (1< _STRING_LENGTH) + return NULL; + + for (i = 0; i < _STRING_COUNT; i++) { + if (_strings_alloc & (1 << i)) + continue; + _strings_alloc |= (1 << i); + return _strings[i]; + } + return NULL; +} + +static void free_string(char *s) +{ + int i; + for (i = 0; i < _STRING_COUNT; i++) { + if (_strings[i] == s) { + _strings_alloc &= ~(1 << i); + break; + } + } } /* Deallocate the memory taken to hold a hent structure */ -static void -free_hent(struct hostent * hent) -{ - if (hent->h_name) { - free_string(hent->h_name); - } - _hent_alloc = 0; +static void free_hent(struct hostent *hent) +{ + if (hent->h_name) { + free_string(hent->h_name); + } + _hent_alloc = 0; } /* Allocate hent structure with room for one in_addr. Returns NULL on failure. */ -static struct hostent* -alloc_hent(void) -{ - struct hostent *hent; - - if (_hent_alloc) return NULL; - - hent = &_hent; - memset(hent, 0, sizeof(struct hostent)); - hent->h_addr_list = _h_addr_list; - hent->h_addr_list[0] = (char*)&_h_addr_list0; - hent->h_addr_list[1] = NULL; - _hent_alloc = 1; - - return hent; -} - -static __inline__ void -free_stored_hent(void) -{ - free_hent( &_hent ); -} - -static __inline__ void -store_hent(struct hostent *hent) -{ - hent=hent; // avoid warning +static struct hostent *alloc_hent(void) +{ + struct hostent *hent; + + if (_hent_alloc) + return NULL; + + hent = &_hent; + memset(hent, 0, sizeof(struct hostent)); + hent->h_addr_list = _h_addr_list; + hent->h_addr_list[0] = (char *)&_h_addr_list0; + hent->h_addr_list[1] = NULL; + _hent_alloc = 1; + + return hent; +} + +static __inline__ void free_stored_hent(void) +{ + free_hent(&_hent); +} + +static __inline__ void store_hent(struct hostent *hent) +{ + hent = hent; // avoid warning } @@ -182,104 +173,103 @@ if it fails, otherwise put the response back in msg and return the length of the response. */ -static int -send_recv(char * msg, int len, int msglen) -{ - struct dns_header *dns_hdr; - int finished = false; - int read = 0; - - dns_hdr = (struct dns_header *) msg; - - do { - int len_togo = len; - struct timeval timeout; - struct sockaddr_in local_addr, from_addr; - - 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 (__udp_sendto(msg, len_togo, &server, &local_addr) < 0) - return -1; - - memset((char *)&from_addr, 0, sizeof(from_addr)); - - timeout.tv_sec = CYGNUM_REDBOOT_NETWORKING_DNS_TIMEOUT; - timeout.tv_usec = 0; - - read = __udp_recvfrom(msg, len, &from_addr, &local_addr, &timeout); - if (read < 0) - return -1; - - /* Reply to an old query. Ignore it */ - if (ntohs(dns_hdr->id) != (id-1)) { - continue; - } - finished = true; - } while (!finished); - - return read; -} - -void -set_dns(char* new_ip) -{ - in_addr_t dns_ip; - - memset(&server.sin_addr, 0, sizeof(server.sin_addr)); - if (!inet_aton(new_ip, &dns_ip)) { - diag_printf("Bad DNS server address: %s\n", new_ip); - } else { - memcpy(&server.sin_addr, &dns_ip, sizeof(dns_ip)); - /* server config is valid */ - s = 0; - } -} - -void -show_dns(void) -{ - diag_printf(", DNS server IP: %s", inet_ntoa((in_addr_t *)&server.sin_addr)); - if (0 == server.sin_addr.s_addr) { - s = -1; - } +static int send_recv(char *msg, int len, int msglen) +{ + struct dns_header *dns_hdr; + int finished = false; + int read = 0; + + dns_hdr = (struct dns_header *)msg; + + do { + int len_togo = len; + struct timeval timeout; + struct sockaddr_in local_addr, from_addr; + + 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 (__udp_sendto(msg, len_togo, &server, &local_addr) < 0) + return -1; + + memset((char *)&from_addr, 0, sizeof(from_addr)); + + timeout.tv_sec = CYGNUM_REDBOOT_NETWORKING_DNS_TIMEOUT; + timeout.tv_usec = 0; + + read = + __udp_recvfrom(msg, len, &from_addr, &local_addr, &timeout); + if (read < 0) + return -1; + + /* Reply to an old query. Ignore it */ + if (ntohs(dns_hdr->id) != (id - 1)) { + continue; + } + finished = true; + } while (!finished); + + return read; +} + +void set_dns(char *new_ip) +{ + in_addr_t dns_ip; + + memset(&server.sin_addr, 0, sizeof(server.sin_addr)); + if (!inet_aton(new_ip, &dns_ip)) { + diag_printf("Bad DNS server address: %s\n", new_ip); + } else { + memcpy(&server.sin_addr, &dns_ip, sizeof(dns_ip)); + /* server config is valid */ + s = 0; + } +} + +void show_dns(void) +{ + diag_printf(", DNS server IP: %s", + inet_ntoa((in_addr_t *) & server.sin_addr)); + if (0 == server.sin_addr.s_addr) { + s = -1; + } } /* Initialise the resolver. Open a socket and bind it to the address of the server. return -1 if something goes wrong, otherwise 0 */ -int -redboot_dns_res_init(void) -{ - memset((char *)&server, 0, sizeof(server)); - server.sin_len = sizeof(server); - server.sin_family = AF_INET; - server.sin_port = htons(DOMAIN_PORT); - cyg_drv_mutex_init(&dns_mutex); - - /* If we got a DNS server address from the DHCP/BOOTP, then use that address */ - if ( __bootp_dns_set ) { - memcpy(&server.sin_addr, &__bootp_dns_addr, sizeof(__bootp_dns_addr) ); - s = 0; - } - else { +int redboot_dns_res_init(void) +{ + memset((char *)&server, 0, sizeof(server)); + server.sin_len = sizeof(server); + server.sin_family = AF_INET; + server.sin_port = htons(DOMAIN_PORT); + cyg_drv_mutex_init(&dns_mutex); + + /* If we got a DNS server address from the DHCP/BOOTP, then use that address */ + if (__bootp_dns_set) { + memcpy(&server.sin_addr, &__bootp_dns_addr, + sizeof(__bootp_dns_addr)); + s = 0; + } else { #ifdef CYGSEM_REDBOOT_FLASH_CONFIG - { - ip_addr_t dns_ip; - - flash_get_config("dns_ip", &dns_ip, CONFIG_IP); - if (dns_ip[0] == 0 && dns_ip[1] == 0 && dns_ip[2] == 0 && dns_ip[3] == 0) - return -1; - memcpy(&server.sin_addr, &dns_ip, sizeof(dns_ip)); - /* server config is valid */ - s = 0; - } + { + ip_addr_t dns_ip; + + flash_get_config("dns_ip", &dns_ip, CONFIG_IP); + if (dns_ip[0] == 0 && dns_ip[1] == 0 && dns_ip[2] == 0 + && dns_ip[3] == 0) + return -1; + memcpy(&server.sin_addr, &dns_ip, sizeof(dns_ip)); + /* server config is valid */ + s = 0; + } #else - // Use static configuration - set_dns(__Xstr(CYGPKG_REDBOOT_NETWORKING_DNS_IP)); + // Use static configuration + set_dns(__Xstr(CYGPKG_REDBOOT_NETWORKING_DNS_IP)); #endif - } - - return 0; + } + + return 0; } Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade.c (revision 12368) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade.c (revision 12368) @@ -0,0 +1,147 @@ +/* +firmware upgrade code for DD-WRT webflash images +*/ + +#include +#include +#include +#include +#include "fwupgrade.h" + +/* some variables from flash.c */ +extern void *flash_start, *flash_end; +extern int flash_block_size, flash_num_blocks; +#ifdef CYGOPT_REDBOOT_FIS +extern void *fis_work_block; +extern void *fis_addr; +extern int fisdir_size; // Size of FIS directory. +#endif +//extern void _show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat); +extern void fis_update_directory(void); + +//#define TRACE diag_printf("DBG: %s:%d\n", __FUNCTION__, __LINE__) + +#define TRACE + +#define TRX_MAGIC 0x30524448 /* "HDR0" */ +#define TRX_VERSION 1 +#define TRX_MAX_LEN 0x8A0000 +#define TRX_NO_HEADER 1 /* Do not write TRX header */ + +//#if __BYTE_ORDER == __BIG_ENDIAN +unsigned int bswap_32(unsigned int *values) +{ + unsigned char *p = (unsigned char *)values; + unsigned char a; + a = p[3]; + p[3] = p[0]; + p[0] = a; + a = p[2]; + p[2] = p[1]; + p[1] = a; + return *values; +} + +#define STORE32_LE(X) bswap_32(X) + +//#elif __BYTE_ORDER == __LITTLE_ENDIAN +//#define STORE32_LE(X) (X) +//#else +//#error unkown endianness! +//#endif + +struct trx_header { + unsigned int magic; /* "HDR0" */ + unsigned int len; /* Length of file including header */ + unsigned int crc32; /* 32-bit CRC from flag_version to end of file */ + unsigned int flag_version; /* 0:15 flags, 16:31 version */ + unsigned int offsets[3]; /* Offsets of partitions from start of header */ +}; + +extern void fis_init(int argc, char *argv[], int force); + +int fw_check_image_ddwrt(unsigned char *addr, unsigned long maxlen, + int do_flash) +{ + struct trx_header *base = (struct trx_header *)addr; + struct trx_header trx; + memcpy(&trx, base, sizeof(trx)); + trx.magic = STORE32_LE(&trx.magic); + trx.len = STORE32_LE(&trx.len); + trx.crc32 = STORE32_LE(&trx.crc32); + if (trx.magic != TRX_MAGIC || trx.len < sizeof(struct trx_header)) { + diag_printf("DD-WRT_FW: Bad trx header\n"); + return -1; + } +//if (STORE32_LE(&trx.flag_version) & TRX_NO_HEADER) + trx.len -= sizeof(struct trx_header); + + unsigned int crc; + crc = + cyg_crc32_accumulate(0xffffffff, (unsigned char *)&trx.flag_version, + sizeof(struct trx_header) - 12); + crc = + cyg_crc32_accumulate(crc, addr + sizeof(struct trx_header), + trx.len); + if (crc == trx.crc32) { + if (!do_flash) + diag_printf("DD-WRT_FW: DD-WRT FW CRC Okay\n"); + } else { + diag_printf + ("DD-WRT_FW: DD-WRT FW CRC Failed (Calculated=0x%08X,Real=0x%08X\n", + crc, trx.crc32); + return -1; + } + if (do_flash) { + char *arg[] = { "fis", "init" }; + fis_init(2, arg, 1); + void *err_addr; + flash_read(fis_addr, fis_work_block, fisdir_size, + (void **)&err_addr); + struct fis_image_desc *img = NULL; + int i, stat; + img = fis_lookup("RedBoot", &i); + if (i != 0) { + diag_printf + ("DD-WRT_FW: RedBoot partition is not the first partition\n"); + return -1; + } + unsigned int flash_addr = img->flash_base + img->size; + diag_printf("DD-WRT_FW: flash base is 0x%08X\n", flash_addr); + if ((stat = + flash_erase((void *)flash_addr, trx.len, + (void **)&err_addr)) != 0) { + diag_printf("DD-WRT_FW: Can't erase region at %p: %s\n", + err_addr, flash_errmsg(stat)); + return -1; + } + if ((stat = + flash_program((void *)flash_addr, + (void *)(addr + sizeof(struct trx_header)), + trx.len, (void **)&err_addr)) != 0) { + diag_printf + ("DD-WRT_FW: Can't program region at %p: %s\n", + err_addr, flash_errmsg(stat)); + return -1; + } + img = fis_lookup("linux", &i); + if (!img) { + img = (struct fis_image_desc *)fis_work_block; + for (i = 0; i < fisdir_size / sizeof(*img); i++, img++) { + if (img->name[0] == (unsigned char)0xFF) { + break; + } + } + memset(img, 0, sizeof(*img)); + strcpy(img->name, "linux"); + } + img->flash_base = flash_addr; + img->mem_base = 0x80041000; + img->entry_point = 0x80041000; // Hope it's been set + img->size = trx.len; + img->data_length = trx.len; + fis_update_directory(); + diag_printf("DD-WRT_FW: flashing done\n"); + } + return 0; +} Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/tcp.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/tcp.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/tcp.c (revision 12368) @@ -61,5 +61,4 @@ #define MAX_TCP_DATA (MAX_TCP_SEGMENT - sizeof(tcp_header_t)) - /* sequence number comparison macros */ #define SEQ_LT(a,b) ((int)((a)-(b)) < 0) @@ -75,25 +74,24 @@ #ifdef BSP_LOG -static char * -flags_to_str(octet f) -{ - static char str[7], *p; - - p = str; - - if (f & TCP_FLAG_FIN) - *p++ = 'F'; - if (f & TCP_FLAG_SYN) - *p++ = 'S'; - if (f & TCP_FLAG_RST) - *p++ = 'R'; - if (f & TCP_FLAG_PSH) - *p++ = 'P'; - if (f & TCP_FLAG_ACK) - *p++ = 'A'; - if (f & TCP_FLAG_URG) - *p++ = 'U'; - *p = '\0'; - return str; +static char *flags_to_str(octet f) +{ + static char str[7], *p; + + p = str; + + if (f & TCP_FLAG_FIN) + *p++ = 'F'; + if (f & TCP_FLAG_SYN) + *p++ = 'S'; + if (f & TCP_FLAG_RST) + *p++ = 'R'; + if (f & TCP_FLAG_PSH) + *p++ = 'P'; + if (f & TCP_FLAG_ACK) + *p++ = 'A'; + if (f & TCP_FLAG_URG) + *p++ = 'U'; + *p = '\0'; + return str; } #endif @@ -108,42 +106,104 @@ * Format and send an outgoing segment. */ -static void -tcp_send(tcp_socket_t *s, int flags, int resend) -{ - tcp_header_t *tcp; - ip_header_t *ip; - pktbuf_t *pkt = &s->pkt; - unsigned short cksum; - dword tcp_magic; - int tcp_magic_size = sizeof(tcp_magic); - - ip = pkt->ip_hdr; - tcp = pkt->tcp_hdr; - - if (flags & TCP_FLAG_SYN) { - /* If SYN, assume no data and send MSS option in tcp header */ - pkt->pkt_bytes = sizeof(tcp_header_t) + 4; - tcp->hdr_len = 6; - tcp_magic = htonl(0x02040000 | MAX_TCP_DATA); - memcpy((unsigned char *)(tcp+1), &tcp_magic, tcp_magic_size); - s->data_bytes = 0; - } else { - pkt->pkt_bytes = s->data_bytes + sizeof(tcp_header_t); +static void tcp_send(tcp_socket_t * s, int flags, int resend) +{ + tcp_header_t *tcp; + ip_header_t *ip; + pktbuf_t *pkt = &s->pkt; + unsigned short cksum; + dword tcp_magic; + int tcp_magic_size = sizeof(tcp_magic); + + ip = pkt->ip_hdr; + tcp = pkt->tcp_hdr; + + if (flags & TCP_FLAG_SYN) { + /* If SYN, assume no data and send MSS option in tcp header */ + pkt->pkt_bytes = sizeof(tcp_header_t) + 4; + tcp->hdr_len = 6; + tcp_magic = htonl(0x02040000 | MAX_TCP_DATA); + memcpy((unsigned char *)(tcp + 1), &tcp_magic, tcp_magic_size); + s->data_bytes = 0; + } else { + pkt->pkt_bytes = s->data_bytes + sizeof(tcp_header_t); + tcp->hdr_len = 5; + } + + /* tcp header */ + tcp->reserved = 0; + tcp->seqnum = htonl(s->seq); + tcp->acknum = htonl(s->ack); + tcp->checksum = 0; + + if (!resend) { + tcp->src_port = htons(s->our_port); + tcp->dest_port = htons(s->his_port); + tcp->flags = flags; + /* always set PUSH flag if sending data */ + if (s->data_bytes) + tcp->flags |= TCP_FLAG_PSH; + tcp->window = htons(MAX_TCP_DATA); + tcp->urgent = 0; + + /* fill in some pseudo-header fields */ + memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t)); + memcpy(ip->destination, s->his_addr.ip_addr, sizeof(ip_addr_t)); + ip->protocol = IP_PROTO_TCP; + } + + /* another pseudo-header field */ + ip->length = htons(pkt->pkt_bytes); + + /* compute tcp checksum */ + cksum = __sum((word *) tcp, pkt->pkt_bytes, __pseudo_sum(ip)); + tcp->checksum = htons(cksum); + + __ip_send(pkt, IP_PROTO_TCP, &s->his_addr); + + // HACK! If this delay is not present, then if the target system sends + // back data (not just an ACK), then somehow we miss it :-( + CYGACC_CALL_IF_DELAY_US(2 * 1000); + + BSPLOG(bsp_log("tcp_send: state[%d] flags[%s] ack[%x] data[%d].\n", + s->state, flags_to_str(tcp->flags), s->ack, + s->data_bytes)); + + if (s->state == _TIME_WAIT) { + // If 'reuse' is set on socket, close after 1 second, otherwise 2 minutes + __timer_set(&s->timer, s->reuse ? 1000 : 120000, do_close, s); + } else if ((tcp->flags & (TCP_FLAG_FIN | TCP_FLAG_SYN)) + || s->data_bytes) + __timer_set(&s->timer, 1000, do_retrans, s); +} + +static pktbuf_t ack_pkt; +static word ack_buf[ETH_MIN_PKTLEN / sizeof(word)]; + +/* + * Send an ack. + */ +static void send_ack(tcp_socket_t * s) +{ + tcp_header_t *tcp; + ip_header_t *ip; + unsigned short cksum; + + ack_pkt.buf = ack_buf; + ack_pkt.bufsize = sizeof(ack_buf); + ack_pkt.ip_hdr = ip = (ip_header_t *) ack_buf; + ack_pkt.tcp_hdr = tcp = (tcp_header_t *) (ip + 1); + ack_pkt.pkt_bytes = sizeof(tcp_header_t); + + /* tcp header */ tcp->hdr_len = 5; - } - - /* tcp header */ - tcp->reserved = 0; - tcp->seqnum = htonl(s->seq); - tcp->acknum = htonl(s->ack); - tcp->checksum = 0; - - if (!resend) { + tcp->reserved = 0; + tcp->seqnum = htonl(s->seq); + tcp->acknum = htonl(s->ack); + tcp->checksum = 0; + tcp->src_port = htons(s->our_port); tcp->dest_port = htons(s->his_port); - tcp->flags = flags; - /* always set PUSH flag if sending data */ - if (s->data_bytes) - tcp->flags |= TCP_FLAG_PSH; + tcp->flags = TCP_FLAG_ACK; + tcp->window = htons(MAX_TCP_DATA); tcp->urgent = 0; @@ -153,142 +213,74 @@ memcpy(ip->destination, s->his_addr.ip_addr, sizeof(ip_addr_t)); ip->protocol = IP_PROTO_TCP; - } - - /* another pseudo-header field */ - ip->length = htons(pkt->pkt_bytes); - - /* compute tcp checksum */ - cksum = __sum((word *)tcp, pkt->pkt_bytes, __pseudo_sum(ip)); - tcp->checksum = htons(cksum); - - __ip_send(pkt, IP_PROTO_TCP, &s->his_addr); - - // HACK! If this delay is not present, then if the target system sends - // back data (not just an ACK), then somehow we miss it :-( - CYGACC_CALL_IF_DELAY_US(2*1000); - - BSPLOG(bsp_log("tcp_send: state[%d] flags[%s] ack[%x] data[%d].\n", - s->state, flags_to_str(tcp->flags), s->ack, s->data_bytes)); - - if (s->state == _TIME_WAIT) { - // If 'reuse' is set on socket, close after 1 second, otherwise 2 minutes - __timer_set(&s->timer, s->reuse ? 1000 : 120000, do_close, s); - } - else if ((tcp->flags & (TCP_FLAG_FIN | TCP_FLAG_SYN)) || s->data_bytes) - __timer_set(&s->timer, 1000, do_retrans, s); -} - -static pktbuf_t ack_pkt; -static word ack_buf[ETH_MIN_PKTLEN/sizeof(word)]; - -/* - * Send an ack. - */ -static void -send_ack(tcp_socket_t *s) -{ - tcp_header_t *tcp; - ip_header_t *ip; - unsigned short cksum; - - ack_pkt.buf = ack_buf; - ack_pkt.bufsize = sizeof(ack_buf); - ack_pkt.ip_hdr = ip = (ip_header_t *)ack_buf; - ack_pkt.tcp_hdr = tcp = (tcp_header_t *)(ip + 1); - ack_pkt.pkt_bytes = sizeof(tcp_header_t); - - /* tcp header */ - tcp->hdr_len = 5; - tcp->reserved = 0; - tcp->seqnum = htonl(s->seq); - tcp->acknum = htonl(s->ack); - tcp->checksum = 0; - - tcp->src_port = htons(s->our_port); - tcp->dest_port = htons(s->his_port); - tcp->flags = TCP_FLAG_ACK; - - tcp->window = htons(MAX_TCP_DATA); - tcp->urgent = 0; - - /* fill in some pseudo-header fields */ - memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t)); - memcpy(ip->destination, s->his_addr.ip_addr, sizeof(ip_addr_t)); - ip->protocol = IP_PROTO_TCP; - - /* another pseudo-header field */ - ip->length = htons(sizeof(tcp_header_t)); - - /* compute tcp checksum */ - cksum = __sum((word *)tcp, sizeof(*tcp), __pseudo_sum(ip)); - tcp->checksum = htons(cksum); - - __ip_send(&ack_pkt, IP_PROTO_TCP, &s->his_addr); -} - + + /* another pseudo-header field */ + ip->length = htons(sizeof(tcp_header_t)); + + /* compute tcp checksum */ + cksum = __sum((word *) tcp, sizeof(*tcp), __pseudo_sum(ip)); + tcp->checksum = htons(cksum); + + __ip_send(&ack_pkt, IP_PROTO_TCP, &s->his_addr); +} /* * Send a reset for a bogus incoming segment. */ -static void -send_reset(pktbuf_t *pkt, ip_route_t *r) -{ - ip_header_t *ip = pkt->ip_hdr; - tcp_header_t *tcp = pkt->tcp_hdr; - dword seq, ack; - word src, dest; - word cksum; - - seq = ntohl(tcp->acknum); - ack = ntohl(tcp->seqnum); - src = ntohs(tcp->dest_port); - dest = ntohs(tcp->src_port); - - tcp = (tcp_header_t *)(ip + 1); - pkt->pkt_bytes = sizeof(tcp_header_t); - - /* tcp header */ - tcp->hdr_len = 5; - tcp->reserved = 0; - tcp->seqnum = htonl(seq); - tcp->acknum = htonl(ack); - tcp->window = htons(1024); - tcp->urgent = 0; - tcp->checksum = 0; - tcp->src_port = htons(src); - tcp->dest_port = htons(dest); - tcp->flags = TCP_FLAG_RST | TCP_FLAG_ACK; - - /* fill in some pseudo-header fields */ - memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t)); - memcpy(ip->destination, r->ip_addr, sizeof(ip_addr_t)); - ip->protocol = IP_PROTO_TCP; - ip->length = htons(pkt->pkt_bytes); - - /* compute tcp checksum */ - cksum = __sum((word *)tcp, pkt->pkt_bytes, __pseudo_sum(ip)); - tcp->checksum = htons(cksum); - - __ip_send(pkt, IP_PROTO_TCP, r); -} - - +static void send_reset(pktbuf_t * pkt, ip_route_t * r) +{ + ip_header_t *ip = pkt->ip_hdr; + tcp_header_t *tcp = pkt->tcp_hdr; + dword seq, ack; + word src, dest; + word cksum; + + seq = ntohl(tcp->acknum); + ack = ntohl(tcp->seqnum); + src = ntohs(tcp->dest_port); + dest = ntohs(tcp->src_port); + + tcp = (tcp_header_t *) (ip + 1); + pkt->pkt_bytes = sizeof(tcp_header_t); + + /* tcp header */ + tcp->hdr_len = 5; + tcp->reserved = 0; + tcp->seqnum = htonl(seq); + tcp->acknum = htonl(ack); + tcp->window = htons(1024); + tcp->urgent = 0; + tcp->checksum = 0; + tcp->src_port = htons(src); + tcp->dest_port = htons(dest); + tcp->flags = TCP_FLAG_RST | TCP_FLAG_ACK; + + /* fill in some pseudo-header fields */ + memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t)); + memcpy(ip->destination, r->ip_addr, sizeof(ip_addr_t)); + ip->protocol = IP_PROTO_TCP; + ip->length = htons(pkt->pkt_bytes); + + /* compute tcp checksum */ + cksum = __sum((word *) tcp, pkt->pkt_bytes, __pseudo_sum(ip)); + tcp->checksum = htons(cksum); + + __ip_send(pkt, IP_PROTO_TCP, r); +} /* * Remove given socket from socket list. */ -static void -unlink_socket(tcp_socket_t *s) -{ - tcp_socket_t *prev, *tp; - - for (prev = NULL, tp = tcp_list; tp; prev = tp, tp = tp->next) - if (tp == s) { - BSPLOG(bsp_log("unlink tcp socket.\n")); - if (prev) - prev->next = s->next; - else - tcp_list = s->next; - } +static void unlink_socket(tcp_socket_t * s) +{ + tcp_socket_t *prev, *tp; + + for (prev = NULL, tp = tcp_list; tp; prev = tp, tp = tp->next) + if (tp == s) { + BSPLOG(bsp_log("unlink tcp socket.\n")); + if (prev) + prev->next = s->next; + else + tcp_list = s->next; + } } @@ -296,49 +288,41 @@ * Retransmit last packet. */ -static void -do_retrans(void *p) -{ - BSPLOG(bsp_log("tcp do_retrans.\n")); - tcp_send((tcp_socket_t *)p, 0, 1); -} - - -static void -do_close(void *p) -{ - BSPLOG(bsp_log("tcp do_close.\n")); - /* close connection */ - ((tcp_socket_t *)p)->state = _CLOSED; - unlink_socket(p); -} - - -static void -free_rxlist(tcp_socket_t *s) -{ - pktbuf_t *p; - - BSPLOG(bsp_log("tcp free_rxlist.\n")); - - while ((p = s->rxlist) != NULL) { - s->rxlist = p->next; - __pktbuf_free(p); - } -} - +static void do_retrans(void *p) +{ + BSPLOG(bsp_log("tcp do_retrans.\n")); + tcp_send((tcp_socket_t *) p, 0, 1); +} + +static void do_close(void *p) +{ + BSPLOG(bsp_log("tcp do_close.\n")); + /* close connection */ + ((tcp_socket_t *) p)->state = _CLOSED; + unlink_socket(p); +} + +static void free_rxlist(tcp_socket_t * s) +{ + pktbuf_t *p; + + BSPLOG(bsp_log("tcp free_rxlist.\n")); + + while ((p = s->rxlist) != NULL) { + s->rxlist = p->next; + __pktbuf_free(p); + } +} /* * Handle a conection reset. */ -static void -do_reset(tcp_socket_t *s) -{ - /* close connection */ - s->state = _CLOSED; - __timer_cancel(&s->timer); - free_rxlist(s); - unlink_socket(s); -} - +static void do_reset(tcp_socket_t * s) +{ + /* close connection */ + s->state = _CLOSED; + __timer_cancel(&s->timer); + free_rxlist(s); + unlink_socket(s); +} /* @@ -346,500 +330,504 @@ * Returns true if packet is queued on rxlist, false otherwise. */ -static int -handle_data(tcp_socket_t *s, pktbuf_t *pkt) -{ - tcp_header_t *tcp = pkt->tcp_hdr; - unsigned int diff, seq; - int data_len; - char *data_ptr; - pktbuf_t *p; - - data_len = pkt->pkt_bytes - (tcp->hdr_len << 2); - data_ptr = ((char *)tcp) + (tcp->hdr_len << 2); - - seq = ntohl(tcp->seqnum); - - BSPLOG(bsp_log("tcp data: seq[%x] len[%d].\n", seq, data_len)); - - if (SEQ_LE(seq, s->ack)) { - /* - * Figure difference between which byte we're expecting and which byte - * is sent first. Adjust data length and data pointer accordingly. - */ - diff = s->ack - seq; - data_len -= diff; - data_ptr += diff; - - if (data_len > 0) { - /* queue the new data */ - s->ack += data_len; - pkt->next = NULL; - if ((p = s->rxlist) != NULL) { - while (p->next) - p = p->next; - p->next = pkt; - BSPLOG(bsp_log("tcp data: Add pkt[%x] len[%d].\n", - pkt, data_len)); - } else { - s->rxlist = pkt; - s->rxcnt = data_len; - s->rxptr = data_ptr; - BSPLOG(bsp_log("tcp data: pkt[%x] len[%d].\n", - pkt, data_len)); - } - return 1; - } - } - return 0; -} - - -static void -handle_ack(tcp_socket_t *s, pktbuf_t *pkt) -{ - tcp_header_t *tcp = pkt->tcp_hdr; - dword ack; - int advance; - char *dp; - - /* process ack value in packet */ - ack = ntohl(tcp->acknum); - - BSPLOG(bsp_log("Rcvd tcp ACK %x\n", ack)); - - if (SEQ_GT(ack, s->seq)) { - __timer_cancel(&s->timer); - advance = ack - s->seq; - if (advance > s->data_bytes) - advance = s->data_bytes; - - BSPLOG(bsp_log("seq advance %d", advance)); - - if (advance > 0) { - s->seq += advance; - s->data_bytes -= advance; - if (s->data_bytes) { - /* other end ack'd only part of the pkt */ - BSPLOG(bsp_log(" %d bytes left", s->data_bytes)); - dp = (char *)(s->pkt.tcp_hdr + 1); - memcpy(dp, dp + advance, s->data_bytes); - } - } - } - BSPLOG(bsp_log("\n")); -} - +static int handle_data(tcp_socket_t * s, pktbuf_t * pkt) +{ + tcp_header_t *tcp = pkt->tcp_hdr; + unsigned int diff, seq; + int data_len; + char *data_ptr; + pktbuf_t *p; + + data_len = pkt->pkt_bytes - (tcp->hdr_len << 2); + data_ptr = ((char *)tcp) + (tcp->hdr_len << 2); + + seq = ntohl(tcp->seqnum); + + BSPLOG(bsp_log("tcp data: seq[%x] len[%d].\n", seq, data_len)); + + if (SEQ_LE(seq, s->ack)) { + /* + * Figure difference between which byte we're expecting and which byte + * is sent first. Adjust data length and data pointer accordingly. + */ + diff = s->ack - seq; + data_len -= diff; + data_ptr += diff; + + if (data_len > 0) { + /* queue the new data */ + s->ack += data_len; + pkt->next = NULL; + if ((p = s->rxlist) != NULL) { + while (p->next) + p = p->next; + p->next = pkt; + BSPLOG(bsp_log + ("tcp data: Add pkt[%x] len[%d].\n", pkt, + data_len)); + } else { + s->rxlist = pkt; + s->rxcnt = data_len; + s->rxptr = data_ptr; + BSPLOG(bsp_log("tcp data: pkt[%x] len[%d].\n", + pkt, data_len)); + } + return 1; + } + } + return 0; +} + +static void handle_ack(tcp_socket_t * s, pktbuf_t * pkt) +{ + tcp_header_t *tcp = pkt->tcp_hdr; + dword ack; + int advance; + char *dp; + + /* process ack value in packet */ + ack = ntohl(tcp->acknum); + + BSPLOG(bsp_log("Rcvd tcp ACK %x\n", ack)); + + if (SEQ_GT(ack, s->seq)) { + __timer_cancel(&s->timer); + advance = ack - s->seq; + if (advance > s->data_bytes) + advance = s->data_bytes; + + BSPLOG(bsp_log("seq advance %d", advance)); + + if (advance > 0) { + s->seq += advance; + s->data_bytes -= advance; + if (s->data_bytes) { + /* other end ack'd only part of the pkt */ + BSPLOG(bsp_log + (" %d bytes left", s->data_bytes)); + dp = (char *)(s->pkt.tcp_hdr + 1); + memcpy(dp, dp + advance, s->data_bytes); + } + } + } + BSPLOG(bsp_log("\n")); +} /* * Handle incoming TCP packets. */ -void -__tcp_handler(pktbuf_t *pkt, ip_route_t *r) -{ - tcp_header_t *tcp = pkt->tcp_hdr; - ip_header_t *ip = pkt->ip_hdr; - tcp_socket_t *prev,*s; - dword ack; - int queued = 0; - - /* set length for pseudo sum calculation */ - ip->length = htons(pkt->pkt_bytes); - - if (__sum((word *)tcp, pkt->pkt_bytes, __pseudo_sum(ip)) == 0) { - for (prev = NULL, s = tcp_list; s; prev = s, s = s->next) { - if (s->our_port == ntohs(tcp->dest_port)) { - if (s->his_port == 0) - break; - if (s->his_port == ntohs(tcp->src_port) && - !memcmp(r->ip_addr, s->his_addr.ip_addr, sizeof(ip_addr_t))) - break; - } - } - - if (s) { - /* found the socket this packet belongs to */ - - /* refresh his ethernet address */ - memcpy(s->his_addr.enet_addr, r->enet_addr, sizeof(enet_addr_t)); - - if (s->state != _SYN_RCVD && tcp->flags & TCP_FLAG_RST) { - BSPLOG(bsp_log("TCP_FLAG_RST rcvd\n")); - do_reset(s); +void __tcp_handler(pktbuf_t * pkt, ip_route_t * r) +{ + tcp_header_t *tcp = pkt->tcp_hdr; + ip_header_t *ip = pkt->ip_hdr; + tcp_socket_t *prev, *s; + dword ack; + int queued = 0; + + /* set length for pseudo sum calculation */ + ip->length = htons(pkt->pkt_bytes); + + if (__sum((word *) tcp, pkt->pkt_bytes, __pseudo_sum(ip)) == 0) { + for (prev = NULL, s = tcp_list; s; prev = s, s = s->next) { + if (s->our_port == ntohs(tcp->dest_port)) { + if (s->his_port == 0) + break; + if (s->his_port == ntohs(tcp->src_port) && + !memcmp(r->ip_addr, s->his_addr.ip_addr, + sizeof(ip_addr_t))) + break; + } + } + + if (s) { + /* found the socket this packet belongs to */ + + /* refresh his ethernet address */ + memcpy(s->his_addr.enet_addr, r->enet_addr, + sizeof(enet_addr_t)); + + if (s->state != _SYN_RCVD && tcp->flags & TCP_FLAG_RST) { + BSPLOG(bsp_log("TCP_FLAG_RST rcvd\n")); + do_reset(s); + __pktbuf_free(pkt); + return; + } + + switch (s->state) { + + case _SYN_SENT: + /* active open not supported */ + if (tcp->flags != (TCP_FLAG_SYN | TCP_FLAG_ACK)) { + do_reset(s); + __pktbuf_free(pkt); + return; + } + s->state = _ESTABLISHED; + s->ack = ntohl(tcp->seqnum) + 1; + s->seq = ntohl(tcp->acknum); + __timer_cancel(&s->timer); + send_ack(s); + break; + + case _LISTEN: + if (tcp->flags & TCP_FLAG_SYN) { + s->state = _SYN_RCVD; + s->ack = ntohl(tcp->seqnum) + 1; + s->his_port = ntohs(tcp->src_port); + memcpy(s->his_addr.ip_addr, r->ip_addr, + sizeof(ip_addr_t)); + s->data_bytes = 0; + + BSPLOG(bsp_log + ("SYN from %d.%d.%d.%d:%d (seq %x)\n", + s->his_addr.ip_addr[0], + s->his_addr.ip_addr[1], + s->his_addr.ip_addr[2], + s->his_addr.ip_addr[3], + s->his_port, + ntohl(tcp->seqnum))); + + tcp_send(s, TCP_FLAG_SYN | TCP_FLAG_ACK, + 0); + } else + send_reset(pkt, r); + break; + + case _SYN_RCVD: + BSPLOG(bsp_log("_SYN_RCVD timer cancel.\n")); + __timer_cancel(&s->timer); + + /* go back to _LISTEN state if reset */ + if (tcp->flags & TCP_FLAG_RST) { + s->state = _LISTEN; + + BSPLOG(bsp_log + ("_SYN_RCVD --> _LISTEN\n")); + + } else if (tcp->flags & TCP_FLAG_SYN) { + /* apparently our SYN/ACK was lost? */ + tcp_send(s, 0, 1); + + BSPLOG(bsp_log + ("retransmitting SYN/ACK\n")); + + } else if ((tcp->flags & TCP_FLAG_ACK) && + ntohl(tcp->acknum) == (s->seq + 1)) { + /* we've established the connection */ + s->state = _ESTABLISHED; + s->seq++; + + BSPLOG(bsp_log + ("ACK received - connection established\n")); + } + break; + + case _ESTABLISHED: + case _CLOSE_WAIT: + ack = s->ack; /* save original ack */ + if (tcp->flags & TCP_FLAG_ACK) + handle_ack(s, pkt); + + queued = handle_data(s, pkt); + + if ((tcp->flags & TCP_FLAG_FIN) && + ntohl(tcp->seqnum) == s->ack) { + + BSPLOG(bsp_log + ("FIN received - going to _CLOSE_WAIT\n")); + + s->ack++; + s->state = _CLOSE_WAIT; + } + /* + * Send an ack if neccessary. + */ + if (s->ack != ack + || pkt->pkt_bytes > (tcp->hdr_len << 2)) + send_ack(s); + break; + + case _LAST_ACK: + if (tcp->flags & TCP_FLAG_ACK) { + handle_ack(s, pkt); + if (ntohl(tcp->acknum) == (s->seq + 1)) { + BSPLOG(bsp_log + ("_LAST_ACK --> _CLOSED\n")); + s->state = _CLOSED; + unlink_socket(s); + } + } + break; + + case _FIN_WAIT_1: + if (tcp->flags & TCP_FLAG_ACK) { + handle_ack(s, pkt); + if (ntohl(tcp->acknum) == (s->seq + 1)) { + /* got ACK for FIN packet */ + s->seq++; + if (tcp->flags & TCP_FLAG_FIN) { + BSPLOG(bsp_log + ("_FIN_WAIT_1 --> _TIME_WAIT\n")); + s->ack++; + s->state = _TIME_WAIT; + send_ack(s); + } else { + s->state = _FIN_WAIT_2; + BSPLOG(bsp_log + ("_FIN_WAIT_1 --> _FIN_WAIT_2\n")); + } + break; /* All done for now */ + } + } + /* At this point, no ACK for FIN has been seen, so check for + simultaneous close */ + if (tcp->flags & TCP_FLAG_FIN) { + BSPLOG(bsp_log + ("_FIN_WAIT_1 --> _CLOSING\n")); + __timer_cancel(&s->timer); + s->ack++; + s->state = _CLOSING; + /* FIN is resent so the timeout and retry for this packet + will also take care of timeout and resend of the + previously sent FIN (which got us to FIN_WAIT_1). While + not technically correct, resending FIN only causes a + duplicate FIN (same sequence number) which should be + ignored by the other end. */ + tcp_send(s, TCP_FLAG_FIN | TCP_FLAG_ACK, + 0); + } + break; + + case _FIN_WAIT_2: + queued = handle_data(s, pkt); + if (tcp->flags & TCP_FLAG_FIN) { + BSPLOG(bsp_log + ("_FIN_WAIT_2 --> _TIME_WAIT\n")); + s->ack++; + s->state = _TIME_WAIT; + send_ack(s); + } + break; + + case _CLOSING: + if (tcp->flags & TCP_FLAG_ACK) { + handle_ack(s, pkt); + if (ntohl(tcp->acknum) == (s->seq + 1)) { + /* got ACK for FIN packet */ + BSPLOG(bsp_log + ("_CLOSING --> _TIME_WAIT\n")); + __timer_cancel(&s->timer); + s->state = _TIME_WAIT; + } + } + break; + + case _TIME_WAIT: + BSPLOG(bsp_log("_TIME_WAIT resend.\n")); + if (tcp->flags & TCP_FLAG_FIN) + tcp_send(s, 0, 1); /* just resend ack */ + break; + } + } else { + BSPLOG(bsp_log + ("Unexpected segment from: %d.%d.%d.%d:%d\n", + r->ip_addr[0], r->ip_addr[1], r->ip_addr[3], + r->ip_addr[4], ntohs(tcp->src_port))); + send_reset(pkt, r); + } + } + if (!queued) __pktbuf_free(pkt); - return; - } - - switch (s->state) { - - case _SYN_SENT: - /* active open not supported */ - if (tcp->flags != (TCP_FLAG_SYN | TCP_FLAG_ACK)) { - do_reset(s); - __pktbuf_free(pkt); - return; - } - s->state = _ESTABLISHED; - s->ack = ntohl(tcp->seqnum) + 1; - s->seq = ntohl(tcp->acknum); - __timer_cancel(&s->timer); - send_ack(s); - break; - - case _LISTEN: - if (tcp->flags & TCP_FLAG_SYN) { - s->state = _SYN_RCVD; - s->ack = ntohl(tcp->seqnum) + 1; - s->his_port = ntohs(tcp->src_port); - memcpy(s->his_addr.ip_addr, r->ip_addr, sizeof(ip_addr_t)); - s->data_bytes = 0; - - BSPLOG(bsp_log("SYN from %d.%d.%d.%d:%d (seq %x)\n", - s->his_addr.ip_addr[0],s->his_addr.ip_addr[1], - s->his_addr.ip_addr[2],s->his_addr.ip_addr[3], - s->his_port, ntohl(tcp->seqnum))); - - tcp_send(s, TCP_FLAG_SYN | TCP_FLAG_ACK, 0); - } - else - send_reset(pkt, r); - break; - - case _SYN_RCVD: - BSPLOG(bsp_log("_SYN_RCVD timer cancel.\n")); - __timer_cancel(&s->timer); - - /* go back to _LISTEN state if reset */ - if (tcp->flags & TCP_FLAG_RST) { - s->state = _LISTEN; - - BSPLOG(bsp_log("_SYN_RCVD --> _LISTEN\n")); - - } else if (tcp->flags & TCP_FLAG_SYN) { - /* apparently our SYN/ACK was lost? */ - tcp_send(s, 0, 1); - - BSPLOG(bsp_log("retransmitting SYN/ACK\n")); - - } else if ((tcp->flags & TCP_FLAG_ACK) && - ntohl(tcp->acknum) == (s->seq + 1)) { - /* we've established the connection */ - s->state = _ESTABLISHED; - s->seq++; - - BSPLOG(bsp_log("ACK received - connection established\n")); - } - break; - - case _ESTABLISHED: - case _CLOSE_WAIT: - ack = s->ack; /* save original ack */ - if (tcp->flags & TCP_FLAG_ACK) - handle_ack(s, pkt); - - queued = handle_data(s, pkt); - - if ((tcp->flags & TCP_FLAG_FIN) && - ntohl(tcp->seqnum) == s->ack) { - - BSPLOG(bsp_log("FIN received - going to _CLOSE_WAIT\n")); - - s->ack++; - s->state = _CLOSE_WAIT; - } - /* - * Send an ack if neccessary. - */ - if (s->ack != ack || pkt->pkt_bytes > (tcp->hdr_len << 2)) - send_ack(s); - break; - - case _LAST_ACK: - if (tcp->flags & TCP_FLAG_ACK) { - handle_ack(s, pkt); - if (ntohl(tcp->acknum) == (s->seq + 1)) { - BSPLOG(bsp_log("_LAST_ACK --> _CLOSED\n")); - s->state = _CLOSED; - unlink_socket(s); - } - } - break; - - case _FIN_WAIT_1: - if (tcp->flags & TCP_FLAG_ACK) { - handle_ack(s, pkt); - if (ntohl(tcp->acknum) == (s->seq + 1)) { - /* got ACK for FIN packet */ - s->seq++; - if (tcp->flags & TCP_FLAG_FIN) { - BSPLOG(bsp_log("_FIN_WAIT_1 --> _TIME_WAIT\n")); - s->ack++; - s->state = _TIME_WAIT; - send_ack(s); +} + +void __tcp_poll(void) +{ + __enet_poll(); + __timer_poll(); +} + +int __tcp_listen(tcp_socket_t * s, word port) +{ + BSPLOG(bsp_log("tcp_listen: s[%p] port[%x]\n", s, port)); + + memset(s, 0, sizeof(tcp_socket_t)); + s->state = _LISTEN; + s->our_port = port; + s->pkt.buf = (word *) s->pktbuf; + s->pkt.bufsize = ETH_MAX_PKTLEN; + s->pkt.ip_hdr = (ip_header_t *) s->pkt.buf; + s->pkt.tcp_hdr = (tcp_header_t *) (s->pkt.ip_hdr + 1); + + s->next = tcp_list; + +#if 0 + /* limit to one open socket at a time */ + if (s->next) { + BSPLOG(bsp_log("tcp_listen: recursion error\n")); + BSPLOG(while (1)) ; + } +#endif + + tcp_list = s; + + return 0; +} + +/* + * SO_REUSEADDR, no 2MSL. + */ +void __tcp_so_reuseaddr(tcp_socket_t * s) +{ +// BSPLOG(bsp_log("__tcp_so_reuseaddr.\n")); + s->reuse = 0x01; +} + +/* + * Block while waiting for all data to be transmitted. + */ +void __tcp_drain(tcp_socket_t * s) +{ +// BSPLOG(bsp_log("__tcp_drain.\n")); + while (s->state != _CLOSED && s->data_bytes) + __tcp_poll(); +// BSPLOG(bsp_log("__tcp_drain done.\n")); +} + +/* + * Close the tcp connection. + */ +static void do_abort(void *s) +{ + BSPLOG(bsp_log("do_abort: send RST\n")); + tcp_send((tcp_socket_t *) s, TCP_FLAG_ACK | TCP_FLAG_RST, 0); + __timer_cancel(&abort_timer); + ((tcp_socket_t *) s)->state = _CLOSED; + free_rxlist((tcp_socket_t *) s); + unlink_socket((tcp_socket_t *) s); +} + +void __tcp_abort(tcp_socket_t * s, unsigned long delay) +{ + __timer_set(&abort_timer, delay, do_abort, s); +} + +/* + * Close the tcp connection. + */ +void __tcp_close(tcp_socket_t * s) +{ + __tcp_drain(s); + if (s->state == _ESTABLISHED || s->state == _SYN_RCVD) { + BSPLOG(bsp_log("__tcp_close: going to _FIN_WAIT_1\n")); + s->state = _FIN_WAIT_1; + tcp_send(s, TCP_FLAG_ACK | TCP_FLAG_FIN, 0); + } else if (s->state == _CLOSE_WAIT) { + + BSPLOG(bsp_log("__tcp_close: going to _LAST_ACK\n")); + + s->state = _LAST_ACK; + tcp_send(s, TCP_FLAG_ACK | TCP_FLAG_FIN, 0); + } + free_rxlist(s); +} + +/* + * Wait for connection to be fully closed. + */ +void __tcp_close_wait(tcp_socket_t * s) +{ + BSPLOG(bsp_log("__tcp_close_wait.\n")); + while (s->state != _CLOSED) + __tcp_poll(); + BSPLOG(bsp_log("__tcp_close_wait done.\n")); +} + +/* + * Read up to 'len' bytes without blocking. + */ +int __tcp_read(tcp_socket_t * s, char *buf, int len) +{ + int nread; + pktbuf_t *pkt; + tcp_header_t *tcp; + + if (len <= 0 || s->rxcnt == 0) + return 0; + + if (s->state != _ESTABLISHED && s->rxcnt == 0) + return -1; + + nread = 0; + while (len) { + if (len < s->rxcnt) { + memcpy(buf, s->rxptr, len); + BSPLOG(bsp_log("tcp_read: read %d bytes.\n", len)); + s->rxptr += len; + s->rxcnt -= len; + nread += len; + + BSPLOG(bsp_log + ("tcp_read: %d bytes left in rxlist head.\n", + s->rxcnt)); + + break; + } else { + memcpy(buf, s->rxptr, s->rxcnt); + BSPLOG(bsp_log + ("tcp_read: read %d bytes. pkt[%x] freed.\n", + s->rxcnt, s->rxlist)); + nread += s->rxcnt; + buf += s->rxcnt; + len -= s->rxcnt; + + /* setup for next packet in list */ + pkt = s->rxlist; + s->rxlist = pkt->next; + __pktbuf_free(pkt); + + if ((pkt = s->rxlist) != NULL) { + tcp = pkt->tcp_hdr; + s->rxcnt = pkt->pkt_bytes - (tcp->hdr_len << 2); + s->rxptr = ((char *)tcp) + (tcp->hdr_len << 2); + + BSPLOG(bsp_log + ("tcp_read: next pkt[%x] has %d bytes.\n", + s->rxlist, s->rxcnt)); } else { - s->state = _FIN_WAIT_2; - BSPLOG(bsp_log("_FIN_WAIT_1 --> _FIN_WAIT_2\n")); + + BSPLOG(bsp_log("tcp_read: no more data.\n")); + + s->rxcnt = 0; + break; } - break; /* All done for now */ - } - } - /* At this point, no ACK for FIN has been seen, so check for - simultaneous close */ - if (tcp->flags & TCP_FLAG_FIN) { - BSPLOG(bsp_log("_FIN_WAIT_1 --> _CLOSING\n")); - __timer_cancel(&s->timer); - s->ack++; - s->state = _CLOSING; - /* FIN is resent so the timeout and retry for this packet - will also take care of timeout and resend of the - previously sent FIN (which got us to FIN_WAIT_1). While - not technically correct, resending FIN only causes a - duplicate FIN (same sequence number) which should be - ignored by the other end. */ - tcp_send(s, TCP_FLAG_FIN | TCP_FLAG_ACK, 0); - } - break; - - case _FIN_WAIT_2: - queued = handle_data(s, pkt); - if (tcp->flags & TCP_FLAG_FIN) { - BSPLOG(bsp_log("_FIN_WAIT_2 --> _TIME_WAIT\n")); - s->ack++; - s->state = _TIME_WAIT; - send_ack(s); - } - break; - - case _CLOSING: - if (tcp->flags & TCP_FLAG_ACK) { - handle_ack(s, pkt); - if (ntohl(tcp->acknum) == (s->seq + 1)) { - /* got ACK for FIN packet */ - BSPLOG(bsp_log("_CLOSING --> _TIME_WAIT\n")); - __timer_cancel(&s->timer); - s->state = _TIME_WAIT; - } - } - break; - - case _TIME_WAIT: - BSPLOG(bsp_log("_TIME_WAIT resend.\n")); - if (tcp->flags & TCP_FLAG_FIN) - tcp_send(s, 0, 1); /* just resend ack */ - break; - } - } else { - BSPLOG(bsp_log("Unexpected segment from: %d.%d.%d.%d:%d\n", - r->ip_addr[0], r->ip_addr[1], r->ip_addr[3], - r->ip_addr[4], ntohs(tcp->src_port))); - send_reset(pkt, r); - } - } - if (!queued) - __pktbuf_free(pkt); -} - - -void -__tcp_poll(void) -{ - __enet_poll(); - __timer_poll(); -} - - -int -__tcp_listen(tcp_socket_t *s, word port) -{ - BSPLOG(bsp_log("tcp_listen: s[%p] port[%x]\n", s, port)); - - memset(s, 0, sizeof(tcp_socket_t)); - s->state = _LISTEN; - s->our_port = port; - s->pkt.buf = (word *)s->pktbuf; - s->pkt.bufsize = ETH_MAX_PKTLEN; - s->pkt.ip_hdr = (ip_header_t *)s->pkt.buf; - s->pkt.tcp_hdr = (tcp_header_t *)(s->pkt.ip_hdr + 1); - - s->next = tcp_list; - -#if 0 - /* limit to one open socket at a time */ - if (s->next) { - BSPLOG(bsp_log("tcp_listen: recursion error\n")); - BSPLOG(while(1)); - } -#endif - - tcp_list = s; - - return 0; -} - -/* - * SO_REUSEADDR, no 2MSL. - */ -void -__tcp_so_reuseaddr(tcp_socket_t *s) -{ -// BSPLOG(bsp_log("__tcp_so_reuseaddr.\n")); - s->reuse = 0x01; -} - -/* - * Block while waiting for all data to be transmitted. - */ -void -__tcp_drain(tcp_socket_t *s) -{ -// BSPLOG(bsp_log("__tcp_drain.\n")); - while (s->state != _CLOSED && s->data_bytes) - __tcp_poll(); -// BSPLOG(bsp_log("__tcp_drain done.\n")); -} - - -/* - * Close the tcp connection. - */ -static void -do_abort(void *s) -{ - BSPLOG(bsp_log("do_abort: send RST\n")); - tcp_send((tcp_socket_t *)s, TCP_FLAG_ACK | TCP_FLAG_RST, 0); - __timer_cancel(&abort_timer); - ((tcp_socket_t *)s)->state = _CLOSED; - free_rxlist((tcp_socket_t *)s); - unlink_socket((tcp_socket_t *)s); -} - -void -__tcp_abort(tcp_socket_t *s, unsigned long delay) -{ - __timer_set(&abort_timer, delay, do_abort, s); -} - -/* - * Close the tcp connection. - */ -void -__tcp_close(tcp_socket_t *s) -{ - __tcp_drain(s); - if (s->state == _ESTABLISHED || s->state == _SYN_RCVD) { - BSPLOG(bsp_log("__tcp_close: going to _FIN_WAIT_1\n")); - s->state = _FIN_WAIT_1; - tcp_send(s, TCP_FLAG_ACK | TCP_FLAG_FIN, 0); - } else if (s->state == _CLOSE_WAIT) { - - BSPLOG(bsp_log("__tcp_close: going to _LAST_ACK\n")); - - s->state = _LAST_ACK; - tcp_send(s, TCP_FLAG_ACK | TCP_FLAG_FIN, 0); - } - free_rxlist(s); -} - - -/* - * Wait for connection to be fully closed. - */ -void -__tcp_close_wait(tcp_socket_t *s) -{ - BSPLOG(bsp_log("__tcp_close_wait.\n")); - while (s->state != _CLOSED) - __tcp_poll(); - BSPLOG(bsp_log("__tcp_close_wait done.\n")); -} - - -/* - * Read up to 'len' bytes without blocking. - */ -int -__tcp_read(tcp_socket_t *s, char *buf, int len) -{ - int nread; - pktbuf_t *pkt; - tcp_header_t *tcp; - - if (len <= 0 || s->rxcnt == 0) - return 0; - - if (s->state != _ESTABLISHED && s->rxcnt == 0) - return -1; - - nread = 0; - while (len) { - if (len < s->rxcnt) { - memcpy(buf, s->rxptr, len); - BSPLOG(bsp_log("tcp_read: read %d bytes.\n", len)); - s->rxptr += len; - s->rxcnt -= len; - nread += len; - - BSPLOG(bsp_log("tcp_read: %d bytes left in rxlist head.\n", - s->rxcnt)); - - break; - } else { - memcpy(buf, s->rxptr, s->rxcnt); - BSPLOG(bsp_log("tcp_read: read %d bytes. pkt[%x] freed.\n", - s->rxcnt, s->rxlist)); - nread += s->rxcnt; - buf += s->rxcnt; - len -= s->rxcnt; - - /* setup for next packet in list */ - pkt = s->rxlist; - s->rxlist = pkt->next; - __pktbuf_free(pkt); - - if ((pkt = s->rxlist) != NULL) { - tcp = pkt->tcp_hdr; - s->rxcnt = pkt->pkt_bytes - (tcp->hdr_len << 2); - s->rxptr = ((char *)tcp) + (tcp->hdr_len << 2); - - BSPLOG(bsp_log("tcp_read: next pkt[%x] has %d bytes.\n", - s->rxlist, s->rxcnt)); - } else { - - BSPLOG(bsp_log("tcp_read: no more data.\n")); - - s->rxcnt = 0; - break; - } - } - } - return nread; -} - + } + } + return nread; +} /* * Write up to 'len' bytes without blocking */ -int -__tcp_write(tcp_socket_t *s, char *buf, int len) -{ - tcp_header_t *tcp = s->pkt.tcp_hdr; - - if (len <= 0) - return 0; - - if (s->state != _ESTABLISHED && s->state != _CLOSE_WAIT) - return -1; - - if (s->data_bytes) - return 0; - - if (len > MAX_TCP_DATA) - len = MAX_TCP_DATA; - - memcpy(tcp + 1, buf, len); - s->data_bytes = len; - - tcp_send(s, TCP_FLAG_ACK, 0); - - return len; +int __tcp_write(tcp_socket_t * s, char *buf, int len) +{ + tcp_header_t *tcp = s->pkt.tcp_hdr; + + if (len <= 0) + return 0; + + if (s->state != _ESTABLISHED && s->state != _CLOSE_WAIT) + return -1; + + if (s->data_bytes) + return 0; + + if (len > MAX_TCP_DATA) + len = MAX_TCP_DATA; + + memcpy(tcp + 1, buf, len); + s->data_bytes = len; + + tcp_send(s, TCP_FLAG_ACK, 0); + + return len; } @@ -848,74 +836,71 @@ * If connection collapses, return -1 */ +int __tcp_write_block(tcp_socket_t * s, char *buf, int len) +{ + int total = 0; + int n; + + while (len) { + if (s->state == _CLOSE_WAIT) { + // This connection is tring to close + // This connection is breaking + if (s->data_bytes == 0 && s->rxcnt == 0) + __tcp_close(s); + } + if (s->state == _CLOSED) { + // The connection is gone! + return -1; + } + n = __tcp_write(s, buf, len); + if (n > 0) { + len -= n; + buf += n; + } + __tcp_poll(); + } + __tcp_drain(s); + return total; +} + +/* + * Establish a new [outgoing] connection, with a timeout. + */ int -__tcp_write_block(tcp_socket_t *s, char *buf, int len) -{ - int total = 0; - int n; - - while (len) { - if (s->state == _CLOSE_WAIT) { - // This connection is tring to close - // This connection is breaking - if (s->data_bytes == 0 && s->rxcnt == 0) - __tcp_close(s); - } - if (s->state == _CLOSED) { - // The connection is gone! - return -1; - } - n = __tcp_write(s, buf, len); - if (n > 0) { - len -= n; - buf += n; - } - __tcp_poll(); - } - __tcp_drain(s); - return total; -} - -/* - * Establish a new [outgoing] connection, with a timeout. - */ -int -__tcp_open(tcp_socket_t *s, struct sockaddr_in *host, - word port, int timeout, int *err) -{ - // Fill in socket details - memset(s, 0, sizeof(tcp_socket_t)); - s->state = _SYN_SENT; - s->our_port = port; - s->his_port = host->sin_port; - s->pkt.buf = (word *)s->pktbuf; - s->pkt.bufsize = ETH_MAX_PKTLEN; - s->pkt.ip_hdr = (ip_header_t *)s->pkt.buf; - s->pkt.tcp_hdr = (tcp_header_t *)(s->pkt.ip_hdr + 1); - s->seq = (port << 16) | 0xDE77; - s->ack = 0; - if (__arp_lookup((ip_addr_t *)&host->sin_addr, &s->his_addr) < 0) { - diag_printf("%s: Can't find address of server\n", __FUNCTION__); - return -1; - } - s->next = tcp_list; - tcp_list = s; - - // Send off the SYN packet to open the connection - tcp_send(s, TCP_FLAG_SYN, 0); - // Wait for connection to establish - while (s->state != _ESTABLISHED) { - if (s->state == _CLOSED) { - diag_printf("TCP open - host closed connection\n"); - return -1; - } - if (--timeout <= 0) { - diag_printf("TCP open - connection timed out\n"); - return -1; - } - MS_TICKS_DELAY(); - __tcp_poll(); - } - return 0; -} - - +__tcp_open(tcp_socket_t * s, struct sockaddr_in *host, + word port, int timeout, int *err) +{ + // Fill in socket details + memset(s, 0, sizeof(tcp_socket_t)); + s->state = _SYN_SENT; + s->our_port = port; + s->his_port = host->sin_port; + s->pkt.buf = (word *) s->pktbuf; + s->pkt.bufsize = ETH_MAX_PKTLEN; + s->pkt.ip_hdr = (ip_header_t *) s->pkt.buf; + s->pkt.tcp_hdr = (tcp_header_t *) (s->pkt.ip_hdr + 1); + s->seq = (port << 16) | 0xDE77; + s->ack = 0; + if (__arp_lookup((ip_addr_t *) & host->sin_addr, &s->his_addr) < 0) { + diag_printf("%s: Can't find address of server\n", __FUNCTION__); + return -1; + } + s->next = tcp_list; + tcp_list = s; + + // Send off the SYN packet to open the connection + tcp_send(s, TCP_FLAG_SYN, 0); + // Wait for connection to establish + while (s->state != _ESTABLISHED) { + if (s->state == _CLOSED) { + diag_printf("TCP open - host closed connection\n"); + return -1; + } + if (--timeout <= 0) { + diag_printf("TCP open - connection timed out\n"); + return -1; + } + MS_TICKS_DELAY(); + __tcp_poll(); + } + return 0; +} Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/icmp.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/icmp.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/icmp.c (revision 12368) @@ -58,5 +58,5 @@ * Handle ICMP packets. */ -static void default_icmp_handler(pktbuf_t *pkt, ip_route_t *dest); +static void default_icmp_handler(pktbuf_t * pkt, ip_route_t * dest); static icmp_handler_t icmp_handler = default_icmp_handler; @@ -66,24 +66,21 @@ * Returns zero if successful, -1 if the user_handler is already used. */ -int -__icmp_install_listener(icmp_handler_t user_handler) +int __icmp_install_listener(icmp_handler_t user_handler) { - if (icmp_handler == user_handler) { - return -1; - } - icmp_handler = user_handler; - return 0; + if (icmp_handler == user_handler) { + return -1; + } + icmp_handler = user_handler; + return 0; } - /* * Replace a user defined handler by the default handler. */ -void -__icmp_remove_listener(void) +void __icmp_remove_listener(void) { - if (icmp_handler != default_icmp_handler) { - icmp_handler = default_icmp_handler; - } + if (icmp_handler != default_icmp_handler) { + icmp_handler = default_icmp_handler; + } } @@ -92,16 +89,13 @@ * should be sent to. */ -void -__icmp_handler(pktbuf_t *pkt, ip_route_t *dest) +void __icmp_handler(pktbuf_t * pkt, ip_route_t * dest) { - (*icmp_handler)(pkt, dest); + (*icmp_handler) (pkt, dest); - BSPLOG(bsp_log("icmp: dest[%s] type[%d] seq[%d]\n", - inet_ntoa(pkt->ip_hdr->destination), - pkt->icmp_hdr->type, - pkt->icmp_hdr->seqnum)); - __pktbuf_free(pkt); + BSPLOG(bsp_log("icmp: dest[%s] type[%d] seq[%d]\n", + inet_ntoa(pkt->ip_hdr->destination), + pkt->icmp_hdr->type, pkt->icmp_hdr->seqnum)); + __pktbuf_free(pkt); } - /* @@ -109,18 +103,17 @@ * outgoing echo reply. */ -static void -default_icmp_handler(pktbuf_t *pkt, ip_route_t *dest) +static void default_icmp_handler(pktbuf_t * pkt, ip_route_t * dest) { - word cksum; + word cksum; - if (pkt->icmp_hdr->type == ICMP_TYPE_ECHOREQUEST - && pkt->icmp_hdr->code == 0 - && __sum((word *)pkt->icmp_hdr, pkt->pkt_bytes, 0) == 0) { + if (pkt->icmp_hdr->type == ICMP_TYPE_ECHOREQUEST + && pkt->icmp_hdr->code == 0 + && __sum((word *) pkt->icmp_hdr, pkt->pkt_bytes, 0) == 0) { - pkt->icmp_hdr->type = ICMP_TYPE_ECHOREPLY; - pkt->icmp_hdr->checksum = 0; - cksum = __sum((word *)pkt->icmp_hdr, pkt->pkt_bytes, 0); - pkt->icmp_hdr->checksum = htons(cksum); - __ip_send(pkt, IP_PROTO_ICMP, dest); - } + pkt->icmp_hdr->type = ICMP_TYPE_ECHOREPLY; + pkt->icmp_hdr->checksum = 0; + cksum = __sum((word *) pkt->icmp_hdr, pkt->pkt_bytes, 0); + pkt->icmp_hdr->checksum = htons(cksum); + __ip_send(pkt, IP_PROTO_ICMP, dest); + } } Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/udp.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/udp.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/udp.c (revision 12368) @@ -74,5 +74,4 @@ static udp_socket_t *udp_list; - /* * Install a handler for incoming udp packets. @@ -80,189 +79,189 @@ * Returns zero if successful, -1 if socket is already used. */ +int __udp_install_listener(udp_socket_t * s, word port, udp_handler_t handler) +{ + udp_socket_t *p; + + /* + * Make sure we only have one handler per port. + */ + for (p = udp_list; p; p = p->next) + if (p->our_port == port) + return -1; + + s->our_port = htons(port); + s->handler = handler; + s->next = udp_list; + udp_list = s; + + return 0; +} + +/* + * Remove the handler for the given socket. + */ +void __udp_remove_listener(word port) +{ + udp_socket_t *prev, *s; + + for (prev = NULL, s = udp_list; s; prev = s, s = s->next) + if (s->our_port == htons(port)) { + if (prev) + prev->next = s->next; + else + udp_list = s->next; + } +} + +/* + * Handle incoming UDP packets. + */ +void __udp_handler(pktbuf_t * pkt, ip_route_t * r) +{ + udp_header_t *udp = pkt->udp_hdr; + ip_header_t *ip = pkt->ip_hdr; + udp_socket_t *s; + + if (udp->checksum == 0xffff) + udp->checksum = 0; + + /* copy length for pseudo sum calculation */ + ip->length = udp->length; + + if (__sum((word *) udp, ntohs(udp->length), __pseudo_sum(ip)) == 0) { + for (s = udp_list; s; s = s->next) { + if (s->our_port == udp->dest_port) { + (*s->handler) (s, + ((char *)udp) + + sizeof(udp_header_t), + ntohs(udp->length) - + sizeof(udp_header_t), r, + ntohs(udp->src_port)); + __pktbuf_free(pkt); + return; + } + } + } + __pktbuf_free(pkt); +} + +/* + * Send a UDP packet. + */ int -__udp_install_listener(udp_socket_t *s, word port, udp_handler_t handler) -{ - udp_socket_t *p; - - /* - * Make sure we only have one handler per port. - */ - for (p = udp_list; p; p = p->next) - if (p->our_port == port) - return -1; - - s->our_port = htons(port); - s->handler = handler; - s->next = udp_list; - udp_list = s; - - return 0; -} - - -/* - * Remove the handler for the given socket. - */ -void -__udp_remove_listener(word port) -{ - udp_socket_t *prev, *s; - - for (prev = NULL, s = udp_list; s; prev = s, s = s->next) - if (s->our_port == htons(port)) { - if (prev) - prev->next = s->next; - else - udp_list = s->next; - } -} - - -/* - * Handle incoming UDP packets. - */ -void -__udp_handler(pktbuf_t *pkt, ip_route_t *r) -{ - udp_header_t *udp = pkt->udp_hdr; - ip_header_t *ip = pkt->ip_hdr; - udp_socket_t *s; - - if (udp->checksum == 0xffff) +__udp_send(char *buf, int len, ip_route_t * dest_ip, + word dest_port, word src_port) +{ + pktbuf_t *pkt; + udp_header_t *udp; + ip_header_t *ip; + unsigned short cksum; + int ret; + + /* dumb */ + if (len > MAX_UDP_DATA) + return -1; + + /* just drop it if can't get a buffer */ + if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL) + return -1; + + udp = pkt->udp_hdr; + ip = pkt->ip_hdr; + + pkt->pkt_bytes = len + sizeof(udp_header_t); + + udp->src_port = htons(src_port); + udp->dest_port = htons(dest_port); + udp->length = htons(pkt->pkt_bytes); udp->checksum = 0; - /* copy length for pseudo sum calculation */ - ip->length = udp->length; - - if (__sum((word *)udp, ntohs(udp->length), __pseudo_sum(ip)) == 0) { - for (s = udp_list; s; s = s->next) { - if (s->our_port == udp->dest_port) { - (*s->handler)(s, ((char *)udp) + sizeof(udp_header_t), - ntohs(udp->length) - sizeof(udp_header_t), - r, ntohs(udp->src_port)); - __pktbuf_free(pkt); + memcpy(((char *)udp) + sizeof(udp_header_t), buf, len); + + /* fill in some pseudo-header fields */ + memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t)); + memcpy(ip->destination, dest_ip->ip_addr, sizeof(ip_addr_t)); + ip->protocol = IP_PROTO_UDP; + ip->length = udp->length; + + cksum = __sum((word *) udp, pkt->pkt_bytes, __pseudo_sum(ip)); + udp->checksum = htons(cksum); + + ret = __ip_send(pkt, IP_PROTO_UDP, dest_ip); + __pktbuf_free(pkt); + return ret; +} + +int +__udp_sendto(char *data, int len, struct sockaddr_in *server, + struct sockaddr_in *local) +{ + ip_route_t rt; + + if (__arp_lookup((ip_addr_t *) & server->sin_addr, &rt) < 0) { + diag_printf("%s: Can't find address of server\n", __FUNCTION__); + return -1; + } else { + __udp_send(data, len, &rt, ntohs(server->sin_port), + ntohs(local->sin_port)); + return 0; + } +} + +static char *recvfrom_buf; +static int recvfrom_len; +static struct sockaddr_in *recvfrom_server; + +static void +__udp_recvfrom_handler(udp_socket_t * skt, char *buf, int len, + ip_route_t * src_route, word src_port) +{ + if (recvfrom_server == NULL || recvfrom_buf == NULL) return; - } - } - } - __pktbuf_free(pkt); -} - - -/* - * Send a UDP packet. - */ + + if (recvfrom_server->sin_port + && recvfrom_server->sin_port != htons(src_port)) + return; + + // Move data to waiting buffer + recvfrom_len = len; + memcpy(recvfrom_buf, buf, len); + if (recvfrom_server) { + recvfrom_server->sin_port = htons(src_port); + memcpy(&recvfrom_server->sin_addr, &src_route->ip_addr, + sizeof(src_route->ip_addr)); + recvfrom_buf = (char *)0; // Tell reader we got a packet + } else { + diag_printf("udp_recvfrom - dropped packet of %d bytes\n", len); + } +} + int -__udp_send(char *buf, int len, ip_route_t *dest_ip, - word dest_port, word src_port) -{ - pktbuf_t *pkt; - udp_header_t *udp; - ip_header_t *ip; - unsigned short cksum; - int ret; - - /* dumb */ - if (len > MAX_UDP_DATA) - return -1; - - /* just drop it if can't get a buffer */ - if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL) - return -1; - - udp = pkt->udp_hdr; - ip = pkt->ip_hdr; - - pkt->pkt_bytes = len + sizeof(udp_header_t); - - udp->src_port = htons(src_port); - udp->dest_port = htons(dest_port); - udp->length = htons(pkt->pkt_bytes); - udp->checksum = 0; - - memcpy(((char *)udp) + sizeof(udp_header_t), buf, len); - - /* fill in some pseudo-header fields */ - memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t)); - memcpy(ip->destination, dest_ip->ip_addr, sizeof(ip_addr_t)); - ip->protocol = IP_PROTO_UDP; - ip->length = udp->length; - - cksum = __sum((word *)udp, pkt->pkt_bytes, __pseudo_sum(ip)); - udp->checksum = htons(cksum); - - ret = __ip_send(pkt, IP_PROTO_UDP, dest_ip); - __pktbuf_free(pkt); - return ret; -} - -int -__udp_sendto(char *data, int len, struct sockaddr_in *server, - struct sockaddr_in *local) -{ - ip_route_t rt; - - if (__arp_lookup((ip_addr_t *)&server->sin_addr, &rt) < 0) { - diag_printf("%s: Can't find address of server\n", __FUNCTION__); - return -1; - } else { - __udp_send(data, len, &rt, ntohs(server->sin_port), ntohs(local->sin_port)); - return 0; - } -} - -static char *recvfrom_buf; -static int recvfrom_len; -static struct sockaddr_in *recvfrom_server; - -static void -__udp_recvfrom_handler(udp_socket_t *skt, char *buf, int len, - ip_route_t *src_route, word src_port) -{ - if (recvfrom_server == NULL || recvfrom_buf == NULL) - return; - - if (recvfrom_server->sin_port && recvfrom_server->sin_port != htons(src_port)) - return; - - // Move data to waiting buffer - recvfrom_len = len; - memcpy(recvfrom_buf, buf, len); - if (recvfrom_server) { - recvfrom_server->sin_port = htons(src_port); - memcpy(&recvfrom_server->sin_addr, &src_route->ip_addr, sizeof(src_route->ip_addr)); - recvfrom_buf = (char *)0; // Tell reader we got a packet - } else { - diag_printf("udp_recvfrom - dropped packet of %d bytes\n", len); - } -} - -int -__udp_recvfrom(char *data, int len, struct sockaddr_in *server, - struct sockaddr_in *local, struct timeval *timo) -{ - int res, my_port, total_ms; - udp_socket_t skt; - unsigned long start; - - my_port = ntohs(local->sin_port); - if (__udp_install_listener(&skt, my_port, __udp_recvfrom_handler) < 0) { - return -1; - } - recvfrom_buf = data; - recvfrom_len = len; - recvfrom_server = server; - total_ms = (timo->tv_sec * 1000) + (timo->tv_usec / 1000); - start = MS_TICKS(); - res = -1; - do { - __enet_poll(); // Handle the hardware - if (!recvfrom_buf) { - // Data have arrived - res = recvfrom_len; - break; - } - } while ((MS_TICKS_DELAY() - start) < total_ms); - __udp_remove_listener(my_port); - return res; -} +__udp_recvfrom(char *data, int len, struct sockaddr_in *server, + struct sockaddr_in *local, struct timeval *timo) +{ + int res, my_port, total_ms; + udp_socket_t skt; + unsigned long start; + + my_port = ntohs(local->sin_port); + if (__udp_install_listener(&skt, my_port, __udp_recvfrom_handler) < 0) { + return -1; + } + recvfrom_buf = data; + recvfrom_len = len; + recvfrom_server = server; + total_ms = (timo->tv_sec * 1000) + (timo->tv_usec / 1000); + start = MS_TICKS(); + res = -1; + do { + __enet_poll(); // Handle the hardware + if (!recvfrom_buf) { + // Data have arrived + res = recvfrom_len; + break; + } + } while ((MS_TICKS_DELAY() - start) < total_ms); + __udp_remove_listener(my_port); + return res; +} Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/inet_addr.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/inet_addr.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/inet_addr.c (revision 12368) @@ -56,63 +56,62 @@ #include -bool -inet_aton(const char *s, in_addr_t *addr) +bool inet_aton(const char *s, in_addr_t * addr) { - int i, val, radix, digit; - unsigned long res = 0; - bool first; - char c; - - for (i = 0; i < 4; i++) { - // Parse next digit string - first = true; - val = 0; - radix = 10; - while ((c = *s++) != '\0') { - if (first && (c == '0') && (_tolower(*s) == 'x')) { - radix = 16; - s++; // Skip over 0x - c = *s++; - } - first = false; - if (_is_hex(c) && ((digit = _from_hex(c)) < radix)) { - // Valid digit - val = (val * radix) + digit; - } else if (c == '.' && i < 3) { // all but last terminate by '.' - break; - } else { - return false; - } - } - // merge result + int i, val, radix, digit; + unsigned long res = 0; + bool first; + char c; + + for (i = 0; i < 4; i++) { + // Parse next digit string + first = true; + val = 0; + radix = 10; + while ((c = *s++) != '\0') { + if (first && (c == '0') && (_tolower(*s) == 'x')) { + radix = 16; + s++; // Skip over 0x + c = *s++; + } + first = false; + if (_is_hex(c) && ((digit = _from_hex(c)) < radix)) { + // Valid digit + val = (val * radix) + digit; + } else if (c == '.' && i < 3) { // all but last terminate by '.' + break; + } else { + return false; + } + } + // merge result #ifdef __LITTLE_ENDIAN__ - res |= val << ((3-i)*8); // 24, 16, 8, 0 + res |= val << ((3 - i) * 8); // 24, 16, 8, 0 #else - res = (res << 8) | val; + res = (res << 8) | val; #endif - if ('\0' == c) { - if (0 == i) { // first field found end of string - res = val; // no shifting, use it as the whole thing - break; // permit entering a single number - } - if (3 > i) // we found end of string before getting 4 fields - return false; - } - // after that we check that it was 0..255 only - if (val &~0xff) return false; - } - addr->s_addr = htonl(res); - return true; + if ('\0' == c) { + if (0 == i) { // first field found end of string + res = val; // no shifting, use it as the whole thing + break; // permit entering a single number + } + if (3 > i) // we found end of string before getting 4 fields + return false; + } + // after that we check that it was 0..255 only + if (val & ~0xff) + return false; + } + addr->s_addr = htonl(res); + return true; } // Assumes address is in network byte order -char * -inet_ntoa(in_addr_t *addr) +char *inet_ntoa(in_addr_t * addr) { - static char str[32]; - unsigned char *ap; + static char str[32]; + unsigned char *ap; - ap = (unsigned char *)addr; - diag_sprintf(str, "%d.%d.%d.%d", ap[0], ap[1], ap[2], ap[3]); - return str; + ap = (unsigned char *)addr; + diag_sprintf(str, "%d.%d.%d.%d", ap[0], ap[1], ap[2], ap[3]); + return str; } Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade.h =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade.h (revision 12368) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade.h (revision 12368) @@ -0,0 +1,22 @@ + +#ifndef __ddwrt_fw__ +#define __ddwrt_fw__ + +/* do header, partition and final signature check */ +extern int fw_check_image_ddwrt(unsigned char *addr, unsigned long maxlen, + int do_flash); +extern int fw_check_image_ubnt(unsigned char *addr, unsigned long maxlen, + int do_flash); +extern int fw_check_image_wili(unsigned char *addr, unsigned long maxlen, + int do_flash); + +#define MAX_IMAGE_SIZE 0x7E0000 /* 4mb - 64k */ + +#define MAX_PART_SIZE 0x800000 /* 3mb - valid only for ar531x */ + +/* these variables will be initialized in do_tftpd() */ +CYG_ADDRWORD BASE_ADDR; +CYG_ADDRWORD FW_TEMP_BASE; +/***********************************************************************************/ + +#endif /* __wilibox_fw__ */ Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/enet.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/enet.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/enet.c (revision 12368) @@ -55,5 +55,5 @@ #include #include -#include // Logical driver interfaces +#include // Logical driver interfaces //#define ENET_STATS 1 @@ -75,48 +75,48 @@ #define NUM_EXTRA_HANDLERS 4 static struct { - int type; - pkt_handler_t handler; + int type; + pkt_handler_t handler; } eth_handlers[NUM_EXTRA_HANDLERS]; -pkt_handler_t -__eth_install_listener(int eth_type, pkt_handler_t handler) -{ - int i, empty; - pkt_handler_t old; - - if (eth_type > 0x800 || handler != (pkt_handler_t)0) { - empty = -1; - for (i = 0; i < NUM_EXTRA_HANDLERS; i++) { - if (eth_handlers[i].type == eth_type) { - // Replace existing handler - old = eth_handlers[i].handler; - eth_handlers[i].handler = handler; - return old; - } - if (eth_handlers[i].type == 0) { - empty = i; - } +pkt_handler_t __eth_install_listener(int eth_type, pkt_handler_t handler) +{ + int i, empty; + pkt_handler_t old; + + if (eth_type > 0x800 || handler != (pkt_handler_t) 0) { + empty = -1; + for (i = 0; i < NUM_EXTRA_HANDLERS; i++) { + if (eth_handlers[i].type == eth_type) { + // Replace existing handler + old = eth_handlers[i].handler; + eth_handlers[i].handler = handler; + return old; + } + if (eth_handlers[i].type == 0) { + empty = i; + } + } + if (empty >= 0) { + // Found a free slot + eth_handlers[empty].type = eth_type; + eth_handlers[empty].handler = handler; + return (pkt_handler_t) 0; + } } - if (empty >= 0) { - // Found a free slot - eth_handlers[empty].type = eth_type; - eth_handlers[empty].handler = handler; - return (pkt_handler_t)0; + diag_printf + ("** Warning: can't install listener for ethernet type 0x%02x\n", + eth_type); + return (pkt_handler_t) 0; +} + +void __eth_remove_listener(int eth_type) +{ + int i; + + for (i = 0; i < NUM_EXTRA_HANDLERS; i++) { + if (eth_handlers[i].type == eth_type) { + eth_handlers[i].type = 0; + } } - } - diag_printf("** Warning: can't install listener for ethernet type 0x%02x\n", eth_type); - return (pkt_handler_t)0; -} - -void -__eth_remove_listener(int eth_type) -{ - int i; - - for (i = 0; i < NUM_EXTRA_HANDLERS; i++) { - if (eth_handlers[i].type == eth_type) { - eth_handlers[i].type = 0; - } - } } @@ -125,104 +125,104 @@ * are available. */ -void -__enet_poll(void) -{ - pktbuf_t *pkt; - eth_header_t eth_hdr; - int i, type; +void __enet_poll(void) +{ + pktbuf_t *pkt; + eth_header_t eth_hdr; + int i, type; #ifdef DEBUG_PKT_EXHAUSTION - static bool was_exhausted = false; -#endif - - while (true) { - /* - * Try to get a free pktbuf and return if none - * are available. - */ - if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL) { + static bool was_exhausted = false; +#endif + + while (true) { + /* + * Try to get a free pktbuf and return if none + * are available. + */ + if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL) { #ifdef DEBUG_PKT_EXHAUSTION - if (!was_exhausted) { - int old = start_console(); // Force output to standard port - diag_printf("__enet_poll: no more buffers\n"); - __pktbuf_dump(); - was_exhausted = true; - end_console(old); - } -#endif - return; - } + if (!was_exhausted) { + int old = start_console(); // Force output to standard port + diag_printf("__enet_poll: no more buffers\n"); + __pktbuf_dump(); + was_exhausted = true; + end_console(old); + } +#endif + return; + } #ifdef DEBUG_PKT_EXHAUSTION - was_exhausted = false; // Report the next time we're out of buffers -#endif - - if ((pkt->pkt_bytes = eth_drv_read((char *)ð_hdr, (char *)pkt->buf, - ETH_MAX_PKTLEN)) > 0) { -#ifdef ENET_STATS - ++num_received; -#endif - switch (type = ntohs(eth_hdr.type)) { - - case ETH_TYPE_IP: -#ifdef ENET_STATS - ++num_ip; -#endif - pkt->ip_hdr = (ip_header_t *)pkt->buf; - __ip_handler(pkt, ð_hdr.source); - break; - - case ETH_TYPE_ARP: -#ifdef ENET_STATS - ++num_arp; -#endif - pkt->arp_hdr = (arp_header_t *)pkt->buf; - __arp_handler(pkt); - break; + was_exhausted = false; // Report the next time we're out of buffers +#endif + + if ((pkt->pkt_bytes = + eth_drv_read((char *)ð_hdr, (char *)pkt->buf, + ETH_MAX_PKTLEN)) > 0) { +#ifdef ENET_STATS + ++num_received; +#endif + switch (type = ntohs(eth_hdr.type)) { + + case ETH_TYPE_IP: +#ifdef ENET_STATS + ++num_ip; +#endif + pkt->ip_hdr = (ip_header_t *) pkt->buf; + __ip_handler(pkt, ð_hdr.source); + break; + + case ETH_TYPE_ARP: +#ifdef ENET_STATS + ++num_arp; +#endif + pkt->arp_hdr = (arp_header_t *) pkt->buf; + __arp_handler(pkt); + break; #ifdef NET_SUPPORT_RARP - case ETH_TYPE_RARP: -#ifdef ENET_STATS - ++num_rarp; -#endif - pkt->arp_hdr = (arp_header_t *)pkt->buf; - __rarp_handler(pkt); - break; -#endif - - default: - if (type > 0x800) { - for (i = 0; i < NUM_EXTRA_HANDLERS; i++) { - if (eth_handlers[i].type == type) { - (eth_handlers[i].handler)(pkt, ð_hdr); - } - } - } - __pktbuf_free(pkt); - break; - } - } else { - __pktbuf_free(pkt); - break; - } - } -} - - + case ETH_TYPE_RARP: +#ifdef ENET_STATS + ++num_rarp; +#endif + pkt->arp_hdr = (arp_header_t *) pkt->buf; + __rarp_handler(pkt); + break; +#endif + + default: + if (type > 0x800) { + for (i = 0; i < NUM_EXTRA_HANDLERS; i++) { + if (eth_handlers[i].type == + type) { + (eth_handlers + [i].handler) (pkt, + ð_hdr); + } + } + } + __pktbuf_free(pkt); + break; + } + } else { + __pktbuf_free(pkt); + break; + } + } +} /* * Send an ethernet packet. */ -void -__enet_send(pktbuf_t *pkt, enet_addr_t *dest, int eth_type) -{ - eth_header_t eth_hdr; - - // Set up ethernet header - memcpy(ð_hdr.destination, dest, sizeof(enet_addr_t)); - memcpy(ð_hdr.source, __local_enet_addr, sizeof(enet_addr_t)); - eth_hdr.type = htons(eth_type); - - eth_drv_write((char *)ð_hdr, (char *)pkt->buf, pkt->pkt_bytes); -#ifdef ENET_STATS - ++num_transmitted; +void __enet_send(pktbuf_t * pkt, enet_addr_t * dest, int eth_type) +{ + eth_header_t eth_hdr; + + // Set up ethernet header + memcpy(ð_hdr.destination, dest, sizeof(enet_addr_t)); + memcpy(ð_hdr.source, __local_enet_addr, sizeof(enet_addr_t)); + eth_hdr.type = htons(eth_type); + + eth_drv_write((char *)ð_hdr, (char *)pkt->buf, pkt->pkt_bytes); +#ifdef ENET_STATS + ++num_transmitted; #endif } @@ -230,19 +230,15 @@ #ifdef __LITTLE_ENDIAN__ -unsigned long -ntohl(unsigned long x) -{ - return (((x & 0x000000FF) << 24) | - ((x & 0x0000FF00) << 8) | - ((x & 0x00FF0000) >> 8) | - ((x & 0xFF000000) >> 24)); -} - -unsigned long -ntohs(unsigned short x) -{ - return (((x & 0x00FF) << 8) | - ((x & 0xFF00) >> 8)); -} - -#endif +unsigned long ntohl(unsigned long x) +{ + return (((x & 0x000000FF) << 24) | + ((x & 0x0000FF00) << 8) | + ((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24)); +} + +unsigned long ntohs(unsigned short x) +{ + return (((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8)); +} + +#endif Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/pktbuf.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/pktbuf.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/pktbuf.c (revision 12368) @@ -63,50 +63,48 @@ int max_alloc = 0; int num_alloc = 0; -int num_free = 0; +int num_free = 0; #endif -static pktbuf_t pktbuf_list[MAX_PKTBUF]; -static word bufdata[MAX_PKTBUF][ETH_MAX_PKTLEN/2 + 1]; +static pktbuf_t pktbuf_list[MAX_PKTBUF]; +static word bufdata[MAX_PKTBUF][ETH_MAX_PKTLEN / 2 + 1]; static pktbuf_t *free_list; - /* * Initialize the free list. */ -void -__pktbuf_init(void) +void __pktbuf_init(void) { - int i; - word *p; - static int init = 0; + int i; + word *p; + static int init = 0; - if (init) return; - init = 1; + if (init) + return; + init = 1; - for (i = 0; i < MAX_PKTBUF; i++) { - p = bufdata[i]; - if ((((unsigned long)p) & 2) != 0) - ++p; - pktbuf_list[i].buf = p; - pktbuf_list[i].bufsize = ETH_MAX_PKTLEN; - pktbuf_list[i].next = free_list; - free_list = &pktbuf_list[i]; - } + for (i = 0; i < MAX_PKTBUF; i++) { + p = bufdata[i]; + if ((((unsigned long)p) & 2) != 0) + ++p; + pktbuf_list[i].buf = p; + pktbuf_list[i].bufsize = ETH_MAX_PKTLEN; + pktbuf_list[i].next = free_list; + free_list = &pktbuf_list[i]; + } } -void -__pktbuf_dump(void) +void __pktbuf_dump(void) { - int i; - for (i = 0; i < MAX_PKTBUF; i++) { - diag_printf("Buf[%d]/%p: buf: %p, len: %d/%d, next: %p\n", - i, - (void*)&pktbuf_list[i], - (void*)pktbuf_list[i].buf, - pktbuf_list[i].bufsize, - pktbuf_list[i].pkt_bytes, - (void*)pktbuf_list[i].next); - } - diag_printf("Free list = %p\n", (void*)free_list); + int i; + for (i = 0; i < MAX_PKTBUF; i++) { + diag_printf("Buf[%d]/%p: buf: %p, len: %d/%d, next: %p\n", + i, + (void *)&pktbuf_list[i], + (void *)pktbuf_list[i].buf, + pktbuf_list[i].bufsize, + pktbuf_list[i].pkt_bytes, + (void *)pktbuf_list[i].next); + } + diag_printf("Free list = %p\n", (void *)free_list); } @@ -114,54 +112,49 @@ * simple pktbuf allocation */ -pktbuf_t * -__pktbuf_alloc(int nbytes) +pktbuf_t *__pktbuf_alloc(int nbytes) { - pktbuf_t *p = free_list; + pktbuf_t *p = free_list; - if (p) { - free_list = p->next; - p->ip_hdr = (ip_header_t *)p->buf; - p->tcp_hdr = (tcp_header_t *)(p->ip_hdr + 1); - p->pkt_bytes = 0; + if (p) { + free_list = p->next; + p->ip_hdr = (ip_header_t *) p->buf; + p->tcp_hdr = (tcp_header_t *) (p->ip_hdr + 1); + p->pkt_bytes = 0; #if BUFF_STATS - ++num_alloc; - if ((num_alloc - num_free) > max_alloc) - max_alloc = num_alloc - num_free; + ++num_alloc; + if ((num_alloc - num_free) > max_alloc) + max_alloc = num_alloc - num_free; #endif - } - return p; + } + return p; } - /* * free a pktbuf. */ -void -__pktbuf_free(pktbuf_t *pkt) +void __pktbuf_free(pktbuf_t * pkt) { #if BUFF_STATS - --num_alloc; + --num_alloc; #endif #ifdef BSP_LOG - { - int i; - word *p; + { + int i; + word *p; - for (i = 0; i < MAX_PKTBUF; i++) { - p = bufdata[i]; - if ((((unsigned long)p) & 2) == 0) - ++p; - if (p == (word *)pkt) - break; + for (i = 0; i < MAX_PKTBUF; i++) { + p = bufdata[i]; + if ((((unsigned long)p) & 2) == 0) + ++p; + if (p == (word *) pkt) + break; + } + if (i < MAX_PKTBUF) { + BSPLOG(bsp_log("__pktbuf_free: bad pkt[%x].\n", pkt)); + BSPLOG(while (1)) ; + } } - if (i < MAX_PKTBUF) { - BSPLOG(bsp_log("__pktbuf_free: bad pkt[%x].\n", pkt)); - BSPLOG(while(1)); - } - } #endif - pkt->next = free_list; - free_list = pkt; + pkt->next = free_list; + free_list = pkt; } - - Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/ping.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/ping.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/ping.c (revision 12368) @@ -62,187 +62,195 @@ static void do_ping(int argc, char *argv[]); -RedBoot_cmd("ping", - "Network connectivity test", - "[-v] [-n ] [-l ] [-t ] [-r ]\n" - " [-i ] -h ", - do_ping - ); +RedBoot_cmd("ping", + "Network connectivity test", + "[-v] [-n ] [-l ] [-t ] [-r ]\n" + " [-i ] -h ", do_ping); static bool icmp_received; static icmp_header_t hold_hdr; -static void -handle_icmp(pktbuf_t *pkt, ip_route_t *src_route) +static void handle_icmp(pktbuf_t * pkt, ip_route_t * src_route) { - icmp_header_t *icmp; - unsigned short cksum; - - icmp = pkt->icmp_hdr; - if (icmp->type == ICMP_TYPE_ECHOREQUEST - && icmp->code == 0 - && __sum((word *)icmp, pkt->pkt_bytes, 0) == 0) { - - icmp->type = ICMP_TYPE_ECHOREPLY; - icmp->checksum = 0; - cksum = __sum((word *)icmp, pkt->pkt_bytes, 0); - icmp->checksum = htons(cksum); - __ip_send(pkt, IP_PROTO_ICMP, src_route); - } else if (icmp->type == ICMP_TYPE_ECHOREPLY) { - memcpy(&hold_hdr, icmp, sizeof(*icmp)); - icmp_received = true; - } + icmp_header_t *icmp; + unsigned short cksum; + + icmp = pkt->icmp_hdr; + if (icmp->type == ICMP_TYPE_ECHOREQUEST + && icmp->code == 0 + && __sum((word *) icmp, pkt->pkt_bytes, 0) == 0) { + + icmp->type = ICMP_TYPE_ECHOREPLY; + icmp->checksum = 0; + cksum = __sum((word *) icmp, pkt->pkt_bytes, 0); + icmp->checksum = htons(cksum); + __ip_send(pkt, IP_PROTO_ICMP, src_route); + } else if (icmp->type == ICMP_TYPE_ECHOREPLY) { + memcpy(&hold_hdr, icmp, sizeof(*icmp)); + icmp_received = true; + } } -static void -do_ping(int argc, char *argv[]) +static void do_ping(int argc, char *argv[]) { - struct option_info opts[7]; - long count, timeout, length, rate, start_time, end_time, timer, received, tries; - char *local_ip_addr, *host_ip_addr; - bool local_ip_addr_set, host_ip_addr_set, count_set, - timeout_set, length_set, rate_set, verbose; - struct sockaddr_in local_addr, host_addr; - ip_addr_t hold_addr; - icmp_header_t *icmp; - pktbuf_t *pkt; - ip_header_t *ip; - unsigned short cksum; - ip_route_t dest_ip; - - init_opts(&opts[0], 'n', true, OPTION_ARG_TYPE_NUM, - (void *)&count, (bool *)&count_set, " - number of packets to test"); - init_opts(&opts[1], 't', true, OPTION_ARG_TYPE_NUM, - (void *)&timeout, (bool *)&timeout_set, " - max #ms per packet [rount trip]"); - init_opts(&opts[2], 'i', true, OPTION_ARG_TYPE_STR, - (void *)&local_ip_addr, (bool *)&local_ip_addr_set, "local IP address"); - init_opts(&opts[3], 'h', true, OPTION_ARG_TYPE_STR, - (void *)&host_ip_addr, (bool *)&host_ip_addr_set, "host name or IP address"); - init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM, - (void *)&length, (bool *)&length_set, " - size of payload"); - init_opts(&opts[5], 'v', false, OPTION_ARG_TYPE_FLG, - (void *)&verbose, (bool *)0, "verbose operation"); - init_opts(&opts[6], 'r', true, OPTION_ARG_TYPE_NUM, - (void *)&rate, (bool *)&rate_set, " - time between packets"); - if (!scan_opts(argc, argv, 1, opts, 7, (void **)0, 0, "")) { - diag_printf("PING - Invalid option specified\n"); - return; - } - // Set defaults; this has to be done _after_ the scan, since it will - // have destroyed all values not explicitly set. - if (local_ip_addr_set) { - if (!_gethostbyname(local_ip_addr, (in_addr_t *)&local_addr)) { - diag_printf("PING - Invalid local name: %s\n", local_ip_addr); - return; - } - } else { - memcpy((in_addr_t *)&local_addr, __local_ip_addr, sizeof(__local_ip_addr)); - } - if (host_ip_addr_set) { - if (!_gethostbyname(host_ip_addr, (in_addr_t *)&host_addr)) { - diag_printf("PING - Invalid host name: %s\n", host_ip_addr); - return; - } - if (__arp_lookup((ip_addr_t *)&host_addr.sin_addr, &dest_ip) < 0) { - diag_printf("PING: Cannot reach server '%s' (%s)\n", - host_ip_addr, inet_ntoa((in_addr_t *)&host_addr)); - return; - } - } else { - diag_printf("PING - host name or IP address required\n"); - return; - } + struct option_info opts[7]; + long count, timeout, length, rate, start_time, end_time, timer, + received, tries; + char *local_ip_addr, *host_ip_addr; + bool local_ip_addr_set, host_ip_addr_set, count_set, + timeout_set, length_set, rate_set, verbose; + struct sockaddr_in local_addr, host_addr; + ip_addr_t hold_addr; + icmp_header_t *icmp; + pktbuf_t *pkt; + ip_header_t *ip; + unsigned short cksum; + ip_route_t dest_ip; + + init_opts(&opts[0], 'n', true, OPTION_ARG_TYPE_NUM, + (void *)&count, (bool *) & count_set, + " - number of packets to test"); + init_opts(&opts[1], 't', true, OPTION_ARG_TYPE_NUM, (void *)&timeout, + (bool *) & timeout_set, + " - max #ms per packet [rount trip]"); + init_opts(&opts[2], 'i', true, OPTION_ARG_TYPE_STR, + (void *)&local_ip_addr, (bool *) & local_ip_addr_set, + "local IP address"); + init_opts(&opts[3], 'h', true, OPTION_ARG_TYPE_STR, + (void *)&host_ip_addr, (bool *) & host_ip_addr_set, + "host name or IP address"); + init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM, (void *)&length, + (bool *) & length_set, " - size of payload"); + init_opts(&opts[5], 'v', false, OPTION_ARG_TYPE_FLG, (void *)&verbose, + (bool *) 0, "verbose operation"); + init_opts(&opts[6], 'r', true, OPTION_ARG_TYPE_NUM, (void *)&rate, + (bool *) & rate_set, " - time between packets"); + if (!scan_opts(argc, argv, 1, opts, 7, (void **)0, 0, "")) { + diag_printf("PING - Invalid option specified\n"); + return; + } + // Set defaults; this has to be done _after_ the scan, since it will + // have destroyed all values not explicitly set. + if (local_ip_addr_set) { + if (!_gethostbyname(local_ip_addr, (in_addr_t *) & local_addr)) { + diag_printf("PING - Invalid local name: %s\n", + local_ip_addr); + return; + } + } else { + memcpy((in_addr_t *) & local_addr, __local_ip_addr, + sizeof(__local_ip_addr)); + } + if (host_ip_addr_set) { + if (!_gethostbyname(host_ip_addr, (in_addr_t *) & host_addr)) { + diag_printf("PING - Invalid host name: %s\n", + host_ip_addr); + return; + } + if (__arp_lookup((ip_addr_t *) & host_addr.sin_addr, &dest_ip) < + 0) { + diag_printf("PING: Cannot reach server '%s' (%s)\n", + host_ip_addr, + inet_ntoa((in_addr_t *) & host_addr)); + return; + } + } else { + diag_printf("PING - host name or IP address required\n"); + return; + } #define DEFAULT_LENGTH 64 #define DEFAULT_COUNT 10 #define DEFAULT_TIMEOUT 1000 #define DEFAULT_RATE 1000 - if (!rate_set) { - rate = DEFAULT_RATE; - } - if (!length_set) { - length = DEFAULT_LENGTH; - } - if ((length < 64) || (length > 1400)) { - diag_printf("Invalid length specified: %ld\n", length); - return; - } - if (!count_set) { - count = DEFAULT_COUNT; - } - if (!timeout_set) { - timeout = DEFAULT_TIMEOUT; - } - // Note: two prints here because 'inet_ntoa' returns a static pointer - diag_printf("Network PING - from %s", - inet_ntoa((in_addr_t *)&local_addr)); - diag_printf(" to %s\n", - inet_ntoa((in_addr_t *)&host_addr)); - received = 0; - __icmp_install_listener(handle_icmp); - // Save default "local" address - memcpy(hold_addr, __local_ip_addr, sizeof(hold_addr)); - for (tries = 0; tries < count; tries++) { - // The network stack uses the global variable '__local_ip_addr' - memcpy(__local_ip_addr, &local_addr, sizeof(__local_ip_addr)); - // Build 'ping' request - if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL) { - // Give up if no packets - something is wrong - break; - } - - icmp = pkt->icmp_hdr; - ip = pkt->ip_hdr; - pkt->pkt_bytes = length + sizeof(icmp_header_t); - - icmp->type = ICMP_TYPE_ECHOREQUEST; - icmp->code = 0; - icmp->checksum = 0; - icmp->seqnum = htons(tries+1); - cksum = __sum((word *)icmp, pkt->pkt_bytes, 0); - icmp->checksum = htons(cksum); - - memcpy(ip->source, (in_addr_t *)&local_addr, sizeof(ip_addr_t)); - memcpy(ip->destination, (in_addr_t *)&host_addr, sizeof(ip_addr_t)); - ip->protocol = IP_PROTO_ICMP; - ip->length = htons(pkt->pkt_bytes); - - __ip_send(pkt, IP_PROTO_ICMP, &dest_ip); - __pktbuf_free(pkt); - - start_time = MS_TICKS(); - timer = start_time + timeout; - icmp_received = false; - while (!icmp_received && (MS_TICKS_DELAY() < timer)) { - if (_rb_break(1)) { - goto abort; - } - MS_TICKS_DELAY(); - __enet_poll(); - } - end_time = MS_TICKS(); - - timer = MS_TICKS() + rate; - while (MS_TICKS_DELAY() < timer) { - if (_rb_break(1)) { - goto abort; - } - MS_TICKS_DELAY(); - __enet_poll(); - } - - if (icmp_received) { - received++; - if (verbose) { - diag_printf(" seq: %ld, time: %ld (ticks)\n", - ntohs(hold_hdr.seqnum), end_time-start_time); - } - } - } - abort: - __icmp_remove_listener(); - // Clean up - memcpy(__local_ip_addr, &hold_addr, sizeof(__local_ip_addr)); - // Report - diag_printf("PING - received %ld of %ld expected\n", received, count); + if (!rate_set) { + rate = DEFAULT_RATE; + } + if (!length_set) { + length = DEFAULT_LENGTH; + } + if ((length < 64) || (length > 1400)) { + diag_printf("Invalid length specified: %ld\n", length); + return; + } + if (!count_set) { + count = DEFAULT_COUNT; + } + if (!timeout_set) { + timeout = DEFAULT_TIMEOUT; + } + // Note: two prints here because 'inet_ntoa' returns a static pointer + diag_printf("Network PING - from %s", + inet_ntoa((in_addr_t *) & local_addr)); + diag_printf(" to %s\n", inet_ntoa((in_addr_t *) & host_addr)); + received = 0; + __icmp_install_listener(handle_icmp); + // Save default "local" address + memcpy(hold_addr, __local_ip_addr, sizeof(hold_addr)); + for (tries = 0; tries < count; tries++) { + // The network stack uses the global variable '__local_ip_addr' + memcpy(__local_ip_addr, &local_addr, sizeof(__local_ip_addr)); + // Build 'ping' request + if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL) { + // Give up if no packets - something is wrong + break; + } + + icmp = pkt->icmp_hdr; + ip = pkt->ip_hdr; + pkt->pkt_bytes = length + sizeof(icmp_header_t); + + icmp->type = ICMP_TYPE_ECHOREQUEST; + icmp->code = 0; + icmp->checksum = 0; + icmp->seqnum = htons(tries + 1); + cksum = __sum((word *) icmp, pkt->pkt_bytes, 0); + icmp->checksum = htons(cksum); + + memcpy(ip->source, (in_addr_t *) & local_addr, + sizeof(ip_addr_t)); + memcpy(ip->destination, (in_addr_t *) & host_addr, + sizeof(ip_addr_t)); + ip->protocol = IP_PROTO_ICMP; + ip->length = htons(pkt->pkt_bytes); + + __ip_send(pkt, IP_PROTO_ICMP, &dest_ip); + __pktbuf_free(pkt); + + start_time = MS_TICKS(); + timer = start_time + timeout; + icmp_received = false; + while (!icmp_received && (MS_TICKS_DELAY() < timer)) { + if (_rb_break(1)) { + goto abort; + } + MS_TICKS_DELAY(); + __enet_poll(); + } + end_time = MS_TICKS(); + + timer = MS_TICKS() + rate; + while (MS_TICKS_DELAY() < timer) { + if (_rb_break(1)) { + goto abort; + } + MS_TICKS_DELAY(); + __enet_poll(); + } + + if (icmp_received) { + received++; + if (verbose) { + diag_printf(" seq: %ld, time: %ld (ticks)\n", + ntohs(hold_hdr.seqnum), + end_time - start_time); + } + } + } +abort: + __icmp_remove_listener(); + // Clean up + memcpy(__local_ip_addr, &hold_addr, sizeof(__local_ip_addr)); + // Report + diag_printf("PING - received %ld of %ld expected\n", received, count); } -#endif //CYGPKG_REDBOOT_NETWORKING +#endif //CYGPKG_REDBOOT_NETWORKING Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/main.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/main.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/main.c (revision 12368) @@ -156,7 +156,35 @@ void bist(void) CYGBLD_ATTRIB_WEAK; +#define RESCUE_SCRIPT "tftpd\n" + +int in_rescue_mode = 0; + + +#include +static int rescue_mode(void) +{ + int b; + int inverse = (RESETBUTTON&0xf0); + int resetgpio = RESETBUTTON&0x0F; +#if defined(CYGPKG_HAL_MIPS_AR2316) + b = ((*(volatile unsigned int *)(AR2316_GPIO_DI)) >> + resetgpio) & 1; +#else + b = ((*(volatile unsigned int *)(AR531X_GPIO_DI)) >> + resetgpio) & 1; +#endif + if (inverse) + b=(1-b); + return b; +} + void bist(void) { + if (rescue_mode()) { + diag_printf("Reset button pressed - switching to rescue mode.\n"); + in_rescue_mode = 1; + } + } @@ -330,4 +358,9 @@ #endif do_version(0,0); + + if (in_rescue_mode) { + diag_printf("Starting RESCUE script...\n"); + script = RESCUE_SCRIPT; + } #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT Index: /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/flash.c =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/flash.c (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/flash.c (revision 12368) @@ -91,5 +91,5 @@ "Initialize FLASH Image System [FIS]", "[-f]", - fis_init, + fis_init_comp, FIS_cmds ); @@ -143,4 +143,5 @@ FIS_cmds ); +#if defined(CYGPKG_HAL_MIPS_AR2316) local_cmd_entry("create256", "Create an image", @@ -157,4 +158,5 @@ FIS_cmds ); +#endif #endif @@ -334,7 +336,11 @@ fis_endian_fixup(fis_work_block); } - -static void -fis_init(int argc, char *argv[]) +void fis_init(int argc, char *argv[],int force); + +static void fis_init_comp(int argc, char *argv[]) +{ +fis_init(argc, argv,0); +} +void fis_init(int argc, char *argv[],int force) { int stat; @@ -353,5 +359,5 @@ } - if (!verify_action("About to initialize [format] FLASH image system")) { + if (!force && !verify_action("About to initialize [format] FLASH image system")) { diag_printf("** Aborted\n"); return; @@ -962,4 +968,5 @@ } +#if defined(CYGPKG_HAL_MIPS_AR2316) static void @@ -983,4 +990,5 @@ } +#endif static void fis_create(int argc, char *argv[]) Index: /ar5315_microredboot/microredboot/ecos/packages/hal/mips/mips64/current/cdl/hal_mips_mips64.cdl =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/hal/mips/mips64/current/cdl/hal_mips_mips64.cdl (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/hal/mips/mips64/current/cdl/hal_mips_mips64.cdl (revision 12368) @@ -143,5 +143,5 @@ flavor data no_define - default_value { "-mips64 -EL -msoft-float -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority -G0" } + default_value { "-mips64 -EL -msoft-float -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -Os -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority -G0" } description " This option controls the global compiler flags which Index: /ar5315_microredboot/microredboot/ecos/packages/ecos.db =================================================================== --- /ar5315_microredboot/microredboot/ecos/packages/ecos.db (revision 12281) +++ /ar5315_microredboot/microredboot/ecos/packages/ecos.db (revision 12368) @@ -2104,4 +2104,13 @@ } +package CYGPKG_CRC { + alias { "CRC support" crc } + directory services/crc + script crc.cdl + description " +This package provides support for CRC functions, including the +POSIX 1003 defined CRC algorithm." +} + package CYGPKG_CPULOAD { Index: /ar5315_microredboot/microredboot/build_targets.sh =================================================================== --- /ar5315_microredboot/microredboot/build_targets.sh (revision 12324) +++ /ar5315_microredboot/microredboot/build_targets.sh (revision 12368) @@ -1,10 +1,15 @@ #default gpio 6 rm -f images/* -make ap51 ap61 RESETBUTTON=0x06 +make ap51 ap61 RESETBUTTON=0x06 FIS=0 mkdir images_default cp images/*.rom images_default +rm -f images/* +make ap61 RESETBUTTON=0x06 FIS=1 +mkdir images_dir300 +cp images/*.rom images_dir300 + #senao like inverted gpio 5 -make ap51 RESETBUTTON=0x15 +make ap51 RESETBUTTON=0x15 FIS=2 mkdir images_senao cp images/*.rom images_senao @@ -17,10 +22,10 @@ rm -f images/* -make ap48 RESETBUTTON=0x16 +make ap48 RESETBUTTON=0x16 FIS=0 mkdir images_senao cp images/*.rom images_senao rm -f images/* -make ap48 RESETBUTTON=0x06 +make ap48 RESETBUTTON=0x06 FIS=0 mkdir images_default cp images/*.rom images_default @@ -29,3 +34,4 @@ cp -rv images_senao /GruppenLW/releases/images cp -rv images_default /GruppenLW/releases/images +cp -rv images_dir300 /GruppenLW/releases/images cp -rv images_wrt54g2 /GruppenLW/releases/images Index: /ar5315_microredboot/microredboot/boot/src/misc_lzma.c =================================================================== --- /ar5315_microredboot/microredboot/boot/src/misc_lzma.c (revision 12346) +++ /ar5315_microredboot/microredboot/boot/src/misc_lzma.c (revision 12368) @@ -238,7 +238,7 @@ printf("Board: %s\n", ddboard); char *resetbutton = nvram_get("resetbutton_enable"); - if (resetbutton && !strcmp(resetbutton, "1")) - puts("reset button manual override detected! (nvram var resetbutton_enable=1)\n"); - if (resetTouched() || (resetbutton && !strcmp(resetbutton, "1"))) { + if (resetbutton && !strcmp(resetbutton, "0")) + puts("reset button manual override detected! (nvram var resetbutton_enable=0)\n"); + if (resetTouched() || (resetbutton && !strcmp(resetbutton, "0"))) { puts("Reset Button triggered\nBooting Recovery RedBoot\n"); Index: /ar5315_microredboot/microredboot/makefile =================================================================== --- /ar5315_microredboot/microredboot/makefile (revision 12319) +++ /ar5315_microredboot/microredboot/makefile (revision 12368) @@ -13,4 +13,8 @@ ifndef RESETBUTTON export RESETBUTTON=0x16 +endif + +ifndef FIS +export FIS=0 endif @@ -84,5 +88,7 @@ if [ -n "${TARGET_NAME}" ]; then sudo cp redboot.rom $(TFTPPATH)/${TARGET_NAME}.rom; else sudo cp redboot.rom $(TFTPPATH)/$@.rom; fi -PLATFORM_RAM_BUILD = make -C $(RAMBUILD_DIR); \ +PLATFORM_RAM_BUILD = echo "\#define RESETBUTTON ${RESETBUTTON}" > ecos/packages/redboot/current/src/ramconfig.h; \ + echo "\#define FISTYPE ${FIS}" >> ecos/packages/redboot/current/src/ramconfig.h; \ + make -C $(RAMBUILD_DIR); \ cd $(RAMBUILD_DIR)/install/bin; \ mipsisa32-elf-objcopy -O binary redboot.elf redboot.bin; \