aboutsummaryrefslogtreecommitdiffstats
path: root/package/uboot-lantiq/patches
diff options
context:
space:
mode:
Diffstat (limited to 'package/uboot-lantiq/patches')
-rw-r--r--package/uboot-lantiq/patches/000-build-infos.patch60
-rw-r--r--package/uboot-lantiq/patches/010-fix-mips-flags.patch25
-rw-r--r--package/uboot-lantiq/patches/020-mips-enhancements.patch124
-rw-r--r--package/uboot-lantiq/patches/030-cfi-addr-fixup.patch225
-rw-r--r--package/uboot-lantiq/patches/040-compile.patch20
-rw-r--r--package/uboot-lantiq/patches/050-portability.patch31
-rw-r--r--package/uboot-lantiq/patches/100-ifx_targets.patch135
-rw-r--r--package/uboot-lantiq/patches/200-httpd.patch6164
-rw-r--r--package/uboot-lantiq/patches/300-arcadyan.patch98
-rw-r--r--package/uboot-lantiq/patches/400-lzma.patch1687
-rw-r--r--package/uboot-lantiq/patches/500-gigasx.patch35
11 files changed, 8604 insertions, 0 deletions
diff --git a/package/uboot-lantiq/patches/000-build-infos.patch b/package/uboot-lantiq/patches/000-build-infos.patch
new file mode 100644
index 000000000..bd185d9b5
--- /dev/null
+++ b/package/uboot-lantiq/patches/000-build-infos.patch
@@ -0,0 +1,60 @@
+Add output like in linux kernel for current compiled file
+Used normaly in combination with make option -s
+
+Like in following example:
+
+$ make -s V=1
+[CC] tools/img2srec.c
+[CC] tools/bmp_logo.c
+[CC] examples/hello_world.c
+
+--- a/config.mk
++++ b/config.mk
+@@ -234,17 +234,47 @@ export TEXT_BASE PLATFORM_CPPFLAGS PLATF
+
+ #########################################################################
+
++ifndef KBUILD_VERBOSE
++ KBUILD_VERBOSE:=0
++endif
++ifeq ("$(origin V)", "command line")
++ KBUILD_VERBOSE:=$(V)
++endif
++ifeq (,$(findstring s,$(MAKEFLAGS)))
++ KBUILD_VERBOSE:=0
++endif
++
++ifneq ($(KBUILD_VERBOSE),0)
++ define MESSAGE
++ @printf " %s %s/%s\n" $(1) $(2) $(3)
++ endef
++else
++ define MESSAGE
++ endef
++endif
++
+ # Allow boards to use custom optimize flags on a per dir/file basis
+ BCURDIR := $(notdir $(CURDIR))
++
+ $(obj)%.s: %.S
++ $(call MESSAGE, [CPP],$(subst $(SRCTREE)/,,$(CURDIR)),$<)
++ #echo $(CPP) $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $<
+ $(CPP) $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $<
+ $(obj)%.o: %.S
++ $(call MESSAGE, [AS], $(subst $(SRCTREE)/,,$(CURDIR)),$<)
++ #echo $(CC) $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $< -c
+ $(CC) $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $< -c
+ $(obj)%.o: %.c
++ $(call MESSAGE, [CC], $(subst $(SRCTREE)/,,$(CURDIR)),$<)
++ #echo $(CC) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
+ $(CC) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
+ $(obj)%.i: %.c
++ $(call MESSAGE, [CPP],$(subst $(SRCTREE)/,,$(CURDIR)),$<)
++ #echo $(CPP) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
+ $(CPP) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
+ $(obj)%.s: %.c
++ $(call MESSAGE, [CC], $(subst $(SRCTREE)/,,$(CURDIR)),$<)
++ #echo $(CC) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c -S
+ $(CC) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c -S
+
+ #########################################################################
diff --git a/package/uboot-lantiq/patches/010-fix-mips-flags.patch b/package/uboot-lantiq/patches/010-fix-mips-flags.patch
new file mode 100644
index 000000000..6dd7d8f56
--- /dev/null
+++ b/package/uboot-lantiq/patches/010-fix-mips-flags.patch
@@ -0,0 +1,25 @@
+--- a/cpu/mips/config.mk
++++ b/cpu/mips/config.mk
+@@ -23,17 +23,19 @@
+ v=$(shell $(AS) --version | grep 'GNU assembler' | egrep -o '2\.[0-9\.]+' | cut -d. -f2)
+ MIPSFLAGS:=$(shell \
+ if [ "$v" -lt "14" ]; then \
+- echo "-mcpu=4kc"; \
++ echo "-mcpu=mips32"; \
+ else \
+- echo "-march=4kc -mtune=4kc"; \
++ echo "-mips32 -march=mips32 -mtune=mips32"; \
+ fi)
+
++ifndef ENDIANNESS
+ ifneq (,$(findstring 4KCle,$(CROSS_COMPILE)))
+ ENDIANNESS = -EL
+ else
+ ENDIANNESS = -EB
+ endif
++endif
+
+-MIPSFLAGS += $(ENDIANNESS)
++MIPSFLAGS += $(ENDIANNESS) -fno-schedule-insns -fno-schedule-insns2
+
+ PLATFORM_CPPFLAGS += $(MIPSFLAGS)
diff --git a/package/uboot-lantiq/patches/020-mips-enhancements.patch b/package/uboot-lantiq/patches/020-mips-enhancements.patch
new file mode 100644
index 000000000..d05646770
--- /dev/null
+++ b/package/uboot-lantiq/patches/020-mips-enhancements.patch
@@ -0,0 +1,124 @@
+--- a/cpu/mips/start.S
++++ b/cpu/mips/start.S
+@@ -69,6 +69,9 @@ _start:
+ #elif defined(CONFIG_PURPLE)
+ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
+ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
++#elif defined(CONFIG_SYS_EBU_BOOT)
++ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
++ .word 0x00000000 /* phase of the flash */
+ #else
+ RVECENT(romReserved,2)
+ #endif
+@@ -202,7 +205,25 @@ _start:
+ * 128 * 8 == 1024 == 0x400
+ * so this is address R_VEC+0x400 == 0xbfc00400
+ */
+-#ifdef CONFIG_PURPLE
++#ifndef CONFIG_PURPLE
++ XVECENT(romExcHandle,0x400); /* bfc00400: Int, CauseIV=1 */
++ RVECENT(romReserved,129);
++ RVECENT(romReserved,130);
++ RVECENT(romReserved,131);
++ RVECENT(romReserved,132);
++ RVECENT(romReserved,133);
++ RVECENT(romReserved,134);
++ RVECENT(romReserved,135);
++ RVECENT(romReserved,136);
++ RVECENT(romReserved,137);
++ RVECENT(romReserved,138);
++ RVECENT(romReserved,139);
++ RVECENT(romReserved,140);
++ RVECENT(romReserved,141);
++ RVECENT(romReserved,142);
++ RVECENT(romReserved,143);
++ XVECENT(romExcHandle,0x480); /* bfc00480: EJTAG debug exception */
++#else /* CONFIG_PURPLE */
+ /* 0xbfc00400 */
+ .word 0xdc870000
+ .word 0xfca70000
+@@ -228,6 +249,12 @@ _start:
+ #endif /* CONFIG_PURPLE */
+ .align 4
+ reset:
++#ifdef CONFIG_SYS_MIPS_MULTI_CPU
++ mfc0 k0, CP0_EBASE
++ and k0, EBASEF_CPUNUM
++ bne k0, zero, ifx_mips_handler_cpux
++ nop
++#endif
+
+ /* Clear watch registers.
+ */
+@@ -239,6 +266,16 @@ reset:
+
+ setup_c0_status_reset
+
++#if defined(CONFIG_MIPS24KEC) || defined(CONFIG_MIPS34KC)
++ /* CONFIG7 register */
++ /* Erratum "RPS May Cause Incorrect Instruction Execution"
++ * for 24KEC and 34KC */
++ mfc0 k0, CP0_CONFIG, 7
++ li k1, MIPS_CONF7_RPS
++ or k0, k1
++ mtc0 k0, CP0_CONFIG, 7
++#endif
++
+ /* Init Timer */
+ mtc0 zero, CP0_COUNT
+ mtc0 zero, CP0_COMPARE
+@@ -270,9 +307,12 @@ reset:
+ jalr t9
+ nop
+
++#ifndef CONFIG_SYS_MIPS_CACHE_OPER_MODE
++#define CONFIG_SYS_MIPS_CACHE_OPER_MODE CONF_CM_CACHABLE_NONCOHERENT
++#endif
+ /* ... and enable them.
+ */
+- li t0, CONF_CM_CACHABLE_NONCOHERENT
++ li t0, CONFIG_SYS_MIPS_CACHE_OPER_MODE
+ mtc0 t0, CP0_CONFIG
+ #endif /* !CONFIG_SKIP_LOWLEVEL_INIT */
+
+@@ -419,3 +459,15 @@ romReserved:
+
+ romExcHandle:
+ b romExcHandle
++
++ /* Additional handlers.
++ */
++#ifdef CONFIG_SYS_MIPS_MULTI_CPU
++/*
++ * Stop Slave CPUs
++ */
++ifx_mips_handler_cpux:
++ wait;
++ b ifx_mips_handler_cpux;
++ nop;
++#endif
+--- a/include/asm-mips/mipsregs.h
++++ b/include/asm-mips/mipsregs.h
+@@ -57,6 +57,7 @@
+ #define CP0_CAUSE $13
+ #define CP0_EPC $14
+ #define CP0_PRID $15
++#define CP0_EBASE $15,1
+ #define CP0_CONFIG $16
+ #define CP0_LLADDR $17
+ #define CP0_WATCHLO $18
+@@ -395,6 +396,14 @@
+ #define CAUSEF_BD (_ULCAST_(1) << 31)
+
+ /*
++ * Bits in the coprocessor 0 EBase register
++ */
++#define EBASEB_CPUNUM 0
++#define EBASEF_CPUNUM (0x3ff << EBASEB_CPUNUM)
++#define EBASEB_EXPBASE 12
++#define EBASEF_EXPBASE (0x3ffff << EBASEB_EXPBASE)
++
++/*
+ * Bits in the coprocessor 0 config register.
+ */
+ /* Generic bits. */
diff --git a/package/uboot-lantiq/patches/030-cfi-addr-fixup.patch b/package/uboot-lantiq/patches/030-cfi-addr-fixup.patch
new file mode 100644
index 000000000..8f95da1f7
--- /dev/null
+++ b/package/uboot-lantiq/patches/030-cfi-addr-fixup.patch
@@ -0,0 +1,225 @@
+--- a/drivers/mtd/cfi_flash.c
++++ b/drivers/mtd/cfi_flash.c
+@@ -85,6 +85,22 @@ flash_info_t flash_info[CFI_MAX_FLASH_BA
+ #define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_8BIT
+ #endif
+
++/*
++ * Check if address fixup macros are defined, define defaults otherwise
++ */
++#ifndef FLASH_FIXUP_ADDR_8
++#define FLASH_FIXUP_ADDR_8(addr) (addr)
++#endif
++#ifndef FLASH_FIXUP_ADDR_16
++#define FLASH_FIXUP_ADDR_16(addr) (addr)
++#endif
++#ifndef FLASH_FIXUP_ADDR_32
++#define FLASH_FIXUP_ADDR_32(addr) (addr)
++#endif
++#ifndef FLASH_FIXUP_ADDR_64
++#define FLASH_FIXUP_ADDR_64(addr) (addr)
++#endif
++
+ static void __flash_write8(u8 value, void *addr)
+ {
+ __raw_writeb(value, addr);
+@@ -264,9 +280,9 @@ static inline uchar flash_read_uchar (fl
+
+ cp = flash_map (info, 0, offset);
+ #if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
+- retval = flash_read8(cp);
++ retval = flash_read8(FLASH_FIXUP_ADDR_8(cp));
+ #else
+- retval = flash_read8(cp + info->portwidth - 1);
++ retval = flash_read8(FLASH_FIXUP_ADDR_8(cp) + info->portwidth - 1);
+ #endif
+ flash_unmap (info, 0, offset, cp);
+ return retval;
+@@ -280,7 +296,7 @@ static inline ushort flash_read_word (fl
+ ushort *addr, retval;
+
+ addr = flash_map (info, 0, offset);
+- retval = flash_read16 (addr);
++ retval = flash_read16 (FLASH_FIXUP_ADDR_16(addr));
+ flash_unmap (info, 0, offset, addr);
+ return retval;
+ }
+@@ -305,19 +321,28 @@ static ulong flash_read_long (flash_info
+ debug ("long addr is at %p info->portwidth = %d\n", addr,
+ info->portwidth);
+ for (x = 0; x < 4 * info->portwidth; x++) {
+- debug ("addr[%x] = 0x%x\n", x, flash_read8(addr + x));
++ debug ("addr[%x] = 0x%x\n", x,
++ flash_read8(FLASH_FIXUP_ADDR_32(addr) + x));
+ }
+ #endif
+ #if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
+- retval = ((flash_read8(addr) << 16) |
+- (flash_read8(addr + info->portwidth) << 24) |
+- (flash_read8(addr + 2 * info->portwidth)) |
+- (flash_read8(addr + 3 * info->portwidth) << 8));
++ retval = ((flash_read8(FLASH_FIXUP_ADDR_8
++ (addr) << 16) |
++ (flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + info->portwidth)) << 24) |
++ (flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + 2 * info->portwidth))) |
++ (flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + 3 * info->portwidth)) << 8));
+ #else
+- retval = ((flash_read8(addr + 2 * info->portwidth - 1) << 24) |
+- (flash_read8(addr + info->portwidth - 1) << 16) |
+- (flash_read8(addr + 4 * info->portwidth - 1) << 8) |
+- (flash_read8(addr + 3 * info->portwidth - 1)));
++ retval = ((flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + 2 * info->portwidth - 1)) << 24) |
++ (flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + info->portwidth - 1)) << 16) |
++ (flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + 4 * info->portwidth - 1)) << 8) |
++ (flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + 3 * info->portwidth - 1))));
+ #endif
+ flash_unmap(info, sect, offset, addr);
+
+@@ -338,21 +363,22 @@ void flash_write_cmd (flash_info_t * inf
+ flash_make_cmd (info, cmd, &cword);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+- debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr, cmd,
+- cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+- flash_write8(cword.c, addr);
++ debug ("fwc addr %p cmd %x %x 8bit x %d bit\n",
++ FLASH_FIXUP_ADDR_8(addr), cmd, cword.c,
++ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ flash_write8(cword.c, FLASH_FIXUP_ADDR_8(addr));
+ break;
+ case FLASH_CFI_16BIT:
+- debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr,
+- cmd, cword.w,
++ debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n",
++ FLASH_FIXUP_ADDR_16(addr), cmd, cword.w,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+- flash_write16(cword.w, addr);
++ flash_write16(cword.w, FLASH_FIXUP_ADDR_16(addr));
+ break;
+ case FLASH_CFI_32BIT:
+- debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr,
+- cmd, cword.l,
++ debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n",
++ FLASH_FIXUP_ADDR_32(addr), cmd, cword.l,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+- flash_write32(cword.l, addr);
++ flash_write32(cword.l, FLASH_FIXUP_ADDR_32(addr));
+ break;
+ case FLASH_CFI_64BIT:
+ #ifdef DEBUG
+@@ -362,11 +388,11 @@ void flash_write_cmd (flash_info_t * inf
+ print_longlong (str, cword.ll);
+
+ debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
+- addr, cmd, str,
++ FLASH_FIXUP_ADDR_64(addr), cmd, str,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+ }
+ #endif
+- flash_write64(cword.ll, addr);
++ flash_write64(cword.ll, FLASH_FIXUP_ADDR_64(addr));
+ break;
+ }
+
+@@ -397,16 +423,19 @@ static int flash_isequal (flash_info_t *
+ debug ("is= cmd %x(%c) addr %p ", cmd, cmd, addr);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+- debug ("is= %x %x\n", flash_read8(addr), cword.c);
+- retval = (flash_read8(addr) == cword.c);
++ debug ("is= %x %x\n",
++ flash_read8(FLASH_FIXUP_ADDR_8(addr)), cword.c);
++ retval = (flash_read8(FLASH_FIXUP_ADDR_8(addr)) == cword.c);
+ break;
+ case FLASH_CFI_16BIT:
+- debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w);
+- retval = (flash_read16(addr) == cword.w);
++ debug ("is= %4.4x %4.4x\n",
++ flash_read16(FLASH_FIXUP_ADDR_16(addr)), cword.w);
++ retval = (flash_read16(FLASH_FIXUP_ADDR_16(addr)) == cword.w);
+ break;
+ case FLASH_CFI_32BIT:
+- debug ("is= %8.8x %8.8lx\n", flash_read32(addr), cword.l);
+- retval = (flash_read32(addr) == cword.l);
++ debug ("is= %8.8x %8.8lx\n",
++ flash_read32(FLASH_FIXUP_ADDR_32(addr)), cword.l);
++ retval = (flash_read32(FLASH_FIXUP_ADDR_32(addr)) == cword.l);
+ break;
+ case FLASH_CFI_64BIT:
+ #ifdef DEBUG
+@@ -414,12 +443,13 @@ static int flash_isequal (flash_info_t *
+ char str1[20];
+ char str2[20];
+
+- print_longlong (str1, flash_read64(addr));
++ print_longlong (str1, flash_read64(FLASH_FIXUP_ADDR_64
++ (addr)));
+ print_longlong (str2, cword.ll);
+ debug ("is= %s %s\n", str1, str2);
+ }
+ #endif
+- retval = (flash_read64(addr) == cword.ll);
++ retval = (flash_read64(FLASH_FIXUP_ADDR_64(addr)) == cword.ll);
+ break;
+ default:
+ retval = 0;
+@@ -443,16 +473,20 @@ static int flash_isset (flash_info_t * i
+ flash_make_cmd (info, cmd, &cword);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+- retval = ((flash_read8(addr) & cword.c) == cword.c);
++ retval = ((flash_read8(FLASH_FIXUP_ADDR_8(addr))
++ & cword.c) == cword.c);
+ break;
+ case FLASH_CFI_16BIT:
+- retval = ((flash_read16(addr) & cword.w) == cword.w);
++ retval = ((flash_read16(FLASH_FIXUP_ADDR_16(addr))
++ & cword.w) == cword.w);
+ break;
+ case FLASH_CFI_32BIT:
+- retval = ((flash_read32(addr) & cword.l) == cword.l);
++ retval = ((flash_read32(FLASH_FIXUP_ADDR_32(addr))
++ & cword.l) == cword.l);
+ break;
+ case FLASH_CFI_64BIT:
+- retval = ((flash_read64(addr) & cword.ll) == cword.ll);
++ retval = ((flash_read64(FLASH_FIXUP_ADDR_64(addr))
++ & cword.ll) == cword.ll);
+ break;
+ default:
+ retval = 0;
+@@ -476,17 +510,22 @@ static int flash_toggle (flash_info_t *
+ flash_make_cmd (info, cmd, &cword);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+- retval = flash_read8(addr) != flash_read8(addr);
++ retval = flash_read8(FLASH_FIXUP_ADDR_8(addr)) !=
++ flash_read8(FLASH_FIXUP_ADDR_8(addr));
+ break;
+ case FLASH_CFI_16BIT:
+- retval = flash_read16(addr) != flash_read16(addr);
++ retval = flash_read16(FLASH_FIXUP_ADDR_16(addr)) !=
++ flash_read16(FLASH_FIXUP_ADDR_16(addr));
+ break;
+ case FLASH_CFI_32BIT:
+- retval = flash_read32(addr) != flash_read32(addr);
++ retval = flash_read32(FLASH_FIXUP_ADDR_32(addr)) !=
++ flash_read32(FLASH_FIXUP_ADDR_32(addr));
+ break;
+ case FLASH_CFI_64BIT:
+- retval = ( (flash_read32( addr ) != flash_read32( addr )) ||
+- (flash_read32(addr+4) != flash_read32(addr+4)) );
++ retval = ( (flash_read32(FLASH_FIXUP_ADDR_64( addr )) !=
++ flash_read32(FLASH_FIXUP_ADDR_64( addr ))) ||
++ (flash_read32(FLASH_FIXUP_ADDR_64(addr+4)) !=
++ flash_read32(FLASH_FIXUP_ADDR_64(addr+4))) );
+ break;
+ default:
+ retval = 0;
diff --git a/package/uboot-lantiq/patches/040-compile.patch b/package/uboot-lantiq/patches/040-compile.patch
new file mode 100644
index 000000000..c00230069
--- /dev/null
+++ b/package/uboot-lantiq/patches/040-compile.patch
@@ -0,0 +1,20 @@
+--- a/common/env_common.c
++++ b/common/env_common.c
+@@ -26,6 +26,7 @@
+
+ #include <common.h>
+ #include <command.h>
++#include <configs/ifx-common.h>
+ #include <environment.h>
+ #include <linux/stddef.h>
+ #include <malloc.h>
+--- a/common/env_embedded.c
++++ b/common/env_embedded.c
+@@ -27,6 +27,7 @@
+ #define __ASM_STUB_PROCESSOR_H__ /* don't include asm/processor. */
+ #include <config.h>
+ #undef __ASSEMBLY__
++#include <configs/ifx-common.h>
+ #include <environment.h>
+
+ /*
diff --git a/package/uboot-lantiq/patches/050-portability.patch b/package/uboot-lantiq/patches/050-portability.patch
new file mode 100644
index 000000000..ae38ad68e
--- /dev/null
+++ b/package/uboot-lantiq/patches/050-portability.patch
@@ -0,0 +1,31 @@
+--- a/tools/kwbimage.c
++++ b/tools/kwbimage.c
+@@ -206,6 +206,28 @@ INVL_DATA:
+ exit (EXIT_FAILURE);
+ }
+
++#ifndef __GLIBC__
++static ssize_t
++getline(char **line, size_t *len, FILE *fd)
++{
++ char *tmp;
++ int tmplen;
++
++ tmp = fgetln(fd, &tmplen);
++ if (!tmp)
++ return -1;
++
++ if (!*line || tmplen > *len) {
++ *len = tmplen + 1;
++ *line = realloc(*line, *len);
++ }
++
++ strncpy(*line, tmp, tmplen);
++ line[tmplen] = 0;
++ return tmplen;
++}
++#endif
++
+ /*
+ * this function sets the kwbimage header by-
+ * 1. Abstracting input command line arguments data
diff --git a/package/uboot-lantiq/patches/100-ifx_targets.patch b/package/uboot-lantiq/patches/100-ifx_targets.patch
new file mode 100644
index 000000000..dcd931cb8
--- /dev/null
+++ b/package/uboot-lantiq/patches/100-ifx_targets.patch
@@ -0,0 +1,135 @@
+--- a/MAKEALL
++++ b/MAKEALL
+@@ -730,6 +730,12 @@
+ ## MIPS Systems (default = big endian)
+ #########################################################################
+
++LIST_ifxcpe=" \
++ easy50712 \
++ easy50712_DDR166M \
++ easy50712_DDR166M_ramboot \
++"
++
+ LIST_mips4kc=" \
+ incaip \
+ qemu_mips \
+@@ -761,6 +767,7 @@
+ "
+
+ LIST_mips=" \
++ ${LIST_ifxcpe} \
+ ${LIST_mips4kc} \
+ ${LIST_mips5kc} \
+ ${LIST_au1xx0} \
+--- a/Makefile
++++ b/Makefile
+@@ -447,7 +447,7 @@
+ set -e ; \
+ : Extract the config macros ; \
+ $(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | \
+- sed -n -f tools/scripts/define2mk.sed > $@.tmp && \
++ sed -n -f tools/scripts/define2mk.sed |sort > $@.tmp && \
+ mv $@.tmp $@
+
+ #########################################################################
+@@ -3370,7 +3370,7 @@
+ { echo "#define CPU_CLOCK_RATE 150000000" >>$(obj)include/config.h ; \
+ $(XECHO) "... with 150MHz system clock" ; \
+ }
+- @$(MKCONFIG) -a $(call xtract_incaip,$@) mips mips incaip
++ @$(MKCONFIG) -a $(call xtract_incaip,$@) mips mips incaip infineon
+
+ tb0229_config: unconfig
+ @$(MKCONFIG) $(@:_config=) mips mips tb0229
+@@ -3411,6 +3411,53 @@
+ @$(MKCONFIG) -a vct mips mips vct micronas
+
+ #########################################################################
++## MIPS32 ifxcpe
++#########################################################################
++
++easy50712%config : unconfig
++ @mkdir -p $(obj)include
++ @mkdir -p $(obj)board/infineon/easy50712
++ @[ -z "$(findstring ramboot,$@)" ] || \
++ { echo "TEXT_BASE = 0xA0400000" >$(obj)board/infineon/easy50712/config.tmp ; \
++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \
++ $(XECHO) "... with ramboot configuration" ; \
++ }
++ @if [ "$(findstring _DDR,$@)" -a -z "$(findstring ramboot,$@)" ] ; then \
++ echo "#define CONFIG_USE_DDR_RAM" >>$(obj)include/config.h ; \
++ echo "#define CONFIG_BOOTSTRAP" >>$(obj)include/config.h ; \
++ DDR=$(subst DDR,,$(filter DDR%,$(subst _, ,$@))); \
++ case "$${DDR}" in \
++ 111M|166M|e111M|e166M|promos400|samsung166|psc166) \
++ $(XECHO) "... with DDR RAM config $${DDR}" ; \
++ echo "#define CONFIG_USE_DDR_RAM_CFG_$${DDR}" >>$(obj)include/config.h ;; \
++ *) $(XECHO) "... DDR RAM config \\\"$${DDR}\\\" unknown, use default"; \
++ esac; \
++ fi
++ @$(MKCONFIG) -a $(word 1,$(subst _, ,$@)) mips mips easy50712 infineon danube
++
++easy50812%config : unconfig
++ @mkdir -p $(obj)include
++ @mkdir -p $(obj)board/infineon/easy50812
++ @[ -z "$(findstring ramboot,$@)" ] || \
++ { echo "TEXT_BASE = 0xA0400000" >$(obj)board/infineon/easy50812/config.tmp ; \
++ echo "CONFIG_BOOTSTRAP = 0" >>$(obj)board/infineon/easy50812/config.tmp ; \
++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \
++ $(XECHO) "... with ramboot configuration" ; \
++ }
++ @if [ "$(findstring _DDR,$@)" -a -z "$(findstring ramboot,$@)" ] ; then \
++ echo "#define CONFIG_USE_DDR_RAM" >>$(obj)include/config.h ; \
++ echo "#define CONFIG_BOOTSTRAP" >>$(obj)include/config.h ; \
++ DDR=$(subst DDR,,$(filter DDR%,$(subst _, ,$@))); \
++ case "$${DDR}" in \
++ 111M|166M|e111M|e166M|promos400|samsung166|psc166) \
++ $(XECHO) "... with DDR RAM config $${DDR}" ; \
++ echo "#define CONFIG_USE_DDR_RAM_CFG_$${DDR}" >>$(obj)include/config.h ;; \
++ *) $(XECHO) "... DDR RAM config \\\"$${DDR}\\\" unknown, use default"; \
++ esac; \
++ fi
++ @$(MKCONFIG) -a $(word 1,$(subst _, ,$@)) mips mips easy50812 infineon ar9
++
++#########################################################################
+ ## MIPS32 AU1X00
+ #########################################################################
+
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -43,6 +43,7 @@
+ COBJS-$(CONFIG_FSLDMAFEC) += fsl_mcdmafec.o mcfmii.o
+ COBJS-$(CONFIG_FTMAC100) += ftmac100.o
+ COBJS-$(CONFIG_GRETH) += greth.o
++COBJS-$(CONFIG_IFX_ETOP) += ifx_etop.o
+ COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o
+ COBJS-$(CONFIG_KIRKWOOD_EGIGA) += kirkwood_egiga.o
+ COBJS-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -28,6 +28,7 @@
+ COBJS-$(CONFIG_ARM_DCC) += arm_dcc.o
+ COBJS-$(CONFIG_AT91RM9200_USART) += at91rm9200_usart.o
+ COBJS-$(CONFIG_ATMEL_USART) += atmel_usart.o
++COBJS-$(CONFIG_IFX_ASC) += ifx_asc.o
+ COBJS-$(CONFIG_MCFUART) += mcfuart.o
+ COBJS-$(CONFIG_NS9750_UART) += ns9750_serial.o
+ COBJS-$(CONFIG_SYS_NS16550) += ns16550.o
+--- a/include/netdev.h
++++ b/include/netdev.h
+@@ -57,6 +57,7 @@
+ int ftmac100_initialize(bd_t *bits);
+ int greth_initialize(bd_t *bis);
+ void gt6426x_eth_initialize(bd_t *bis);
++int ifx_etop_initialize(bd_t *bis);
+ int inca_switch_initialize(bd_t *bis);
+ int kirkwood_egiga_initialize(bd_t *bis);
+ int lan91c96_initialize(u8 dev_num, int base_addr);
+@@ -85,6 +86,7 @@
+ int uli526x_initialize(bd_t *bis);
+ int sh_eth_initialize(bd_t *bis);
+ int dm9000_initialize(bd_t *bis);
++int lq_eth_initialize(bd_t * bis);
+
+ /* Boards with PCI network controllers can call this from their board_eth_init()
+ * function to initialize whatever's on board.
diff --git a/package/uboot-lantiq/patches/200-httpd.patch b/package/uboot-lantiq/patches/200-httpd.patch
new file mode 100644
index 000000000..b0ab3b6af
--- /dev/null
+++ b/package/uboot-lantiq/patches/200-httpd.patch
@@ -0,0 +1,6164 @@
+--- a/common/cmd_net.c
++++ b/common/cmd_net.c
+@@ -43,6 +43,18 @@ U_BOOT_CMD(
+ "[loadAddress] [[hostIPaddr:]bootfilename]"
+ );
+
++#if defined(CONFIG_CMD_HTTPD)
++int do_httpd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
++{
++ return NetLoopHttpd();
++}
++
++U_BOOT_CMD(
++ httpd, 1, 1, do_httpd,
++ "httpd\t- start webserver", ""
++);
++#endif
++
+ int do_tftpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+ {
+ return netboot_common (TFTP, cmdtp, argc, argv);
+--- /dev/null
++++ b/include/httpd.h
+@@ -0,0 +1,17 @@
++#ifndef _UIP_HTTPD_H__
++#define _UIP_HTTPD_H__
++
++void HttpdStart (void);
++void HttpdHandler (void);
++
++/* board specific implementation */
++extern int do_http_upgrade(const unsigned char *data, const ulong size);
++
++#define HTTP_PROGRESS_START 0
++#define HTTP_PROGRESS_TIMEOUT 1
++#define HTTP_PROGRESS_UPLOAD_READY 2
++#define HTTP_PROGRESS_UGRADE_READY 3
++#define HTTP_PROGRESS_UGRADE_FAILED 4
++extern int do_http_progress(const int state);
++
++#endif
+--- a/include/net.h
++++ b/include/net.h
+@@ -383,7 +383,8 @@ extern int NetTimeOffset; /* offset ti
+
+ /* Initialize the network adapter */
+ extern int NetLoop(proto_t);
+-
++extern int NetLoopHttpd(void);
++extern void NetSendHttpd(void);
+ /* Shutdown adapters and cleanup */
+ extern void NetStop(void);
+
+--- a/net/Makefile
++++ b/net/Makefile
+@@ -26,6 +26,8 @@ include $(TOPDIR)/config.mk
+ # CFLAGS += -DDEBUG
+
+ LIB = $(obj)libnet.a
++UIPDIR = uip-0.9
++$(shell mkdir -p $(obj)$(UIPDIR))
+
+ COBJS-$(CONFIG_CMD_NET) += bootp.o
+ COBJS-$(CONFIG_CMD_DNS) += dns.o
+@@ -36,6 +40,8 @@ COBJS-$(CONFIG_CMD_NET) += rarp.o
+ COBJS-$(CONFIG_CMD_SNTP) += sntp.o
+ COBJS-$(CONFIG_CMD_NET) += tftp.o
+
++COBJS-$(CONFIG_CMD_HTTPD) += httpd.o $(UIPDIR)/fs.o $(UIPDIR)/httpd.o $(UIPDIR)/uip_arp.o $(UIPDIR)/uip_arch.o $(UIPDIR)/uip.o
++
+ COBJS := $(COBJS-y)
+ SRCS := $(COBJS:.o=.c)
+ OBJS := $(addprefix $(obj),$(COBJS))
+--- /dev/null
++++ b/net/httpd.c
+@@ -0,0 +1,52 @@
++/*
++ * Copyright 1994, 1995, 2000 Neil Russell.
++ * (See License)
++ * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de
++ */
++
++#include <common.h>
++#include <command.h>
++#include <net.h>
++#include "uip-0.9/uipopt.h"
++#include "uip-0.9/uip.h"
++#include "uip-0.9/uip_arp.h"
++
++
++#if defined(CONFIG_CMD_HTTPD)
++
++#define TIMEOUT 5
++
++static int arptimer = 0;
++
++void
++HttpdHandler (void)
++{
++ int i;
++ for(i = 0; i < UIP_CONNS; i++) {
++ uip_periodic(i);
++ if(uip_len > 0) {
++ uip_arp_out();
++ NetSendHttpd();
++ }
++ }
++ if(++arptimer == 20) {
++ uip_arp_timer();
++ arptimer = 0;
++ }
++}
++
++static void
++HttpdTimeout (void)
++{
++ puts ("T ");
++ NetSetTimeout (TIMEOUT * 1000, HttpdTimeout);
++}
++
++void
++HttpdStart (void)
++{
++ uip_init();
++ httpd_init();
++}
++
++#endif
+--- a/net/net.c
++++ b/net/net.c
+@@ -95,6 +95,19 @@
+ #if defined(CONFIG_CMD_DNS)
+ #include "dns.h"
+ #endif
++#if defined(CONFIG_CMD_HTTPD)
++#include "httpd.h"
++#include "uip-0.9/uipopt.h"
++#include "uip-0.9/uip.h"
++#include "uip-0.9/uip_arp.h"
++static int https_running = 0;
++int httpd_upload_complete = 0;
++unsigned char *httpd_upload_data = 0;
++extern int upload_running;
++void NetReceiveHttpd(volatile uchar * inpkt, int len);
++void NetSendHttpd(void);
++extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
++#endif
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+@@ -1308,6 +1321,13 @@ NetReceive(volatile uchar * inpkt, int l
+
+ debug("packet received\n");
+
++#if defined(CONFIG_CMD_HTTPD)
++ if(https_running) {
++ NetReceiveHttpd(inpkt, len);
++ return;
++ }
++#endif
++
+ NetRxPacket = inpkt;
+ NetRxPacketLen = len;
+ et = (Ethernet_t *)inpkt;
+@@ -1922,3 +1942,162 @@ ushort getenv_VLAN(char *var)
+ {
+ return (string_to_VLAN(getenv(var)));
+ }
++
++#if defined(CONFIG_CMD_HTTPD)
++
++void
++NetSendHttpd(void)
++{
++ volatile uchar *tmpbuf = NetTxPacket;
++ int i;
++
++ for(i = 0; i < 40 + UIP_LLH_LEN; i++) {
++ tmpbuf[i] = uip_buf[i];
++ }
++
++ for(; i < uip_len; i++) {
++ tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN];
++ }
++ eth_send(NetTxPacket, uip_len);
++}
++
++#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
++
++void
++NetReceiveHttpd(volatile uchar * inpkt, int len)
++{
++ memcpy(uip_buf, inpkt, len);
++ uip_len = len;
++ if(BUF->type == htons(UIP_ETHTYPE_IP)) {
++ uip_arp_ipin();
++ uip_input();
++ if(uip_len > 0) {
++ uip_arp_out();
++ NetSendHttpd();
++ }
++ } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {
++ uip_arp_arpin();
++ if(uip_len > 0) {
++ NetSendHttpd();
++ }
++ }
++}
++
++int
++NetLoopHttpd(void)
++{
++ unsigned long long tout = 0;
++ bd_t *bd = gd->bd;
++ unsigned short int ip[2];
++
++#ifdef CONFIG_NET_MULTI
++ NetRestarted = 0;
++ NetDevExists = 0;
++#endif
++
++ /* XXX problem with bss workaround */
++ NetArpWaitPacketMAC = NULL;
++ NetArpWaitTxPacket = NULL;
++ NetArpWaitPacketIP = 0;
++ NetArpWaitReplyIP = 0;
++ NetArpWaitTxPacket = NULL;
++ NetTxPacket = NULL;
++ NetTryCount = 1;
++
++ if (!NetTxPacket) {
++ int i;
++ /*
++ * Setup packet buffers, aligned correctly.
++ */
++ NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
++ NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
++ for (i = 0; i < PKTBUFSRX; i++) {
++ NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
++ }
++ }
++
++ if (!NetArpWaitTxPacket) {
++ NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
++ NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
++ NetArpWaitTxPacketSize = 0;
++ }
++
++restart:
++
++ eth_halt();
++#ifdef CONFIG_NET_MULTI
++ eth_set_current();
++#endif
++ if (eth_init(bd) < 0) {
++ eth_halt();
++ return(-1);
++ }
++
++#ifdef CONFIG_NET_MULTI
++ memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);
++#else
++ eth_getenv_enetaddr("ethaddr", NetOurEther);
++#endif
++
++ NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
++ NetOurGatewayIP = getenv_IPaddr ("gatewayip");
++ NetOurSubnetMask= getenv_IPaddr ("netmask");
++ NetOurVLAN = getenv_VLAN("vlan");
++ NetOurNativeVLAN = getenv_VLAN("nvlan");
++
++ printf("starting httpd server from server %ld.%ld.%ld.%ld\n",
++ (bd->bi_ip_addr & 0xff000000) >> 24,
++ (bd->bi_ip_addr & 0x00ff0000) >> 16,
++ (bd->bi_ip_addr & 0x0000ff00) >> 8,
++ (bd->bi_ip_addr & 0x000000ff));
++
++ HttpdStart();
++
++ ip[0] = ((bd->bi_ip_addr & 0xffff0000) >> 16);
++ ip[1] = (bd->bi_ip_addr & 0x0000ffff);
++ uip_sethostaddr(ip);
++
++ do_http_progress(HTTP_PROGRESS_START);
++
++ https_running = 1;
++ for (;;) {
++ unsigned long long t1;
++ WATCHDOG_RESET();
++ if(eth_rx() > 0) {
++ HttpdHandler();
++ } else {
++ t1 = get_ticks();
++ if(t1 - tout > 1000) {
++ do_http_progress(HTTP_PROGRESS_TIMEOUT);
++ tout = t1;
++ }
++ }
++ if(!httpd_upload_complete)
++ continue;
++ printf("Bytes transferred = %ld (%lx hex)\n",
++ NetBootFileXferSize,
++ NetBootFileXferSize);
++ eth_halt();
++ do_http_progress(HTTP_PROGRESS_UPLOAD_READY);
++ if(do_http_upgrade(&httpd_upload_data[0], NetBootFileXferSize) == 0) {
++ do_http_progress(HTTP_PROGRESS_UGRADE_READY);
++ udelay(1000 * 10);
++ do_reset (0,0,0,0);
++ return 0;
++ }
++ break;
++ }
++ https_running = 0;
++ NetBootFileXferSize = 0;
++ httpd_upload_complete = 0;
++ upload_running = 0;
++// free(httpd_upload_data);
++
++ do_http_progress(HTTP_PROGRESS_UGRADE_FAILED);
++
++ goto restart;
++
++ return -1;
++}
++
++#endif
+--- /dev/null
++++ b/net/uip-0.9/Makefile
+@@ -0,0 +1,54 @@
++# Copyright (c) 2001, Adam Dunkels.
++# All rights reserved.
++#
++# Redistribution and use in source and binary forms, with or without
++# modification, are permitted provided that the following conditions
++# are met:
++# 1. Redistributions of source code must retain the above copyright
++# notice, this list of conditions and the following disclaimer.
++# 2. Redistributions in binary form must reproduce the above copyright
++# notice, this list of conditions and the following disclaimer in the
++# documentation and/or other materials provided with the distribution.
++# 3. All advertising materials mentioning features or use of this software
++# must display the following acknowledgement:
++# This product includes software developed by Adam Dunkels.
++# 4. The name of the author may not be used to endorse or promote
++# products derived from this software without specific prior
++# written permission.
++#
++# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
++# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
++# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
++# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++#
++# This file is part of the uIP TCP/IP stack.
++#
++# $Id: Makefile,v 1.8.2.2 2003/10/04 22:54:17 adam Exp $
++#
++
++CC=gcc
++CFLAGS=-Wall -fpack-struct -DDUMP=0
++
++all: uip
++
++uip: uip.o uip_arch.o tapdev.o httpd.o main.o fs.o uip_arp.o
++ $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
++
++%.o: %.c
++ $(CC) $(CFLAGS) -c $^ -o $@
++
++clean:
++ rm -f *.o *~ *core uip
++
++
++
++
++
++
+--- /dev/null
++++ b/net/uip-0.9/fs.c
+@@ -0,0 +1,154 @@
++/**
++ * \addtogroup httpd
++ * @{
++ */
++
++/**
++ * \file
++ * HTTP server read-only file system code.
++ * \author Adam Dunkels <adam@dunkels.com>
++ *
++ * A simple read-only filesystem.
++ */
++
++/*
++ * Copyright (c) 2001, Swedish Institute of Computer Science.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. Neither the name of the Institute nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ * This file is part of the lwIP TCP/IP stack.
++ *
++ * Author: Adam Dunkels <adam@sics.se>
++ *
++ * $Id: fs.c,v 1.7.2.3 2003/10/07 13:22:27 adam Exp $
++ */
++
++#include "uip.h"
++#include "httpd.h"
++#include "fs.h"
++#include "fsdata.h"
++
++#include "fsdata.c"
++
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++static u16_t count[FS_NUMFILES];
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++
++/*-----------------------------------------------------------------------------------*/
++static u8_t
++fs_strcmp(const char *str1, const char *str2)
++{
++ u8_t i;
++ i = 0;
++ loop:
++
++ if(str2[i] == 0 ||
++ str1[i] == '\r' ||
++ str1[i] == '\n') {
++ return 0;
++ }
++
++ if(str1[i] != str2[i]) {
++ return 1;
++ }
++
++
++ ++i;
++ goto loop;
++}
++/*-----------------------------------------------------------------------------------*/
++int
++fs_open(const char *name, struct fs_file *file)
++{
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++ u16_t i = 0;
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++ struct fsdata_file_noconst *f;
++
++ for(f = (struct fsdata_file_noconst *)FS_ROOT;
++ f != NULL;
++ f = (struct fsdata_file_noconst *)f->next) {
++
++ if(fs_strcmp(name, f->name) == 0) {
++ file->data = f->data;
++ file->len = f->len;
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++ ++count[i];
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++ return 1;
++ }
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++ ++i;
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++
++ }
++ return 0;
++}
++/*-----------------------------------------------------------------------------------*/
++void
++fs_init(void)
++{
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++ u16_t i;
++ for(i = 0; i < FS_NUMFILES; i++) {
++ count[i] = 0;
++ }
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++}
++/*-----------------------------------------------------------------------------------*/
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++u16_t fs_count
++(char *name)
++{
++ struct fsdata_file_noconst *f;
++ u16_t i;
++
++ i = 0;
++ for(f = (struct fsdata_file_noconst *)FS_ROOT;
++ f != NULL;
++ f = (struct fsdata_file_noconst *)f->next) {
++
++ if(fs_strcmp(name, f->name) == 0) {
++ return count[i];
++ }
++ ++i;
++ }
++ return 0;
++}
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++/*-----------------------------------------------------------------------------------*/
+--- /dev/null
++++ b/net/uip-0.9/fs.h
+@@ -0,0 +1,80 @@
++/**
++ * \addtogroup httpd
++ * @{
++ */
++
++/**
++ * \file
++ * HTTP server read-only file system header file.
++ * \author Adam Dunkels <adam@dunkels.com>
++ */
++
++/*
++ * Copyright (c) 2001, Swedish Institute of Computer Science.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. Neither the name of the Institute nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ * This file is part of the lwIP TCP/IP stack.
++ *
++ * Author: Adam Dunkels <adam@sics.se>
++ *
++ * $Id: fs.h,v 1.6.2.3 2003/10/07 13:22:27 adam Exp $
++ */
++#ifndef __FS_H__
++#define __FS_H__
++
++#include "uip.h"
++
++/**
++ * An open file in the read-only file system.
++ */
++struct fs_file {
++ char *data; /**< The actual file data. */
++ int len; /**< The length of the file data. */
++};
++
++/**
++ * Open a file in the read-only file system.
++ *
++ * \param name The name of the file.
++ *
++ * \param file The file pointer, which must be allocated by caller and
++ * will be filled in by the function.
++ */
++int fs_open(const char *name, struct fs_file *file);
++
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++u16_t fs_count(char *name);
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++
++/**
++ * Initialize the read-only file system.
++ */
++void fs_init(void);
++
++#endif /* __FS_H__ */
+--- /dev/null
++++ b/net/uip-0.9/fsdata.c
+@@ -0,0 +1,199 @@
++static const char data_flashing_html[] = {
++ /* /flashing.html */
++ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62,
++ 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d,
++ 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30,
++ 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68,
++ 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25,
++ 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23,
++ 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
++ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
++ 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34,
++ 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72,
++ 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61,
++ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
++ 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31,
++ 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e,
++ 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68,
++ 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
++
++static const char data_fail_html[] = {
++ /* /fail.html */
++ 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9,
++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c,
++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9,
++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46,
++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49,
++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65,
++ 0x3e, 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa,
++ 0x9, 0x9, 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73,
++ 0x68, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65,
++ 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, 0x45,
++ 0x52, 0x52, 0x4f, 0x52, 0x20, 0x2d, 0x20, 0x74, 0x68, 0x65,
++ 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x79, 0x6f, 0x75,
++ 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20,
++ 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
++ 0x70, 0x61, 0x73, 0x73, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66,
++ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x50,
++ 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x61, 0x6b, 0x65,
++ 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75,
++ 0x73, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x66, 0x69,
++ 0x63, 0x69, 0x61, 0x6c, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74,
++ 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64,
++ 0x20, 0x62, 0x79, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
++ 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e,
++ 0x66, 0x6f, 0x6e, 0x6f, 0x73, 0x66, 0x65, 0x72, 0x61, 0x2e,
++ 0x6f, 0x72, 0x67, 0x2f, 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f,
++ 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c,
++ 0x3e, 0xa, };
++
++static const char data_404_html[] = {
++ /* /404.html */
++ 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34,
++ 0x30, 0x34, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f,
++ 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53,
++ 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50,
++ 0x2f, 0x30, 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70,
++ 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73,
++ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f,
++ 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e,
++ 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a,
++ 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c,
++ 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e,
++ 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f,
++ 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65,
++ 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e,
++ 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, 0x20,
++ 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66,
++ 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c,
++ 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x2f,
++ 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d,
++ 0x6c, 0x3e, };
++
++static const char data_index_html[] = {
++ /* /index.html */
++ 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9,
++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c,
++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9,
++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46,
++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49,
++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65,
++ 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e,
++ 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74,
++ 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69,
++ 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74,
++ 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a,
++ 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
++ 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62,
++ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
++ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62,
++ 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9,
++ 0x3c, 0x68, 0x31, 0x3e, 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65,
++ 0x72, 0x61, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66,
++ 0x65, 0x20, 0x55, 0x49, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa,
++ 0x9, 0x9, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65,
++ 0x74, 0x68, 0x6f, 0x64, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x74,
++ 0x22, 0x20, 0x65, 0x6e, 0x63, 0x74, 0x79, 0x70, 0x65, 0x3d,
++ 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74,
++ 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61,
++ 0x22, 0x3e, 0xa, 0x9, 0x9, 0x9, 0x3c, 0x69, 0x6e, 0x70,
++ 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69,
++ 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x66, 0x69,
++ 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x3e, 0xa, 0x9, 0x9,
++ 0x9, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79,
++ 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x3e,
++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e,
++ 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa,
++ 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
++
++static const char data_flash_html[] = {
++ /* /flash.html */
++ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9,
++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c,
++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9,
++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46,
++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49,
++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65,
++ 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e,
++ 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74,
++ 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69,
++ 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74,
++ 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a,
++ 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
++ 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62,
++ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
++ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62,
++ 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9,
++ 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x69,
++ 0x6e, 0x67, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9,
++ 0x54, 0x68, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
++ 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x72,
++ 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6c,
++ 0x61, 0x73, 0x68, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68,
++ 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70,
++ 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x2c, 0x20, 0x74, 0x68,
++ 0x65, 0x20, 0x6c, 0x65, 0x64, 0x73, 0x20, 0x77, 0x69, 0x6c,
++ 0x6c, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x6f,
++ 0x20, 0x62, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0xa, 0xa, 0x9,
++ 0x9, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x61, 0x20, 0x73,
++ 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x6c,
++ 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68,
++ 0x65, 0x20, 0x62, 0x6f, 0x78, 0x20, 0x77, 0x69, 0x6c, 0x6c,
++ 0x20, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0xa, 0x9, 0x3c,
++ 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68,
++ 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
++
++const struct fsdata_file file_flashing_html[] = {{NULL, data_flashing_html, data_flashing_html + 15, sizeof(data_flashing_html) - 15}};
++
++const struct fsdata_file file_fail_html[] = {{file_flashing_html, data_fail_html, data_fail_html + 11, sizeof(data_fail_html) - 11}};
++
++const struct fsdata_file file_404_html[] = {{file_fail_html, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}};
++
++const struct fsdata_file file_index_html[] = {{file_404_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}};
++
++const struct fsdata_file file_flash_html[] = {{file_index_html, data_flash_html, data_flash_html + 12, sizeof(data_flash_html) - 12}};
++
++#define FS_ROOT file_flash_html
++
++#define FS_NUMFILES 5
+\ No newline at end of file
+--- /dev/null
++++ b/net/uip-0.9/fsdata.h
+@@ -0,0 +1,64 @@
++/*
++ * Copyright (c) 2001, Swedish Institute of Computer Science.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. Neither the name of the Institute nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ * This file is part of the lwIP TCP/IP stack.
++ *
++ * Author: Adam Dunkels <adam@sics.se>
++ *
++ * $Id: fsdata.h,v 1.4.2.1 2003/10/04 22:54:06 adam Exp $
++ */
++#ifndef __FSDATA_H__
++#define __FSDATA_H__
++
++#include "uipopt.h"
++
++struct fsdata_file {
++ const struct fsdata_file *next;
++ const char *name;
++ const char *data;
++ const int len;
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++ u16_t count;
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++};
++
++struct fsdata_file_noconst {
++ struct fsdata_file *next;
++ char *name;
++ char *data;
++ int len;
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++ u16_t count;
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++};
++
++#endif /* __FSDATA_H__ */
+--- /dev/null
++++ b/net/uip-0.9/httpd.c
+@@ -0,0 +1,278 @@
++#include "uip.h"
++#include "httpd.h"
++#include "fs.h"
++#include "fsdata.h"
++#include <asm/addrspace.h>
++
++#define HTTP_NONE 0
++#define HTTP_FILE 1
++#define HTTP_FIRMWARE 2
++
++#define PRINT(x) printf("%s", x)
++#define PRINTLN(x) printf("%s\n", x)
++
++extern unsigned long do_http_tmp_address(void);
++
++struct httpd_state *hs;
++
++extern const struct fsdata_file file_index_html;
++extern const struct fsdata_file file_404_html;
++extern const struct fsdata_file file_flash_html;
++extern int httpd_upload_complete;
++extern unsigned char *httpd_upload_data;
++unsigned char *upload_data;
++extern ulong NetBootFileXferSize;
++int upload_running = 0;
++
++#define ISO_G 0x47
++#define ISO_E 0x45
++#define ISO_T 0x54
++#define ISO_P 0x50
++#define ISO_O 0x4f
++#define ISO_S 0x53
++#define ISO_T 0x54
++#define ISO_slash 0x2f
++#define ISO_c 0x63
++#define ISO_g 0x67
++#define ISO_i 0x69
++#define ISO_space 0x20
++#define ISO_nl 0x0a
++#define ISO_cr 0x0d
++#define ISO_a 0x61
++#define ISO_t 0x74
++#define ISO_hash 0x23
++#define ISO_period 0x2e
++
++static char eol[3] = { 0x0d, 0x0a, 0x00 };
++static char eol2[5] = { 0x0d, 0x0a, 0x0d, 0x0a, 0x00 };
++static char boundary[128];
++static int boundary_len = 0;
++
++/* we use this so that we can do without the ctype library */
++#define is_digit(c) ((c) >= '0' && (c) <= '9')
++static int atoi(const char *s)
++{
++ int i=0;
++
++ while (is_digit(*s))
++ i = i*10 + *(s++) - '0';
++ return i;
++}
++
++void
++httpd_init(void)
++{
++ fs_init();
++ uip_listen(HTONS(80));
++}
++
++void
++httpd_appcall(void)
++{
++ struct fs_file fsfile;
++ u8_t i;
++ switch(uip_conn->lport) {
++ case HTONS(80):
++ hs = (struct httpd_state *)(uip_conn->appstate);
++ if(uip_connected())
++ {
++ hs->state = HTTP_NONE;
++ hs->count = 0;
++ return;
++ } else if(uip_poll())
++ {
++ if(hs->count++ >= 1000) {
++ uip_abort();
++ }
++ return;
++ } else if(uip_newdata() && hs->state == HTTP_NONE)
++ {
++ if(uip_appdata[0] == ISO_G &&
++ uip_appdata[1] == ISO_E &&
++ uip_appdata[2] == ISO_T &&
++ uip_appdata[3] == ISO_space)
++ {
++ hs->state = HTTP_FILE;
++ }
++ if(uip_appdata[0] == ISO_P &&
++ uip_appdata[1] == ISO_O &&
++ uip_appdata[2] == ISO_S &&
++ uip_appdata[3] == ISO_T &&
++ uip_appdata[4] == ISO_space)
++ {
++ hs->state = HTTP_FIRMWARE;
++ }
++ if(hs->state == HTTP_NONE)
++ {
++ uip_abort();
++ return;
++ }
++ if(hs->state == HTTP_FILE)
++ {
++ for(i = 4; i < 40; ++i)
++ {
++ if(uip_appdata[i] == ISO_space ||
++ uip_appdata[i] == ISO_cr ||
++ uip_appdata[i] == ISO_nl)
++ {
++ uip_appdata[i] = 0;
++ break;
++ }
++ }
++
++ PRINT("request for file ");
++ PRINTLN(&uip_appdata[4]);
++ if(uip_appdata[4] == ISO_slash &&
++ uip_appdata[5] == 0)
++ {
++ fs_open(file_index_html.name, &fsfile);
++ } else {
++ if(!fs_open((const char *)&uip_appdata[4], &fsfile))
++ {
++ PRINTLN("couldn't open file");
++ fs_open(file_index_html.name, &fsfile);
++ }
++ }
++ hs->script = 0;
++ hs->state = HTTP_FILE;
++ hs->dataptr = fsfile.data;
++ hs->count = fsfile.len;
++ }
++ if(hs->state == HTTP_FIRMWARE)
++ {
++ unsigned char *start = (unsigned char*)uip_appdata;
++ char *clen = strstr(start, "Content-Length:");
++ int len = 0;
++ unsigned char *next, *end;
++ unsigned char *boundary_start;
++ int i;
++ uip_appdata[uip_len] = '\0';
++ if(clen)
++ {
++ clen += sizeof("Content-Length:");
++ next = strstr(clen, eol);
++ if(next)
++ {
++ len = atoi(clen);
++ next++;
++ printf("expecting %d bytes\n", len);
++ upload_data = httpd_upload_data = (unsigned char *)do_http_tmp_address();
++ printf("received data will be stored at 0x%08X\n", upload_data);
++ if(!upload_data)
++ {
++ printf("failed to allocate memory\n");
++ uip_close();
++ return;
++ }
++ } else {
++ uip_close();
++ return;
++ }
++ }
++ if(len < 4 * 1024)
++ {
++ uip_close();
++ return;
++ }
++ boundary_start = strstr(next, "---");
++ if(!boundary_start)
++ {
++ uip_close();
++ return;
++ }
++ end = strstr(boundary_start, eol);
++ if(!eol)
++ {
++ uip_close();
++ return;
++ }
++ boundary_len = end - boundary_start;
++ memcpy(boundary, boundary_start, boundary_len);
++ boundary[boundary_len] = 0;
++ next = strstr(boundary_start, "name=\"firmware\";");
++ if(!next)
++ {
++ uip_close();
++ return;
++ }
++ next = strstr(next, eol2);
++ if(!next)
++ {
++ printf("could not find start of data\n");
++ uip_close();
++ return;
++ }
++ next += 4;
++ hs->script = 0;
++ hs->state = HTTP_FIRMWARE;
++ hs->upload = uip_len - (next - start);
++ hs->upload_total = len - (int)(next - boundary_start);
++ hs->upload_total -= (strlen(boundary) + 6);
++ //printf("storing %d bytes at %p\n", (int)hs->upload, upload_data);
++ for(i = 0; i < hs->upload; i++)
++ upload_data[i] = next[i];
++ upload_data += (int)hs->upload;
++ printf("%d / %d\n", (int)hs->upload, hs->upload_total);
++ uip_slen = 0;
++ return;
++ }
++ }
++
++ if(hs->state == HTTP_FIRMWARE)
++ {
++ if(uip_newdata())
++ {
++ int i;
++ hs->count = 0;
++ uip_appdata[uip_len] = '\0';
++ hs->upload += uip_len;
++ //printf("storing %d bytes at %p\n", uip_len, upload_data);
++ printf("%d / %d\n", (int)hs->upload, hs->upload_total);
++ for(i = 0; i < uip_len; i++)
++ upload_data[i] = uip_appdata[i];
++ upload_data += uip_len;
++ uip_slen = 0;
++ if(hs->upload >= hs->upload_total)
++ {
++ upload_running = 1;
++ NetBootFileXferSize = hs->upload_total;
++ fs_open(file_flash_html.name, &fsfile);
++ hs->script = 0;
++ hs->state = HTTP_FILE;
++ hs->dataptr = fsfile.data;
++ hs->count = fsfile.len;
++ }
++ }
++ }
++ if(hs->state == HTTP_FILE)
++ {
++ if(uip_acked())
++ {
++ if(hs->count >= uip_conn->len)
++ {
++ hs->count -= uip_conn->len;
++ hs->dataptr += uip_conn->len;
++ } else {
++ hs->count = 0;
++ }
++ if(hs->count == 0)
++ {
++ if(upload_running)
++ {
++ int i;
++ httpd_upload_complete = 1;
++ // for(i = 0; i < hs->upload_total; i++)
++ // printf("%c", httpd_upload_data[i]);
++ }
++ uip_close();
++ }
++ }
++ uip_send(hs->dataptr, hs->count);
++ }
++ break;
++
++ default:
++ uip_abort();
++ break;
++ }
++}
+--- /dev/null
++++ b/net/uip-0.9/httpd.h
+@@ -0,0 +1,83 @@
++/**
++ * \addtogroup httpd
++ * @{
++ */
++
++/**
++ * \file
++ * HTTP server header file.
++ * \author Adam Dunkels <adam@dunkels.com>
++ */
++
++/*
++ * Copyright (c) 2001, Adam Dunkels.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: httpd.h,v 1.4.2.3 2003/10/06 22:56:44 adam Exp $
++ *
++ */
++
++#ifndef __HTTPD_H__
++#define __HTTPD_H__
++
++void httpd_init(void);
++void httpd_appcall(void);
++
++/* UIP_APPCALL: the name of the application function. This function
++ must return void and take no arguments (i.e., C type "void
++ appfunc(void)"). */
++#ifndef UIP_APPCALL
++#define UIP_APPCALL httpd_appcall
++#endif
++
++struct httpd_state {
++ u8_t state;
++ u16_t count;
++ char *dataptr;
++ char *script;
++ unsigned int upload;
++ unsigned int upload_total;
++};
++
++
++/* UIP_APPSTATE_SIZE: The size of the application-specific state
++ stored in the uip_conn structure. */
++#ifndef UIP_APPSTATE_SIZE
++#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state))
++#endif
++
++#define FS_STATISTICS 1
++
++extern struct httpd_state *hs;
++
++
++/* we copy the data to RAM+10MB */
++#define TMP_DATA 0x8A100000
++
++#endif /* __HTTPD_H__ */
+--- /dev/null
++++ b/net/uip-0.9/main.c
+@@ -0,0 +1,88 @@
++/*
++ * Copyright (c) 2001-2003, Adam Dunkels.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: main.c,v 1.10.2.1 2003/10/04 22:54:17 adam Exp $
++ *
++ */
++
++
++#include "uip.h"
++#include "uip_arp.h"
++#include "tapdev.h"
++#include "httpd.h"
++
++#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
++
++#ifndef NULL
++#define NULL (void *)0
++#endif /* NULL */
++
++/*-----------------------------------------------------------------------------------*/
++int
++main(void)
++{
++ u8_t i, arptimer;
++ tapdev_init();
++ uip_init();
++ httpd_init();
++ arptimer = 0;
++ while(1) {
++ uip_len = tapdev_read();
++ if(uip_len == 0) {
++ for(i = 0; i < UIP_CONNS; i++) {
++ uip_periodic(i);
++ if(uip_len > 0) {
++ uip_arp_out();
++ tapdev_send();
++ }
++ }
++
++ if(++arptimer == 20) {
++ uip_arp_timer();
++ arptimer = 0;
++ }
++ } else {
++ if(BUF->type == htons(UIP_ETHTYPE_IP)) {
++ uip_arp_ipin();
++ uip_input();
++ if(uip_len > 0) {
++ uip_arp_out();
++ tapdev_send();
++ }
++ } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {
++ uip_arp_arpin();
++ if(uip_len > 0) {
++ tapdev_send();
++ }
++ }
++ }
++ }
++ return 0;
++}
+--- /dev/null
++++ b/net/uip-0.9/tapdev.c
+@@ -0,0 +1,192 @@
++/*
++ * Copyright (c) 2001, Swedish Institute of Computer Science.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * 3. Neither the name of the Institute nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ * Author: Adam Dunkels <adam@sics.se>
++ *
++ * $Id: tapdev.c,v 1.7.2.1 2003/10/07 13:23:19 adam Exp $
++ */
++
++
++#include <fcntl.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <unistd.h>
++#include <string.h>
++#include <sys/ioctl.h>
++#include <sys/socket.h>
++#include <sys/types.h>
++#include <sys/time.h>
++#include <sys/uio.h>
++#include <sys/socket.h>
++
++#ifdef linux
++#include <sys/ioctl.h>
++#include <linux/if.h>
++#include <linux/if_tun.h>
++#define DEVTAP "/dev/net/tun"
++#else /* linux */
++#define DEVTAP "/dev/tap0"
++#endif /* linux */
++
++#include "uip.h"
++
++static int fd;
++
++static unsigned long lasttime;
++static struct timezone tz;
++
++/*-----------------------------------------------------------------------------------*/
++void
++tapdev_init(void)
++{
++ char buf[1024];
++
++ fd = open(DEVTAP, O_RDWR);
++ if(fd == -1) {
++ perror("tapdev: tapdev_init: open");
++ exit(1);
++ }
++
++#ifdef linux
++ {
++ struct ifreq ifr;
++ memset(&ifr, 0, sizeof(ifr));
++ ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
++ if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
++ perror(buf);
++ exit(1);
++ }
++ }
++#endif /* Linux */
++
++ snprintf(buf, sizeof(buf), "ifconfig tap0 inet %d.%d.%d.%d",
++ UIP_DRIPADDR0, UIP_DRIPADDR1, UIP_DRIPADDR2, UIP_DRIPADDR3);
++ system(buf);
++
++ lasttime = 0;
++}
++
++void dump_mem(int type, int len)
++{
++#if DUMP == 1
++ int i;
++ for(i = 0; i < len; i++)
++ printf("%c", uip_buf[i]);
++ if(type)
++ {
++ printf("\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01");
++ printf("\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01");
++ } else {
++ printf("\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02");
++ printf("\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02");
++ }
++ fflush(stdout);
++#endif
++}
++
++/*-----------------------------------------------------------------------------------*/
++unsigned int
++tapdev_read(void)
++{
++ fd_set fdset;
++ struct timeval tv, now;
++ int ret;
++
++ if(lasttime >= 500000) {
++ lasttime = 0;
++ return 0;
++ }
++
++ tv.tv_sec = 0;
++ tv.tv_usec = 500000 - lasttime;
++
++
++ FD_ZERO(&fdset);
++ FD_SET(fd, &fdset);
++
++ gettimeofday(&now, &tz);
++ ret = select(fd + 1, &fdset, NULL, NULL, &tv);
++ if(ret == 0) {
++ lasttime = 0;
++ return 0;
++ }
++ ret = read(fd, uip_buf, UIP_BUFSIZE);
++ if(ret == -1) {
++ perror("tap_dev: tapdev_read: read");
++ }
++ gettimeofday(&tv, &tz);
++ lasttime += (tv.tv_sec - now.tv_sec) * 1000000 + (tv.tv_usec - now.tv_usec);
++ dump_mem(0, ret);
++ return ret;
++}
++/*-----------------------------------------------------------------------------------*/
++void
++tapdev_send(void)
++{
++ int ret;
++ struct iovec iov[2];
++
++#ifdef linux
++ {
++ char tmpbuf[UIP_BUFSIZE];
++ int i;
++
++ for(i = 0; i < 40 + UIP_LLH_LEN; i++) {
++ tmpbuf[i] = uip_buf[i];
++ }
++
++ for(; i < uip_len; i++) {
++ tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN];
++ }
++
++ ret = write(fd, tmpbuf, uip_len);
++ }
++#else
++
++ if(uip_len < 40 + UIP_LLH_LEN) {
++ ret = write(fd, uip_buf, uip_len + UIP_LLH_LEN);
++ } else {
++ iov[0].iov_base = uip_buf;
++ iov[0].iov_len = 40 + UIP_LLH_LEN;
++ iov[1].iov_base = (char *)uip_appdata;
++ iov[1].iov_len = uip_len - (40 + UIP_LLH_LEN);
++
++ ret = writev(fd, iov, 2);
++ }
++#endif
++ dump_mem(1, ret);
++
++ if(ret == -1) {
++ perror("tap_dev: tapdev_send: writev");
++ exit(1);
++ }
++}
++/*-----------------------------------------------------------------------------------*/
+--- /dev/null
++++ b/net/uip-0.9/tapdev.h
+@@ -0,0 +1,42 @@
++/*
++ * Copyright (c) 2001, Adam Dunkels.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: tapdev.h,v 1.1.2.1 2003/10/04 22:54:17 adam Exp $
++ *
++ */
++
++#ifndef __TAPDEV_H__
++#define __TAPDEV_H__
++
++void tapdev_init(void);
++unsigned int tapdev_read(void);
++void tapdev_send(void);
++
++#endif /* __TAPDEV_H__ */
+--- /dev/null
++++ b/net/uip-0.9/uip.c
+@@ -0,0 +1,1503 @@
++/**
++ * \addtogroup uip
++ * @{
++ */
++
++/**
++ * \file
++ * The uIP TCP/IP stack code.
++ * \author Adam Dunkels <adam@dunkels.com>
++ */
++
++/*
++ * Copyright (c) 2001-2003, Adam Dunkels.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $
++ *
++ */
++
++/*
++This is a small implementation of the IP and TCP protocols (as well as
++some basic ICMP stuff). The implementation couples the IP, TCP and the
++application layers very tightly. To keep the size of the compiled code
++down, this code also features heavy usage of the goto statement.
++
++The principle is that we have a small buffer, called the uip_buf, in
++which the device driver puts an incoming packet. The TCP/IP stack
++parses the headers in the packet, and calls upon the application. If
++the remote host has sent data to the application, this data is present
++in the uip_buf and the application read the data from there. It is up
++to the application to put this data into a byte stream if needed. The
++application will not be fed with data that is out of sequence.
++
++If the application whishes to send data to the peer, it should put its
++data into the uip_buf, 40 bytes from the start of the buffer. The
++TCP/IP stack will calculate the checksums, and fill in the necessary
++header fields and finally send the packet back to the peer.
++*/
++
++#include "uip.h"
++#include "uipopt.h"
++#include "uip_arch.h"
++
++/*-----------------------------------------------------------------------------------*/
++/* Variable definitions. */
++
++
++/* The IP address of this host. If it is defined to be fixed (by setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set here. Otherwise, the address */
++#if UIP_FIXEDADDR > 0
++const unsigned short int uip_hostaddr[2] =
++ {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
++ HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
++const unsigned short int uip_arp_draddr[2] =
++ {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
++ HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
++const unsigned short int uip_arp_netmask[2] =
++ {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
++ HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
++#else
++unsigned short int uip_hostaddr[2];
++unsigned short int uip_arp_draddr[2], uip_arp_netmask[2];
++#endif /* UIP_FIXEDADDR */
++
++u8_t uip_buf[UIP_BUFSIZE+2]; /* The packet buffer that contains
++ incoming packets. */
++volatile u8_t *uip_appdata; /* The uip_appdata pointer points to
++ application data. */
++volatile u8_t *uip_sappdata; /* The uip_appdata pointer points to the
++ application data which is to be sent. */
++#if UIP_URGDATA > 0
++volatile u8_t *uip_urgdata; /* The uip_urgdata pointer points to
++ urgent data (out-of-band data), if
++ present. */
++volatile u8_t uip_urglen, uip_surglen;
++#endif /* UIP_URGDATA > 0 */
++
++volatile unsigned short int uip_len, uip_slen;
++ /* The uip_len is either 8 or 16 bits,
++ depending on the maximum packet
++ size. */
++
++volatile u8_t uip_flags; /* The uip_flags variable is used for
++ communication between the TCP/IP stack
++ and the application program. */
++struct uip_conn *uip_conn; /* uip_conn always points to the current
++ connection. */
++
++struct uip_conn uip_conns[UIP_CONNS];
++ /* The uip_conns array holds all TCP
++ connections. */
++unsigned short int uip_listenports[UIP_LISTENPORTS];
++ /* The uip_listenports list all currently
++ listning ports. */
++#if UIP_UDP
++struct uip_udp_conn *uip_udp_conn;
++struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
++#endif /* UIP_UDP */
++
++
++static unsigned short int ipid; /* Ths ipid variable is an increasing
++ number that is used for the IP ID
++ field. */
++
++static u8_t iss[4]; /* The iss variable is used for the TCP
++ initial sequence number. */
++
++#if UIP_ACTIVE_OPEN
++static unsigned short int lastport; /* Keeps track of the last port used for
++ a new connection. */
++#endif /* UIP_ACTIVE_OPEN */
++
++/* Temporary variables. */
++volatile u8_t uip_acc32[4];
++static u8_t c, opt;
++static unsigned short int tmp16;
++
++/* Structures and definitions. */
++#define TCP_FIN 0x01
++#define TCP_SYN 0x02
++#define TCP_RST 0x04
++#define TCP_PSH 0x08
++#define TCP_ACK 0x10
++#define TCP_URG 0x20
++#define TCP_CTL 0x3f
++
++#define ICMP_ECHO_REPLY 0
++#define ICMP_ECHO 8
++
++/* Macros. */
++#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
++#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0])
++#define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
++#define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
++
++#if UIP_STATISTICS == 1
++struct uip_stats uip_stat;
++#define UIP_STAT(s) s
++#else
++#define UIP_STAT(s)
++#endif /* UIP_STATISTICS == 1 */
++
++#if UIP_LOGGING == 1
++extern void puts(const char *s);
++#define UIP_LOG(m) puts(m)
++#else
++#define UIP_LOG(m)
++#endif /* UIP_LOGGING == 1 */
++
++/*-----------------------------------------------------------------------------------*/
++void
++uip_init(void)
++{
++ for(c = 0; c < UIP_LISTENPORTS; ++c) {
++ uip_listenports[c] = 0;
++ }
++ for(c = 0; c < UIP_CONNS; ++c) {
++ uip_conns[c].tcpstateflags = CLOSED;
++ }
++#if UIP_ACTIVE_OPEN
++ lastport = 1024;
++#endif /* UIP_ACTIVE_OPEN */
++
++#if UIP_UDP
++ for(c = 0; c < UIP_UDP_CONNS; ++c) {
++ uip_udp_conns[c].lport = 0;
++ }
++#endif /* UIP_UDP */
++
++
++ /* IPv4 initialization. */
++#if UIP_FIXEDADDR == 0
++ uip_hostaddr[0] = uip_hostaddr[1] = 0;
++#endif /* UIP_FIXEDADDR */
++
++}
++/*-----------------------------------------------------------------------------------*/
++#if UIP_ACTIVE_OPEN
++struct uip_conn *
++uip_connect(unsigned short int *ripaddr, unsigned short int rport)
++{
++ register struct uip_conn *conn, *cconn;
++
++ /* Find an unused local port. */
++ again:
++ ++lastport;
++
++ if(lastport >= 32000) {
++ lastport = 4096;
++ }
++
++ /* Check if this port is already in use, and if so try to find
++ another one. */
++ for(c = 0; c < UIP_CONNS; ++c) {
++ conn = &uip_conns[c];
++ if(conn->tcpstateflags != CLOSED &&
++ conn->lport == htons(lastport)) {
++ goto again;
++ }
++ }
++
++
++ conn = 0;
++ for(c = 0; c < UIP_CONNS; ++c) {
++ cconn = &uip_conns[c];
++ if(cconn->tcpstateflags == CLOSED) {
++ conn = cconn;
++ break;
++ }
++ if(cconn->tcpstateflags == TIME_WAIT) {
++ if(conn == 0 ||
++ cconn->timer > uip_conn->timer) {
++ conn = cconn;
++ }
++ }
++ }
++
++ if(conn == 0) {
++ return 0;
++ }
++
++ conn->tcpstateflags = SYN_SENT;
++
++ conn->snd_nxt[0] = iss[0];
++ conn->snd_nxt[1] = iss[1];
++ conn->snd_nxt[2] = iss[2];
++ conn->snd_nxt[3] = iss[3];
++
++ conn->initialmss = conn->mss = UIP_TCP_MSS;
++
++ conn->len = 1; /* TCP length of the SYN is one. */
++ conn->nrtx = 0;
++ conn->timer = 1; /* Send the SYN next time around. */
++ conn->rto = UIP_RTO;
++ conn->sa = 0;
++ conn->sv = 16;
++ conn->lport = htons(lastport);
++ conn->rport = rport;
++ conn->ripaddr[0] = ripaddr[0];
++ conn->ripaddr[1] = ripaddr[1];
++
++ return conn;
++}
++#endif /* UIP_ACTIVE_OPEN */
++/*-----------------------------------------------------------------------------------*/
++#if UIP_UDP
++struct uip_udp_conn *
++uip_udp_new(unsigned short int *ripaddr, unsigned short int rport)
++{
++ register struct uip_udp_conn *conn;
++
++ /* Find an unused local port. */
++ again:
++ ++lastport;
++
++ if(lastport >= 32000) {
++ lastport = 4096;
++ }
++
++ for(c = 0; c < UIP_UDP_CONNS; ++c) {
++ if(uip_udp_conns[c].lport == lastport) {
++ goto again;
++ }
++ }
++
++
++ conn = 0;
++ for(c = 0; c < UIP_UDP_CONNS; ++c) {
++ if(uip_udp_conns[c].lport == 0) {
++ conn = &uip_udp_conns[c];
++ break;
++ }
++ }
++
++ if(conn == 0) {
++ return 0;
++ }
++
++ conn->lport = HTONS(lastport);
++ conn->rport = HTONS(rport);
++ conn->ripaddr[0] = ripaddr[0];
++ conn->ripaddr[1] = ripaddr[1];
++
++ return conn;
++}
++#endif /* UIP_UDP */
++/*-----------------------------------------------------------------------------------*/
++void
++uip_unlisten(unsigned short int port)
++{
++ for(c = 0; c < UIP_LISTENPORTS; ++c) {
++ if(uip_listenports[c] == port) {
++ uip_listenports[c] = 0;
++ return;
++ }
++ }
++}
++/*-----------------------------------------------------------------------------------*/
++void
++uip_listen(unsigned short int port)
++{
++ for(c = 0; c < UIP_LISTENPORTS; ++c) {
++ if(uip_listenports[c] == 0) {
++ uip_listenports[c] = port;
++ return;
++ }
++ }
++}
++/*-----------------------------------------------------------------------------------*/
++/* XXX: IP fragment reassembly: not well-tested. */
++
++#if UIP_REASSEMBLY
++#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
++static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
++static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
++static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,
++ 0x0f, 0x07, 0x03, 0x01};
++static unsigned short int uip_reasslen;
++static u8_t uip_reassflags;
++#define UIP_REASS_FLAG_LASTFRAG 0x01
++static u8_t uip_reasstmr;
++
++#define IP_HLEN 20
++#define IP_MF 0x20
++
++static u8_t
++uip_reass(void)
++{
++ unsigned short int offset, len;
++ unsigned short int i;
++
++ /* If ip_reasstmr is zero, no packet is present in the buffer, so we
++ write the IP header of the fragment into the reassembly
++ buffer. The timer is updated with the maximum age. */
++ if(uip_reasstmr == 0) {
++ memcpy(uip_reassbuf, &BUF->vhl, IP_HLEN);
++ uip_reasstmr = UIP_REASS_MAXAGE;
++ uip_reassflags = 0;
++ /* Clear the bitmap. */
++ memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0);
++ }
++
++ /* Check if the incoming fragment matches the one currently present
++ in the reasembly buffer. If so, we proceed with copying the
++ fragment into the buffer. */
++ if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
++ BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
++ BUF->destipaddr[0] == FBUF->destipaddr[0] &&
++ BUF->destipaddr[1] == FBUF->destipaddr[1] &&
++ BUF->ipid[0] == FBUF->ipid[0] &&
++ BUF->ipid[1] == FBUF->ipid[1]) {
++
++ len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;
++ offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;
++
++ /* If the offset or the offset + fragment length overflows the
++ reassembly buffer, we discard the entire packet. */
++ if(offset > UIP_REASS_BUFSIZE ||
++ offset + len > UIP_REASS_BUFSIZE) {
++ uip_reasstmr = 0;
++ goto nullreturn;
++ }
++
++ /* Copy the fragment into the reassembly buffer, at the right
++ offset. */
++ memcpy(&uip_reassbuf[IP_HLEN + offset],
++ (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
++ len);
++
++ /* Update the bitmap. */
++ if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
++ /* If the two endpoints are in the same byte, we only update
++ that byte. */
++
++ uip_reassbitmap[offset / (8 * 8)] |=
++ bitmap_bits[(offset / 8 ) & 7] &
++ ~bitmap_bits[((offset + len) / 8 ) & 7];
++ } else {
++ /* If the two endpoints are in different bytes, we update the
++ bytes in the endpoints and fill the stuff inbetween with
++ 0xff. */
++ uip_reassbitmap[offset / (8 * 8)] |=
++ bitmap_bits[(offset / 8 ) & 7];
++ for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
++ uip_reassbitmap[i] = 0xff;
++ }
++ uip_reassbitmap[(offset + len) / (8 * 8)] |=
++ ~bitmap_bits[((offset + len) / 8 ) & 7];
++ }
++
++ /* If this fragment has the More Fragments flag set to zero, we
++ know that this is the last fragment, so we can calculate the
++ size of the entire packet. We also set the
++ IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
++ the final fragment. */
++
++ if((BUF->ipoffset[0] & IP_MF) == 0) {
++ uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
++ uip_reasslen = offset + len;
++ }
++
++ /* Finally, we check if we have a full packet in the buffer. We do
++ this by checking if we have the last fragment and if all bits
++ in the bitmap are set. */
++ if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
++ /* Check all bytes up to and including all but the last byte in
++ the bitmap. */
++ for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
++ if(uip_reassbitmap[i] != 0xff) {
++ goto nullreturn;
++ }
++ }
++ /* Check the last byte in the bitmap. It should contain just the
++ right amount of bits. */
++ if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
++ (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
++ goto nullreturn;
++ }
++
++ /* If we have come this far, we have a full packet in the
++ buffer, so we allocate a pbuf and copy the packet into it. We
++ also reset the timer. */
++ uip_reasstmr = 0;
++ memcpy(BUF, FBUF, uip_reasslen);
++
++ /* Pretend to be a "normal" (i.e., not fragmented) IP packet
++ from now on. */
++ BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
++ BUF->len[0] = uip_reasslen >> 8;
++ BUF->len[1] = uip_reasslen & 0xff;
++ BUF->ipchksum = 0;
++ BUF->ipchksum = ~(uip_ipchksum());
++
++ return uip_reasslen;
++ }
++ }
++
++ nullreturn:
++ return 0;
++}
++#endif /* UIP_REASSEMBL */
++/*-----------------------------------------------------------------------------------*/
++static void
++uip_add_rcv_nxt(unsigned short int n)
++{
++ uip_add32(uip_conn->rcv_nxt, n);
++ uip_conn->rcv_nxt[0] = uip_acc32[0];
++ uip_conn->rcv_nxt[1] = uip_acc32[1];
++ uip_conn->rcv_nxt[2] = uip_acc32[2];
++ uip_conn->rcv_nxt[3] = uip_acc32[3];
++}
++/*-----------------------------------------------------------------------------------*/
++void
++uip_process(u8_t flag)
++{
++ register struct uip_conn *uip_connr = uip_conn;
++
++ uip_appdata = &uip_buf[40 + UIP_LLH_LEN];
++
++
++ /* Check if we were invoked because of the perodic timer fireing. */
++ if(flag == UIP_TIMER) {
++#if UIP_REASSEMBLY
++ if(uip_reasstmr != 0) {
++ --uip_reasstmr;
++ }
++#endif /* UIP_REASSEMBLY */
++ /* Increase the initial sequence number. */
++ if(++iss[3] == 0) {
++ if(++iss[2] == 0) {
++ if(++iss[1] == 0) {
++ ++iss[0];
++ }
++ }
++ }
++ uip_len = 0;
++ if(uip_connr->tcpstateflags == TIME_WAIT ||
++ uip_connr->tcpstateflags == FIN_WAIT_2) {
++ ++(uip_connr->timer);
++ if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
++ uip_connr->tcpstateflags = CLOSED;
++ }
++ } else if(uip_connr->tcpstateflags != CLOSED) {
++ /* If the connection has outstanding data, we increase the
++ connection's timer and see if it has reached the RTO value
++ in which case we retransmit. */
++ if(uip_outstanding(uip_connr)) {
++ if(uip_connr->timer-- == 0) {
++ if(uip_connr->nrtx == UIP_MAXRTX ||
++ ((uip_connr->tcpstateflags == SYN_SENT ||
++ uip_connr->tcpstateflags == SYN_RCVD) &&
++ uip_connr->nrtx == UIP_MAXSYNRTX)) {
++ uip_connr->tcpstateflags = CLOSED;
++
++ /* We call UIP_APPCALL() with uip_flags set to
++ UIP_TIMEDOUT to inform the application that the
++ connection has timed out. */
++ uip_flags = UIP_TIMEDOUT;
++ UIP_APPCALL();
++
++ /* We also send a reset packet to the remote host. */
++ BUF->flags = TCP_RST | TCP_ACK;
++ goto tcp_send_nodata;
++ }
++
++ /* Exponential backoff. */
++ uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
++ 4:
++ uip_connr->nrtx);
++ ++(uip_connr->nrtx);
++
++ /* Ok, so we need to retransmit. We do this differently
++ depending on which state we are in. In ESTABLISHED, we
++ call upon the application so that it may prepare the
++ data for the retransmit. In SYN_RCVD, we resend the
++ SYNACK that we sent earlier and in LAST_ACK we have to
++ retransmit our FINACK. */
++ UIP_STAT(++uip_stat.tcp.rexmit);
++ switch(uip_connr->tcpstateflags & TS_MASK) {
++ case SYN_RCVD:
++ /* In the SYN_RCVD state, we should retransmit our
++ SYNACK. */
++ goto tcp_send_synack;
++
++#if UIP_ACTIVE_OPEN
++ case SYN_SENT:
++ /* In the SYN_SENT state, we retransmit out SYN. */
++ BUF->flags = 0;
++ goto tcp_send_syn;
++#endif /* UIP_ACTIVE_OPEN */
++
++ case ESTABLISHED:
++ /* In the ESTABLISHED state, we call upon the application
++ to do the actual retransmit after which we jump into
++ the code for sending out the packet (the apprexmit
++ label). */
++ uip_len = 0;
++ uip_slen = 0;
++ uip_flags = UIP_REXMIT;
++ UIP_APPCALL();
++ goto apprexmit;
++
++ case FIN_WAIT_1:
++ case CLOSING:
++ case LAST_ACK:
++ /* In all these states we should retransmit a FINACK. */
++ goto tcp_send_finack;
++
++ }
++ }
++ } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) {
++ /* If there was no need for a retransmission, we poll the
++ application for new data. */
++ uip_len = 0;
++ uip_slen = 0;
++ uip_flags = UIP_POLL;
++ UIP_APPCALL();
++ goto appsend;
++ }
++ }
++ goto drop;
++ }
++#if UIP_UDP
++ if(flag == UIP_UDP_TIMER) {
++ if(uip_udp_conn->lport != 0) {
++ uip_appdata = &uip_buf[UIP_LLH_LEN + 28];
++ uip_len = uip_slen = 0;
++ uip_flags = UIP_POLL;
++ UIP_UDP_APPCALL();
++ goto udp_send;
++ } else {
++ goto drop;
++ }
++ }
++#endif
++
++ /* This is where the input processing starts. */
++ UIP_STAT(++uip_stat.ip.recv);
++
++
++ /* Start of IPv4 input header processing code. */
++
++ /* Check validity of the IP header. */
++ if(BUF->vhl != 0x45) { /* IP version and header length. */
++ UIP_STAT(++uip_stat.ip.drop);
++ UIP_STAT(++uip_stat.ip.vhlerr);
++ UIP_LOG("ip: invalid version or header length.");
++ goto drop;
++ }
++
++ /* Check the size of the packet. If the size reported to us in
++ uip_len doesn't match the size reported in the IP header, there
++ has been a transmission error and we drop the packet. */
++
++ if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */
++ uip_len = (uip_len & 0xff) | (BUF->len[0] << 8);
++ }
++ if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */
++ uip_len = (uip_len & 0xff00) | BUF->len[1];
++ }
++
++ /* Check the fragment flag. */
++ if((BUF->ipoffset[0] & 0x3f) != 0 ||
++ BUF->ipoffset[1] != 0) {
++#if UIP_REASSEMBLY
++ uip_len = uip_reass();
++ if(uip_len == 0) {
++ goto drop;
++ }
++#else
++ UIP_STAT(++uip_stat.ip.drop);
++ UIP_STAT(++uip_stat.ip.fragerr);
++ UIP_LOG("ip: fragment dropped.");
++ goto drop;
++#endif /* UIP_REASSEMBLY */
++ }
++
++ /* If we are configured to use ping IP address configuration and
++ hasn't been assigned an IP address yet, we accept all ICMP
++ packets. */
++#if UIP_PINGADDRCONF
++ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
++ if(BUF->proto == UIP_PROTO_ICMP) {
++ UIP_LOG("ip: possible ping config packet received.");
++ goto icmp_input;
++ } else {
++ UIP_LOG("ip: packet dropped since no address assigned.");
++ goto drop;
++ }
++ }
++#endif /* UIP_PINGADDRCONF */
++
++ /* Check if the packet is destined for our IP address. */
++ if(BUF->destipaddr[0] != uip_hostaddr[0]) {
++ UIP_STAT(++uip_stat.ip.drop);
++ UIP_LOG("ip: packet not for us.");
++ goto drop;
++ }
++ if(BUF->destipaddr[1] != uip_hostaddr[1]) {
++ UIP_STAT(++uip_stat.ip.drop);
++ UIP_LOG("ip: packet not for us.");
++ goto drop;
++ }
++
++ if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
++ checksum. */
++ UIP_STAT(++uip_stat.ip.drop);
++ UIP_STAT(++uip_stat.ip.chkerr);
++ UIP_LOG("ip: bad checksum.");
++ goto drop;
++ }
++
++ if(BUF->proto == UIP_PROTO_TCP) /* Check for TCP packet. If so, jump
++ to the tcp_input label. */
++ goto tcp_input;
++
++#if UIP_UDP
++ if(BUF->proto == UIP_PROTO_UDP)
++ goto udp_input;
++#endif /* UIP_UDP */
++
++ if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from
++ here. */
++ UIP_STAT(++uip_stat.ip.drop);
++ UIP_STAT(++uip_stat.ip.protoerr);
++ UIP_LOG("ip: neither tcp nor icmp.");
++ goto drop;
++ }
++
++ //icmp_input:
++ UIP_STAT(++uip_stat.icmp.recv);
++
++ /* ICMP echo (i.e., ping) processing. This is simple, we only change
++ the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
++ checksum before we return the packet. */
++ if(ICMPBUF->type != ICMP_ECHO) {
++ UIP_STAT(++uip_stat.icmp.drop);
++ UIP_STAT(++uip_stat.icmp.typeerr);
++ UIP_LOG("icmp: not icmp echo.");
++ goto drop;
++ }
++
++ /* If we are configured to use ping IP address assignment, we use
++ the destination IP address of this ping packet and assign it to
++ ourself. */
++#if UIP_PINGADDRCONF
++ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
++ uip_hostaddr[0] = BUF->destipaddr[0];
++ uip_hostaddr[1] = BUF->destipaddr[1];
++ }
++#endif /* UIP_PINGADDRCONF */
++
++ ICMPBUF->type = ICMP_ECHO_REPLY;
++
++ if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
++ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
++ } else {
++ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
++ }
++
++ /* Swap IP addresses. */
++ tmp16 = BUF->destipaddr[0];
++ BUF->destipaddr[0] = BUF->srcipaddr[0];
++ BUF->srcipaddr[0] = tmp16;
++ tmp16 = BUF->destipaddr[1];
++ BUF->destipaddr[1] = BUF->srcipaddr[1];
++ BUF->srcipaddr[1] = tmp16;
++
++ UIP_STAT(++uip_stat.icmp.sent);
++ goto send;
++
++ /* End of IPv4 input header processing code. */
++
++
++#if UIP_UDP
++ /* UDP input processing. */
++ udp_input:
++ /* UDP processing is really just a hack. We don't do anything to the
++ UDP/IP headers, but let the UDP application do all the hard
++ work. If the application sets uip_slen, it has a packet to
++ send. */
++#if UIP_UDP_CHECKSUMS
++ if(uip_udpchksum() != 0xffff) {
++ UIP_STAT(++uip_stat.udp.drop);
++ UIP_STAT(++uip_stat.udp.chkerr);
++ UIP_LOG("udp: bad checksum.");
++ goto drop;
++ }
++#endif /* UIP_UDP_CHECKSUMS */
++
++ /* Demultiplex this UDP packet between the UDP "connections". */
++ for(uip_udp_conn = &uip_udp_conns[0];
++ uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
++ ++uip_udp_conn) {
++ if(uip_udp_conn->lport != 0 &&
++ UDPBUF->destport == uip_udp_conn->lport &&
++ (uip_udp_conn->rport == 0 ||
++ UDPBUF->srcport == uip_udp_conn->rport) &&
++ BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] &&
++ BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) {
++ goto udp_found;
++ }
++ }
++ goto drop;
++
++ udp_found:
++ uip_len = uip_len - 28;
++ uip_appdata = &uip_buf[UIP_LLH_LEN + 28];
++ uip_flags = UIP_NEWDATA;
++ uip_slen = 0;
++ UIP_UDP_APPCALL();
++ udp_send:
++ if(uip_slen == 0) {
++ goto drop;
++ }
++ uip_len = uip_slen + 28;
++
++ BUF->len[0] = (uip_len >> 8);
++ BUF->len[1] = (uip_len & 0xff);
++
++ BUF->proto = UIP_PROTO_UDP;
++
++ UDPBUF->udplen = HTONS(uip_slen + 8);
++ UDPBUF->udpchksum = 0;
++#if UIP_UDP_CHECKSUMS
++ /* Calculate UDP checksum. */
++ UDPBUF->udpchksum = ~(uip_udpchksum());
++ if(UDPBUF->udpchksum == 0) {
++ UDPBUF->udpchksum = 0xffff;
++ }
++#endif /* UIP_UDP_CHECKSUMS */
++
++ BUF->srcport = uip_udp_conn->lport;
++ BUF->destport = uip_udp_conn->rport;
++
++ BUF->srcipaddr[0] = uip_hostaddr[0];
++ BUF->srcipaddr[1] = uip_hostaddr[1];
++ BUF->destipaddr[0] = uip_udp_conn->ripaddr[0];
++ BUF->destipaddr[1] = uip_udp_conn->ripaddr[1];
++
++ uip_appdata = &uip_buf[UIP_LLH_LEN + 40];
++ goto ip_send_nolen;
++#endif /* UIP_UDP */
++
++ /* TCP input processing. */
++ tcp_input:
++ UIP_STAT(++uip_stat.tcp.recv);
++
++ /* Start of TCP input header processing code. */
++
++ if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP
++ checksum. */
++ UIP_STAT(++uip_stat.tcp.drop);
++ UIP_STAT(++uip_stat.tcp.chkerr);
++ UIP_LOG("tcp: bad checksum.");
++ goto drop;
++ }
++
++ /* Demultiplex this segment. */
++ /* First check any active connections. */
++ for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) {
++ if(uip_connr->tcpstateflags != CLOSED &&
++ BUF->destport == uip_connr->lport &&
++ BUF->srcport == uip_connr->rport &&
++ BUF->srcipaddr[0] == uip_connr->ripaddr[0] &&
++ BUF->srcipaddr[1] == uip_connr->ripaddr[1]) {
++ goto found;
++ }
++ }
++
++ /* If we didn't find and active connection that expected the packet,
++ either this packet is an old duplicate, or this is a SYN packet
++ destined for a connection in LISTEN. If the SYN flag isn't set,
++ it is an old packet and we send a RST. */
++ if((BUF->flags & TCP_CTL) != TCP_SYN)
++ goto reset;
++
++ tmp16 = BUF->destport;
++ /* Next, check listening connections. */
++ for(c = 0; c < UIP_LISTENPORTS; ++c) {
++ if(tmp16 == uip_listenports[c])
++ goto found_listen;
++ }
++
++ /* No matching connection found, so we send a RST packet. */
++ UIP_STAT(++uip_stat.tcp.synrst);
++ reset:
++
++ /* We do not send resets in response to resets. */
++ if(BUF->flags & TCP_RST)
++ goto drop;
++
++ UIP_STAT(++uip_stat.tcp.rst);
++
++ BUF->flags = TCP_RST | TCP_ACK;
++ uip_len = 40;
++ BUF->tcpoffset = 5 << 4;
++
++ /* Flip the seqno and ackno fields in the TCP header. */
++ c = BUF->seqno[3];
++ BUF->seqno[3] = BUF->ackno[3];
++ BUF->ackno[3] = c;
++
++ c = BUF->seqno[2];
++ BUF->seqno[2] = BUF->ackno[2];
++ BUF->ackno[2] = c;
++
++ c = BUF->seqno[1];
++ BUF->seqno[1] = BUF->ackno[1];
++ BUF->ackno[1] = c;
++
++ c = BUF->seqno[0];
++ BUF->seqno[0] = BUF->ackno[0];
++ BUF->ackno[0] = c;
++
++ /* We also have to increase the sequence number we are
++ acknowledging. If the least significant byte overflowed, we need
++ to propagate the carry to the other bytes as well. */
++ if(++BUF->ackno[3] == 0) {
++ if(++BUF->ackno[2] == 0) {
++ if(++BUF->ackno[1] == 0) {
++ ++BUF->ackno[0];
++ }
++ }
++ }
++
++ /* Swap port numbers. */
++ tmp16 = BUF->srcport;
++ BUF->srcport = BUF->destport;
++ BUF->destport = tmp16;
++
++ /* Swap IP addresses. */
++ tmp16 = BUF->destipaddr[0];
++ BUF->destipaddr[0] = BUF->srcipaddr[0];
++ BUF->srcipaddr[0] = tmp16;
++ tmp16 = BUF->destipaddr[1];
++ BUF->destipaddr[1] = BUF->srcipaddr[1];
++ BUF->srcipaddr[1] = tmp16;
++
++
++ /* And send out the RST packet! */
++ goto tcp_send_noconn;
++
++ /* This label will be jumped to if we matched the incoming packet
++ with a connection in LISTEN. In that case, we should create a new
++ connection and send a SYNACK in return. */
++ found_listen:
++ /* First we check if there are any connections avaliable. Unused
++ connections are kept in the same table as used connections, but
++ unused ones have the tcpstate set to CLOSED. Also, connections in
++ TIME_WAIT are kept track of and we'll use the oldest one if no
++ CLOSED connections are found. Thanks to Eddie C. Dost for a very
++ nice algorithm for the TIME_WAIT search. */
++ uip_connr = 0;
++ for(c = 0; c < UIP_CONNS; ++c) {
++ if(uip_conns[c].tcpstateflags == CLOSED) {
++ uip_connr = &uip_conns[c];
++ break;
++ }
++ if(uip_conns[c].tcpstateflags == TIME_WAIT) {
++ if(uip_connr == 0 ||
++ uip_conns[c].timer > uip_connr->timer) {
++ uip_connr = &uip_conns[c];
++ }
++ }
++ }
++
++ if(uip_connr == 0) {
++ /* All connections are used already, we drop packet and hope that
++ the remote end will retransmit the packet at a time when we
++ have more spare connections. */
++ UIP_STAT(++uip_stat.tcp.syndrop);
++ UIP_LOG("tcp: found no unused connections.");
++ goto drop;
++ }
++ uip_conn = uip_connr;
++
++ /* Fill in the necessary fields for the new connection. */
++ uip_connr->rto = uip_connr->timer = UIP_RTO;
++ uip_connr->sa = 0;
++ uip_connr->sv = 4;
++ uip_connr->nrtx = 0;
++ uip_connr->lport = BUF->destport;
++ uip_connr->rport = BUF->srcport;
++ uip_connr->ripaddr[0] = BUF->srcipaddr[0];
++ uip_connr->ripaddr[1] = BUF->srcipaddr[1];
++ uip_connr->tcpstateflags = SYN_RCVD;
++
++ uip_connr->snd_nxt[0] = iss[0];
++ uip_connr->snd_nxt[1] = iss[1];
++ uip_connr->snd_nxt[2] = iss[2];
++ uip_connr->snd_nxt[3] = iss[3];
++ uip_connr->len = 1;
++
++ /* rcv_nxt should be the seqno from the incoming packet + 1. */
++ uip_connr->rcv_nxt[3] = BUF->seqno[3];
++ uip_connr->rcv_nxt[2] = BUF->seqno[2];
++ uip_connr->rcv_nxt[1] = BUF->seqno[1];
++ uip_connr->rcv_nxt[0] = BUF->seqno[0];
++ uip_add_rcv_nxt(1);
++
++ /* Parse the TCP MSS option, if present. */
++ if((BUF->tcpoffset & 0xf0) > 0x50) {
++ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
++ opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
++ if(opt == 0x00) {
++ /* End of options. */
++ break;
++ } else if(opt == 0x01) {
++ ++c;
++ /* NOP option. */
++ } else if(opt == 0x02 &&
++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) {
++ /* An MSS option with the right option length. */
++ tmp16 = ((unsigned short int)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
++ (unsigned short int)uip_buf[40 + UIP_LLH_LEN + 3 + c];
++ uip_connr->initialmss = uip_connr->mss =
++ tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
++
++ /* And we are done processing options. */
++ break;
++ } else {
++ /* All other options have a length field, so that we easily
++ can skip past them. */
++ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
++ /* If the length field is zero, the options are malformed
++ and we don't process them further. */
++ break;
++ }
++ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
++ }
++ }
++ }
++
++ /* Our response will be a SYNACK. */
++#if UIP_ACTIVE_OPEN
++ tcp_send_synack:
++ BUF->flags = TCP_ACK;
++
++ tcp_send_syn:
++ BUF->flags |= TCP_SYN;
++#else /* UIP_ACTIVE_OPEN */
++ tcp_send_synack:
++ BUF->flags = TCP_SYN | TCP_ACK;
++#endif /* UIP_ACTIVE_OPEN */
++
++ /* We send out the TCP Maximum Segment Size option with our
++ SYNACK. */
++ BUF->optdata[0] = 2;
++ BUF->optdata[1] = 4;
++ BUF->optdata[2] = (UIP_TCP_MSS) / 256;
++ BUF->optdata[3] = (UIP_TCP_MSS) & 255;
++ uip_len = 44;
++ BUF->tcpoffset = 6 << 4;
++ goto tcp_send;
++
++ /* This label will be jumped to if we found an active connection. */
++ found:
++ uip_conn = uip_connr;
++ uip_flags = 0;
++
++ /* We do a very naive form of TCP reset processing; we just accept
++ any RST and kill our connection. We should in fact check if the
++ sequence number of this reset is wihtin our advertised window
++ before we accept the reset. */
++ if(BUF->flags & TCP_RST) {
++ uip_connr->tcpstateflags = CLOSED;
++ UIP_LOG("tcp: got reset, aborting connection.");
++ uip_flags = UIP_ABORT;
++ UIP_APPCALL();
++ goto drop;
++ }
++ /* Calculated the length of the data, if the application has sent
++ any data to us. */
++ c = (BUF->tcpoffset >> 4) << 2;
++ /* uip_len will contain the length of the actual TCP data. This is
++ calculated by subtracing the length of the TCP header (in
++ c) and the length of the IP header (20 bytes). */
++ uip_len = uip_len - c - 20;
++
++ /* First, check if the sequence number of the incoming packet is
++ what we're expecting next. If not, we send out an ACK with the
++ correct numbers in. */
++ if(uip_len > 0 &&
++ (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
++ BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
++ BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
++ BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
++ goto tcp_send_ack;
++ }
++
++ /* Next, check if the incoming segment acknowledges any outstanding
++ data. If so, we update the sequence number, reset the length of
++ the outstanding data, calculate RTT estimations, and reset the
++ retransmission timer. */
++ if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
++ uip_add32(uip_connr->snd_nxt, uip_connr->len);
++ if(BUF->ackno[0] == uip_acc32[0] &&
++ BUF->ackno[1] == uip_acc32[1] &&
++ BUF->ackno[2] == uip_acc32[2] &&
++ BUF->ackno[3] == uip_acc32[3]) {
++ /* Update sequence number. */
++ uip_connr->snd_nxt[0] = uip_acc32[0];
++ uip_connr->snd_nxt[1] = uip_acc32[1];
++ uip_connr->snd_nxt[2] = uip_acc32[2];
++ uip_connr->snd_nxt[3] = uip_acc32[3];
++
++
++ /* Do RTT estimation, unless we have done retransmissions. */
++ if(uip_connr->nrtx == 0) {
++ signed char m;
++ m = uip_connr->rto - uip_connr->timer;
++ /* This is taken directly from VJs original code in his paper */
++ m = m - (uip_connr->sa >> 3);
++ uip_connr->sa += m;
++ if(m < 0) {
++ m = -m;
++ }
++ m = m - (uip_connr->sv >> 2);
++ uip_connr->sv += m;
++ uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
++
++ }
++ /* Set the acknowledged flag. */
++ uip_flags = UIP_ACKDATA;
++ /* Reset the retransmission timer. */
++ uip_connr->timer = uip_connr->rto;
++ }
++
++ }
++
++ /* Do different things depending on in what state the connection is. */
++ switch(uip_connr->tcpstateflags & TS_MASK) {
++ /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
++ implemented, since we force the application to close when the
++ peer sends a FIN (hence the application goes directly from
++ ESTABLISHED to LAST_ACK). */
++ case SYN_RCVD:
++ /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
++ we are waiting for an ACK that acknowledges the data we sent
++ out the last time. Therefore, we want to have the UIP_ACKDATA
++ flag set. If so, we enter the ESTABLISHED state. */
++ if(uip_flags & UIP_ACKDATA) {
++ uip_connr->tcpstateflags = ESTABLISHED;
++ uip_flags = UIP_CONNECTED;
++ uip_connr->len = 0;
++ if(uip_len > 0) {
++ uip_flags |= UIP_NEWDATA;
++ uip_add_rcv_nxt(uip_len);
++ }
++ uip_slen = 0;
++ UIP_APPCALL();
++ goto appsend;
++ }
++ goto drop;
++#if UIP_ACTIVE_OPEN
++ case SYN_SENT:
++ /* In SYN_SENT, we wait for a SYNACK that is sent in response to
++ our SYN. The rcv_nxt is set to sequence number in the SYNACK
++ plus one, and we send an ACK. We move into the ESTABLISHED
++ state. */
++ if((uip_flags & UIP_ACKDATA) &&
++ BUF->flags == (TCP_SYN | TCP_ACK)) {
++
++ /* Parse the TCP MSS option, if present. */
++ if((BUF->tcpoffset & 0xf0) > 0x50) {
++ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
++ opt = uip_buf[40 + UIP_LLH_LEN + c];
++ if(opt == 0x00) {
++ /* End of options. */
++ break;
++ } else if(opt == 0x01) {
++ ++c;
++ /* NOP option. */
++ } else if(opt == 0x02 &&
++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) {
++ /* An MSS option with the right option length. */
++ tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
++ uip_connr->initialmss =
++ uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
++
++ /* And we are done processing options. */
++ break;
++ } else {
++ /* All other options have a length field, so that we easily
++ can skip past them. */
++ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
++ /* If the length field is zero, the options are malformed
++ and we don't process them further. */
++ break;
++ }
++ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
++ }
++ }
++ }
++ uip_connr->tcpstateflags = ESTABLISHED;
++ uip_connr->rcv_nxt[0] = BUF->seqno[0];
++ uip_connr->rcv_nxt[1] = BUF->seqno[1];
++ uip_connr->rcv_nxt[2] = BUF->seqno[2];
++ uip_connr->rcv_nxt[3] = BUF->seqno[3];
++ uip_add_rcv_nxt(1);
++ uip_flags = UIP_CONNECTED | UIP_NEWDATA;
++ uip_connr->len = 0;
++ uip_len = 0;
++ uip_slen = 0;
++ UIP_APPCALL();
++ goto appsend;
++ }
++ goto reset;
++#endif /* UIP_ACTIVE_OPEN */
++
++ case ESTABLISHED:
++ /* In the ESTABLISHED state, we call upon the application to feed
++ data into the uip_buf. If the UIP_ACKDATA flag is set, the
++ application should put new data into the buffer, otherwise we are
++ retransmitting an old segment, and the application should put that
++ data into the buffer.
++
++ If the incoming packet is a FIN, we should close the connection on
++ this side as well, and we send out a FIN and enter the LAST_ACK
++ state. We require that there is no outstanding data; otherwise the
++ sequence numbers will be screwed up. */
++
++ if(BUF->flags & TCP_FIN) {
++ if(uip_outstanding(uip_connr)) {
++ goto drop;
++ }
++ uip_add_rcv_nxt(1 + uip_len);
++ uip_flags = UIP_CLOSE;
++ if(uip_len > 0) {
++ uip_flags |= UIP_NEWDATA;
++ }
++ UIP_APPCALL();
++ uip_connr->len = 1;
++ uip_connr->tcpstateflags = LAST_ACK;
++ uip_connr->nrtx = 0;
++ tcp_send_finack:
++ BUF->flags = TCP_FIN | TCP_ACK;
++ goto tcp_send_nodata;
++ }
++
++ /* Check the URG flag. If this is set, the segment carries urgent
++ data that we must pass to the application. */
++ if(BUF->flags & TCP_URG) {
++#if UIP_URGDATA > 0
++ uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
++ if(uip_urglen > uip_len) {
++ /* There is more urgent data in the next segment to come. */
++ uip_urglen = uip_len;
++ }
++ uip_add_rcv_nxt(uip_urglen);
++ uip_len -= uip_urglen;
++ uip_urgdata = uip_appdata;
++ uip_appdata += uip_urglen;
++ } else {
++ uip_urglen = 0;
++#endif /* UIP_URGDATA > 0 */
++ uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1];
++ uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];
++ }
++
++
++ /* If uip_len > 0 we have TCP data in the packet, and we flag this
++ by setting the UIP_NEWDATA flag and update the sequence number
++ we acknowledge. If the application has stopped the dataflow
++ using uip_stop(), we must not accept any data packets from the
++ remote host. */
++ if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
++ uip_flags |= UIP_NEWDATA;
++ uip_add_rcv_nxt(uip_len);
++ }
++
++ /* Check if the available buffer space advertised by the other end
++ is smaller than the initial MSS for this connection. If so, we
++ set the current MSS to the window size to ensure that the
++ application does not send more data than the other end can
++ handle.
++
++ If the remote host advertises a zero window, we set the MSS to
++ the initial MSS so that the application will send an entire MSS
++ of data. This data will not be acknowledged by the receiver,
++ and the application will retransmit it. This is called the
++ "persistent timer" and uses the retransmission mechanim.
++ */
++ tmp16 = ((unsigned short int)BUF->wnd[0] << 8) + (unsigned short int)BUF->wnd[1];
++ if(tmp16 > uip_connr->initialmss ||
++ tmp16 == 0) {
++ tmp16 = uip_connr->initialmss;
++ }
++ uip_connr->mss = tmp16;
++
++ /* If this packet constitutes an ACK for outstanding data (flagged
++ by the UIP_ACKDATA flag, we should call the application since it
++ might want to send more data. If the incoming packet had data
++ from the peer (as flagged by the UIP_NEWDATA flag), the
++ application must also be notified.
++
++ When the application is called, the global variable uip_len
++ contains the length of the incoming data. The application can
++ access the incoming data through the global pointer
++ uip_appdata, which usually points 40 bytes into the uip_buf
++ array.
++
++ If the application wishes to send any data, this data should be
++ put into the uip_appdata and the length of the data should be
++ put into uip_len. If the application don't have any data to
++ send, uip_len must be set to 0. */
++ if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {
++ uip_slen = 0;
++ UIP_APPCALL();
++
++ appsend:
++
++ if(uip_flags & UIP_ABORT) {
++ uip_slen = 0;
++ uip_connr->tcpstateflags = CLOSED;
++ BUF->flags = TCP_RST | TCP_ACK;
++ goto tcp_send_nodata;
++ }
++
++ if(uip_flags & UIP_CLOSE) {
++ uip_slen = 0;
++ uip_connr->len = 1;
++ uip_connr->tcpstateflags = FIN_WAIT_1;
++ uip_connr->nrtx = 0;
++ BUF->flags = TCP_FIN | TCP_ACK;
++ goto tcp_send_nodata;
++ }
++
++ /* If uip_slen > 0, the application has data to be sent. */
++ if(uip_slen > 0) {
++
++ /* If the connection has acknowledged data, the contents of
++ the ->len variable should be discarded. */
++ if((uip_flags & UIP_ACKDATA) != 0) {
++ uip_connr->len = 0;
++ }
++
++ /* If the ->len variable is non-zero the connection has
++ already data in transit and cannot send anymore right
++ now. */
++ if(uip_connr->len == 0) {
++
++ /* The application cannot send more than what is allowed by
++ the mss (the minumum of the MSS and the available
++ window). */
++ if(uip_slen > uip_connr->mss) {
++ uip_slen = uip_connr->mss;
++ }
++
++ /* Remember how much data we send out now so that we know
++ when everything has been acknowledged. */
++ uip_connr->len = uip_slen;
++ } else {
++
++ /* If the application already had unacknowledged data, we
++ make sure that the application does not send (i.e.,
++ retransmit) out more than it previously sent out. */
++ uip_slen = uip_connr->len;
++ }
++ } else {
++ uip_connr->len = 0;
++ }
++ uip_connr->nrtx = 0;
++ apprexmit:
++ uip_appdata = uip_sappdata;
++
++ /* If the application has data to be sent, or if the incoming
++ packet had new data in it, we must send out a packet. */
++ if(uip_slen > 0 && uip_connr->len > 0) {
++ /* Add the length of the IP and TCP headers. */
++ uip_len = uip_connr->len + UIP_TCPIP_HLEN;
++ /* We always set the ACK flag in response packets. */
++ BUF->flags = TCP_ACK | TCP_PSH;
++ /* Send the packet. */
++ goto tcp_send_noopts;
++ }
++ /* If there is no data to send, just send out a pure ACK if
++ there is newdata. */
++ if(uip_flags & UIP_NEWDATA) {
++ uip_len = UIP_TCPIP_HLEN;
++ BUF->flags = TCP_ACK;
++ goto tcp_send_noopts;
++ }
++ }
++ goto drop;
++ case LAST_ACK:
++ /* We can close this connection if the peer has acknowledged our
++ FIN. This is indicated by the UIP_ACKDATA flag. */
++ if(uip_flags & UIP_ACKDATA) {
++ uip_connr->tcpstateflags = CLOSED;
++ uip_flags = UIP_CLOSE;
++ UIP_APPCALL();
++ }
++ break;
++
++ case FIN_WAIT_1:
++ /* The application has closed the connection, but the remote host
++ hasn't closed its end yet. Thus we do nothing but wait for a
++ FIN from the other side. */
++ if(uip_len > 0) {
++ uip_add_rcv_nxt(uip_len);
++ }
++ if(BUF->flags & TCP_FIN) {
++ if(uip_flags & UIP_ACKDATA) {
++ uip_connr->tcpstateflags = TIME_WAIT;
++ uip_connr->timer = 0;
++ uip_connr->len = 0;
++ } else {
++ uip_connr->tcpstateflags = CLOSING;
++ }
++ uip_add_rcv_nxt(1);
++ uip_flags = UIP_CLOSE;
++ UIP_APPCALL();
++ goto tcp_send_ack;
++ } else if(uip_flags & UIP_ACKDATA) {
++ uip_connr->tcpstateflags = FIN_WAIT_2;
++ uip_connr->len = 0;
++ goto drop;
++ }
++ if(uip_len > 0) {
++ goto tcp_send_ack;
++ }
++ goto drop;
++
++ case FIN_WAIT_2:
++ if(uip_len > 0) {
++ uip_add_rcv_nxt(uip_len);
++ }
++ if(BUF->flags & TCP_FIN) {
++ uip_connr->tcpstateflags = TIME_WAIT;
++ uip_connr->timer = 0;
++ uip_add_rcv_nxt(1);
++ uip_flags = UIP_CLOSE;
++ UIP_APPCALL();
++ goto tcp_send_ack;
++ }
++ if(uip_len > 0) {
++ goto tcp_send_ack;
++ }
++ goto drop;
++
++ case TIME_WAIT:
++ goto tcp_send_ack;
++
++ case CLOSING:
++ if(uip_flags & UIP_ACKDATA) {
++ uip_connr->tcpstateflags = TIME_WAIT;
++ uip_connr->timer = 0;
++ }
++ }
++ goto drop;
++
++
++ /* We jump here when we are ready to send the packet, and just want
++ to set the appropriate TCP sequence numbers in the TCP header. */
++ tcp_send_ack:
++ BUF->flags = TCP_ACK;
++ tcp_send_nodata:
++ uip_len = 40;
++ tcp_send_noopts:
++ BUF->tcpoffset = 5 << 4;
++ tcp_send:
++ /* We're done with the input processing. We are now ready to send a
++ reply. Our job is to fill in all the fields of the TCP and IP
++ headers before calculating the checksum and finally send the
++ packet. */
++ BUF->ackno[0] = uip_connr->rcv_nxt[0];
++ BUF->ackno[1] = uip_connr->rcv_nxt[1];
++ BUF->ackno[2] = uip_connr->rcv_nxt[2];
++ BUF->ackno[3] = uip_connr->rcv_nxt[3];
++
++ BUF->seqno[0] = uip_connr->snd_nxt[0];
++ BUF->seqno[1] = uip_connr->snd_nxt[1];
++ BUF->seqno[2] = uip_connr->snd_nxt[2];
++ BUF->seqno[3] = uip_connr->snd_nxt[3];
++
++ BUF->proto = UIP_PROTO_TCP;
++
++ BUF->srcport = uip_connr->lport;
++ BUF->destport = uip_connr->rport;
++
++ BUF->srcipaddr[0] = uip_hostaddr[0];
++ BUF->srcipaddr[1] = uip_hostaddr[1];
++ BUF->destipaddr[0] = uip_connr->ripaddr[0];
++ BUF->destipaddr[1] = uip_connr->ripaddr[1];
++
++
++ if(uip_connr->tcpstateflags & UIP_STOPPED) {
++ /* If the connection has issued uip_stop(), we advertise a zero
++ window so that the remote host will stop sending data. */
++ BUF->wnd[0] = BUF->wnd[1] = 0;
++ } else {
++ BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
++ BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
++ }
++
++ tcp_send_noconn:
++
++ BUF->len[0] = (uip_len >> 8);
++ BUF->len[1] = (uip_len & 0xff);
++
++ /* Calculate TCP checksum. */
++ BUF->tcpchksum = 0;
++ BUF->tcpchksum = ~(uip_tcpchksum());
++
++ //ip_send_nolen:
++
++ BUF->vhl = 0x45;
++ BUF->tos = 0;
++ BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
++ BUF->ttl = UIP_TTL;
++ ++ipid;
++ BUF->ipid[0] = ipid >> 8;
++ BUF->ipid[1] = ipid & 0xff;
++
++ /* Calculate IP checksum. */
++ BUF->ipchksum = 0;
++ BUF->ipchksum = ~(uip_ipchksum());
++
++ UIP_STAT(++uip_stat.tcp.sent);
++ send:
++ UIP_STAT(++uip_stat.ip.sent);
++ /* Return and let the caller do the actual transmission. */
++ return;
++ drop:
++ uip_len = 0;
++ return;
++}
++/*-----------------------------------------------------------------------------------*/
++/*unsigned short int
++htons(unsigned short int val)
++{
++ return HTONS(val);
++}*/
++/*-----------------------------------------------------------------------------------*/
++/** @} */
+--- /dev/null
++++ b/net/uip-0.9/uip.h
+@@ -0,0 +1,1066 @@
++/**
++ * \addtogroup uip
++ * @{
++ */
++
++/**
++ * \file
++ * Header file for the uIP TCP/IP stack.
++ * \author Adam Dunkels <adam@dunkels.com>
++ *
++ * The uIP TCP/IP stack header file contains definitions for a number
++ * of C macros that are used by uIP programs as well as internal uIP
++ * structures, TCP/IP header structures and function declarations.
++ *
++ */
++
++
++/*
++ * Copyright (c) 2001-2003, Adam Dunkels.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uip.h,v 1.36.2.7 2003/10/07 13:47:51 adam Exp $
++ *
++ */
++
++#ifndef __UIP_H__
++#define __UIP_H__
++#include <linux/types.h>
++#include <linux/string.h>
++#include <linux/ctype.h>
++#include <malloc.h>
++#include <common.h>
++
++
++#include "uipopt.h"
++
++/*-----------------------------------------------------------------------------------*/
++/* First, the functions that should be called from the
++ * system. Initialization, the periodic timer and incoming packets are
++ * handled by the following three functions.
++ */
++
++/**
++ * \defgroup uipconffunc uIP configuration functions
++ * @{
++ *
++ * The uIP configuration functions are used for setting run-time
++ * parameters in uIP such as IP addresses.
++ */
++
++/**
++ * Set the IP address of this host.
++ *
++ * The IP address is represented as a 4-byte array where the first
++ * octet of the IP address is put in the first member of the 4-byte
++ * array.
++ *
++ * \param addr A pointer to a 4-byte representation of the IP address.
++ *
++ * \hideinitializer
++ */
++#define uip_sethostaddr(addr) do { uip_hostaddr[0] = addr[0]; \
++ uip_hostaddr[1] = addr[1]; } while(0)
++
++/**
++ * Get the IP address of this host.
++ *
++ * The IP address is represented as a 4-byte array where the first
++ * octet of the IP address is put in the first member of the 4-byte
++ * array.
++ *
++ * \param addr A pointer to a 4-byte array that will be filled in with
++ * the currently configured IP address.
++ *
++ * \hideinitializer
++ */
++#define uip_gethostaddr(addr) do { addr[0] = uip_hostaddr[0]; \
++ addr[1] = uip_hostaddr[1]; } while(0)
++
++/** @} */
++
++/**
++ * \defgroup uipinit uIP initialization functions
++ * @{
++ *
++ * The uIP initialization functions are used for booting uIP.
++ */
++
++/**
++ * uIP initialization function.
++ *
++ * This function should be called at boot up to initilize the uIP
++ * TCP/IP stack.
++ */
++void uip_init(void);
++
++/** @} */
++
++/**
++ * \defgroup uipdevfunc uIP device driver functions
++ * @{
++ *
++ * These functions are used by a network device driver for interacting
++ * with uIP.
++ */
++
++/**
++ * Process an incoming packet.
++ *
++ * This function should be called when the device driver has received
++ * a packet from the network. The packet from the device driver must
++ * be present in the uip_buf buffer, and the length of the packet
++ * should be placed in the uip_len variable.
++ *
++ * When the function returns, there may be an outbound packet placed
++ * in the uip_buf packet buffer. If so, the uip_len variable is set to
++ * the length of the packet. If no packet is to be sent out, the
++ * uip_len variable is set to 0.
++ *
++ * The usual way of calling the function is presented by the source
++ * code below.
++ \code
++ uip_len = devicedriver_poll();
++ if(uip_len > 0) {
++ uip_input();
++ if(uip_len > 0) {
++ devicedriver_send();
++ }
++ }
++ \endcode
++ *
++ * \note If you are writing a uIP device driver that needs ARP
++ * (Address Resolution Protocol), e.g., when running uIP over
++ * Ethernet, you will need to call the uIP ARP code before calling
++ * this function:
++ \code
++ #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
++ uip_len = ethernet_devicedrver_poll();
++ if(uip_len > 0) {
++ if(BUF->type == HTONS(UIP_ETHTYPE_IP)) {
++ uip_arp_ipin();
++ uip_input();
++ if(uip_len > 0) {
++ uip_arp_out();
++ ethernet_devicedriver_send();
++ }
++ } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) {
++ uip_arp_arpin();
++ if(uip_len > 0) {
++ ethernet_devicedriver_send();
++ }
++ }
++ \endcode
++ *
++ * \hideinitializer
++ */
++#define uip_input() uip_process(UIP_DATA)
++
++/**
++ * Periodic processing for a connection identified by its number.
++ *
++ * This function does the necessary periodic processing (timers,
++ * polling) for a uIP TCP conneciton, and should be called when the
++ * periodic uIP timer goes off. It should be called for every
++ * connection, regardless of whether they are open of closed.
++ *
++ * When the function returns, it may have an outbound packet waiting
++ * for service in the uIP packet buffer, and if so the uip_len
++ * variable is set to a value larger than zero. The device driver
++ * should be called to send out the packet.
++ *
++ * The ususal way of calling the function is through a for() loop like
++ * this:
++ \code
++ for(i = 0; i < UIP_CONNS; ++i) {
++ uip_periodic(i);
++ if(uip_len > 0) {
++ devicedriver_send();
++ }
++ }
++ \endcode
++ *
++ * \note If you are writing a uIP device driver that needs ARP
++ * (Address Resolution Protocol), e.g., when running uIP over
++ * Ethernet, you will need to call the uip_arp_out() function before
++ * calling the device driver:
++ \code
++ for(i = 0; i < UIP_CONNS; ++i) {
++ uip_periodic(i);
++ if(uip_len > 0) {
++ uip_arp_out();
++ ethernet_devicedriver_send();
++ }
++ }
++ \endcode
++ *
++ * \param conn The number of the connection which is to be periodically polled.
++ *
++ * \hideinitializer
++ */
++#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \
++ uip_process(UIP_TIMER); } while (0)
++
++/**
++ * Periodic processing for a connection identified by a pointer to its structure.
++ *
++ * Same as uip_periodic() but takes a pointer to the actual uip_conn
++ * struct instead of an integer as its argument. This function can be
++ * used to force periodic processing of a specific connection.
++ *
++ * \param conn A pointer to the uip_conn struct for the connection to
++ * be processed.
++ *
++ * \hideinitializer
++ */
++#define uip_periodic_conn(conn) do { uip_conn = conn; \
++ uip_process(UIP_TIMER); } while (0)
++
++#if UIP_UDP
++/**
++ * Periodic processing for a UDP connection identified by its number.
++ *
++ * This function is essentially the same as uip_prerioic(), but for
++ * UDP connections. It is called in a similar fashion as the
++ * uip_periodic() function:
++ \code
++ for(i = 0; i < UIP_UDP_CONNS; i++) {
++ uip_udp_periodic(i);
++ if(uip_len > 0) {
++ devicedriver_send();
++ }
++ }
++ \endcode
++ *
++ * \note As for the uip_periodic() function, special care has to be
++ * taken when using uIP together with ARP and Ethernet:
++ \code
++ for(i = 0; i < UIP_UDP_CONNS; i++) {
++ uip_udp_periodic(i);
++ if(uip_len > 0) {
++ uip_arp_out();
++ ethernet_devicedriver_send();
++ }
++ }
++ \endcode
++ *
++ * \param conn The number of the UDP connection to be processed.
++ *
++ * \hideinitializer
++ */
++#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \
++ uip_process(UIP_UDP_TIMER); } while (0)
++
++/**
++ * Periodic processing for a UDP connection identified by a pointer to
++ * its structure.
++ *
++ * Same as uip_udp_periodic() but takes a pointer to the actual
++ * uip_conn struct instead of an integer as its argument. This
++ * function can be used to force periodic processing of a specific
++ * connection.
++ *
++ * \param conn A pointer to the uip_udp_conn struct for the connection
++ * to be processed.
++ *
++ * \hideinitializer
++ */
++#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \
++ uip_process(UIP_UDP_TIMER); } while (0)
++
++
++#endif /* UIP_UDP */
++
++/**
++ * The uIP packet buffer.
++ *
++ * The uip_buf array is used to hold incoming and outgoing
++ * packets. The device driver should place incoming data into this
++ * buffer. When sending data, the device driver should read the link
++ * level headers and the TCP/IP headers from this buffer. The size of
++ * the link level headers is configured by the UIP_LLH_LEN define.
++ *
++ * \note The application data need not be placed in this buffer, so
++ * the device driver must read it from the place pointed to by the
++ * uip_appdata pointer as illustrated by the following example:
++ \code
++ void
++ devicedriver_send(void)
++ {
++ hwsend(&uip_buf[0], UIP_LLH_LEN);
++ hwsend(&uip_buf[UIP_LLH_LEN], 40);
++ hwsend(uip_appdata, uip_len - 40 - UIP_LLH_LEN);
++ }
++ \endcode
++ */
++extern u8_t uip_buf[UIP_BUFSIZE+2];
++
++/** @} */
++
++/*-----------------------------------------------------------------------------------*/
++/* Functions that are used by the uIP application program. Opening and
++ * closing connections, sending and receiving data, etc. is all
++ * handled by the functions below.
++*/
++/**
++ * \defgroup uipappfunc uIP application functions
++ * @{
++ *
++ * Functions used by an application running of top of uIP.
++ */
++
++/**
++ * Start listening to the specified port.
++ *
++ * \note Since this function expects the port number in network byte
++ * order, a conversion using HTONS() or htons() is necessary.
++ *
++ \code
++ uip_listen(HTONS(80));
++ \endcode
++ *
++ * \param port A 16-bit port number in network byte order.
++ */
++void uip_listen(u16_t port);
++
++/**
++ * Stop listening to the specified port.
++ *
++ * \note Since this function expects the port number in network byte
++ * order, a conversion using HTONS() or htons() is necessary.
++ *
++ \code
++ uip_unlisten(HTONS(80));
++ \endcode
++ *
++ * \param port A 16-bit port number in network byte order.
++ */
++void uip_unlisten(u16_t port);
++
++/**
++ * Connect to a remote host using TCP.
++ *
++ * This function is used to start a new connection to the specified
++ * port on the specied host. It allocates a new connection identifier,
++ * sets the connection to the SYN_SENT state and sets the
++ * retransmission timer to 0. This will cause a TCP SYN segment to be
++ * sent out the next time this connection is periodically processed,
++ * which usually is done within 0.5 seconds after the call to
++ * uip_connect().
++ *
++ * \note This function is avaliable only if support for active open
++ * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h.
++ *
++ * \note Since this function requires the port number to be in network
++ * byte order, a convertion using HTONS() or htons() is necessary.
++ *
++ \code
++ u16_t ipaddr[2];
++
++ uip_ipaddr(ipaddr, 192,168,1,2);
++ uip_connect(ipaddr, HTONS(80));
++ \endcode
++ *
++ * \param ripaddr A pointer to a 4-byte array representing the IP
++ * address of the remote hot.
++ *
++ * \param port A 16-bit port number in network byte order.
++ *
++ * \return A pointer to the uIP connection identifier for the new connection,
++ * or NULL if no connection could be allocated.
++ *
++ */
++struct uip_conn *uip_connect(u16_t *ripaddr, u16_t port);
++
++
++
++/**
++ * \internal
++ *
++ * Check if a connection has outstanding (i.e., unacknowledged) data.
++ *
++ * \param conn A pointer to the uip_conn structure for the connection.
++ *
++ * \hideinitializer
++ */
++#define uip_outstanding(conn) ((conn)->len)
++
++/**
++ * Send data on the current connection.
++ *
++ * This function is used to send out a single segment of TCP
++ * data. Only applications that have been invoked by uIP for event
++ * processing can send data.
++ *
++ * The amount of data that actually is sent out after a call to this
++ * funcion is determined by the maximum amount of data TCP allows. uIP
++ * will automatically crop the data so that only the appropriate
++ * amount of data is sent. The function uip_mss() can be used to query
++ * uIP for the amount of data that actually will be sent.
++ *
++ * \note This function does not guarantee that the sent data will
++ * arrive at the destination. If the data is lost in the network, the
++ * application will be invoked with the uip_rexmit() event being
++ * set. The application will then have to resend the data using this
++ * function.
++ *
++ * \param data A pointer to the data which is to be sent.
++ *
++ * \param len The maximum amount of data bytes to be sent.
++ *
++ * \hideinitializer
++ */
++#define uip_send(data, len) do { uip_sappdata = (data); uip_slen = (len);} while(0)
++
++/**
++ * The length of any incoming data that is currently avaliable (if avaliable)
++ * in the uip_appdata buffer.
++ *
++ * The test function uip_data() must first be used to check if there
++ * is any data available at all.
++ *
++ * \hideinitializer
++ */
++#define uip_datalen() uip_len
++
++/**
++ * The length of any out-of-band data (urgent data) that has arrived
++ * on the connection.
++ *
++ * \note The configuration parameter UIP_URGDATA must be set for this
++ * function to be enabled.
++ *
++ * \hideinitializer
++ */
++#define uip_urgdatalen() uip_urglen
++
++/**
++ * Close the current connection.
++ *
++ * This function will close the current connection in a nice way.
++ *
++ * \hideinitializer
++ */
++#define uip_close() (uip_flags = UIP_CLOSE)
++
++/**
++ * Abort the current connection.
++ *
++ * This function will abort (reset) the current connection, and is
++ * usually used when an error has occured that prevents using the
++ * uip_close() function.
++ *
++ * \hideinitializer
++ */
++#define uip_abort() (uip_flags = UIP_ABORT)
++
++/**
++ * Tell the sending host to stop sending data.
++ *
++ * This function will close our receiver's window so that we stop
++ * receiving data for the current connection.
++ *
++ * \hideinitializer
++ */
++#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED)
++
++/**
++ * Find out if the current connection has been previously stopped with
++ * uip_stop().
++ *
++ * \hideinitializer
++ */
++#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED)
++
++/**
++ * Restart the current connection, if is has previously been stopped
++ * with uip_stop().
++ *
++ * This function will open the receiver's window again so that we
++ * start receiving data for the current connection.
++ *
++ * \hideinitializer
++ */
++#define uip_restart() do { uip_flags |= UIP_NEWDATA; \
++ uip_conn->tcpstateflags &= ~UIP_STOPPED; \
++ } while(0)
++
++
++/* uIP tests that can be made to determine in what state the current
++ connection is, and what the application function should do. */
++
++/**
++ * Is new incoming data available?
++ *
++ * Will reduce to non-zero if there is new data for the application
++ * present at the uip_appdata pointer. The size of the data is
++ * avaliable through the uip_len variable.
++ *
++ * \hideinitializer
++ */
++#define uip_newdata() (uip_flags & UIP_NEWDATA)
++
++/**
++ * Has previously sent data been acknowledged?
++ *
++ * Will reduce to non-zero if the previously sent data has been
++ * acknowledged by the remote host. This means that the application
++ * can send new data.
++ *
++ * \hideinitializer
++ */
++#define uip_acked() (uip_flags & UIP_ACKDATA)
++
++/**
++ * Has the connection just been connected?
++ *
++ * Reduces to non-zero if the current connection has been connected to
++ * a remote host. This will happen both if the connection has been
++ * actively opened (with uip_connect()) or passively opened (with
++ * uip_listen()).
++ *
++ * \hideinitializer
++ */
++#define uip_connected() (uip_flags & UIP_CONNECTED)
++
++/**
++ * Has the connection been closed by the other end?
++ *
++ * Is non-zero if the connection has been closed by the remote
++ * host. The application may then do the necessary clean-ups.
++ *
++ * \hideinitializer
++ */
++#define uip_closed() (uip_flags & UIP_CLOSE)
++
++/**
++ * Has the connection been aborted by the other end?
++ *
++ * Non-zero if the current connection has been aborted (reset) by the
++ * remote host.
++ *
++ * \hideinitializer
++ */
++#define uip_aborted() (uip_flags & UIP_ABORT)
++
++/**
++ * Has the connection timed out?
++ *
++ * Non-zero if the current connection has been aborted due to too many
++ * retransmissions.
++ *
++ * \hideinitializer
++ */
++#define uip_timedout() (uip_flags & UIP_TIMEDOUT)
++
++/**
++ * Do we need to retransmit previously data?
++ *
++ * Reduces to non-zero if the previously sent data has been lost in
++ * the network, and the application should retransmit it. The
++ * application should send the exact same data as it did the last
++ * time, using the uip_send() function.
++ *
++ * \hideinitializer
++ */
++#define uip_rexmit() (uip_flags & UIP_REXMIT)
++
++/**
++ * Is the connection being polled by uIP?
++ *
++ * Is non-zero if the reason the application is invoked is that the
++ * current connection has been idle for a while and should be
++ * polled.
++ *
++ * The polling event can be used for sending data without having to
++ * wait for the remote host to send data.
++ *
++ * \hideinitializer
++ */
++#define uip_poll() (uip_flags & UIP_POLL)
++
++/**
++ * Get the initial maxium segment size (MSS) of the current
++ * connection.
++ *
++ * \hideinitializer
++ */
++#define uip_initialmss() (uip_conn->initialmss)
++
++/**
++ * Get the current maxium segment size that can be sent on the current
++ * connection.
++ *
++ * The current maxiumum segment size that can be sent on the
++ * connection is computed from the receiver's window and the MSS of
++ * the connection (which also is available by calling
++ * uip_initialmss()).
++ *
++ * \hideinitializer
++ */
++#define uip_mss() (uip_conn->mss)
++
++/**
++ * Set up a new UDP connection.
++ *
++ * \param ripaddr A pointer to a 4-byte structure representing the IP
++ * address of the remote host.
++ *
++ * \param rport The remote port number in network byte order.
++ *
++ * \return The uip_udp_conn structure for the new connection or NULL
++ * if no connection could be allocated.
++ */
++struct uip_udp_conn *uip_udp_new(u16_t *ripaddr, u16_t rport);
++
++/**
++ * Removed a UDP connection.
++ *
++ * \param conn A pointer to the uip_udp_conn structure for the connection.
++ *
++ * \hideinitializer
++ */
++#define uip_udp_remove(conn) (conn)->lport = 0
++
++/**
++ * Send a UDP datagram of length len on the current connection.
++ *
++ * This function can only be called in response to a UDP event (poll
++ * or newdata). The data must be present in the uip_buf buffer, at the
++ * place pointed to by the uip_appdata pointer.
++ *
++ * \param len The length of the data in the uip_buf buffer.
++ *
++ * \hideinitializer
++ */
++#define uip_udp_send(len) uip_slen = (len)
++
++/** @} */
++
++/* uIP convenience and converting functions. */
++
++/**
++ * \defgroup uipconvfunc uIP conversion functions
++ * @{
++ *
++ * These functions can be used for converting between different data
++ * formats used by uIP.
++ */
++
++/**
++ * Pack an IP address into a 4-byte array which is used by uIP to
++ * represent IP addresses.
++ *
++ * Example:
++ \code
++ u16_t ipaddr[2];
++
++ uip_ipaddr(&ipaddr, 192,168,1,2);
++ \endcode
++ *
++ * \param addr A pointer to a 4-byte array that will be filled in with
++ * the IP addres.
++ * \param addr0 The first octet of the IP address.
++ * \param addr1 The second octet of the IP address.
++ * \param addr2 The third octet of the IP address.
++ * \param addr3 The forth octet of the IP address.
++ *
++ * \hideinitializer
++ */
++#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \
++ (addr)[0] = HTONS(((addr0) << 8) | (addr1)); \
++ (addr)[1] = HTONS(((addr2) << 8) | (addr3)); \
++ } while(0)
++
++/**
++ * Convert 16-bit quantity from host byte order to network byte order.
++ *
++ * This macro is primarily used for converting constants from host
++ * byte order to network byte order. For converting variables to
++ * network byte order, use the htons() function instead.
++ *
++ * \hideinitializer
++ */
++#ifndef HTONS
++# if BYTE_ORDER == BIG_ENDIAN
++# define HTONS(n) (n)
++# else /* BYTE_ORDER == BIG_ENDIAN */
++# define HTONS(n) ((((u16_t)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))
++# endif /* BYTE_ORDER == BIG_ENDIAN */
++#endif /* HTONS */
++
++/**
++ * Convert 16-bit quantity from host byte order to network byte order.
++ *
++ * This function is primarily used for converting variables from host
++ * byte order to network byte order. For converting constants to
++ * network byte order, use the HTONS() macro instead.
++ */
++#ifndef htons
++u16_t htons(u16_t val);
++#endif /* htons */
++
++/** @} */
++
++/**
++ * Pointer to the application data in the packet buffer.
++ *
++ * This pointer points to the application data when the application is
++ * called. If the application wishes to send data, the application may
++ * use this space to write the data into before calling uip_send().
++ */
++extern volatile u8_t *uip_appdata;
++extern volatile u8_t *uip_sappdata;
++
++#if UIP_URGDATA > 0
++/* u8_t *uip_urgdata:
++ *
++ * This pointer points to any urgent data that has been received. Only
++ * present if compiled with support for urgent data (UIP_URGDATA).
++ */
++extern volatile u8_t *uip_urgdata;
++#endif /* UIP_URGDATA > 0 */
++
++
++/* u[8|16]_t uip_len:
++ *
++ * When the application is called, uip_len contains the length of any
++ * new data that has been received from the remote host. The
++ * application should set this variable to the size of any data that
++ * the application wishes to send. When the network device driver
++ * output function is called, uip_len should contain the length of the
++ * outgoing packet.
++ */
++extern volatile u16_t uip_len, uip_slen;
++
++#if UIP_URGDATA > 0
++extern volatile u8_t uip_urglen, uip_surglen;
++#endif /* UIP_URGDATA > 0 */
++
++
++/**
++ * Representation of a uIP TCP connection.
++ *
++ * The uip_conn structure is used for identifying a connection. All
++ * but one field in the structure are to be considered read-only by an
++ * application. The only exception is the appstate field whos purpose
++ * is to let the application store application-specific state (e.g.,
++ * file pointers) for the connection. The size of this field is
++ * configured in the "uipopt.h" header file.
++ */
++struct uip_conn {
++ u16_t ripaddr[2]; /**< The IP address of the remote host. */
++
++ u16_t lport; /**< The local TCP port, in network byte order. */
++ u16_t rport; /**< The local remote TCP port, in network byte
++ order. */
++
++ u8_t rcv_nxt[4]; /**< The sequence number that we expect to
++ receive next. */
++ u8_t snd_nxt[4]; /**< The sequence number that was last sent by
++ us. */
++ u16_t len; /**< Length of the data that was previously sent. */
++ u16_t mss; /**< Current maximum segment size for the
++ connection. */
++ u16_t initialmss; /**< Initial maximum segment size for the
++ connection. */
++ u8_t sa; /**< Retransmission time-out calculation state
++ variable. */
++ u8_t sv; /**< Retransmission time-out calculation state
++ variable. */
++ u8_t rto; /**< Retransmission time-out. */
++ u8_t tcpstateflags; /**< TCP state and flags. */
++ u8_t timer; /**< The retransmission timer. */
++ u8_t nrtx; /**< The number of retransmissions for the last
++ segment sent. */
++
++ /** The application state. */
++ u8_t appstate[UIP_APPSTATE_SIZE];
++};
++
++
++/* Pointer to the current connection. */
++extern struct uip_conn *uip_conn;
++/* The array containing all uIP connections. */
++extern struct uip_conn uip_conns[UIP_CONNS];
++/**
++ * \addtogroup uiparch
++ * @{
++ */
++
++/**
++ * 4-byte array used for the 32-bit sequence number calculations.
++ */
++extern volatile u8_t uip_acc32[4];
++
++/** @} */
++
++
++#if UIP_UDP
++/**
++ * Representation of a uIP UDP connection.
++ */
++struct uip_udp_conn {
++ u16_t ripaddr[2]; /**< The IP address of the remote peer. */
++ u16_t lport; /**< The local port number in network byte order. */
++ u16_t rport; /**< The remote port number in network byte order. */
++};
++
++extern struct uip_udp_conn *uip_udp_conn;
++extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
++#endif /* UIP_UDP */
++
++/**
++ * The structure holding the TCP/IP statistics that are gathered if
++ * UIP_STATISTICS is set to 1.
++ *
++ */
++struct uip_stats {
++ struct {
++ uip_stats_t drop; /**< Number of dropped packets at the IP
++ layer. */
++ uip_stats_t recv; /**< Number of received packets at the IP
++ layer. */
++ uip_stats_t sent; /**< Number of sent packets at the IP
++ layer. */
++ uip_stats_t vhlerr; /**< Number of packets dropped due to wrong
++ IP version or header length. */
++ uip_stats_t hblenerr; /**< Number of packets dropped due to wrong
++ IP length, high byte. */
++ uip_stats_t lblenerr; /**< Number of packets dropped due to wrong
++ IP length, low byte. */
++ uip_stats_t fragerr; /**< Number of packets dropped since they
++ were IP fragments. */
++ uip_stats_t chkerr; /**< Number of packets dropped due to IP
++ checksum errors. */
++ uip_stats_t protoerr; /**< Number of packets dropped since they
++ were neither ICMP, UDP nor TCP. */
++ } ip; /**< IP statistics. */
++ struct {
++ uip_stats_t drop; /**< Number of dropped ICMP packets. */
++ uip_stats_t recv; /**< Number of received ICMP packets. */
++ uip_stats_t sent; /**< Number of sent ICMP packets. */
++ uip_stats_t typeerr; /**< Number of ICMP packets with a wrong
++ type. */
++ } icmp; /**< ICMP statistics. */
++ struct {
++ uip_stats_t drop; /**< Number of dropped TCP segments. */
++ uip_stats_t recv; /**< Number of recived TCP segments. */
++ uip_stats_t sent; /**< Number of sent TCP segments. */
++ uip_stats_t chkerr; /**< Number of TCP segments with a bad
++ checksum. */
++ uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK
++ number. */
++ uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */
++ uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */
++ uip_stats_t syndrop; /**< Number of dropped SYNs due to too few
++ connections was avaliable. */
++ uip_stats_t synrst; /**< Number of SYNs for closed ports,
++ triggering a RST. */
++ } tcp; /**< TCP statistics. */
++};
++
++/**
++ * The uIP TCP/IP statistics.
++ *
++ * This is the variable in which the uIP TCP/IP statistics are gathered.
++ */
++extern struct uip_stats uip_stat;
++
++
++/*-----------------------------------------------------------------------------------*/
++/* All the stuff below this point is internal to uIP and should not be
++ * used directly by an application or by a device driver.
++ */
++/*-----------------------------------------------------------------------------------*/
++/* u8_t uip_flags:
++ *
++ * When the application is called, uip_flags will contain the flags
++ * that are defined in this file. Please read below for more
++ * infomation.
++ */
++extern volatile u8_t uip_flags;
++
++/* The following flags may be set in the global variable uip_flags
++ before calling the application callback. The UIP_ACKDATA and
++ UIP_NEWDATA flags may both be set at the same time, whereas the
++ others are mutualy exclusive. Note that these flags should *NOT* be
++ accessed directly, but through the uIP functions/macros. */
++
++#define UIP_ACKDATA 1 /* Signifies that the outstanding data was
++ acked and the application should send
++ out new data instead of retransmitting
++ the last data. */
++#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent
++ us new data. */
++#define UIP_REXMIT 4 /* Tells the application to retransmit the
++ data that was last sent. */
++#define UIP_POLL 8 /* Used for polling the application, to
++ check if the application has data that
++ it wants to send. */
++#define UIP_CLOSE 16 /* The remote host has closed the
++ connection, thus the connection has
++ gone away. Or the application signals
++ that it wants to close the
++ connection. */
++#define UIP_ABORT 32 /* The remote host has aborted the
++ connection, thus the connection has
++ gone away. Or the application signals
++ that it wants to abort the
++ connection. */
++#define UIP_CONNECTED 64 /* We have got a connection from a remote
++ host and have set up a new connection
++ for it, or an active connection has
++ been successfully established. */
++
++#define UIP_TIMEDOUT 128 /* The connection has been aborted due to
++ too many retransmissions. */
++
++
++/* uip_process(flag):
++ *
++ * The actual uIP function which does all the work.
++ */
++void uip_process(u8_t flag);
++
++/* The following flags are passed as an argument to the uip_process()
++ function. They are used to distinguish between the two cases where
++ uip_process() is called. It can be called either because we have
++ incoming data that should be processed, or because the periodic
++ timer has fired. */
++
++#define UIP_DATA 1 /* Tells uIP that there is incoming data in
++ the uip_buf buffer. The length of the
++ data is stored in the global variable
++ uip_len. */
++#define UIP_TIMER 2 /* Tells uIP that the periodic timer has
++ fired. */
++#if UIP_UDP
++#define UIP_UDP_TIMER 3
++#endif /* UIP_UDP */
++
++/* The TCP states used in the uip_conn->tcpstateflags. */
++#define CLOSED 0
++#define SYN_RCVD 1
++#define SYN_SENT 2
++#define ESTABLISHED 3
++#define FIN_WAIT_1 4
++#define FIN_WAIT_2 5
++#define CLOSING 6
++#define TIME_WAIT 7
++#define LAST_ACK 8
++#define TS_MASK 15
++
++#define UIP_STOPPED 16
++
++#define UIP_TCPIP_HLEN 40
++
++/* The TCP and IP headers. */
++typedef struct {
++ /* IP header. */
++ u8_t vhl,
++ tos,
++ len[2],
++ ipid[2],
++ ipoffset[2],
++ ttl,
++ proto;
++ u16_t ipchksum;
++ u16_t srcipaddr[2],
++ destipaddr[2];
++
++ /* TCP header. */
++ u16_t srcport,
++ destport;
++ u8_t seqno[4],
++ ackno[4],
++ tcpoffset,
++ flags,
++ wnd[2];
++ u16_t tcpchksum;
++ u8_t urgp[2];
++ u8_t optdata[4];
++} uip_tcpip_hdr;
++
++/* The ICMP and IP headers. */
++typedef struct {
++ /* IP header. */
++ u8_t vhl,
++ tos,
++ len[2],
++ ipid[2],
++ ipoffset[2],
++ ttl,
++ proto;
++ u16_t ipchksum;
++ u16_t srcipaddr[2],
++ destipaddr[2];
++ /* ICMP (echo) header. */
++ u8_t type, icode;
++ u16_t icmpchksum;
++ u16_t id, seqno;
++} uip_icmpip_hdr;
++
++
++/* The UDP and IP headers. */
++typedef struct {
++ /* IP header. */
++ u8_t vhl,
++ tos,
++ len[2],
++ ipid[2],
++ ipoffset[2],
++ ttl,
++ proto;
++ u16_t ipchksum;
++ u16_t srcipaddr[2],
++ destipaddr[2];
++
++ /* UDP header. */
++ u16_t srcport,
++ destport;
++ u16_t udplen;
++ u16_t udpchksum;
++} uip_udpip_hdr;
++
++#define UIP_PROTO_ICMP 1
++#define UIP_PROTO_TCP 6
++#define UIP_PROTO_UDP 17
++
++#if UIP_FIXEDADDR
++extern const u16_t uip_hostaddr[2];
++#else /* UIP_FIXEDADDR */
++extern u16_t uip_hostaddr[2];
++#endif /* UIP_FIXEDADDR */
++
++#endif /* __UIP_H__ */
++
++
++/** @} */
++
+--- /dev/null
++++ b/net/uip-0.9/uip_arch.c
+@@ -0,0 +1,145 @@
++/*
++ * Copyright (c) 2001, Adam Dunkels.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uip_arch.c,v 1.2.2.1 2003/10/04 22:54:17 adam Exp $
++ *
++ */
++
++
++#include "uip.h"
++#include "uip_arch.h"
++
++#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
++#define IP_PROTO_TCP 6
++
++/*-----------------------------------------------------------------------------------*/
++void
++uip_add32(u8_t *op32, u16_t op16)
++{
++
++ uip_acc32[3] = op32[3] + (op16 & 0xff);
++ uip_acc32[2] = op32[2] + (op16 >> 8);
++ uip_acc32[1] = op32[1];
++ uip_acc32[0] = op32[0];
++
++ if(uip_acc32[2] < (op16 >> 8)) {
++ ++uip_acc32[1];
++ if(uip_acc32[1] == 0) {
++ ++uip_acc32[0];
++ }
++ }
++
++
++ if(uip_acc32[3] < (op16 & 0xff)) {
++ ++uip_acc32[2];
++ if(uip_acc32[2] == 0) {
++ ++uip_acc32[1];
++ if(uip_acc32[1] == 0) {
++ ++uip_acc32[0];
++ }
++ }
++ }
++}
++/*-----------------------------------------------------------------------------------*/
++u16_t
++uip_chksum(u16_t *sdata, u16_t len)
++{
++ u16_t acc;
++
++ for(acc = 0; len > 1; len -= 2) {
++ acc += *sdata;
++ if(acc < *sdata) {
++ /* Overflow, so we add the carry to acc (i.e., increase by
++ one). */
++ ++acc;
++ }
++ ++sdata;
++ }
++
++ /* add up any odd byte */
++ if(len == 1) {
++ acc += htons(((u16_t)(*(u8_t *)sdata)) << 8);
++ if(acc < htons(((u16_t)(*(u8_t *)sdata)) << 8)) {
++ ++acc;
++ }
++ }
++
++ return acc;
++}
++/*-----------------------------------------------------------------------------------*/
++u16_t
++uip_ipchksum(void)
++{
++ return uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20);
++}
++/*-----------------------------------------------------------------------------------*/
++u16_t
++uip_tcpchksum(void)
++{
++ u16_t hsum, sum;
++
++
++ /* Compute the checksum of the TCP header. */
++ hsum = uip_chksum((u16_t *)&uip_buf[20 + UIP_LLH_LEN], 20);
++
++ /* Compute the checksum of the data in the TCP packet and add it to
++ the TCP header checksum. */
++ sum = uip_chksum((u16_t *)uip_appdata,
++ (u16_t)(((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 40)));
++
++ if((sum += hsum) < hsum) {
++ ++sum;
++ }
++
++ if((sum += BUF->srcipaddr[0]) < BUF->srcipaddr[0]) {
++ ++sum;
++ }
++ if((sum += BUF->srcipaddr[1]) < BUF->srcipaddr[1]) {
++ ++sum;
++ }
++ if((sum += BUF->destipaddr[0]) < BUF->destipaddr[0]) {
++ ++sum;
++ }
++ if((sum += BUF->destipaddr[1]) < BUF->destipaddr[1]) {
++ ++sum;
++ }
++ if((sum += (u16_t)htons((u16_t)IP_PROTO_TCP)) < (u16_t)htons((u16_t)IP_PROTO_TCP)) {
++ ++sum;
++ }
++
++ hsum = (u16_t)htons((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 20);
++
++ if((sum += hsum) < hsum) {
++ ++sum;
++ }
++
++ return sum;
++}
++/*-----------------------------------------------------------------------------------*/
+--- /dev/null
++++ b/net/uip-0.9/uip_arch.h
+@@ -0,0 +1,130 @@
++/**
++ * \defgroup uiparch Architecture specific uIP functions
++ * @{
++ *
++ * The functions in the architecture specific module implement the IP
++ * check sum and 32-bit additions.
++ *
++ * The IP checksum calculation is the most computationally expensive
++ * operation in the TCP/IP stack and it therefore pays off to
++ * implement this in efficient assembler. The purpose of the uip-arch
++ * module is to let the checksum functions to be implemented in
++ * architecture specific assembler.
++ *
++ */
++
++/**
++ * \file
++ * Declarations of architecture specific functions.
++ * \author Adam Dunkels <adam@dunkels.com>
++ */
++
++/*
++ * Copyright (c) 2001, Adam Dunkels.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uip_arch.h,v 1.1.2.2 2003/10/06 15:10:22 adam Exp $
++ *
++ */
++
++#ifndef __UIP_ARCH_H__
++#define __UIP_ARCH_H__
++
++#include "uip.h"
++
++/**
++ * Carry out a 32-bit addition.
++ *
++ * Because not all architectures for which uIP is intended has native
++ * 32-bit arithmetic, uIP uses an external C function for doing the
++ * required 32-bit additions in the TCP protocol processing. This
++ * function should add the two arguments and place the result in the
++ * global variable uip_acc32.
++ *
++ * \note The 32-bit integer pointed to by the op32 parameter and the
++ * result in the uip_acc32 variable are in network byte order (big
++ * endian).
++ *
++ * \param op32 A pointer to a 4-byte array representing a 32-bit
++ * integer in network byte order (big endian).
++ *
++ * \param op16 A 16-bit integer in host byte order.
++ */
++void uip_add32(u8_t *op32, u16_t op16);
++
++/**
++ * Calculate the Internet checksum over a buffer.
++ *
++ * The Internet checksum is the one's complement of the one's
++ * complement sum of all 16-bit words in the buffer.
++ *
++ * See RFC1071.
++ *
++ * \note This function is not called in the current version of uIP,
++ * but future versions might make use of it.
++ *
++ * \param buf A pointer to the buffer over which the checksum is to be
++ * computed.
++ *
++ * \param len The length of the buffer over which the checksum is to
++ * be computed.
++ *
++ * \return The Internet checksum of the buffer.
++ */
++u16_t uip_chksum(u16_t *buf, u16_t len);
++
++/**
++ * Calculate the IP header checksum of the packet header in uip_buf.
++ *
++ * The IP header checksum is the Internet checksum of the 20 bytes of
++ * the IP header.
++ *
++ * \return The IP header checksum of the IP header in the uip_buf
++ * buffer.
++ */
++u16_t uip_ipchksum(void);
++
++/**
++ * Calculate the TCP checksum of the packet in uip_buf and uip_appdata.
++ *
++ * The TCP checksum is the Internet checksum of data contents of the
++ * TCP segment, and a pseudo-header as defined in RFC793.
++ *
++ * \note The uip_appdata pointer that points to the packet data may
++ * point anywhere in memory, so it is not possible to simply calculate
++ * the Internet checksum of the contents of the uip_buf buffer.
++ *
++ * \return The TCP checksum of the TCP segment in uip_buf and pointed
++ * to by uip_appdata.
++ */
++u16_t uip_tcpchksum(void);
++
++/** @} */
++
++#endif /* __UIP_ARCH_H__ */
+--- /dev/null
++++ b/net/uip-0.9/uip_arp.c
+@@ -0,0 +1,421 @@
++/**
++ * \addtogroup uip
++ * @{
++ */
++
++/**
++ * \defgroup uiparp uIP Address Resolution Protocol
++ * @{
++ *
++ * The Address Resolution Protocol ARP is used for mapping between IP
++ * addresses and link level addresses such as the Ethernet MAC
++ * addresses. ARP uses broadcast queries to ask for the link level
++ * address of a known IP address and the host which is configured with
++ * the IP address for which the query was meant, will respond with its
++ * link level address.
++ *
++ * \note This ARP implementation only supports Ethernet.
++ */
++
++/**
++ * \file
++ * Implementation of the ARP Address Resolution Protocol.
++ * \author Adam Dunkels <adam@dunkels.com>
++ *
++ */
++
++/*
++ * Copyright (c) 2001-2003, Adam Dunkels.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uip_arp.c,v 1.7.2.3 2003/10/06 22:42:30 adam Exp $
++ *
++ */
++
++
++#include "uip_arp.h"
++
++struct arp_hdr {
++ struct uip_eth_hdr ethhdr;
++ u16_t hwtype;
++ u16_t protocol;
++ u8_t hwlen;
++ u8_t protolen;
++ u16_t opcode;
++ struct uip_eth_addr shwaddr;
++ u16_t sipaddr[2];
++ struct uip_eth_addr dhwaddr;
++ u16_t dipaddr[2];
++};
++
++struct ethip_hdr {
++ struct uip_eth_hdr ethhdr;
++ /* IP header. */
++ u8_t vhl,
++ tos,
++ len[2],
++ ipid[2],
++ ipoffset[2],
++ ttl,
++ proto;
++ u16_t ipchksum;
++ u16_t srcipaddr[2],
++ destipaddr[2];
++};
++
++#define ARP_REQUEST 1
++#define ARP_REPLY 2
++
++#define ARP_HWTYPE_ETH 1
++
++struct arp_entry {
++ u16_t ipaddr[2];
++ struct uip_eth_addr ethaddr;
++ u8_t time;
++};
++
++struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0,
++ UIP_ETHADDR1,
++ UIP_ETHADDR2,
++ UIP_ETHADDR3,
++ UIP_ETHADDR4,
++ UIP_ETHADDR5}};
++
++static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
++static u16_t ipaddr[2];
++static u8_t i, c;
++
++static u8_t arptime;
++static u8_t tmpage;
++
++#define BUF ((struct arp_hdr *)&uip_buf[0])
++#define IPBUF ((struct ethip_hdr *)&uip_buf[0])
++/*-----------------------------------------------------------------------------------*/
++/**
++ * Initialize the ARP module.
++ *
++ */
++/*-----------------------------------------------------------------------------------*/
++void
++uip_arp_init(void)
++{
++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
++ memset(arp_table[i].ipaddr, 0, 4);
++ }
++}
++/*-----------------------------------------------------------------------------------*/
++/**
++ * Periodic ARP processing function.
++ *
++ * This function performs periodic timer processing in the ARP module
++ * and should be called at regular intervals. The recommended interval
++ * is 10 seconds between the calls.
++ *
++ */
++/*-----------------------------------------------------------------------------------*/
++void
++uip_arp_timer(void)
++{
++ struct arp_entry *tabptr;
++
++ ++arptime;
++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
++ tabptr = &arp_table[i];
++ if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 &&
++ arptime - tabptr->time >= UIP_ARP_MAXAGE) {
++ memset(tabptr->ipaddr, 0, 4);
++ }
++ }
++
++}
++/*-----------------------------------------------------------------------------------*/
++static void
++uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
++{
++ register struct arp_entry *tabptr = 0;
++ /* Walk through the ARP mapping table and try to find an entry to
++ update. If none is found, the IP -> MAC address mapping is
++ inserted in the ARP table. */
++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
++
++ tabptr = &arp_table[i];
++ /* Only check those entries that are actually in use. */
++ if(tabptr->ipaddr[0] != 0 &&
++ tabptr->ipaddr[1] != 0) {
++
++ /* Check if the source IP address of the incoming packet matches
++ the IP address in this ARP table entry. */
++ if(ipaddr[0] == tabptr->ipaddr[0] &&
++ ipaddr[1] == tabptr->ipaddr[1]) {
++
++ /* An old entry found, update this and return. */
++ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
++ tabptr->time = arptime;
++
++ return;
++ }
++ }
++ }
++
++ /* If we get here, no existing ARP table entry was found, so we
++ create one. */
++
++ /* First, we try to find an unused entry in the ARP table. */
++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
++ tabptr = &arp_table[i];
++ if(tabptr->ipaddr[0] == 0 &&
++ tabptr->ipaddr[1] == 0) {
++ break;
++ }
++ }
++
++ /* If no unused entry is found, we try to find the oldest entry and
++ throw it away. */
++ if(i == UIP_ARPTAB_SIZE) {
++ tmpage = 0;
++ c = 0;
++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
++ tabptr = &arp_table[i];
++ if(arptime - tabptr->time > tmpage) {
++ tmpage = arptime - tabptr->time;
++ c = i;
++ }
++ }
++ i = c;
++ }
++
++ /* Now, i is the ARP table entry which we will fill with the new
++ information. */
++ memcpy(tabptr->ipaddr, ipaddr, 4);
++ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
++ tabptr->time = arptime;
++}
++/*-----------------------------------------------------------------------------------*/
++/**
++ * ARP processing for incoming IP packets
++ *
++ * This function should be called by the device driver when an IP
++ * packet has been received. The function will check if the address is
++ * in the ARP cache, and if so the ARP cache entry will be
++ * refreshed. If no ARP cache entry was found, a new one is created.
++ *
++ * This function expects an IP packet with a prepended Ethernet header
++ * in the uip_buf[] buffer, and the length of the packet in the global
++ * variable uip_len.
++ */
++/*-----------------------------------------------------------------------------------*/
++void
++uip_arp_ipin(void)
++{
++ uip_len -= sizeof(struct uip_eth_hdr);
++
++ /* Only insert/update an entry if the source IP address of the
++ incoming IP packet comes from a host on the local network. */
++ if((IPBUF->srcipaddr[0] & uip_arp_netmask[0]) !=
++ (uip_hostaddr[0] & uip_arp_netmask[0])) {
++ return;
++ }
++ if((IPBUF->srcipaddr[1] & uip_arp_netmask[1]) !=
++ (uip_hostaddr[1] & uip_arp_netmask[1])) {
++ return;
++ }
++ uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src));
++
++ return;
++}
++/*-----------------------------------------------------------------------------------*/
++/**
++ * ARP processing for incoming ARP packets.
++ *
++ * This function should be called by the device driver when an ARP
++ * packet has been received. The function will act differently
++ * depending on the ARP packet type: if it is a reply for a request
++ * that we previously sent out, the ARP cache will be filled in with
++ * the values from the ARP reply. If the incoming ARP packet is an ARP
++ * request for our IP address, an ARP reply packet is created and put
++ * into the uip_buf[] buffer.
++ *
++ * When the function returns, the value of the global variable uip_len
++ * indicates whether the device driver should send out a packet or
++ * not. If uip_len is zero, no packet should be sent. If uip_len is
++ * non-zero, it contains the length of the outbound packet that is
++ * present in the uip_buf[] buffer.
++ *
++ * This function expects an ARP packet with a prepended Ethernet
++ * header in the uip_buf[] buffer, and the length of the packet in the
++ * global variable uip_len.
++ */
++/*-----------------------------------------------------------------------------------*/
++void
++uip_arp_arpin(void)
++{
++
++ if(uip_len < sizeof(struct arp_hdr)) {
++ uip_len = 0;
++ return;
++ }
++
++ uip_len = 0;
++
++ switch(BUF->opcode) {
++ case HTONS(ARP_REQUEST):
++ /* ARP request. If it asked for our address, we send out a
++ reply. */
++ if(BUF->dipaddr[0] == uip_hostaddr[0] &&
++ BUF->dipaddr[1] == uip_hostaddr[1]) {
++ /* The reply opcode is 2. */
++ BUF->opcode = HTONS(2);
++
++ memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6);
++ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
++ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
++ memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
++
++ BUF->dipaddr[0] = BUF->sipaddr[0];
++ BUF->dipaddr[1] = BUF->sipaddr[1];
++ BUF->sipaddr[0] = uip_hostaddr[0];
++ BUF->sipaddr[1] = uip_hostaddr[1];
++
++ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
++ uip_len = sizeof(struct arp_hdr);
++ }
++ break;
++ case HTONS(ARP_REPLY):
++ /* ARP reply. We insert or update the ARP table if it was meant
++ for us. */
++ if(BUF->dipaddr[0] == uip_hostaddr[0] &&
++ BUF->dipaddr[1] == uip_hostaddr[1]) {
++
++ uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
++ }
++ break;
++ }
++
++ return;
++}
++/*-----------------------------------------------------------------------------------*/
++/**
++ * Prepend Ethernet header to an outbound IP packet and see if we need
++ * to send out an ARP request.
++ *
++ * This function should be called before sending out an IP packet. The
++ * function checks the destination IP address of the IP packet to see
++ * what Ethernet MAC address that should be used as a destination MAC
++ * address on the Ethernet.
++ *
++ * If the destination IP address is in the local network (determined
++ * by logical ANDing of netmask and our IP address), the function
++ * checks the ARP cache to see if an entry for the destination IP
++ * address is found. If so, an Ethernet header is prepended and the
++ * function returns. If no ARP cache entry is found for the
++ * destination IP address, the packet in the uip_buf[] is replaced by
++ * an ARP request packet for the IP address. The IP packet is dropped
++ * and it is assumed that they higher level protocols (e.g., TCP)
++ * eventually will retransmit the dropped packet.
++ *
++ * If the destination IP address is not on the local network, the IP
++ * address of the default router is used instead.
++ *
++ * When the function returns, a packet is present in the uip_buf[]
++ * buffer, and the length of the packet is in the global variable
++ * uip_len.
++ */
++/*-----------------------------------------------------------------------------------*/
++void
++uip_arp_out(void)
++{
++ struct arp_entry *tabptr = 0;
++ /* Find the destination IP address in the ARP table and construct
++ the Ethernet header. If the destination IP addres isn't on the
++ local network, we use the default router's IP address instead.
++
++ If not ARP table entry is found, we overwrite the original IP
++ packet with an ARP request for the IP address. */
++
++ /* Check if the destination address is on the local network. */
++ if((IPBUF->destipaddr[0] & uip_arp_netmask[0]) !=
++ (uip_hostaddr[0] & uip_arp_netmask[0]) ||
++ (IPBUF->destipaddr[1] & uip_arp_netmask[1]) !=
++ (uip_hostaddr[1] & uip_arp_netmask[1])) {
++ /* Destination address was not on the local network, so we need to
++ use the default router's IP address instead of the destination
++ address when determining the MAC address. */
++ ipaddr[0] = uip_arp_draddr[0];
++ ipaddr[1] = uip_arp_draddr[1];
++ } else {
++ /* Else, we use the destination IP address. */
++ ipaddr[0] = IPBUF->destipaddr[0];
++ ipaddr[1] = IPBUF->destipaddr[1];
++ }
++
++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
++ tabptr = &arp_table[i];
++ if(ipaddr[0] == tabptr->ipaddr[0] &&
++ ipaddr[1] == tabptr->ipaddr[1])
++ break;
++ }
++
++ if(i == UIP_ARPTAB_SIZE) {
++ /* The destination address was not in our ARP table, so we
++ overwrite the IP packet with an ARP request. */
++
++ memset(BUF->ethhdr.dest.addr, 0xff, 6);
++ memset(BUF->dhwaddr.addr, 0x00, 6);
++ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
++ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
++
++ BUF->dipaddr[0] = ipaddr[0];
++ BUF->dipaddr[1] = ipaddr[1];
++ BUF->sipaddr[0] = uip_hostaddr[0];
++ BUF->sipaddr[1] = uip_hostaddr[1];
++ BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */
++ BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
++ BUF->protocol = HTONS(UIP_ETHTYPE_IP);
++ BUF->hwlen = 6;
++ BUF->protolen = 4;
++ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
++
++ uip_appdata = &uip_buf[40 + UIP_LLH_LEN];
++
++ uip_len = sizeof(struct arp_hdr);
++ return;
++ }
++
++ /* Build an ethernet header. */
++ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
++ memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
++
++ IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
++
++ uip_len += sizeof(struct uip_eth_hdr);
++}
++/*-----------------------------------------------------------------------------------*/
++
++/** @} */
++/** @} */
+--- /dev/null
++++ b/net/uip-0.9/uip_arp.h
+@@ -0,0 +1,201 @@
++/**
++ * \addtogroup uip
++ * @{
++ */
++
++/**
++ * \addtogroup uiparp
++ * @{
++ */
++
++/**
++ * \file
++ * Macros and definitions for the ARP module.
++ * \author Adam Dunkels <adam@dunkels.com>
++ */
++
++
++/*
++ * Copyright (c) 2001-2003, Adam Dunkels.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uip_arp.h,v 1.3.2.2 2003/10/06 15:10:22 adam Exp $
++ *
++ */
++
++#ifndef __UIP_ARP_H__
++#define __UIP_ARP_H__
++
++#include "uip.h"
++
++
++/**
++ * Representation of a 48-bit Ethernet address.
++ */
++struct uip_eth_addr {
++ u8_t addr[6];
++};
++
++extern struct uip_eth_addr uip_ethaddr;
++
++/**
++ * The Ethernet header.
++ */
++struct uip_eth_hdr {
++ struct uip_eth_addr dest;
++ struct uip_eth_addr src;
++ u16_t type;
++};
++
++#define UIP_ETHTYPE_ARP 0x0806
++#define UIP_ETHTYPE_IP 0x0800
++#define UIP_ETHTYPE_IP6 0x86dd
++
++
++/* The uip_arp_init() function must be called before any of the other
++ ARP functions. */
++void uip_arp_init(void);
++
++/* The uip_arp_ipin() function should be called whenever an IP packet
++ arrives from the Ethernet. This function refreshes the ARP table or
++ inserts a new mapping if none exists. The function assumes that an
++ IP packet with an Ethernet header is present in the uip_buf buffer
++ and that the length of the packet is in the uip_len variable. */
++void uip_arp_ipin(void);
++
++/* The uip_arp_arpin() should be called when an ARP packet is received
++ by the Ethernet driver. This function also assumes that the
++ Ethernet frame is present in the uip_buf buffer. When the
++ uip_arp_arpin() function returns, the contents of the uip_buf
++ buffer should be sent out on the Ethernet if the uip_len variable
++ is > 0. */
++void uip_arp_arpin(void);
++
++/* The uip_arp_out() function should be called when an IP packet
++ should be sent out on the Ethernet. This function creates an
++ Ethernet header before the IP header in the uip_buf buffer. The
++ Ethernet header will have the correct Ethernet MAC destination
++ address filled in if an ARP table entry for the destination IP
++ address (or the IP address of the default router) is present. If no
++ such table entry is found, the IP packet is overwritten with an ARP
++ request and we rely on TCP to retransmit the packet that was
++ overwritten. In any case, the uip_len variable holds the length of
++ the Ethernet frame that should be transmitted. */
++void uip_arp_out(void);
++
++/* The uip_arp_timer() function should be called every ten seconds. It
++ is responsible for flushing old entries in the ARP table. */
++void uip_arp_timer(void);
++
++/** @} */
++
++/**
++ * \addtogroup uipconffunc
++ * @{
++ */
++
++/**
++ * Set the default router's IP address.
++ *
++ * \param addr A pointer to a 4-byte array containing the IP address
++ * of the default router.
++ *
++ * \hideinitializer
++ */
++#define uip_setdraddr(addr) do { uip_arp_draddr[0] = addr[0]; \
++ uip_arp_draddr[1] = addr[1]; } while(0)
++
++/**
++ * Set the netmask.
++ *
++ * \param addr A pointer to a 4-byte array containing the IP address
++ * of the netmask.
++ *
++ * \hideinitializer
++ */
++#define uip_setnetmask(addr) do { uip_arp_netmask[0] = addr[0]; \
++ uip_arp_netmask[1] = addr[1]; } while(0)
++
++
++/**
++ * Get the default router's IP address.
++ *
++ * \param addr A pointer to a 4-byte array that will be filled in with
++ * the IP address of the default router.
++ *
++ * \hideinitializer
++ */
++#define uip_getdraddr(addr) do { addr[0] = uip_arp_draddr[0]; \
++ addr[1] = uip_arp_draddr[1]; } while(0)
++
++/**
++ * Get the netmask.
++ *
++ * \param addr A pointer to a 4-byte array that will be filled in with
++ * the value of the netmask.
++ *
++ * \hideinitializer
++ */
++#define uip_getnetmask(addr) do { addr[0] = uip_arp_netmask[0]; \
++ addr[1] = uip_arp_netmask[1]; } while(0)
++
++
++/**
++ * Specifiy the Ethernet MAC address.
++ *
++ * The ARP code needs to know the MAC address of the Ethernet card in
++ * order to be able to respond to ARP queries and to generate working
++ * Ethernet headers.
++ *
++ * \note This macro only specifies the Ethernet MAC address to the ARP
++ * code. It cannot be used to change the MAC address of the Ethernet
++ * card.
++ *
++ * \param eaddr A pointer to a struct uip_eth_addr containing the
++ * Ethernet MAC address of the Ethernet card.
++ *
++ * \hideinitializer
++ */
++#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \
++ uip_ethaddr.addr[1] = eaddr.addr[1];\
++ uip_ethaddr.addr[2] = eaddr.addr[2];\
++ uip_ethaddr.addr[3] = eaddr.addr[3];\
++ uip_ethaddr.addr[4] = eaddr.addr[4];\
++ uip_ethaddr.addr[5] = eaddr.addr[5];} while(0)
++
++/** @} */
++
++/**
++ * \internal Internal variables that are set using the macros
++ * uip_setdraddr and uip_setnetmask.
++ */
++extern u16_t uip_arp_draddr[2], uip_arp_netmask[2];
++#endif /* __UIP_ARP_H__ */
++
++
+--- /dev/null
++++ b/net/uip-0.9/uipopt.h
+@@ -0,0 +1,557 @@
++/**
++ * \defgroup uipopt Configuration options for uIP
++ * @{
++ *
++ * uIP is configured using the per-project configuration file
++ * "uipopt.h". This file contains all compile-time options for uIP and
++ * should be tweaked to match each specific project. The uIP
++ * distribution contains a documented example "uipopt.h" that can be
++ * copied and modified for each project.
++ */
++
++/**
++ * \file
++ * Configuration options for uIP.
++ * \author Adam Dunkels <adam@dunkels.com>
++ *
++ * This file is used for tweaking various configuration options for
++ * uIP. You should make a copy of this file into one of your project's
++ * directories instead of editing this example "uipopt.h" file that
++ * comes with the uIP distribution.
++ */
++
++/*
++ * Copyright (c) 2001-2003, Adam Dunkels.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uipopt.h,v 1.16.2.5 2003/10/07 13:22:51 adam Exp $
++ *
++ */
++
++#ifndef __UIPOPT_H__
++#define __UIPOPT_H__
++
++/*------------------------------------------------------------------------------*/
++/**
++ * \defgroup uipopttypedef uIP type definitions
++ * @{
++ */
++
++/**
++ * The 8-bit unsigned data type.
++ *
++ * This may have to be tweaked for your particular compiler. "unsigned
++ * char" works for most compilers.
++ */
++typedef unsigned char u8_t;
++
++/**
++ * The 16-bit unsigned data type.
++ *
++ * This may have to be tweaked for your particular compiler. "unsigned
++ * short" works for most compilers.
++ */
++typedef unsigned short u16_t;
++
++/**
++ * The statistics data type.
++ *
++ * This datatype determines how high the statistics counters are able
++ * to count.
++ */
++typedef unsigned short uip_stats_t;
++
++/** @} */
++
++/*------------------------------------------------------------------------------*/
++
++/**
++ * \defgroup uipoptstaticconf Static configuration options
++ * @{
++ *
++ * These configuration options can be used for setting the IP address
++ * settings statically, but only if UIP_FIXEDADDR is set to 1. The
++ * configuration options for a specific node includes IP address,
++ * netmask and default router as well as the Ethernet address. The
++ * netmask, default router and Ethernet address are appliciable only
++ * if uIP should be run over Ethernet.
++ *
++ * All of these should be changed to suit your project.
++*/
++
++/**
++ * Determines if uIP should use a fixed IP address or not.
++ *
++ * If uIP should use a fixed IP address, the settings are set in the
++ * uipopt.h file. If not, the macros uip_sethostaddr(),
++ * uip_setdraddr() and uip_setnetmask() should be used instead.
++ *
++ * \hideinitializer
++ */
++#define UIP_FIXEDADDR 0
++
++/**
++ * Ping IP address asignment.
++ *
++ * uIP uses a "ping" packets for setting its own IP address if this
++ * option is set. If so, uIP will start with an empty IP address and
++ * the destination IP address of the first incoming "ping" (ICMP echo)
++ * packet will be used for setting the hosts IP address.
++ *
++ * \note This works only if UIP_FIXEDADDR is 0.
++ *
++ * \hideinitializer
++ */
++#define UIP_PINGADDRCONF 0
++
++#define UIP_IPADDR0 192 /**< The first octet of the IP address of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_IPADDR1 168 /**< The second octet of the IP address of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_IPADDR2 0 /**< The third octet of the IP address of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_IPADDR3 250 /**< The fourth octet of the IP address of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++
++#define UIP_NETMASK0 255 /**< The first octet of the netmask of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_NETMASK1 255 /**< The second octet of the netmask of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_NETMASK2 255 /**< The third octet of the netmask of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_NETMASK3 0 /**< The fourth octet of the netmask of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++
++#define UIP_DRIPADDR0 192 /**< The first octet of the IP address of
++ the default router, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_DRIPADDR1 168 /**< The second octet of the IP address of
++ the default router, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_DRIPADDR2 0 /**< The third octet of the IP address of
++ the default router, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_DRIPADDR3 1 /**< The fourth octet of the IP address of
++ the default router, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++
++/**
++ * Specifies if the uIP ARP module should be compiled with a fixed
++ * Ethernet MAC address or not.
++ *
++ * If this configuration option is 0, the macro uip_setethaddr() can
++ * be used to specify the Ethernet address at run-time.
++ *
++ * \hideinitializer
++ */
++#define UIP_FIXEDETHADDR 0
++
++#define UIP_ETHADDR0 0x00 /**< The first octet of the Ethernet
++ address if UIP_FIXEDETHADDR is
++ 1. \hideinitializer */
++#define UIP_ETHADDR1 0xbd /**< The second octet of the Ethernet
++ address if UIP_FIXEDETHADDR is
++ 1. \hideinitializer */
++#define UIP_ETHADDR2 0x3b /**< The third octet of the Ethernet
++ address if UIP_FIXEDETHADDR is
++ 1. \hideinitializer */
++#define UIP_ETHADDR3 0x33 /**< The fourth octet of the Ethernet
++ address if UIP_FIXEDETHADDR is
++ 1. \hideinitializer */
++#define UIP_ETHADDR4 0x05 /**< The fifth octet of the Ethernet
++ address if UIP_FIXEDETHADDR is
++ 1. \hideinitializer */
++#define UIP_ETHADDR5 0x71 /**< The sixth octet of the Ethernet
++ address if UIP_FIXEDETHADDR is
++ 1. \hideinitializer */
++
++/** @} */
++/*------------------------------------------------------------------------------*/
++/**
++ * \defgroup uipoptip IP configuration options
++ * @{
++ *
++ */
++/**
++ * The IP TTL (time to live) of IP packets sent by uIP.
++ *
++ * This should normally not be changed.
++ */
++#define UIP_TTL 255
++
++/**
++ * Turn on support for IP packet reassembly.
++ *
++ * uIP supports reassembly of fragmented IP packets. This features
++ * requires an additonal amount of RAM to hold the reassembly buffer
++ * and the reassembly code size is approximately 700 bytes. The
++ * reassembly buffer is of the same size as the uip_buf buffer
++ * (configured by UIP_BUFSIZE).
++ *
++ * \note IP packet reassembly is not heavily tested.
++ *
++ * \hideinitializer
++ */
++#define UIP_REASSEMBLY 0
++
++/**
++ * The maximum time an IP fragment should wait in the reassembly
++ * buffer before it is dropped.
++ *
++ */
++#define UIP_REASS_MAXAGE 40
++
++/** @} */
++
++/*------------------------------------------------------------------------------*/
++/**
++ * \defgroup uipoptudp UDP configuration options
++ * @{
++ *
++ * \note The UDP support in uIP is still not entirely complete; there
++ * is no support for sending or receiving broadcast or multicast
++ * packets, but it works well enough to support a number of vital
++ * applications such as DNS queries, though
++ */
++
++/**
++ * Toggles wether UDP support should be compiled in or not.
++ *
++ * \hideinitializer
++ */
++#define UIP_UDP 0
++
++/**
++ * Toggles if UDP checksums should be used or not.
++ *
++ * \note Support for UDP checksums is currently not included in uIP,
++ * so this option has no function.
++ *
++ * \hideinitializer
++ */
++#define UIP_UDP_CHECKSUMS 0
++
++/**
++ * The maximum amount of concurrent UDP connections.
++ *
++ * \hideinitializer
++ */
++#define UIP_UDP_CONNS 10
++
++/**
++ * The name of the function that should be called when UDP datagrams arrive.
++ *
++ * \hideinitializer
++ */
++#define UIP_UDP_APPCALL udp_appcall
++
++/** @} */
++/*------------------------------------------------------------------------------*/
++/**
++ * \defgroup uipopttcp TCP configuration options
++ * @{
++ */
++
++/**
++ * Determines if support for opening connections from uIP should be
++ * compiled in.
++ *
++ * If the applications that are running on top of uIP for this project
++ * do not need to open outgoing TCP connections, this configration
++ * option can be turned off to reduce the code size of uIP.
++ *
++ * \hideinitializer
++ */
++#define UIP_ACTIVE_OPEN 1
++
++/**
++ * The maximum number of simultaneously open TCP connections.
++ *
++ * Since the TCP connections are statically allocated, turning this
++ * configuration knob down results in less RAM used. Each TCP
++ * connection requires approximatly 30 bytes of memory.
++ *
++ * \hideinitializer
++ */
++#define UIP_CONNS 10
++
++/**
++ * The maximum number of simultaneously listening TCP ports.
++ *
++ * Each listening TCP port requires 2 bytes of memory.
++ *
++ * \hideinitializer
++ */
++#define UIP_LISTENPORTS 10
++
++/**
++ * The size of the advertised receiver's window.
++ *
++ * Should be set low (i.e., to the size of the uip_buf buffer) is the
++ * application is slow to process incoming data, or high (32768 bytes)
++ * if the application processes data quickly.
++ *
++ * \hideinitializer
++ */
++#define UIP_RECEIVE_WINDOW 32768
++
++/**
++ * Determines if support for TCP urgent data notification should be
++ * compiled in.
++ *
++ * Urgent data (out-of-band data) is a rarely used TCP feature that
++ * very seldom would be required.
++ *
++ * \hideinitializer
++ */
++#define UIP_URGDATA 1
++
++/**
++ * The initial retransmission timeout counted in timer pulses.
++ *
++ * This should not be changed.
++ */
++#define UIP_RTO 3
++
++/**
++ * The maximum number of times a segment should be retransmitted
++ * before the connection should be aborted.
++ *
++ * This should not be changed.
++ */
++#define UIP_MAXRTX 8
++
++/**
++ * The maximum number of times a SYN segment should be retransmitted
++ * before a connection request should be deemed to have been
++ * unsuccessful.
++ *
++ * This should not need to be changed.
++ */
++#define UIP_MAXSYNRTX 3
++
++/**
++ * The TCP maximum segment size.
++ *
++ * This is should not be to set to more than UIP_BUFSIZE - UIP_LLH_LEN - 40.
++ */
++#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - 40)
++
++/**
++ * How long a connection should stay in the TIME_WAIT state.
++ *
++ * This configiration option has no real implication, and it should be
++ * left untouched.
++ */
++#define UIP_TIME_WAIT_TIMEOUT 120
++
++
++/** @} */
++/*------------------------------------------------------------------------------*/
++/**
++ * \defgroup uipoptarp ARP configuration options
++ * @{
++ */
++
++/**
++ * The size of the ARP table.
++ *
++ * This option should be set to a larger value if this uIP node will
++ * have many connections from the local network.
++ *
++ * \hideinitializer
++ */
++#define UIP_ARPTAB_SIZE 8
++
++/**
++ * The maxium age of ARP table entries measured in 10ths of seconds.
++ *
++ * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD
++ * default).
++ */
++#define UIP_ARP_MAXAGE 120
++
++/** @} */
++
++/*------------------------------------------------------------------------------*/
++
++/**
++ * \defgroup uipoptgeneral General configuration options
++ * @{
++ */
++
++/**
++ * The size of the uIP packet buffer.
++ *
++ * The uIP packet buffer should not be smaller than 60 bytes, and does
++ * not need to be larger than 1500 bytes. Lower size results in lower
++ * TCP throughput, larger size results in higher TCP throughput.
++ *
++ * \hideinitializer
++ */
++#define UIP_BUFSIZE 1500
++
++
++/**
++ * Determines if statistics support should be compiled in.
++ *
++ * The statistics is useful for debugging and to show the user.
++ *
++ * \hideinitializer
++ */
++#define UIP_STATISTICS 1
++
++/**
++ * Determines if logging of certain events should be compiled in.
++ *
++ * This is useful mostly for debugging. The function uip_log()
++ * must be implemented to suit the architecture of the project, if
++ * logging is turned on.
++ *
++ * \hideinitializer
++ */
++#define UIP_LOGGING 0
++
++/**
++ * Print out a uIP log message.
++ *
++ * This function must be implemented by the module that uses uIP, and
++ * is called by uIP whenever a log message is generated.
++ */
++void uip_log(char *msg);
++
++/**
++ * The link level header length.
++ *
++ * This is the offset into the uip_buf where the IP header can be
++ * found. For Ethernet, this should be set to 14. For SLIP, this
++ * should be set to 0.
++ *
++ * \hideinitializer
++ */
++#define UIP_LLH_LEN 14
++
++
++/** @} */
++/*------------------------------------------------------------------------------*/
++/**
++ * \defgroup uipoptcpu CPU architecture configuration
++ * @{
++ *
++ * The CPU architecture configuration is where the endianess of the
++ * CPU on which uIP is to be run is specified. Most CPUs today are
++ * little endian, and the most notable exception are the Motorolas
++ * which are big endian. The BYTE_ORDER macro should be changed to
++ * reflect the CPU architecture on which uIP is to be run.
++ */
++#ifndef LITTLE_ENDIAN
++#define LITTLE_ENDIAN 3412
++#endif /* LITTLE_ENDIAN */
++#ifndef BIG_ENDIAN
++#define BIG_ENDIAN 1234
++#endif /* BIGE_ENDIAN */
++
++/**
++ * The byte order of the CPU architecture on which uIP is to be run.
++ *
++ * This option can be either BIG_ENDIAN (Motorola byte order) or
++ * LITTLE_ENDIAN (Intel byte order).
++ *
++ * \hideinitializer
++ */
++/*#ifndef BYTE_ORDER*/
++#define BYTE_ORDER BIG_ENDIAN
++/*#endif*/ /* BYTE_ORDER */
++
++/** @} */
++/*------------------------------------------------------------------------------*/
++
++/**
++ * \defgroup uipoptapp Appication specific configurations
++ * @{
++ *
++ * An uIP application is implemented using a single application
++ * function that is called by uIP whenever a TCP/IP event occurs. The
++ * name of this function must be registered with uIP at compile time
++ * using the UIP_APPCALL definition.
++ *
++ * uIP applications can store the application state within the
++ * uip_conn structure by specifying the size of the application
++ * structure with the UIP_APPSTATE_SIZE macro.
++ *
++ * The file containing the definitions must be included in the
++ * uipopt.h file.
++ *
++ * The following example illustrates how this can look.
++ \code
++
++void httpd_appcall(void);
++#define UIP_APPCALL httpd_appcall
++
++struct httpd_state {
++ u8_t state;
++ u16_t count;
++ char *dataptr;
++ char *script;
++};
++#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state))
++ \endcode
++ */
++
++/**
++ * \var #define UIP_APPCALL
++ *
++ * The name of the application function that uIP should call in
++ * response to TCP/IP events.
++ *
++ */
++
++/**
++ * \var #define UIP_APPSTATE_SIZE
++ *
++ * The size of the application state that is to be stored in the
++ * uip_conn structure.
++ */
++/** @} */
++
++/* Include the header file for the application program that should be
++ used. If you don't use the example web server, you should change
++ this. */
++#include "httpd.h"
++
++
++#endif /* __UIPOPT_H__ */
+--- a/board/infineon/easy50712/danube.c
++++ b/board/infineon/easy50712/danube.c
+@@ -354,7 +354,7 @@ int do_http_upgrade(const unsigned char
+ }
+ /* write the image to the flash */
+ puts("http ugrade ...\n");
+- sprintf(buf, "era ${kernel_addr} +0x%x; cp.b ${ram_addr} ${kernel_addr} 0x%x", size, size);
++ sprintf(buf, "era ${kernel_addr} +0x%lx; cp.b ${ram_addr} ${kernel_addr} 0x%lx", size, size);
+ return run_command(buf, 0);
+ }
+
+--- a/common/main.c
++++ b/common/main.c
+@@ -273,6 +273,8 @@ static __inline__ int abortboot(int boot
+
+ void main_loop (void)
+ {
++ int ret;
++
+ #ifndef CONFIG_SYS_HUSH_PARSER
+ static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
+ int len;
+@@ -403,12 +407,22 @@ void main_loop (void)
+ # endif
+
+ # ifndef CONFIG_SYS_HUSH_PARSER
+- run_command (s, 0);
++ ret = run_command (s, 0);
+ # else
+- parse_string_outer(s, FLAG_PARSE_SEMICOLON |
++ ret = parse_string_outer(s, FLAG_PARSE_SEMICOLON |
+ FLAG_EXIT_FROM_LOOP);
+ # endif
+
++# ifdef CONFIG_CMD_HTTPD
++ if (ret != 0) {
++ printf("Failed to execute bootcmd "
++ "(maybe invalid u-boot environment?), "
++ "starting httpd to update firmware...\n");
++ NetLoopHttpd();
++ }
++# endif
++
++
+ # ifdef CONFIG_AUTOBOOT_KEYED
+ disable_ctrlc(prev); /* restore Control C checking */
+ # endif
+--- a/include/configs/easy50712.h
++++ b/include/configs/easy50712.h
+@@ -114,4 +114,7 @@
+
+ #define CONFIG_CMD_HTTPD /* enable upgrade via HTTPD */
+
++#define CONFIG_IPADDR 192.168.0.119
++#define CONFIG_ETHADDR 00:01:02:03:04:05
++
+ #endif /* __CONFIG_H */
+--- a/lib_mips/time.c
++++ b/lib_mips/time.c
+@@ -29,6 +29,8 @@ static unsigned long timestamp;
+ /* how many counter cycles in a jiffy */
+ #define CYCLES_PER_JIFFY (CONFIG_SYS_MIPS_TIMER_FREQ + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ
+
++unsigned long ifx_get_cpuclk(void);
++
+ /*
+ * timer without interrupts
+ */
+--- a/net/httpd.c
++++ b/net/httpd.c
+@@ -35,12 +35,14 @@ HttpdHandler (void)
+ }
+ }
+
++#if 0
+ static void
+ HttpdTimeout (void)
+ {
+ puts ("T ");
+ NetSetTimeout (TIMEOUT * 1000, HttpdTimeout);
+ }
++#endif
+
+ void
+ HttpdStart (void)
+--- a/net/net.c
++++ b/net/net.c
+@@ -1966,7 +1966,7 @@ NetSendHttpd(void)
+ void
+ NetReceiveHttpd(volatile uchar * inpkt, int len)
+ {
+- memcpy(uip_buf, inpkt, len);
++ memcpy(uip_buf, (const void *)inpkt, len);
+ uip_len = len;
+ if(BUF->type == htons(UIP_ETHTYPE_IP)) {
+ uip_arp_ipin();
+@@ -1989,6 +1989,7 @@ NetLoopHttpd(void)
+ unsigned long long tout = 0;
+ bd_t *bd = gd->bd;
+ unsigned short int ip[2];
++ struct uip_eth_addr eaddr;
+
+ #ifdef CONFIG_NET_MULTI
+ NetRestarted = 0;
+@@ -2039,6 +2040,15 @@ restart:
+ eth_getenv_enetaddr("ethaddr", NetOurEther);
+ #endif
+
++ eaddr.addr[0] = NetOurEther[0];
++ eaddr.addr[1] = NetOurEther[1];
++ eaddr.addr[2] = NetOurEther[2];
++ eaddr.addr[3] = NetOurEther[3];
++ eaddr.addr[4] = NetOurEther[4];
++ eaddr.addr[5] = NetOurEther[5];
++
++ uip_setethaddr(eaddr);
++
+ NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
+ NetOurGatewayIP = getenv_IPaddr ("gatewayip");
+ NetOurSubnetMask= getenv_IPaddr ("netmask");
+@@ -2072,6 +2082,14 @@ restart:
+ tout = t1;
+ }
+ }
++
++ if (ctrlc()) {
++ eth_halt();
++ puts ("\nAbort\n");
++ return (-1);
++ }
++
++
+ if(!httpd_upload_complete)
+ continue;
+ printf("Bytes transferred = %ld (%lx hex)\n",
+--- a/net/uip-0.9/fsdata.c
++++ b/net/uip-0.9/fsdata.c
+@@ -1,199 +1,108 @@
+-static const char data_flashing_html[] = {
+- /* /flashing.html */
+- 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
+- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
+- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
+- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
+- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
+- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
+- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62,
+- 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d,
+- 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30,
+- 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68,
+- 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25,
+- 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23,
+- 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
+- 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+- 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34,
+- 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72,
+- 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61,
+- 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
+- 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31,
+- 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e,
+- 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68,
+- 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
+-
+-static const char data_fail_html[] = {
+- /* /fail.html */
+- 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
+- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
+- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
+- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
+- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
+- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
+- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9,
+- 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c,
+- 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9,
+- 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46,
+- 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49,
+- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65,
+- 0x3e, 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa,
+- 0x9, 0x9, 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73,
+- 0x68, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65,
+- 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, 0x45,
+- 0x52, 0x52, 0x4f, 0x52, 0x20, 0x2d, 0x20, 0x74, 0x68, 0x65,
+- 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x79, 0x6f, 0x75,
+- 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20,
+- 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
+- 0x70, 0x61, 0x73, 0x73, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66,
+- 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x50,
+- 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x61, 0x6b, 0x65,
+- 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75,
+- 0x73, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x66, 0x69,
+- 0x63, 0x69, 0x61, 0x6c, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74,
+- 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64,
+- 0x20, 0x62, 0x79, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+- 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e,
+- 0x66, 0x6f, 0x6e, 0x6f, 0x73, 0x66, 0x65, 0x72, 0x61, 0x2e,
+- 0x6f, 0x72, 0x67, 0x2f, 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f,
+- 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c,
+- 0x3e, 0xa, };
+-
+-static const char data_404_html[] = {
+- /* /404.html */
+- 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34,
+- 0x30, 0x34, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f,
+- 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53,
+- 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50,
+- 0x2f, 0x30, 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70,
+- 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73,
+- 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f,
+- 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e,
+- 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a,
+- 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c,
+- 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e,
+- 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f,
+- 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65,
+- 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e,
+- 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, 0x20,
+- 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66,
+- 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c,
+- 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x2f,
+- 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d,
+- 0x6c, 0x3e, };
+-
+-static const char data_index_html[] = {
+- /* /index.html */
+- 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
+- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
+- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
+- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
+- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
+- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
+- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9,
+- 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c,
+- 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9,
+- 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46,
+- 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49,
+- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65,
+- 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e,
+- 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74,
+- 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69,
+- 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74,
+- 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a,
+- 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
+- 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62,
+- 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+- 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62,
+- 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9,
+- 0x3c, 0x68, 0x31, 0x3e, 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65,
+- 0x72, 0x61, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66,
+- 0x65, 0x20, 0x55, 0x49, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa,
+- 0x9, 0x9, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65,
+- 0x74, 0x68, 0x6f, 0x64, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x74,
+- 0x22, 0x20, 0x65, 0x6e, 0x63, 0x74, 0x79, 0x70, 0x65, 0x3d,
+- 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74,
+- 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61,
+- 0x22, 0x3e, 0xa, 0x9, 0x9, 0x9, 0x3c, 0x69, 0x6e, 0x70,
+- 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69,
+- 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x66, 0x69,
+- 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x3e, 0xa, 0x9, 0x9,
+- 0x9, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79,
+- 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x3e,
+- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e,
+- 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa,
+- 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
+-
+-static const char data_flash_html[] = {
+- /* /flash.html */
+- 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
+- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
+- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
+- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
+- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
+- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
+- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9,
+- 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c,
+- 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9,
+- 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46,
+- 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49,
+- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65,
+- 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e,
+- 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74,
+- 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69,
+- 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74,
+- 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a,
+- 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
+- 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62,
+- 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+- 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62,
+- 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9,
+- 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x69,
+- 0x6e, 0x67, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9,
+- 0x54, 0x68, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+- 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x72,
+- 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6c,
+- 0x61, 0x73, 0x68, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68,
+- 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70,
+- 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x2c, 0x20, 0x74, 0x68,
+- 0x65, 0x20, 0x6c, 0x65, 0x64, 0x73, 0x20, 0x77, 0x69, 0x6c,
+- 0x6c, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x6f,
+- 0x20, 0x62, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0xa, 0xa, 0x9,
+- 0x9, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x61, 0x20, 0x73,
+- 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x6c,
+- 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68,
+- 0x65, 0x20, 0x62, 0x6f, 0x78, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+- 0x20, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0xa, 0x9, 0x3c,
+- 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68,
+- 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
+-
+-const struct fsdata_file file_flashing_html[] = {{NULL, data_flashing_html, data_flashing_html + 15, sizeof(data_flashing_html) - 15}};
++static const char data_flashing_html[] =
++"HTTP/1.0 200 OK\n"
++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n"
++"Content-type: text/html\n"
++"\n"
++"<html>\n"
++"\t<head>\n"
++"\t\t<title>\n"
++"\t\t\tFailsafe UI\n"
++"\t\t</title>\n"
++"\t</head>\n"
++"\t<body>\n"
++"\t\t<center><h1>Upgrading system...</h1></center>\n"
++"\t</body>\n"
++"</html>\n";
++
++static const char data_fail_html[] =
++"HTTP/1.0 200 OK\n"
++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n"
++"Content-type: text/html\n"
++"\n"
++"<html>\n"
++"\t<head>\n"
++"\t\t<title>\n"
++"\t\t\tFailsafe UI\n"
++"\t\t</title>\n"
++"\t</head>\n"
++"\t<body>\n"
++"\t\t<h1>Flashing failed</h1>\n"
++"\t\tERROR - the image you uploaded failed to pass verification.<br>\n"
++"\t\tPlease make sure to use an official update provided by http://lantiq.com/\n"
++"\t</body>\n"
++"</html>\n";
++
++static const char data_404_html[] =
++"HTTP/1.0 404 File not found\n"
++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n"
++"Content-type: text/html\n"
++"\n"
++"<html>\n"
++"\t<head>\n"
++"\t\t<title>\n"
++"\t\t\tFailsafe UI\n"
++"\t\t</title>\n"
++"\t</head>\n"
++"\t<body>\n"
++"\t\t<center><h1>404 - file not found</h1></center>\n"
++"\t</body>\n"
++"</html>\n";
++
++static const char data_index_html[] =
++"HTTP/1.0 200 OK\n"
++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n"
++"Content-type: text/html\n"
++"\n"
++"<html>\n"
++"\t<head>\n"
++"\t\t<title>\n"
++"\t\t\tFailsafe UI\n"
++"\t\t</title>\n"
++"\t</head>\n"
++"\t<body>\n"
++"\t\t<h1>Failsafe UI</h1>\n"
++"\t\t<form method=\"post\" enctype=\"multipart/form-data\">\n"
++"\t\t\t<input type=file name=firmware>\n"
++"\t\t\t<input type=submit>\n"
++"\t\t</form>\n"
++"\t</body>\n"
++"</html>\n";
++
++static const char data_flash_html[] =
++"HTTP/1.0 200 OK\n"
++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n"
++"Content-type: text/html\n"
++"\n"
++"<html>\n"
++"\t<head>\n"
++"\t\t<title>\n"
++"\t\t\tFailsafe UI\n"
++"\t\t</title>\n"
++"\t</head>\n"
++"\t<body>\n"
++"\t\t<h1>Flashing...</h1>\n"
++"\t\tThe system is now trying to flash. If there is a problem, the LEDs will "
++"start to blink.<br>\n"
++"\n"
++"\t\tAfter a successful update the box will reboot\n"
++"\t</body>\n"
++"</html>\n";
++
++const struct fsdata_file file_flashing_html[] =
++{{NULL, "/flashing.html", data_flashing_html, sizeof(data_flashing_html)}};
++
++const struct fsdata_file file_fail_html[] =
++{{file_flashing_html, "/fail.html", data_fail_html, sizeof(data_fail_html)}};
+
+-const struct fsdata_file file_fail_html[] = {{file_flashing_html, data_fail_html, data_fail_html + 11, sizeof(data_fail_html) - 11}};
++const struct fsdata_file file_404_html[] =
++{{file_fail_html, "/404.html", data_404_html, sizeof(data_404_html)}};
+
+-const struct fsdata_file file_404_html[] = {{file_fail_html, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}};
++const struct fsdata_file file_index_html[] =
++{{file_404_html, "/index.html", data_index_html, sizeof(data_index_html)}};
+
+-const struct fsdata_file file_index_html[] = {{file_404_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}};
+-
+-const struct fsdata_file file_flash_html[] = {{file_index_html, data_flash_html, data_flash_html + 12, sizeof(data_flash_html) - 12}};
++const struct fsdata_file file_flash_html[] =
++{{file_index_html, "/flash.html", data_flash_html, sizeof(data_flash_html)}};
+
+ #define FS_ROOT file_flash_html
+
+-#define FS_NUMFILES 5
+\ No newline at end of file
++#define FS_NUMFILES 5
+--- a/net/uip-0.9/httpd.c
++++ b/net/uip-0.9/httpd.c
+@@ -130,7 +130,7 @@ httpd_appcall(void)
+ if(!fs_open((const char *)&uip_appdata[4], &fsfile))
+ {
+ PRINTLN("couldn't open file");
+- fs_open(file_index_html.name, &fsfile);
++ fs_open(file_404_html.name, &fsfile);
+ }
+ }
+ hs->script = 0;
+@@ -141,7 +141,7 @@ httpd_appcall(void)
+ if(hs->state == HTTP_FIRMWARE)
+ {
+ unsigned char *start = (unsigned char*)uip_appdata;
+- char *clen = strstr(start, "Content-Length:");
++ char *clen = strstr((char *)start, "Content-Length:");
+ int len = 0;
+ unsigned char *next, *end;
+ unsigned char *boundary_start;
+@@ -150,14 +150,14 @@ httpd_appcall(void)
+ if(clen)
+ {
+ clen += sizeof("Content-Length:");
+- next = strstr(clen, eol);
++ next = (unsigned char *)strstr(clen, eol);
+ if(next)
+ {
+ len = atoi(clen);
+ next++;
+ printf("expecting %d bytes\n", len);
+ upload_data = httpd_upload_data = (unsigned char *)do_http_tmp_address();
+- printf("received data will be stored at 0x%08X\n", upload_data);
++ printf("received data will be stored at %p\n", upload_data);
+ if(!upload_data)
+ {
+ printf("failed to allocate memory\n");
+@@ -174,14 +174,14 @@ httpd_appcall(void)
+ uip_close();
+ return;
+ }
+- boundary_start = strstr(next, "---");
++ boundary_start = (unsigned char *)strstr((char *)next, "---");
+ if(!boundary_start)
+ {
+ uip_close();
+ return;
+ }
+- end = strstr(boundary_start, eol);
+- if(!eol)
++ end = (unsigned char *)strstr((char *)boundary_start, eol);
++ if(!end)
+ {
+ uip_close();
+ return;
+@@ -189,13 +189,13 @@ httpd_appcall(void)
+ boundary_len = end - boundary_start;
+ memcpy(boundary, boundary_start, boundary_len);
+ boundary[boundary_len] = 0;
+- next = strstr(boundary_start, "name=\"firmware\";");
++ next = (unsigned char *)strstr((char *)boundary_start, "name=\"firmware\";");
+ if(!next)
+ {
+ uip_close();
+ return;
+ }
+- next = strstr(next, eol2);
++ next = (unsigned char *)strstr((char *)next, eol2);
+ if(!next)
+ {
+ printf("could not find start of data\n");
+@@ -259,7 +259,6 @@ httpd_appcall(void)
+ {
+ if(upload_running)
+ {
+- int i;
+ httpd_upload_complete = 1;
+ // for(i = 0; i < hs->upload_total; i++)
+ // printf("%c", httpd_upload_data[i]);
+@@ -267,7 +266,7 @@ httpd_appcall(void)
+ uip_close();
+ }
+ }
+- uip_send(hs->dataptr, hs->count);
++ uip_send((unsigned char *)hs->dataptr, hs->count);
+ }
+ break;
+
diff --git a/package/uboot-lantiq/patches/300-arcadyan.patch b/package/uboot-lantiq/patches/300-arcadyan.patch
new file mode 100644
index 000000000..a91ac589f
--- /dev/null
+++ b/package/uboot-lantiq/patches/300-arcadyan.patch
@@ -0,0 +1,98 @@
+--- a/common/Makefile
++++ b/common/Makefile
+@@ -127,7 +127,9 @@
+ ifdef CONFIG_PCI
+ COBJS-$(CONFIG_CMD_PCI) += cmd_pci.o
+ endif
++ifdef CONFIG_CMD_PCMCIA
+ COBJS-y += cmd_pcmcia.o
++endif
+ COBJS-$(CONFIG_CMD_PORTIO) += cmd_portio.o
+ COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o
+ COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o
+--- a/drivers/pcmcia/Makefile
++++ b/drivers/pcmcia/Makefile
+@@ -28,9 +28,11 @@
+ COBJS-$(CONFIG_I82365) += i82365.o
+ COBJS-$(CONFIG_8xx) += mpc8xx_pcmcia.o
+ COBJS-$(CONFIG_PXA_PCMCIA) += pxa_pcmcia.o
+-COBJS-y += rpx_pcmcia.o
++#COBJS-y += rpx_pcmcia.o
++COBJS-$(CONFIG_RPX_PCMCIA) += rpx_pcmcia.o
+ COBJS-$(CONFIG_IDE_TI_CARDBUS) += ti_pci1410a.o
+-COBJS-y += tqm8xx_pcmcia.o
++#COBJS-y += tqm8xx_pcmcia.o
++COBJS-$(CONFIG_TQM8XX_PCMCIA) += tqm8xx_pcmcia.o
+ COBJS-$(CONFIG_MARUBUN_PCCARD) += marubun_pcmcia.o
+
+ COBJS := $(COBJS-y)
+--- a/drivers/usb/phy/Makefile
++++ b/drivers/usb/phy/Makefile
+@@ -23,7 +23,7 @@
+ LIB := $(obj)libusb_phy.a
+
+ COBJS-$(CONFIG_TWL4030_USB) += twl4030.o
+-COBJS-y := twl4030.o
++#COBJS-y := twl4030.o
+
+ COBJS := $(COBJS-y)
+ SRCS := $(COBJS:.o=.c)
+--- a/Makefile
++++ b/Makefile
+@@ -3414,6 +3414,42 @@
+ ## MIPS32 ifxcpe
+ #########################################################################
+
++define arcadyan
++$(1) : unconfig
++ @mkdir -p $(obj)include
++ @mkdir -p $(obj)board/arcadyan/
++ @[ -z "$$(findstring brnboot,$$@)" ] || \
++ { echo "TEXT_BASE = 0x80002000" >$(obj)board/arcadyan/config.tmp ; \
++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \
++ echo "#define CONFIG_SYS_BRNBOOT" >>$(obj)include/config.h ; \
++ $(XECHO) "... with brnboot configuration" ; \
++ }
++ @[ -z "$$(findstring ramboot,$$@)" ] || \
++ { echo "TEXT_BASE = 0xA0400000" >$(obj)board/arcadyan/config.tmp ; \
++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \
++ $(XECHO) "... with ramboot configuration" ; \
++ }
++ @if [ "$$(findstring flash,$$@)" ] ; then \
++ echo "#TEXT_BASE = 0xB0050000" >$(obj)board/arcadyan/config.tmp ; \
++ echo "#define CONFIG_BOOTSTRAP" >>$(obj)include/config.h ; \
++ echo "#define CONFIG_USE_DDR_RAM" >>$(obj)include/config.h ; \
++ echo "#define CONFIG_USE_DDR_RAM_CFG_psc166" >>$(obj)include/config.h ; \
++ fi
++ @$(MKCONFIG) -a $$(word 1,$$(subst _, ,$$@)) mips mips arcadyan "" danube
++endef
++
++$(eval $(call arcadyan, arv3527P%config))
++$(eval $(call arcadyan, arv4520PW%config))
++$(eval $(call arcadyan, arv452CPW%config))
++$(eval $(call arcadyan, arv4525PW%config))
++$(eval $(call arcadyan, arv4510PW%config))
++$(eval $(call arcadyan, arv4518PW%config))
++$(eval $(call arcadyan, arv4519PW%config))
++$(eval $(call arcadyan, arv7518PW%config))
++$(eval $(call arcadyan, arv7525PW%config))
++$(eval $(call arcadyan, arv752DPW%config))
++$(eval $(call arcadyan, arv752DPW22%config))
++
+ easy50712%config : unconfig
+ @mkdir -p $(obj)include
+ @mkdir -p $(obj)board/infineon/easy50712
+--- a/net/tftp.c
++++ b/net/tftp.c
+@@ -11,9 +11,9 @@
+ #include "bootp.h"
+
+ #define WELL_KNOWN_PORT 69 /* Well known TFTP port # */
+-#define TIMEOUT 5000UL /* Millisecs to timeout for lost pkt */
++#define TIMEOUT 10000UL /* Millisecs to timeout for lost pkt */
+ #ifndef CONFIG_NET_RETRY_COUNT
+-# define TIMEOUT_COUNT 10 /* # of timeouts before giving up */
++# define TIMEOUT_COUNT 200 /* # of timeouts before giving up */
+ #else
+ # define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT * 2)
+ #endif
diff --git a/package/uboot-lantiq/patches/400-lzma.patch b/package/uboot-lantiq/patches/400-lzma.patch
new file mode 100644
index 000000000..b2f498ac5
--- /dev/null
+++ b/package/uboot-lantiq/patches/400-lzma.patch
@@ -0,0 +1,1687 @@
+--- a/.gitignore
++++ b/.gitignore
+@@ -23,6 +23,11 @@
+ /u-boot.hex
+ /u-boot.map
+ /u-boot.bin
++/u-boot.bin.bz2
++/u-boot.bin.gz
++/u-boot.bin.lzma
++/u-boot.bin.lzo
++/u-boot.dis
+ /u-boot.srec
+ /u-boot.ldr
+ /u-boot.ldr.hex
+@@ -30,6 +35,20 @@
+ /u-boot.lds
+ /u-boot-onenand.bin
+ /u-boot-flexonenand.bin
++/u-boot-bootstrap
++/u-boot-bootstrap.hex
++/u-boot-bootstrap.map
++/u-boot-bootstrap.bin
++/u-boot-bootstrap.bin.bz2
++/u-boot-bootstrap.bin.gz
++/u-boot-bootstrap.bin.lzma
++/u-boot-bootstrap.bin.lzo
++/u-boot-bootstrap.dis
++/u-boot-bootstrap.srec
++/u-boot-bootstrap.ldr
++/u-boot-bootstrap.ldr.hex
++/u-boot-bootstrap.ldr.srec
++/u-boot-bootstrap.lds
+
+ #
+ # Generated files
+@@ -38,6 +57,7 @@
+ *.depend
+ /LOG
+ /errlog
++/.payload.s
+ /reloc_off
+
+ # stgit generated dirs
+@@ -63,3 +83,6 @@
+ /onenand_ipl/onenand-ipl*
+ /onenand_ipl/board/*/onenand*
+ /onenand_ipl/board/*/*.S
++examples/standalone/
++
++setvars
+--- a/Makefile
++++ b/Makefile
+@@ -183,6 +183,12 @@
+
+ OBJS := $(addprefix $(obj),$(OBJS))
+
++ifeq ($(CONFIG_BOOTSTRAP),y)
++BOOTSTRAP_OBJS = cpu/$(ARCH)/start_bootstrap.o
++
++BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_OBJS))
++endif
++
+ LIBS = lib_generic/libgeneric.a
+ LIBS += lib_generic/lzma/liblzma.a
+ LIBS += lib_generic/lzo/liblzo.a
+@@ -254,6 +260,25 @@
+ LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).a
+ LIBBOARD := $(addprefix $(obj),$(LIBBOARD))
+
++ifeq ($(CONFIG_BOOTSTRAP),y)
++BOOTSTRAP_LIBS = lib_generic/libgeneric_bootstrap.a
++BOOTSTRAP_LIBS += cpu/$(ARCH)/lib$(ARCH)_bootstrap.a
++BOOTSTRAP_LIBS += lib_$(ARCH)/lib$(ARCH)_bootstrap.a
++BOOTSTRAP_LIBS += common/libcommon_bootstrap.a
++BOOTSTRAP_LIBS-$(CONFIG_BOOTSTRAP_SERIAL) += drivers/serial/libserial.a
++
++BOOTSTRAP_LIBS-$(CONFIG_BOOTSTRAP_LZMA) += lib_generic/lzma/liblzma.a
++BOOTSTRAP_LIBS-$(CONFIG_BOOTSTRAP_LZO) += lib/lzo/liblzo.a
++BOOTSTRAP_LIBS += $(BOOTSTRAP_LIBS-y)
++
++BOOTSTRAP_LIBS := $(addprefix $(obj),$(BOOTSTRAP_LIBS))
++.PHONY : $(BOOTSTRAP_LIBS)
++
++BOOTSTRAP_LIBBOARD = board/$(BOARDDIR)/lib$(BOARD)_bootstrap.a
++BOOTSTRAP_LIBBOARD := $(addprefix $(obj),$(BOOTSTRAP_LIBBOARD))
++endif
++
++
+ # Add GCC lib
+ ifdef USE_PRIVATE_LIBGCC
+ ifeq ("$(USE_PRIVATE_LIBGCC)", "yes")
+@@ -267,6 +292,9 @@
+ PLATFORM_LIBS += $(PLATFORM_LIBGCC)
+ export PLATFORM_LIBS
+
++BOOTSTRAP_PLATFORM_LIBS += $(PLATFORM_LIBGCC)
++export BOOTSTRAP_PLATFORM_LIBS
++
+ # Special flags for CPP when processing the linker script.
+ # Pass the version down so we can handle backwards compatibility
+ # on the fly.
+@@ -289,12 +317,19 @@
+ __OBJS := $(subst $(obj),,$(OBJS))
+ __LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))
+
++__BOOTSTRAP_OBJS := $(subst $(obj),,$(BOOTSTRAP_OBJS))
++__BOOTSTRAP_LIBS := $(subst $(obj),,$(BOOTSTRAP_LIBS)) $(subst $(obj),,$(BOOTSTRAP_LIBBOARD))
++
+ #########################################################################
+ #########################################################################
+
+ # Always append ALL so that arch config.mk's can add custom ones
+ ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND)
+
++ifeq ($(CONFIG_BOOTSTRAP),y)
++ALL += $(obj)u-boot-bootstrap.srec $(obj)u-boot-bootstrap.bin
++endif
++
+ all: $(ALL)
+
+ $(obj)u-boot.hex: $(obj)u-boot
+@@ -306,6 +341,19 @@
+ $(obj)u-boot.bin: $(obj)u-boot
+ $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
+
++$(obj)u-boot.bin.gz: $(obj)u-boot.bin
++ gzip -c $< > $@
++
++$(obj)u-boot.bin.lzma: $(obj)u-boot.bin
++ echo lzma -e -z -c $< $@
++ lzma e $< $@
++
++$(obj)u-boot.bin.lzo: $(obj)u-boot.bin
++ lzop -9 -c $< > $@
++
++$(obj)u-boot.bin.bz2: $(obj)u-boot.bin
++ bzip2 --best -z -c $< > $@
++
+ $(obj)u-boot.ldr: $(obj)u-boot
+ $(CREATE_LDR_ENV)
+ $(LDR) -T $(CONFIG_BFIN_CPU) -c $@ $< $(LDR_FLAGS)
+@@ -335,12 +383,12 @@
+ $(obj)tools/ubsha1 $(obj)u-boot.bin
+
+ $(obj)u-boot.dis: $(obj)u-boot
+- $(OBJDUMP) -d $< > $@
++ $(OBJDUMP) -S -d $< > $@
+
+ GEN_UBOOT = \
+ UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
+ sed -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
+- cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
++ cd $(LNDIR) && $(LD) --gc-sections $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
+ --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
+ -Map u-boot.map -o u-boot
+ $(obj)u-boot: depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds
+@@ -362,6 +410,120 @@
+ $(LIBBOARD): depend $(LIBS)
+ $(MAKE) -C $(dir $(subst $(obj),,$@))
+
++# Bootstrap targets
++
++ifeq ($(CONFIG_BOOTSTRAP),y)
++$(obj)u-boot-bootstrap.hex: $(obj)u-boot-bootstrap
++ $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@
++
++$(obj)u-boot-bootstrap.srec: $(obj)u-boot-bootstrap
++ $(OBJCOPY) -O srec $< $@
++
++$(obj)u-boot-bootstrap.bin: $(obj)u-boot-bootstrap
++ $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
++ $(BOARD_SIZE_CHECK)
++
++$(obj)u-boot-bootstrap.bin.gz: $(obj)u-boot-bootstrap.bin
++ gzip -c $< > $@
++
++$(obj)u-boot-bootstrap.bin.lzma: $(obj)u-boot-bootstrap.bin
++ lzma -e -z -c $< > $@
++
++$(obj)u-boot.bin-bootstrap.lzo: $(obj)u-boot-bootstrap.bin
++ lzop -9 -c $< > $@
++
++$(obj)u-boot.bin-bootstrap.bz2: $(obj)u-boot-bootstrap.bin
++ bzip2 --best -z -c $< > $@
++
++$(obj)u-boot-bootstrap.ldr: $(obj)u-boot-bootstrap
++ $(CREATE_LDR_ENV)
++ $(LDR) -T $(CONFIG_BFIN_CPU) -c $@ $< $(LDR_FLAGS)
++ $(BOARD_SIZE_CHECK)
++
++$(obj)u-boot-bootstrap.ldr.hex: $(obj)u-boot-bootstrap.ldr
++ $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ -I binary
++
++$(obj)u-boot-bootstrap.ldr.srec: $(obj)u-boot-bootstrap.ldr
++ $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ -I binary
++
++$(obj)u-boot-bootstrap.img: $(obj)u-boot-bootstrap.bin
++ $(obj)tools/mkimage -A $(ARCH) -T firmware -C none \
++ -a $(CONFIG_BOOTSTRAP_BASE) -e 0 \
++ -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
++ sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \
++ -d $< $@
++
++$(obj)u-boot-bootstrap.imx: $(obj)u-boot-bootstrap.bin
++ $(obj)tools/mkimage -n $(IMX_CONFIG) -T imximage \
++ -e $(CONFIG_BOOTSTRAP_BASE) -d $< $@
++
++$(obj)u-boot-bootstrap.kwb: $(obj)u-boot-bootstrap.bin
++ $(obj)tools/mkimage -n $(CONFIG_SYS_KWD_CONFIG) -T kwbimage \
++ -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) -d $< $@
++
++$(obj)u-boot-bootstrap.sha1: $(obj)u-boot-bootstrap.bin
++ $(obj)tools/ubsha1 $(obj)u-boot-bootstrap.bin
++
++$(obj)u-boot-bootstrap.dis: $(obj)u-boot-bootstrap
++ echo $(OBJDUMP) -S -d $< > $@
++ $(OBJDUMP) -S -d $< > $@
++
++PAYLOAD_FILE_BASE=$(obj)u-boot.bin
++ifeq ($(CONFIG_BOOTSTRAP_GZIP),y)
++PAYLOAD_FILE_EXT:=.gz
++endif
++ifeq ($(CONFIG_BOOTSTRAP_LZMA),y)
++PAYLOAD_FILE_EXT:=.lzma
++endif
++ifeq ($(CONFIG_BOOTSTRAP_LZO),y)
++PAYLOAD_FILE_EXT:=.lzo
++endif
++ifeq ($(CONFIG_BOOTSTRAP_BZIP2),y)
++PAYLOAD_FILE_EXT:=.bz2
++endif
++
++PAYLOAD_FILE := $(PAYLOAD_FILE_BASE)$(PAYLOAD_FILE_EXT)
++
++$(obj).payload.s: $(PAYLOAD_FILE)
++ echo ".globl payload_start" > $@
++ echo ".globl payload_end" >> $@
++ echo ".globl payload_size" >> $@
++ echo ".globl payload_uncsize" >> $@
++ echo .section .payload,\"a\",@progbits >> $@
++ echo "payload_size:" >> $@
++ echo -n ".word " >> $@
++ wc -c $(PAYLOAD_FILE) | cut -f1 -d' ' >> $@
++ echo "payload_uncsize:" >> $@
++ echo -n ".word " >> $@
++ wc -c $(obj)u-boot.bin | cut -f1 -d' ' >> $@
++ echo "payload_start:" >> $@
++ echo .incbin \"$(PAYLOAD_FILE)\" >> $@
++ echo "payload_end:" >> $@
++
++
++GEN_UBOOT_BOOTSTRAP = \
++ UNDEF_SYM=`$(OBJDUMP) -x $(BOOTSTRAP_LIBBOARD) $(BOOTSTRAP_LIBS) | \
++ sed -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
++ cd $(LNDIR) && $(LD) --gc-sections $(BOOTSTRAP_LDFLAGS) $$UNDEF_SYM $(obj).payload.o $(__BOOTSTRAP_OBJS) \
++ --start-group $(__BOOTSTRAP_LIBS) --end-group $(BOOTSTRAP_PLATFORM_LIBS) \
++ -Map u-boot-bootstrap.map -o u-boot-bootstrap
++
++$(obj)u-boot-bootstrap: depend $(SUBDIRS) $(BOOTSTRAP_OBJS) $(BOOTSTRAP_LIBS) $(BOOTSTRAP_LDSCRIPT) $(obj)u-boot-bootstrap.lds $(obj).payload.o #$(BOOTSTRAP_LIBBOARD)
++ #echo "--------$(BOOTSTRAP_LIBBOARD)"
++ #echo "$(GEN_UBOOT_BOOTSTRAP)"
++ $(GEN_UBOOT_BOOTSTRAP)
++ifeq ($(CONFIG_KALLSYMS),y)
++ smap=`$(call SYSTEM_MAP,u-boot-bootstrap) | \
++ awk '$$2 ~ /[tTwW]/ {printf $$1 $$3 "\\\\000"}'` ; \
++ $(CC) $(CFLAGS) -DSYSTEM_MAP="\"$${smap}\"" \
++ -c common/system_map.c -o $(obj)common/system_map.o
++ $(GEN_UBOOT_BOOTSTRAP) $(obj)common/system_map.o
++endif
++
++$(BOOTSTRAP_LIBBOARD): depend $(BOOTSTRAP_LIBS)
++ $(MAKE) -C $(dir $(subst $(obj),,$@)) $(notdir $@)
++endif
++
+ $(SUBDIRS): depend
+ $(MAKE) -C $@ all
+
+@@ -371,6 +533,9 @@
+ $(obj)u-boot.lds: $(LDSCRIPT)
+ $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$^ >$@
+
++$(obj)u-boot-bootstrap.lds: $(BOOTSTRAP_LDSCRIPT)
++ $(CPP) $(CPPFLAGS) $(BOOTSTRAP_LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$^ >$@
++
+ $(NAND_SPL): $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mk
+ $(MAKE) -C nand_spl/board/$(BOARDDIR) all
+
+@@ -3829,6 +3994,7 @@
+ $(obj)board/netstar/{eeprom,crcek,crcit,*.srec,*.bin} \
+ $(obj)board/trab/trab_fkt $(obj)board/voiceblue/eeprom \
+ $(obj)board/armltd/{integratorap,integratorcp}/u-boot.lds \
++ $(obj)u-boot-bootstrap.lds \
+ $(obj)lib_blackfin/u-boot.lds \
+ $(obj)u-boot.lds \
+ $(obj)cpu/blackfin/bootrom-asm-offsets.[chs]
+@@ -3853,6 +4019,12 @@
+ @rm -f $(obj)u-boot $(obj)u-boot.map $(obj)u-boot.hex $(ALL)
+ @rm -f $(obj)u-boot.kwb
+ @rm -f $(obj)u-boot.imx
++ @rm -f $(obj)u-boot.bin{.gz,.lzma,.lzo,.bz2}
++ @rm -f $(obj)u-boot-bootstrap $(obj)u-boot-bootstrap.map $(obj)u-boot-bootstrap.hex
++ @rm -f $(obj)u-boot-bootstrap.kwb
++ @rm -f $(obj)u-boot-bootstrap.imx
++ @rm -f $(obj)u-boot-bootstrap.bin{.gz,.lzma,.lzo,.bz2}
++ @rm -f $(obj).payload.s
+ @rm -f $(obj)tools/{env/crc32.c,inca-swap-bytes}
+ @rm -f $(obj)cpu/mpc824x/bedbug_603e.c
+ @rm -f $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm
+--- a/lib_mips/config.mk
++++ b/lib_mips/config.mk
+@@ -47,6 +47,6 @@
+ # On the other hand, we want PIC in the U-Boot code to relocate it from ROM
+ # to RAM. $28 is always used as gp.
+ #
+-PLATFORM_CPPFLAGS += -G 0 -mabicalls -fpic
++PLATFORM_CPPFLAGS += -G 0 -mabicalls -fpic -g
+ PLATFORM_CPPFLAGS += -msoft-float
+ PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib
+--- /dev/null
++++ b/cpu/mips/reset.c
+@@ -0,0 +1,39 @@
++/*
++ * (C) Copyright 2003
++ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#include <common.h>
++#include <command.h>
++#include <asm/mipsregs.h>
++#include <asm/reboot.h>
++
++void __attribute__((weak)) _machine_restart(void)
++{
++}
++
++int __attribute__((weak)) do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
++{
++ _machine_restart();
++
++ fprintf(stderr, "*** reset failed ***\n");
++ return 0;
++}
+--- /dev/null
++++ b/cpu/mips/reset_bootstrap.c
+@@ -0,0 +1,39 @@
++/*
++ * (C) Copyright 2003
++ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#include <common.h>
++#include <command.h>
++#include <asm/mipsregs.h>
++#include <asm/reboot.h>
++
++void __attribute__((weak)) _machine_restart(void)
++{
++}
++
++int __attribute__((weak)) do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
++{
++ _machine_restart();
++
++ printf("*** reset failed ***\n");
++ return 0;
++}
+--- /dev/null
++++ b/cpu/mips/start_bootstrap.S
+@@ -0,0 +1,534 @@
++/*
++ * Startup Code for MIPS32 CPU-core base on start.S source
++ *
++ * Copyright (c) 2010 Industrie Dial Face S.p.A.
++ * Luigi 'Comio' Mantellini <luigi.mantellini@idf-hit.com>
++ *
++ * Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++//#include <generated/generic-asm-offsets.h>
++#include <config.h>
++#include <asm/regdef.h>
++//#include <asm/mipsregs.h>
++#define CP0_INDEX $0
++#define CP0_RANDOM $1
++#define CP0_ENTRYLO0 $2
++#define CP0_ENTRYLO1 $3
++#define CP0_CONF $3
++#define CP0_CONTEXT $4
++#define CP0_PAGEMASK $5
++#define CP0_WIRED $6
++#define CP0_INFO $7
++#define CP0_BADVADDR $8
++#define CP0_COUNT $9
++#define CP0_ENTRYHI $10
++#define CP0_COMPARE $11
++#define CP0_STATUS $12
++#define CP0_CAUSE $13
++#define CP0_EPC $14
++#define CP0_PRID $15
++#define CP0_EBASE $15,1
++#define CP0_CONFIG $16
++#define CP0_LLADDR $17
++#define CP0_WATCHLO $18
++#define CP0_WATCHHI $19
++#define CP0_XCONTEXT $20
++#define CP0_FRAMEMASK $21
++#define CP0_DIAGNOSTIC $22
++#define CP0_DEBUG $23
++#define CP0_DEPC $24
++#define CP0_PERFORMANCE $25
++#define CP0_ECC $26
++#define CP0_CACHEERR $27
++#define CP0_TAGLO $28
++#define CP0_TAGHI $29
++#define CP0_ERROREPC $30
++#define CP0_DESAVE $31
++#define ST0_CU0 0x10000000
++#define CONF_CM_UNCACHED 2
++#define CONF_CM_CACHABLE_NONCOHERENT 3
++#define EBASEB_CPUNUM 0
++#define EBASEF_CPUNUM (0x3ff << EBASEB_CPUNUM)
++#define MIPS_CONF7_RPS 4 //((unsigned long)(1) << 2)
++#define CONF_CM_CACHABLE_NONCOHERENT 3
++#ifndef CONFIG_SYS_MIPS_CACHE_OPER_MODE
++#define CONFIG_SYS_MIPS_CACHE_OPER_MODE CONF_CM_CACHABLE_NONCOHERENT
++#endif
++
++ /*
++ * For the moment disable interrupts, mark the kernel mode and
++ * set ST0_KX so that the CPU does not spit fire when using
++ * 64-bit addresses.
++ */
++ .macro setup_c0_status set clr
++ .set push
++ mfc0 t0, CP0_STATUS
++ or t0, ST0_CU0 | \set | 0x1f | \clr
++ xor t0, 0x1f | \clr
++ mtc0 t0, CP0_STATUS
++ .set noreorder
++ sll zero, 3 # ehb
++ .set pop
++ .endm
++
++ .macro setup_c0_status_reset
++#ifdef CONFIG_64BIT
++ setup_c0_status ST0_KX 0
++#else
++ setup_c0_status 0 0
++#endif
++ .endm
++
++#define RVECENT(f,n) \
++ b f; nop
++#define XVECENT(f,bev) \
++ b f ; \
++ li k0,bev
++
++ .set noreorder
++
++ .globl _start
++ .text
++_start:
++ RVECENT(reset,0) /* U-boot entry point */
++ RVECENT(reset,1) /* software reboot */
++#if defined(CONFIG_INCA_IP)
++ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
++ .word 0x00000000 /* phase of the flash */
++#elif defined(CONFIG_PURPLE)
++ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
++ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
++#else
++ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
++ .word 0x00000000 /* phase of the flash */
++#endif
++ RVECENT(romReserved,3)
++ RVECENT(romReserved,4)
++ RVECENT(romReserved,5)
++ RVECENT(romReserved,6)
++ RVECENT(romReserved,7)
++ RVECENT(romReserved,8)
++ RVECENT(romReserved,9)
++ RVECENT(romReserved,10)
++ RVECENT(romReserved,11)
++ RVECENT(romReserved,12)
++ RVECENT(romReserved,13)
++ RVECENT(romReserved,14)
++ RVECENT(romReserved,15)
++ RVECENT(romReserved,16)
++ RVECENT(romReserved,17)
++ RVECENT(romReserved,18)
++ RVECENT(romReserved,19)
++ RVECENT(romReserved,20)
++ RVECENT(romReserved,21)
++ RVECENT(romReserved,22)
++ RVECENT(romReserved,23)
++ RVECENT(romReserved,24)
++ RVECENT(romReserved,25)
++ RVECENT(romReserved,26)
++ RVECENT(romReserved,27)
++ RVECENT(romReserved,28)
++ RVECENT(romReserved,29)
++ RVECENT(romReserved,30)
++ RVECENT(romReserved,31)
++ RVECENT(romReserved,32)
++ RVECENT(romReserved,33)
++ RVECENT(romReserved,34)
++ RVECENT(romReserved,35)
++ RVECENT(romReserved,36)
++ RVECENT(romReserved,37)
++ RVECENT(romReserved,38)
++ RVECENT(romReserved,39)
++ RVECENT(romReserved,40)
++ RVECENT(romReserved,41)
++ RVECENT(romReserved,42)
++ RVECENT(romReserved,43)
++ RVECENT(romReserved,44)
++ RVECENT(romReserved,45)
++ RVECENT(romReserved,46)
++ RVECENT(romReserved,47)
++ RVECENT(romReserved,48)
++ RVECENT(romReserved,49)
++ RVECENT(romReserved,50)
++ RVECENT(romReserved,51)
++ RVECENT(romReserved,52)
++ RVECENT(romReserved,53)
++ RVECENT(romReserved,54)
++ RVECENT(romReserved,55)
++ RVECENT(romReserved,56)
++ RVECENT(romReserved,57)
++ RVECENT(romReserved,58)
++ RVECENT(romReserved,59)
++ RVECENT(romReserved,60)
++ RVECENT(romReserved,61)
++ RVECENT(romReserved,62)
++ RVECENT(romReserved,63)
++ XVECENT(romExcHandle,0x200) /* bfc00200: R4000 tlbmiss vector */
++ RVECENT(romReserved,65)
++ RVECENT(romReserved,66)
++ RVECENT(romReserved,67)
++ RVECENT(romReserved,68)
++ RVECENT(romReserved,69)
++ RVECENT(romReserved,70)
++ RVECENT(romReserved,71)
++ RVECENT(romReserved,72)
++ RVECENT(romReserved,73)
++ RVECENT(romReserved,74)
++ RVECENT(romReserved,75)
++ RVECENT(romReserved,76)
++ RVECENT(romReserved,77)
++ RVECENT(romReserved,78)
++ RVECENT(romReserved,79)
++ XVECENT(romExcHandle,0x280) /* bfc00280: R4000 xtlbmiss vector */
++ RVECENT(romReserved,81)
++ RVECENT(romReserved,82)
++ RVECENT(romReserved,83)
++ RVECENT(romReserved,84)
++ RVECENT(romReserved,85)
++ RVECENT(romReserved,86)
++ RVECENT(romReserved,87)
++ RVECENT(romReserved,88)
++ RVECENT(romReserved,89)
++ RVECENT(romReserved,90)
++ RVECENT(romReserved,91)
++ RVECENT(romReserved,92)
++ RVECENT(romReserved,93)
++ RVECENT(romReserved,94)
++ RVECENT(romReserved,95)
++ XVECENT(romExcHandle,0x300) /* bfc00300: R4000 cache vector */
++ RVECENT(romReserved,97)
++ RVECENT(romReserved,98)
++ RVECENT(romReserved,99)
++ RVECENT(romReserved,100)
++ RVECENT(romReserved,101)
++ RVECENT(romReserved,102)
++ RVECENT(romReserved,103)
++ RVECENT(romReserved,104)
++ RVECENT(romReserved,105)
++ RVECENT(romReserved,106)
++ RVECENT(romReserved,107)
++ RVECENT(romReserved,108)
++ RVECENT(romReserved,109)
++ RVECENT(romReserved,110)
++ RVECENT(romReserved,111)
++ XVECENT(romExcHandle,0x380) /* bfc00380: R4000 general vector */
++ RVECENT(romReserved,113)
++ RVECENT(romReserved,114)
++ RVECENT(romReserved,115)
++ RVECENT(romReserved,116)
++ RVECENT(romReserved,116)
++ RVECENT(romReserved,118)
++ RVECENT(romReserved,119)
++ RVECENT(romReserved,120)
++ RVECENT(romReserved,121)
++ RVECENT(romReserved,122)
++ RVECENT(romReserved,123)
++ RVECENT(romReserved,124)
++ RVECENT(romReserved,125)
++ RVECENT(romReserved,126)
++ RVECENT(romReserved,127)
++
++ /* We hope there are no more reserved vectors!
++ * 128 * 8 == 1024 == 0x400
++ * so this is address R_VEC+0x400 == 0xbfc00400
++ */
++#if 1
++ XVECENT(romExcHandle,0x400); /* bfc00400: Int, CauseIV=1 */
++ RVECENT(romReserved,129);
++ RVECENT(romReserved,130);
++ RVECENT(romReserved,131);
++ RVECENT(romReserved,132);
++ RVECENT(romReserved,133);
++ RVECENT(romReserved,134);
++ RVECENT(romReserved,135);
++ RVECENT(romReserved,136);
++ RVECENT(romReserved,137);
++ RVECENT(romReserved,138);
++ RVECENT(romReserved,139);
++ RVECENT(romReserved,140);
++ RVECENT(romReserved,141);
++ RVECENT(romReserved,142);
++ RVECENT(romReserved,143);
++ XVECENT(romExcHandle,0x480); /* bfc00480: EJTAG debug exception */
++#elif defined(CONFIG_PURPLE)
++/* 0xbfc00400 */
++ .word 0xdc870000
++ .word 0xfca70000
++ .word 0x20840008
++ .word 0x20a50008
++ .word 0x20c6ffff
++ .word 0x14c0fffa
++ .word 0x00000000
++ .word 0x03e00008
++ .word 0x00000000
++ .word 0x00000000
++/* 0xbfc00428 */
++ .word 0xdc870000
++ .word 0xfca70000
++ .word 0x20840008
++ .word 0x20a50008
++ .word 0x20c6ffff
++ .word 0x14c0fffa
++ .word 0x00000000
++ .word 0x03e00008
++ .word 0x00000000
++ .word 0x00000000
++#endif /* CONFIG_PURPLE */
++ .align 4
++reset:
++#ifdef CONFIG_SYS_MIPS_MULTI_CPU
++ mfc0 k0, CP0_EBASE
++ and k0, EBASEF_CPUNUM
++ bne k0, zero, ifx_mips_handler_cpux
++ nop
++#endif
++ /* Clear watch registers.
++ */
++ mtc0 zero, CP0_WATCHLO
++ mtc0 zero, CP0_WATCHHI
++
++ /* WP(Watch Pending), SW0/1 should be cleared. */
++ mtc0 zero, CP0_CAUSE
++
++ setup_c0_status_reset
++#if defined(CONFIG_MIPS24KEC) || defined(CONFIG_MIPS34KC)
++ /* CONFIG7 register */
++ /* Erratum "RPS May Cause Incorrect Instruction Execution"
++ * for 24KEC and 34KC */
++ mfc0 k0, CP0_CONFIG, 7
++ li k1, MIPS_CONF7_RPS
++ or k0, k1
++ mtc0 k0, CP0_CONFIG, 7
++#endif
++
++ /* Init Timer */
++ mtc0 zero, CP0_COUNT
++ mtc0 zero, CP0_COMPARE
++
++ /* CONFIG0 register */
++ li t0, CONF_CM_UNCACHED
++ mtc0 t0, CP0_CONFIG
++
++ /* Initialize $gp.
++ */
++ bal 1f
++ nop
++ .word _gp
++1:
++ lw gp, 0(ra)
++
++ /* Initialize any external memory.
++ */
++ la t9, lowlevel_init
++ jalr t9
++ nop
++
++ /* Initialize caches...
++ */
++ la t9, mips_cache_reset
++ jalr t9
++ nop
++
++ /* ... and enable them.
++ */
++ li t0, CONF_CM_CACHABLE_NONCOHERENT /*CONFIG_SYS_MIPS_CACHE_OPER_MODE*/
++ mtc0 t0, CP0_CONFIG
++
++ /* Set up temporary stack.
++ */
++#ifdef CONFIG_SYS_INIT_RAM_LOCK_MIPS
++ li a0, CONFIG_SYS_INIT_SP_OFFSET
++ la t9, mips_cache_lock
++ jalr t9
++ nop
++#endif
++
++ li t0, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
++ la sp, 0(t0)
++
++ la t9, bootstrap_board_init_f
++ jr t9
++ nop
++
++/*
++ * void relocate_code (addr_sp, gd, addr_moni)
++ *
++ * This "function" does not return, instead it continues in RAM
++ * after relocating the monitor code.
++ *
++ * a0 = addr_sp
++ * a1 = gd
++ * a2 = destination address
++ */
++ .globl relocate_code
++ .ent relocate_code
++relocate_code:
++ move sp, a0 /* Set new stack pointer */
++
++ li t0, CONFIG_BOOTSTRAP_TEXT_BASE
++ la t3, in_ram
++ lw t2, -12(t3) /* t2 <-- uboot_end_data */
++ move t1, a2
++ move s2, a2 /* s2 <-- destination address */
++
++ /*
++ * Fix $gp:
++ *
++ * New $gp = (Old $gp - CONFIG_SYS_MONITOR_BASE) + Destination Address
++ */
++ move t6, gp
++ sub gp, CONFIG_BOOTSTRAP_TEXT_BASE
++ add gp, a2 /* gp now adjusted */
++ sub s1, gp, t6 /* s1 <-- relocation offset */
++
++ /*
++ * t0 = source address
++ * t1 = target address
++ * t2 = source end address
++ */
++
++ /*
++ * Save destination address and size for later usage in flush_cache()
++ */
++ move s0, a1 /* save gd in s0 */
++ move a0, t1 /* a0 <-- destination addr */
++ sub a1, t2, t0 /* a1 <-- size */
++
++ /* On the purple board we copy the code earlier in a special way
++ * in order to solve flash problems
++ */
++#ifndef CONFIG_PURPLE
++1:
++ lw t3, 0(t0)
++ sw t3, 0(t1)
++ addu t0, 4
++ ble t0, t2, 1b
++ addu t1, 4 /* delay slot */
++#endif
++
++ /* If caches were enabled, we would have to flush them here.
++ */
++
++ /* a0 & a1 are already set up for flush_cache(start, size) */
++ la t9, flush_cache
++ jalr t9
++ nop
++
++ /* Jump to where we've relocated ourselves.
++ */
++ addi t0, s2, in_ram - _start
++ jr t0
++ nop
++
++ .word _gp
++ .word _GLOBAL_OFFSET_TABLE_
++ .word uboot_end_data
++ .word uboot_end
++ .word num_got_entries
++
++in_ram:
++ /*
++ * Now we want to update GOT.
++ *
++ * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
++ * generated by GNU ld. Skip these reserved entries from relocation.
++ */
++ lw t3, -4(t0) /* t3 <-- num_got_entries */
++ lw t4, -16(t0) /* t4 <-- _GLOBAL_OFFSET_TABLE_ */
++ lw t5, -20(t0) /* t5 <-- _gp */
++ sub t4, t5 /* compute offset*/
++ add t4, t4, gp /* t4 now holds relocated _GLOBAL_OFFSET_TABLE_ */
++ addi t4, t4, 8 /* Skipping first two entries. */
++ li t2, 2
++1:
++ lw t1, 0(t4)
++ beqz t1, 2f
++ add t1, s1
++ sw t1, 0(t4)
++2:
++ addi t2, 1
++ blt t2, t3, 1b
++ addi t4, 4 /* delay slot */
++
++ /* Clear BSS.
++ */
++ lw t1, -12(t0) /* t1 <-- uboot_end_data */
++ lw t2, -8(t0) /* t2 <-- uboot_end */
++ add t1, s1 /* adjust pointers */
++ add t2, s1
++
++ sub t1, 4
++1:
++ addi t1, 4
++ bltl t1, t2, 1b
++ sw zero, 0(t1) /* delay slot */
++
++ move a0, s0 /* a0 <-- gd */
++ la t9, bootstrap_board_init_r
++ jr t9
++ move a1, s2 /* delay slot */
++
++ .end relocate_code
++
++/*
++ * void copy_and_jump (void)
++ *
++ * This function copies/unzips the u-boot image and runs it.
++ * This "function" does not return
++ *
++*/
++ .globl copy_and_jump
++ .ent copy_and_jump
++copy_and_jump:
++
++ /* copy_uboot(CONFIG_SYS_MONITOR_BASE, payload_uncsize, payload_start, payload_size) */
++ li a0, CONFIG_SYS_MONITOR_BASE
++ la a1, payload_uncsize
++ lw a1, 0(a1)
++ la a2, payload_start
++ la a3, payload_size
++ la t9, copy_uboot
++ jalr t9
++ lw a3, 0(a3) /* delay slot */
++
++ li t9, CONFIG_SYS_MONITOR_BASE
++ jr t9
++ nop
++
++ .end copy_and_jump
++
++ /* Exception handlers.
++ */
++romReserved:
++ b romReserved
++
++romExcHandle:
++ b romExcHandle
++#ifdef CONFIG_SYS_MIPS_MULTI_CPU
++/*
++ * Stop Slave CPUs
++ */
++ifx_mips_handler_cpux:
++ wait;
++ b ifx_mips_handler_cpux;
++ nop;
++#endif
+--- a/lib_mips/Makefile
++++ b/lib_mips/Makefile
+@@ -24,6 +24,9 @@
+ include $(TOPDIR)/config.mk
+
+ LIB = $(obj)lib$(ARCH).a
++BOOTSTRAP_LIB = $(obj)lib$(ARCH)_bootstrap.a
++
++BOOTSTRAP_LIB-$(CONFIG_BOOTSTRAP) = $(BOOTSTRAP_LIB)
+
+ SOBJS-y +=
+
+@@ -35,12 +38,21 @@
+ endif
+ COBJS-y += time.o
+
+-SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += board_bootstrap.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += time.o
++
++BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_SOBJS-y) $(BOOTSTRAP_COBJS-y))
++
++SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) $(BOOTSTRAP_SOBJS-y:.o=.S) $(BOOTSTRAP_COBJS-y:.o=.c)
+ OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
++all: $(obj).depend $(LIB) $(BOOTSTRAP_LIB)
+ $(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
++$(BOOTSTRAP_LIB): $(obj).depend $(BOOTSTRAP_OBJS)
++ $(AR) $(ARFLAGS) $@ $(BOOTSTRAP_OBJS)
++
+ #########################################################################
+
+ # defines $(obj).depend target
+--- /dev/null
++++ b/lib_mips/board_bootstrap.c
+@@ -0,0 +1,270 @@
++/*
++ * (C) Copyright 2010 Industrie Dial Face S.p.A.
++ * Luigi 'Comio' Mantellini, luigi.mantellini@idf-hit.com
++ *
++ * (C) Copyright 2003
++ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#include <common.h>
++#include <command.h>
++#include <malloc.h>
++#include <stdio_dev.h>
++
++DECLARE_GLOBAL_DATA_PTR;
++
++extern int timer_init(void);
++
++extern int incaip_set_cpuclk(void);
++
++extern ulong uboot_end_data;
++extern ulong uboot_end;
++
++#ifdef CONFIG_BOOTSTRAP_SERIAL
++static char *failed = "*** failed ***\n";
++#endif
++/*
++ * mips_io_port_base is the begin of the address space to which x86 style
++ * I/O ports are mapped.
++ */
++unsigned long mips_io_port_base = -1;
++
++int __board_early_init_f(void)
++{
++ /*
++ * Nothing to do in this dummy implementation
++ */
++ return 0;
++}
++
++int board_early_init_f(void) __attribute__((weak, alias("__board_early_init_f")));
++int bootstrap_board_early_init_f(void) __attribute__((weak, alias("board_early_init_f")));
++
++static int bootstrap_init_func_ram (void)
++{
++ if ((gd->ram_size = bootstrap_initdram (0)) > 0) {
++ return (0);
++ }
++#ifdef CONFIG_BOOTSTRAP_SERIAL
++ puts (failed);
++#endif
++ return (1);
++}
++
++static int bootstrap_display_banner(void)
++{
++#ifdef CONFIG_BOOTSTRAP_SERIAL
++ puts ("bootstrap...");
++#endif
++ return (0);
++}
++
++static int bootstrap_init_baudrate (void)
++{
++#if defined(CONFIG_BOOTSTRAP_BAUDRATE)
++ gd->baudrate = CONFIG_BOOTSTRAP_BAUDRATE;
++#else
++ gd->baudrate = CONFIG_BAUDRATE;
++#endif
++ return 0;
++}
++
++/*
++ * Breath some life into the board...
++ *
++ * The first part of initialization is running from Flash memory;
++ * its main purpose is to initialize the RAM so that we
++ * can relocate the monitor code to RAM.
++ */
++
++/*
++ * All attempts to come up with a "common" initialization sequence
++ * that works for all boards and architectures failed: some of the
++ * requirements are just _too_ different. To get rid of the resulting
++ * mess of board dependend #ifdef'ed code we now make the whole
++ * initialization sequence configurable to the user.
++ *
++ * The requirements for any new initalization function is simple: it
++ * receives a pointer to the "global data" structure as it's only
++ * argument, and returns an integer return code, where 0 means
++ * "continue" and != 0 means "fatal error, hang the system".
++ */
++typedef int (init_fnc_t) (void);
++
++static init_fnc_t *init_sequence[] = {
++ bootstrap_board_early_init_f,
++ timer_init,
++ bootstrap_init_baudrate,/* initialze baudrate settings */
++#ifdef CONFIG_BOOTSTRAP_SERIAL
++ serial_init, /* serial communications setup */
++#endif
++ bootstrap_display_banner, /* say that we are here */
++ bootstrap_checkboard,
++ bootstrap_init_func_ram,
++ NULL,
++};
++
++
++void bootstrap_board_init_f(ulong bootflag)
++{
++ gd_t gd_data, *id;
++ bd_t *bd;
++ init_fnc_t **init_fnc_ptr;
++ ulong addr, addr_sp, len = (ulong)&uboot_end - CONFIG_BOOTSTRAP_TEXT_BASE;
++ ulong *s;
++
++ /* Pointer is writable since we allocated a register for it.
++ */
++ gd = &gd_data;
++ /* compiler optimization barrier needed for GCC >= 3.4 */
++ __asm__ __volatile__("": : :"memory");
++
++ memset ((void *)gd, 0, sizeof (gd_t));
++
++ for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
++ if ((*init_fnc_ptr)() != 0) {
++ bootstrap_hang ();
++ }
++ }
++
++ /*
++ * Now that we have DRAM mapped and working, we can
++ * relocate the code and continue running from DRAM.
++ */
++ addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
++
++ /* We can reserve some RAM "on top" here.
++ */
++
++ /* round down to next 4 kB limit.
++ */
++ addr &= ~(4096 - 1);
++ debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);
++
++ /* Reserve memory for U-Boot code, data & bss
++ * round down to next 16 kB limit
++ */
++ addr -= len;
++ addr &= ~(16 * 1024 - 1);
++
++ debug ("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
++
++ /* Reserve memory for malloc() arena.
++ */
++ addr_sp = addr - CONFIG_SYS_MALLOC_LEN;
++ debug ("Reserving %dk for malloc() at: %08lx\n",
++ CONFIG_SYS_MALLOC_LEN >> 10, addr_sp);
++
++ /*
++ * (permanently) allocate a Board Info struct
++ * and a permanent copy of the "global" data
++ */
++ addr_sp -= sizeof(bd_t);
++ bd = (bd_t *)addr_sp;
++ gd->bd = bd;
++ debug ("Reserving %zu Bytes for Board Info at: %08lx\n",
++ sizeof(bd_t), addr_sp);
++
++ addr_sp -= sizeof(gd_t);
++ id = (gd_t *)addr_sp;
++ debug ("Reserving %zu Bytes for Global Data at: %08lx\n",
++ sizeof (gd_t), addr_sp);
++
++ /* Reserve memory for boot params.
++ */
++ addr_sp -= CONFIG_SYS_BOOTPARAMS_LEN;
++ bd->bi_boot_params = addr_sp;
++ debug ("Reserving %dk for boot params() at: %08lx\n",
++ CONFIG_SYS_BOOTPARAMS_LEN >> 10, addr_sp);
++
++ /*
++ * Finally, we set up a new (bigger) stack.
++ *
++ * Leave some safety gap for SP, force alignment on 16 byte boundary
++ * Clear initial stack frame
++ */
++ addr_sp -= 16;
++ addr_sp &= ~0xF;
++ s = (ulong *)addr_sp;
++ *s-- = 0;
++ *s-- = 0;
++ addr_sp = (ulong)s;
++ debug ("Stack Pointer at: %08lx\n", addr_sp);
++
++ /*
++ * Save local variables to board info struct
++ */
++ bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; /* start of DRAM memory */
++ bd->bi_memsize = gd->ram_size; /* size of DRAM memory in bytes */
++ bd->bi_baudrate = gd->baudrate; /* Console Baudrate */
++
++ memcpy (id, (void *)gd, sizeof (gd_t));
++
++ /* On the purple board we copy the code in a special way
++ * in order to solve flash problems
++ */
++ relocate_code (addr_sp, id, addr);
++
++ /* NOTREACHED - relocate_code() does not return */
++}
++/************************************************************************
++ *
++ * This is the next part if the initialization sequence: we are now
++ * running from RAM and have a "normal" C environment, i. e. global
++ * data can be written, BSS has been cleared, the stack size in not
++ * that critical any more, etc.
++ *
++ ************************************************************************
++ */
++
++void bootstrap_board_init_r (gd_t *id, ulong dest_addr)
++{
++ extern void malloc_bin_reloc (void);
++ extern void copy_and_jump(void);
++
++ bd_t *bd;
++
++ gd = id;
++ gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
++
++ debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
++
++ gd->reloc_off = dest_addr - CONFIG_BOOTSTRAP_TEXT_BASE;
++
++ bd = gd->bd;
++
++ /* The Malloc area is immediately below the monitor copy in DRAM */
++ mem_malloc_init(CONFIG_BOOTSTRAP_BASE + gd->reloc_off -
++ CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN);
++ malloc_bin_reloc();
++
++ copy_and_jump();
++
++ /* NOTREACHED - no way out of command loop except booting */
++}
++
++void bootstrap_hang (void)
++{
++#ifdef CONFIG_BOOTSTRAP_SERIAL
++ puts ("### ERROR ### Please RESET the board ###\n");
++#endif
++ for (;;);
++}
+--- a/common/Makefile
++++ b/common/Makefile
+@@ -24,6 +24,9 @@
+ include $(TOPDIR)/config.mk
+
+ LIB = $(obj)libcommon.a
++BOOTSTRAP_LIB = $(obj)libcommon_bootstrap.a
++
++BOOTSTRAP_LIB-$(CONFIG_BOOTSTRAP) = $(BOOTSTRAP_LIB)
+
+ AOBJS =
+
+@@ -168,18 +171,27 @@
+ COBJS-$(CONFIG_UPDATE_TFTP) += update.o
+ COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
+
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += dlmalloc.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_SERIAL) += console_bootstrap.o
++
++BOOTSTRAP_COBJS := $(sort $(BOOTSTRAP_COBJS-y))
++BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_COBJS))
++
+
+ COBJS := $(sort $(COBJS-y))
+-SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c)
++SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c) $(BOOTSTRAP_COBJS:.o=.c)
+ OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS))
+
+ CPPFLAGS += -I..
+
+-all: $(LIB) $(AOBJS)
++all: $(LIB) $(BOOTSTRAP_LIB-y) $(AOBJS)
+
+ $(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
++$(BOOTSTRAP_LIB): $(obj).depend $(BOOTSTRAP_OBJS)
++ $(AR) $(ARFLAGS) $@ $(BOOTSTRAP_OBJS)
++
+ $(obj)env_embedded.o: $(src)env_embedded.c $(obj)../tools/envcrc
+ $(CC) $(AFLAGS) -Wa,--no-warn \
+ -DENV_CRC=$(shell $(obj)../tools/envcrc) \
+--- /dev/null
++++ b/common/console_bootstrap.c
+@@ -0,0 +1,81 @@
++/*
++ * (C) Copyright 2000
++ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#include <common.h>
++#include <stdarg.h>
++#include <malloc.h>
++
++/** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
++
++int getc(void)
++{
++ /* Send directly to the handler */
++ return serial_getc();
++}
++
++int tstc(void)
++{
++ /* Send directly to the handler */
++ return serial_tstc();
++}
++
++void putc(const char c)
++{
++ /* Send directly to the handler */
++ serial_putc(c);
++}
++
++void puts(const char *s)
++{
++ serial_puts(s);
++}
++
++void printf(const char *fmt, ...)
++{
++ va_list args;
++ char printbuffer[CONFIG_SYS_PBSIZE];
++
++ va_start(args, fmt);
++
++ /* For this to work, printbuffer must be larger than
++ * anything we ever want to print.
++ */
++ vsprintf(printbuffer, fmt, args);
++ va_end(args);
++
++ /* Print the string */
++ puts(printbuffer);
++}
++
++void vprintf(const char *fmt, va_list args)
++{
++ char printbuffer[CONFIG_SYS_PBSIZE];
++
++ /* For this to work, printbuffer must be larger than
++ * anything we ever want to print.
++ */
++ vsprintf(printbuffer, fmt, args);
++
++ /* Print the string */
++ puts(printbuffer);
++}
+--- a/config.mk
++++ b/config.mk
+@@ -136,7 +136,7 @@
+ ARFLAGS = crv
+ endif
+ RELFLAGS= $(PLATFORM_RELFLAGS)
+-DBGFLAGS= -g # -DDEBUG
++DBGFLAGS= -g
+ OPTFLAGS= -Os #-fomit-frame-pointer
+ ifndef LDSCRIPT
+ #LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug
+@@ -146,6 +146,11 @@
+ LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
+ endif
+ endif
++ifeq ($(CONFIG_BOOTSTRAP),y)
++ifndef BOOTSTRAP_LDSCRIPT
++BOOTSTRAP_LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-bootstrap.lds
++endif
++endif
+ OBJCFLAGS += --gap-fill=0xff
+
+ gccincdir := $(shell $(CC) -print-file-name=include)
+@@ -156,6 +161,10 @@
+ CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
+ endif
+
++ifneq ($(CONFIG_BOOTSTRAP_TEXT_BASE),)
++CPPFLAGS += -DCONFIG_BOOTSTRAP_TEXT_BASE=$(CONFIG_BOOTSTRAP_TEXT_BASE)
++endif
++
+ ifneq ($(RESET_VECTOR_ADDRESS),)
+ CPPFLAGS += -DRESET_VECTOR_ADDRESS=$(RESET_VECTOR_ADDRESS)
+ endif
+@@ -176,6 +185,7 @@
+ endif
+
+ CFLAGS += $(call cc-option,-fno-stack-protector)
++CFLAGS += $(call cc-option,-ffunction-sections)
+
+ # avoid trigraph warnings while parsing pci.h (produced by NIOS gcc-2.9)
+ # this option have to be placed behind -Wall -- that's why it is here
+@@ -203,6 +213,13 @@
+ LDFLAGS += -Ttext $(TEXT_BASE)
+ endif
+
++ifeq ($(CONFIG_BOOTSTRAP),y)
++BOOTSTRAP_LDFLAGS += -Bstatic -T $(obj)u-boot-bootstrap.lds $(PLATFORM_LDFLAGS)
++ifneq ($(CONFIG_BOOTSTRAP_TEXT_BASE),)
++BOOTSTRAP_LDFLAGS += -Ttext $(CONFIG_BOOTSTRAP_TEXT_BASE)
++endif
++endif
++
+ # Location of a usable BFD library, where we define "usable" as
+ # "built for ${HOST}, supports ${TARGET}". Sensible values are
+ # - When cross-compiling: the root of the cross-environment
+--- a/include/common.h
++++ b/include/common.h
+@@ -722,6 +722,27 @@
+ int cpu_release(int nr, int argc, char *argv[]);
+ #endif
+
++/* Bootstrap specific code */
++#ifdef CONFIG_BOOTSTRAP
++void bootstrap_hang(void) __attribute__ ((noreturn));
++void bootstrap_board_init_f(ulong) __attribute__ ((noreturn));
++void bootstrap_board_init_r(gd_t *, ulong) __attribute__ ((noreturn));
++int bootstrap_checkboard(void);
++
++int bootstrap_serial_init(void);
++void bootstrap_serial_exit(void);
++void bootstrap_serial_setbrg(void);
++void bootstrap_serial_putc(const char);
++void bootstrap_serial_putc_raw(const char);
++void bootstrap_serial_puts(const char *);
++int bootstrap_serial_getc(void);
++int bootstrap_serial_tstc(void);
++
++phys_size_t bootstrap_initdram (int);
++
++int copy_uboot(void *dst, size_t unc_size, void *src, size_t size);
++#endif
++
+ #endif /* __ASSEMBLY__ */
+
+ /* Put only stuff here that the assembler can digest */
+--- a/lib_generic/Makefile
++++ b/lib_generic/Makefile
+@@ -24,6 +24,9 @@
+ include $(TOPDIR)/config.mk
+
+ LIB = $(obj)libgeneric.a
++BOOTSTRAP_LIB = $(obj)libgeneric_bootstrap.a
++
++BOOTSTRAP_LIB-$(CONFIG_BOOTSTRAP) = $(BOOTSTRAP_LIB)
+
+ COBJS-$(CONFIG_ADDR_MAP) += addr_map.o
+ COBJS-$(CONFIG_BZIP2) += bzlib.o
+@@ -50,14 +53,37 @@
+ COBJS-y += vsprintf.o
+ COBJS-$(CONFIG_ZLIB) += zlib.o
+ COBJS-$(CONFIG_RBTREE) += rbtree.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += string.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += vsprintf.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += div64.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += ctype.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += time.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += bootstrap.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_GZIP) += zlib.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_GZIP) += gunzip.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_GZIP) += crc32.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_BZIP2) += bzlib.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_BZIP2) += bzlib_crctable.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_BZIP2) += bzlib_decompress.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_BZIP2) += bzlib_randtable.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_BZIP2) += bzlib_huffman.o
++
++BOOTSTRAP_COBJS := $(BOOTSTRAP_COBJS-y)
++BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_COBJS))
+
+ COBJS := $(COBJS-y)
+-SRCS := $(COBJS:.o=.c)
++SRCS := $(COBJS:.o=.c) $(BOOTSTRAP_COBJS:.o=.c)
+ OBJS := $(addprefix $(obj),$(COBJS))
+
++all: $(obj).depend $(LIB) $(BOOTSTRAP_LIB-y)
++
+ $(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
++$(BOOTSTRAP_LIB): $(obj).depend $(BOOTSTRAP_OBJS)
++ $(AR) $(ARFLAGS) $@ $(BOOTSTRAP_OBJS)
++
++
+ #########################################################################
+
+ # defines $(obj).depend target
+--- /dev/null
++++ b/lib_generic/bootstrap.c
+@@ -0,0 +1,95 @@
++/*
++ * (C) Copyright 2010 Industrie Dial Face S.p.A.
++ * Luigi 'Comio' Mantellini, luigi.mantellini@idf-hit.com
++ *
++ * (C) Copyright 2003
++ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#include <common.h>
++#include <command.h>
++#include <stdio_dev.h>
++
++#ifdef CONFIG_BOOTSTRAP_LZMA
++#include <lzma/LzmaTypes.h>
++#include <lzma/LzmaDec.h>
++#include <lzma/LzmaTools.h>
++#endif /* CONFIG_BOOTSTRAP_LZMA */
++
++#ifdef CONFIG_BOOTSTRAP_LZO
++#include <linux/lzo.h>
++#endif /* CONFIG_BOOTSTRAP_LZO */
++
++#ifdef CONFIG_BOOTSTRAP_BZIP2
++#include <bzlib.h>
++#endif
++
++DECLARE_GLOBAL_DATA_PTR;
++
++#if defined(CONFIG_BOOTSTRAP_SERIAL)
++static const char *algo =
++#if defined(CONFIG_BOOTSTRAP_GZIP)
++ "gzip";
++#elif defined(CONFIG_BOOTSTRAP_LZMA)
++ "lzma";
++#elif defined(CONFIG_BOOTSTRAP_LZO)
++ "lzo";
++#elif defined(CONFIG_BOOTSTRAP_BZIP2)
++ "bzip2";
++#else
++ "flat";
++#endif
++#endif
++
++int copy_uboot(void *dst, size_t unc_size, void *src, size_t size)
++{
++ int ret;
++ debug("copy from %p (%d) to %p (%d)\n", src, size, dst, unc_size);
++#if defined(CONFIG_BOOTSTRAP_SERIAL)
++ printf("Uncompressing payload (%s)...", algo);
++#endif
++#if defined(CONFIG_BOOTSTRAP_GZIP)
++ ret = gunzip(dst, unc_size, src, &size);
++#elif defined(CONFIG_BOOTSTRAP_LZMA)
++ SizeT outsize = unc_size;
++ ret = lzmaBuffToBuffDecompress(dst, &outsize, src, size);
++#elif defined(CONFIG_BOOTSTRAP_LZO)
++ uint unc_len = unc_size;
++ ret = lzop_decompress(src, size, dst, &unc_len);
++#elif defined(CONFIG_BOOTSTRAP_BZIP2)
++ uint unc_len = unc_size;
++ ret = BZ2_bzBuffToBuffDecompress ((char*)dst, &unc_len, (char *)src, size, CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
++#else
++ memcpy(dst, src, size);
++ ret = 0;
++#endif
++ if (ret) {
++#if defined(CONFIG_BOOTSTRAP_SERIAL)
++ printf("failed with error %d.\n", ret);
++#endif
++ bootstrap_hang();
++ } else {
++#if defined(CONFIG_BOOTSTRAP_SERIAL)
++ puts("done.\n");
++#endif
++ }
++ return ret;
++}
+--- a/lib_generic/lzma/Makefile
++++ b/lib_generic/lzma/Makefile
+@@ -32,7 +32,9 @@
+
+ CFLAGS += -D_LZMA_PROB32
+
+-COBJS-$(CONFIG_LZMA) += LzmaDec.o LzmaTools.o
++COBJS-$(CONFIG_LZMA)$(CONFIG_BOOTSTRAP_LZMA) += LzmaDec.o LzmaTools.o
++
++COBJS-y += $(COBJS-yy)
+
+ COBJS = $(COBJS-y)
+ SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+--- a/lib_generic/lzo/Makefile
++++ b/lib_generic/lzo/Makefile
+@@ -27,7 +27,9 @@
+
+ SOBJS =
+
+-COBJS-$(CONFIG_LZO) += lzo1x_decompress.o
++COBJS-$(CONFIG_LZO)$(CONFIG_BOOTSTRAP_LZO) += lzo1x_decompress.o
++
++COBJS-y += $(OBJS-yy)
+
+ COBJS = $(COBJS-y)
+ SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+--- a/cpu/mips/Makefile
++++ b/cpu/mips/Makefile
+@@ -24,25 +24,46 @@
+ include $(TOPDIR)/config.mk
+
+ LIB = $(obj)lib$(CPU).a
++BOOTSTRAP_LIB = $(obj)lib$(CPU)_bootstrap.a
++
++BOOTSTRAP_LIB-$(CONFIG_BOOTSTRAP) = $(BOOTSTRAP_LIB)
+
+ START = start.o
+ SOBJS-y = cache.o
+-COBJS-y = cpu.o interrupts.o
++COBJS-y = cpu.o reset.o interrupts.o
+
+ SOBJS-$(CONFIG_INCA_IP) += incaip_wdt.o
+ COBJS-$(CONFIG_INCA_IP) += asc_serial.o incaip_clock.o
++#COBJS-$(CONFIG_IFX_ASC) += ifx_asc.o
+ COBJS-$(CONFIG_PURPLE) += asc_serial.o
+ COBJS-$(CONFIG_SOC_AU1X00) += au1x00_eth.o au1x00_serial.o au1x00_usb_ohci.o
+
+-SRCS := $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
++#BOOTSTRAP_START = start_bootstrap.o
++BOOTSTRAP_START-$(CONFIG_BOOTSTRAP) += start_bootstrap.o #$(BOOTSTRAP_START)
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += cpu.o interrupts.o reset_bootstrap.o
++BOOTSTRAP_SOBJS-$(CONFIG_BOOTSTRAP) += cache.o
++BOOTSTRAP_COBJS-$(CONFIG_DANUBE) += danube-clock.o
++BOOTSTRAP_COBJS-$(CONFIG_AR9) += ar9-clock.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_SERIAL) += ifx_asc.o
++
++BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_SOBJS-y) $(BOOTSTRAP_COBJS-y))
++BOOTSTRAP_START := $(addprefix $(obj),$(BOOTSTRAP_START-y))
++
++SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) $(BOOTSTRAP_START-y:.o=.S) $(BOOTSTRAP_SOBJS-y:.o=.S) $(BOOTSTRAP_COBJS-y:.o=.c)
+ OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+ START := $(addprefix $(obj),$(START))
+
+-all: $(obj).depend $(START) $(LIB)
++all: $(obj).depend $(START) $(LIB) $(BOOTSTRAP_START-y) $(BOOTSTRAP_LIB-y)
+
+-$(LIB): $(OBJS)
++$(LIB): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
++#$(BOOTSTRAP_START): $(obj).depend
++
++$(BOOTSTRAP_LIB): $(BOOTSTRAP_OBJS)
++ $(AR) $(ARFLAGS) $@ $(BOOTSTRAP_OBJS)
++
++
+ #########################################################################
+
+ # defines $(obj).depend target
diff --git a/package/uboot-lantiq/patches/500-gigasx.patch b/package/uboot-lantiq/patches/500-gigasx.patch
new file mode 100644
index 000000000..fe384ef78
--- /dev/null
+++ b/package/uboot-lantiq/patches/500-gigasx.patch
@@ -0,0 +1,35 @@
+--- a/Makefile
++++ b/Makefile
+@@ -3613,6 +3613,32 @@
+ $(eval $(call arcadyan, arv752DPW%config))
+ $(eval $(call arcadyan, arv752DPW22%config))
+
++gigaSX76X%config : unconfig
++ @mkdir -p $(obj)include
++ @mkdir -p $(obj)board/infineon/easy50712
++ @[ -z "$(findstring ramboot,$@)" ] || \
++ { echo "TEXT_BASE = 0xA0400000" >$(obj)board/infineon/easy50712/config.tmp ; \
++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \
++ $(XECHO) "... with ramboot configuration" ; \
++ }
++ @if [ "$(findstring _DDR,$@)" -a -z "$(findstring ramboot,$@)" ] ; then \
++ echo "#define CONFIG_USE_DDR_RAM" >>$(obj)include/config.h ; \
++ echo "#define CONFIG_BOOTSTRAP" >>$(obj)include/config.h ; \
++ DDR=$(subst DDR,,$(filter DDR%,$(subst _, ,$@))); \
++ case "$${DDR}" in \
++ 111M|166M|e111M|e166M|promos400|samsung166|psc166) \
++ $(XECHO) "... with DDR RAM config $${DDR}" ; \
++ echo "#define CONFIG_USE_DDR_RAM_CFG_$${DDR}" >>$(obj)include/config.h ;; \
++ *) $(XECHO) "... DDR RAM config \\\"$${DDR}\\\" unknown, use default"; \
++ esac; \
++ fi
++ echo "#define CONFIG_SWITCH_PORT1 1" >>$(obj)include/config.h
++ echo "#define CONFIG_SWITCH_PIN 3" >>$(obj)include/config.h
++ echo "#define CONFIG_BUTTON_PORT0 1" >>$(obj)include/config.h
++ echo "#define CONFIG_BUTTON_PIN 14" >>$(obj)include/config.h
++ echo "#define CONFIG_BUTTON_LEVEL 1" >>$(obj)include/config.h
++ @$(MKCONFIG) -a easy50712 mips mips easy50712 infineon danube
++
+ easy50712%config : unconfig
+ @mkdir -p $(obj)include
+ @mkdir -p $(obj)board/infineon/easy50712