add a hacked up version of upslug2 which is able to flash a wrt350nv2 in recovery...
authorFelix Fietkau <nbd@openwrt.org>
Sat, 12 Dec 2009 02:00:50 +0000 (02:00 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 12 Dec 2009 02:00:50 +0000 (02:00 +0000)
SVN-Revision: 18765

tools/Makefile
tools/upslug2/Makefile [new file with mode: 0644]
tools/upslug2/patches/100-libpcap_fix.patch [new file with mode: 0644]
tools/upslug2/patches/110-wrt350nv2_support.patch [new file with mode: 0644]

index 272c6254351788f205d71ac2d17eb747e66fcd38..276233ef571483ea3129303e0f35c541282cf1c1 100644 (file)
@@ -16,7 +16,7 @@ endif
 tools-y += m4 autoconf automake bison pkg-config sed mklibs
 tools-y += sstrip ipkg-utils genext2fs mtd-utils mkimage
 tools-y += firmware-utils patch-cmdline quilt yaffs2
-tools-y += wrt350nv2-builder
+tools-$(CONFIG_TARGET_orion) += wrt350nv2-builder upslug2
 ifneq ($(CONFIG_LINUX_2_4)$(CONFIG_LINUX_2_6_21)$(CONFIG_LINUX_2_6_25)$(CONFIG_LINUX_2_6_28),)
 tools-y += squashfs lzma-old
 else
@@ -89,5 +89,5 @@ $(curdir)//compile = $(STAGING_DIR)/.prepared $(STAGING_DIR_HOST)/.prepared $($(
 $(curdir)/ := .config prereq
 $(curdir)//install = $(1)/compile
 
-$(eval $(call stampfile,$(curdir),tools,install,,CONFIG_CCACHE CONFIG_powerpc CONFIG_GCC_VERSION_4_3 CONFIG_GCC_USE_GRAPHITE))
+$(eval $(call stampfile,$(curdir),tools,install,,CONFIG_CCACHE CONFIG_powerpc CONFIG_GCC_VERSION_4_3 CONFIG_GCC_USE_GRAPHITE CONFIG_TARGET_orion))
 $(eval $(call subdir,$(curdir)))
diff --git a/tools/upslug2/Makefile b/tools/upslug2/Makefile
new file mode 100644 (file)
index 0000000..6a73853
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=upslug2
+PKG_VERSION:=20071227
+
+PKG_SOURCE_URL:=http://svn.nslu2-linux.org/svnroot/upslug2/trunk
+PKG_SOURCE_PROTO:=svn
+PKG_SOURCE_SUBDIR:=upslug2-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=41
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+
+include $(INCLUDE_DIR)/host-build.mk
+
+unexport CFLAGS
+
+define Host/Configure
+       (cd $(HOST_BUILD_DIR); \
+               aclocal && autoconf && \
+               autoheader && \
+               automake --add-missing; \
+       )
+       $(Host/Configure/Default)
+endef
+
+ifneq ($(HOST_OS),Linux)
+       HOST_CONFIGURE_ARGS += --with-libpcap
+endif
+
+$(eval $(call HostBuild))
diff --git a/tools/upslug2/patches/100-libpcap_fix.patch b/tools/upslug2/patches/100-libpcap_fix.patch
new file mode 100644 (file)
index 0000000..1e14de4
--- /dev/null
@@ -0,0 +1,153 @@
+--- a/pcap_wire.cc
++++ b/pcap_wire.cc
+@@ -18,6 +18,7 @@
+ #include <sys/time.h>
+ #include <sys/select.h>
++#include <sys/poll.h>
+ /* Ways of finding the hardware MAC on this machine... */
+ /* This is the Linux only fallback. */
+@@ -130,20 +131,18 @@ namespace NSLU2Upgrade {
+                * non-static (real) Handler.
+                */
+               void Handler(const struct pcap_pkthdr *packet_header, const u_char *packet) {
+-                      /* This should only be called once... */
+-                      if (captured)
+-                              throw std::logic_error("Handler called twice");
+-
+                       /* Verify the protocol and originating address of the packet, then
+                        * return this packet.
+                        */
++                      if (captured)
++                              return;
+                       if (packet_header->caplen > 14 && (broadcast ||
+                               std::memcmp(packet+6, header, 6) == 0)) {
+-                              /* Record the address and copy the data */
+-                              std::memcpy(source, packet+6, 6);
+                               const size_t len(packet_header->caplen - 14);
+                               if (len > captureSize)
+-                                      throw std::logic_error("packet too long");
++                                      return;
++                              /* Record the address and copy the data */
++                              std::memcpy(source, packet+6, 6);
+                               std::memcpy(captureBuffer, packet+14, len);
+                               captureSize = len;
+                               captured = true;
+@@ -156,7 +155,7 @@ namespace NSLU2Upgrade {
+                        * packet and the buffer should be big enough.
+                        */
+                       if (packet_header->caplen < packet_header->len)
+-                              throw std::logic_error("truncated packet");
++                              return;
+                       /*IGNORE EVIL: known evil cast */
+                       reinterpret_cast<PCapWire*>(user)->Handler(packet_header, packet);
+@@ -173,56 +172,24 @@ namespace NSLU2Upgrade {
+               virtual void Receive(void *buffer, size_t &size, unsigned long timeout) {
+                       /* Now try to read packets until the timeout has been consumed.
+                        */
+-                      struct timeval tvStart;
+-                      if (timeout > 0 && gettimeofday(&tvStart, 0) != 0)
+-                              throw OSError(errno, "gettimeofday(base)");
++                      int time_count;
+                       captureBuffer = buffer;
+                       captureSize = size;
+                       captured = false;
++                      time_count = timeout / 2000; /* 2 ms intervals */
++                      time_count++;
+                       do {
+                               /*IGNORE EVIL: known evil cast */
+-                              int count(pcap_dispatch(pcap, 1, PCapHandler,
+-                                                      reinterpret_cast<u_char*>(this)));
++                              int count = pcap_dispatch(pcap, 1, PCapHandler,
++                                                      reinterpret_cast<u_char*>(this));
+-                              if (count > 0) {
+-                                      /* Were any packets handled? */
+-                                      if (captured) {
+-                                              size = captureSize;
+-                                              return;
+-                                      }
+-                                      /* else try again. */
+-                              } else if (count == 0) {
+-                                      /* Nothing to handle - do the timeout, do this
+-                                       * by waiting a bit then trying again, the trick
+-                                       * to this is to work out how long to wait each
+-                                       * time, for the moment a 10ms delay is used.
+-                                       */
+-                                      if (timeout == 0)
+-                                              break;
+-
+-                                      struct timeval tvNow;
+-                                      if (gettimeofday(&tvNow, 0) != 0)
+-                                              throw OSError(errno, "gettimeofday(now)");
+-
+-                                      unsigned long t(tvNow.tv_sec - tvStart.tv_sec);
+-                                      t *= 1000000;
+-                                      t += tvNow.tv_usec;
+-                                      t -= tvStart.tv_usec;
+-                                      if (t > timeout)
+-                                              break;
+-
+-                                      tvNow.tv_sec = 0;
+-                                      tvNow.tv_usec = timeout-t;
+-                                      if (tvNow.tv_usec > 10000)
+-                                              tvNow.tv_usec = 10000;
+-
+-                                      /* Delay, may be interrupted - this should
+-                                       * be portable to the BSDs (since the
+-                                       * technique originates in BSD.)
+-                                       */
+-                                      (void)select(0, 0, 0, 0, &tvNow);
+-                              } else {
++                              /* Were any packets handled? */
++                              if (captured) {
++                                      size = captureSize;
++                                      return;
++                              }
++                              if (count < 0) {
+                                       /* Error condition. */
+                                       if (count == -1) {
+                                               if (errno != EINTR)
+@@ -232,7 +199,8 @@ namespace NSLU2Upgrade {
+                                       } else
+                                               throw std::logic_error("pcap unexpected result");
+                               }
+-                      } while (timeout != 0);
++                              time_count--;
++                      } while (time_count > 0);
+                       /* Here on timeout. */
+                       size = 0;
+@@ -288,6 +256,7 @@ NSLU2Upgrade::Wire *NSLU2Upgrade::Wire::
+               const unsigned char *mac, const unsigned char *address, int uid) {
+       /* This is used to store the error passed to throw. */
+       static char PCapErrbuf[PCAP_ERRBUF_SIZE];
++      struct bpf_program fp;
+       /* Check the device name.  If not given use 'DEFAULT_ETHERNET_IF'. */
+       if (device == NULL)
+@@ -301,20 +270,12 @@ NSLU2Upgrade::Wire *NSLU2Upgrade::Wire::
+                * for other ethernet MACs.  (Because the code above does not
+                * check that the destination matches the device in use).
+                */
+-              pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 1/*ms*/, PCapErrbuf);
++              pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 2/*ms*/, PCapErrbuf);
+               if (pcap == NULL)
+                       throw WireError(errno, PCapErrbuf);
+       }
+-      /* Always do a non-blocking read, because the 'timeout' above
+-       * doesn't work on Linux (return is immediate) and on OSX (and
+-       * maybe other BSDs) the interface tends to hang waiting for
+-       * the timeout to expire even after receiving a single packet.
+-       */
+-      if (pcap_setnonblock(pcap, true, PCapErrbuf))
+-              throw WireError(errno, PCapErrbuf);
+-
+       try {
+               /* The MAC of the transmitting device is needed - without
+                * this the return packet won't go to the right place!
diff --git a/tools/upslug2/patches/110-wrt350nv2_support.patch b/tools/upslug2/patches/110-wrt350nv2_support.patch
new file mode 100644 (file)
index 0000000..eea7cc4
--- /dev/null
@@ -0,0 +1,279 @@
+--- a/nslu2_image.cc
++++ b/nslu2_image.cc
+@@ -54,28 +54,44 @@ namespace NSLU2Image {
+                               int &address, int &length) {
+                       address = image.tellg();
+                       length = buffer_length;
+-                      if (address+length > NSLU2Protocol::FlashSize)
+-                              length = NSLU2Protocol::FlashSize-address;
++                      if (address+length > EndAddress)
++                              length = EndAddress-address;
+                       if (length > 0)
+                               SafeRead(&image, buffer, length, "image (read)");
+               }
++              virtual void GetBoundaries(int &start, int &end)
++              {
++                      start = BaseAddress;
++                      end = EndAddress;
++              }
++
+               /* Rewind to the start of the image (or the Kernel if not
+                * doing a complete reprogram).
+                */
+               virtual void Rewind(void) {
+-                      SafeSeek(&image, reprogram ? 0 : NSLU2Protocol::BaseAddress,
++                      SafeSeek(&image, reprogram ? 0 : BaseAddress,
+                                       "image (seek)");
+               }
+       private:
++              int BaseAddress;
++              int EndAddress;
++
+               /* Validate that this really is an image file. */
+               void Validate(const char *i) {
+                       char signature[8];
+                       SafeSeek(&image, -8, i, std::ios::end);
+                       SafeRead(&image, signature, 8, i);
+-                      if (memcmp(signature, "eRcOmM", 6) != 0)
++
++                      if (memcmp(signature, "eRcOmM", 6) == 0) {
++                              BaseAddress = NSLU2Protocol::BaseAddress;
++                              EndAddress = NSLU2Protocol::FlashSize;
++                      } else if (memcmp(signature + 1, "sErCoMm", 7) == 0) {
++                              BaseAddress = 0;
++                              EndAddress = NSLU2Protocol::FlashSize - 0x40000;
++                      } else
+                               throw NSLU2Image::FileError(DataError, i, 0);
+               }
+@@ -93,6 +109,12 @@ namespace NSLU2Image {
+               virtual ~SynthesiseImage() {
+               }
++              void GetBoundaries(int &start, int &end)
++              {
++                      start = NSLU2Protocol::BaseAddress;
++                      end = NSLU2Protocol::FlashSize;
++              }
++
+               /* Get the next block of bytes, returns an address and length, false if
+                * there is a problem.
+                */
+--- a/nslu2_image.h
++++ b/nslu2_image.h
+@@ -35,6 +35,8 @@ namespace NSLU2Image {
+               virtual ~Image() {
+               }
++              virtual void GetBoundaries(int &start, int &end) = 0;
++
+               /* Get the next block of bytes, returns an address and length.
+                */
+               virtual void GetBytes(char *buffer, size_t buffer_length,
+--- a/nslu2_upgrade.cc
++++ b/nslu2_upgrade.cc
+@@ -95,7 +95,7 @@ namespace NSLU2Upgrade {
+       class RealDoUpgrade : public DoUpgrade {
+       public:
+-              RealDoUpgrade(Wire *w, Progress *p, bool r) :
++              RealDoUpgrade(Wire *w, Progress *p, bool r, int start, int end) :
+                       wire(w), progress(p), sequenceError(-1), reprogram(r),
+                       lastType(NSLU2Protocol::InvalidType) {
+                       if (reprogram) {
+@@ -105,6 +105,8 @@ namespace NSLU2Upgrade {
+                               NSLU2Protocol::UpgradeStartPacket packet(seq);
+                               wire->Send(packet.PacketBuffer(), packet.PacketLength());
+                       }
++                      BaseAddress = start;
++                      EndAddress = end;
+               }
+               virtual ~RealDoUpgrade() {
+@@ -205,8 +207,8 @@ namespace NSLU2Upgrade {
+       };
+-      DoUpgrade *DoUpgrade::MakeDoUpgrade(Wire *wire, Progress *progress, bool reprogram) {
+-              return new RealDoUpgrade(wire, progress, reprogram);
++      DoUpgrade *DoUpgrade::MakeDoUpgrade(Wire *wire, Progress *progress, bool reprogram, int start, int end) {
++              return new RealDoUpgrade(wire, progress, reprogram, start, end);
+       }
+ };
+@@ -421,13 +423,18 @@ void NSLU2Upgrade::RealDoUpgrade::Upgrad
+       /* Simple upgrade programs only the addresses beyound BaseAddress,
+        * reprogram overwrites the whole flash.
+        */
+-      if (!reprogram && address < NSLU2Protocol::BaseAddress) {
++      if (!reprogram && address < BaseAddress) {
+               length += address;
+-              if (length <= NSLU2Protocol::BaseAddress)
++              if (length <= BaseAddress)
+                       return; /* nothing to do. */
+-              address = NSLU2Protocol::BaseAddress;
++              address = BaseAddress;
+               length -= address;
+       }
++      if (!reprogram && address + length > EndAddress) {
++              if (address >= EndAddress)
++                      return; /* nothing to do. */
++              length -= EndAddress - address;
++      }
+ #if 1
+       /* Skip blocks of 255 valued bytes - the erase clears the flash to this
+@@ -495,11 +502,11 @@ void NSLU2Upgrade::RealDoUpgrade::Verify
+               Finish();
+       /* Verify never verifies anything below BaseAddress. */
+-      if (address < NSLU2Protocol::BaseAddress) {
++      if (address < BaseAddress) {
+               length += address;
+-              if (length <= NSLU2Protocol::BaseAddress)
++              if (length <= BaseAddress)
+                       return; /* nothing to do. */
+-              address = NSLU2Protocol::BaseAddress;
++              address = BaseAddress;
+               length -= address;
+       }
+--- a/nslu2_upgrade.h
++++ b/nslu2_upgrade.h
+@@ -206,6 +206,8 @@ namespace NSLU2Upgrade {
+       class DoUpgrade {
+       public:
++              int BaseAddress;
++              int EndAddress;
+               virtual ~DoUpgrade() {
+               }
+@@ -228,7 +230,7 @@ namespace NSLU2Upgrade {
+               virtual void Reboot(void) = 0;
+                       /* Reboot the NSLU2. */
+-              static DoUpgrade *MakeDoUpgrade(Wire *wire, Progress *progress, bool reprogram);
++              static DoUpgrade *MakeDoUpgrade(Wire *wire, Progress *progress, bool reprogram, int start, int end);
+                       /* Instantiate a real DoUpgrade, returns NULL if the object
+                        * cannot be instantiated.
+                        *
+--- a/upslug2.cc
++++ b/upslug2.cc
+@@ -21,8 +21,8 @@
+ class ProgressBar : public UpSlug2::CharacterProgressBar<80> {
+ public:
+-      ProgressBar(bool reprogram, const unsigned char *t) :
+-              UpSlug2::CharacterProgressBar<80>(reprogram, 64),
++      ProgressBar(bool reprogram, const unsigned char *t, int start, int end) :
++              UpSlug2::CharacterProgressBar<80>(reprogram, 64, start, end),
+               target(t), displayed(false), ticker(0) {
+       }
+@@ -95,7 +95,7 @@ private:
+                       else if (seen == -1) {
+                               seen = 0;
+                               if (!reprogram)
+-                                      sent -= NSLU2Protocol::BaseAddress;
++                                      sent -= NSLU2Protocol::FlashSize - (EndAddress - BaseAddress);
+                       } else
+                               sent -= seen;
+@@ -423,7 +423,7 @@ int main(int argc, char **argv) {
+ { 0,                                                            0,                 0,  0  }
+       };
+-      do switch (getopt_long(argc, argv, "he:d:t:f:vUni:Ck:r:R:j:p:P:T:F:E:", options, 0)) {
++      do switch (getopt_long(argc, argv, "he:d:t:f:vUni:Ck:r:R:j:op:P:T:F:E:", options, 0)) {
+       case  -1: if (optind < argc) {
+                         std::fprintf(stderr, "%s: unrecognised option\n", argv[optind]);
+                         std::exit(1);
+@@ -523,16 +523,22 @@ done:
+               if (mac && got_kernel) {
+                       Pointer<NSLU2Upgrade::Wire> wire(NSLU2Upgrade::Wire::MakeWire(device, fromMac, mac, euid));
+-                      ProgressBar progress(reprogram, mac);
++                      int BaseAddress = NSLU2Protocol::BaseAddress;
++                      int EndAddress = NSLU2Protocol::FlashSize;
+                       if (full_image) { /* complete image. */
+                               /* The full image case allows a complete reprogram. */
++                              NSLU2Image::Image *image_p;
+                               Pointer<NSLU2Image::Image> image(
+                                               NSLU2Image::Image::MakeImage(
+                                                       reprogram, full_image));
++                              image_p = image.p;
++                              image_p->GetBoundaries(BaseAddress, EndAddress);
++                              ProgressBar progress(reprogram, mac, BaseAddress, EndAddress);
+                               Pointer<NSLU2Upgrade::DoUpgrade> upgrade(
+                                       NSLU2Upgrade::DoUpgrade::MakeDoUpgrade(
+-                                              wire.p, &progress, reprogram));
++                                              wire.p, &progress, reprogram,
++                                              BaseAddress, EndAddress));
+                               progress.FirstDisplay();
+                               Upgrade(upgrade.p, image.p, no_upgrade, no_verify);
+                               progress.EndDisplay();
+@@ -551,9 +557,11 @@ done:
+                                                       fis_payload,
+                                                       product_id, protocol_id,
+                                                       firmware_version, extra_version));
++                              ProgressBar progress(reprogram, mac, BaseAddress, EndAddress);
+                               Pointer<NSLU2Upgrade::DoUpgrade> upgrade(
+                                       NSLU2Upgrade::DoUpgrade::MakeDoUpgrade(
+-                                              wire.p, &progress, false));
++                                              wire.p, &progress, false,
++                                              BaseAddress, EndAddress));
+                               progress.FirstDisplay();
+                               Upgrade(upgrade.p, image.p, no_upgrade, no_verify);
+                               progress.EndDisplay();
+--- a/upslug2_progress.h
++++ b/upslug2_progress.h
+@@ -161,15 +161,19 @@ namespace UpSlug2 {
+                       Timedout,   /* *: timeout on a sent packet for this address. */
+                       NumberOfStates
+               } Status;
+-              
++              int BaseAddress;
++              int EndAddress;
++
+               /* reprogram says whether this is a full reprogram (the entire
+                * flash will be erased) or not (the leading, RedBoot, SysConf
+                * partitions are not erased).
+                * resolution should be about 6 for a command line (character)
+                * progress bar and 8 for a GUI (pixel) progress bar.
+                */
+-              ProgressBar(bool r) :
++              ProgressBar(bool r, int start, int end) :
+                       reprogram(r), timeout(false), retransmit(false), status(Init) {
++                      BaseAddress = start;
++                      EndAddress = end;
+               }
+               /* lowWaterMark..(highWaterMark-1) bytes are in state 'st',
+@@ -179,8 +183,8 @@ namespace UpSlug2 {
+                       /* These initial settings cover the majority of cases
+                        * correctly.
+                        */
+-                      lowWaterMark = reprogram ? 0 : NSLU2Protocol::BaseAddress;
+-                      highWaterMark = status >= st ? NSLU2Protocol::FlashSize-1 : 0;
++                      lowWaterMark = reprogram ? 0 : BaseAddress;
++                      highWaterMark = status >= st ? EndAddress-1 : 0;
+                       switch (st) {
+                       case Init:
+                               /* Everything has an initial value... */
+@@ -286,9 +290,9 @@ namespace UpSlug2 {
+        */
+       template <int characters> class CharacterProgressBar : public ProgressBar {
+       public:
+-              CharacterProgressBar(bool reprogram, int n, const char ind[NumberOfStates] = 0) :
++              CharacterProgressBar(bool reprogram, int n, int start, int end, const char ind[NumberOfStates] = 0) :
+                       numberOfCharacters(n > characters || n < 1 ? characters : n),
+-                      ProgressBar(reprogram) {
++                      ProgressBar(reprogram, start, end) {
+                       if (ind)
+                               std::memcpy(indicators, ind, NumberOfStates);
+                       else