--- 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