summaryrefslogtreecommitdiffstats
path: root/tools/upslug2
diff options
context:
space:
mode:
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2009-12-12 02:00:50 +0000
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2009-12-12 02:00:50 +0000
commitc6d72ac57a4815a82990b6138ec39e991a9b1afe (patch)
tree26c267b1edc29d414f72c80b9b53d8147aa8f2b7 /tools/upslug2
parent67c938cebaad6850ceb593305543df8c331e0ca8 (diff)
add a hacked up version of upslug2 which is able to flash a wrt350nv2 in recovery mode
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@18765 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'tools/upslug2')
-rw-r--r--tools/upslug2/Makefile35
-rw-r--r--tools/upslug2/patches/100-libpcap_fix.patch153
-rw-r--r--tools/upslug2/patches/110-wrt350nv2_support.patch279
3 files changed, 467 insertions, 0 deletions
diff --git a/tools/upslug2/Makefile b/tools/upslug2/Makefile
new file mode 100644
index 000000000..6a73853f3
--- /dev/null
+++ b/tools/upslug2/Makefile
@@ -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
index 000000000..1e14de451
--- /dev/null
+++ b/tools/upslug2/patches/100-libpcap_fix.patch
@@ -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
index 000000000..eea7cc4d0
--- /dev/null
+++ b/tools/upslug2/patches/110-wrt350nv2_support.patch
@@ -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