| 1 | --- a/nslu2_image.cc |
| 2 | +++ b/nslu2_image.cc |
| 3 | @@ -54,28 +54,44 @@ namespace NSLU2Image { |
| 4 | int &address, int &length) { |
| 5 | address = image.tellg(); |
| 6 | length = buffer_length; |
| 7 | - if (address+length > NSLU2Protocol::FlashSize) |
| 8 | - length = NSLU2Protocol::FlashSize-address; |
| 9 | + if (address+length > EndAddress) |
| 10 | + length = EndAddress-address; |
| 11 | if (length > 0) |
| 12 | SafeRead(&image, buffer, length, "image (read)"); |
| 13 | } |
| 14 | |
| 15 | + virtual void GetBoundaries(int &start, int &end) |
| 16 | + { |
| 17 | + start = BaseAddress; |
| 18 | + end = EndAddress; |
| 19 | + } |
| 20 | + |
| 21 | /* Rewind to the start of the image (or the Kernel if not |
| 22 | * doing a complete reprogram). |
| 23 | */ |
| 24 | virtual void Rewind(void) { |
| 25 | - SafeSeek(&image, reprogram ? 0 : NSLU2Protocol::BaseAddress, |
| 26 | + SafeSeek(&image, reprogram ? 0 : BaseAddress, |
| 27 | "image (seek)"); |
| 28 | } |
| 29 | |
| 30 | private: |
| 31 | + int BaseAddress; |
| 32 | + int EndAddress; |
| 33 | + |
| 34 | /* Validate that this really is an image file. */ |
| 35 | void Validate(const char *i) { |
| 36 | char signature[8]; |
| 37 | |
| 38 | SafeSeek(&image, -8, i, std::ios::end); |
| 39 | SafeRead(&image, signature, 8, i); |
| 40 | - if (memcmp(signature, "eRcOmM", 6) != 0) |
| 41 | + |
| 42 | + if (memcmp(signature, "eRcOmM", 6) == 0) { |
| 43 | + BaseAddress = NSLU2Protocol::BaseAddress; |
| 44 | + EndAddress = NSLU2Protocol::FlashSize; |
| 45 | + } else if (memcmp(signature + 1, "sErCoMm", 7) == 0) { |
| 46 | + BaseAddress = 0; |
| 47 | + EndAddress = NSLU2Protocol::FlashSize - 0x40000; |
| 48 | + } else |
| 49 | throw NSLU2Image::FileError(DataError, i, 0); |
| 50 | } |
| 51 | |
| 52 | @@ -93,6 +109,12 @@ namespace NSLU2Image { |
| 53 | virtual ~SynthesiseImage() { |
| 54 | } |
| 55 | |
| 56 | + void GetBoundaries(int &start, int &end) |
| 57 | + { |
| 58 | + start = NSLU2Protocol::BaseAddress; |
| 59 | + end = NSLU2Protocol::FlashSize; |
| 60 | + } |
| 61 | + |
| 62 | /* Get the next block of bytes, returns an address and length, false if |
| 63 | * there is a problem. |
| 64 | */ |
| 65 | --- a/nslu2_image.h |
| 66 | +++ b/nslu2_image.h |
| 67 | @@ -35,6 +35,8 @@ namespace NSLU2Image { |
| 68 | virtual ~Image() { |
| 69 | } |
| 70 | |
| 71 | + virtual void GetBoundaries(int &start, int &end) = 0; |
| 72 | + |
| 73 | /* Get the next block of bytes, returns an address and length. |
| 74 | */ |
| 75 | virtual void GetBytes(char *buffer, size_t buffer_length, |
| 76 | --- a/nslu2_upgrade.cc |
| 77 | +++ b/nslu2_upgrade.cc |
| 78 | @@ -95,7 +95,7 @@ namespace NSLU2Upgrade { |
| 79 | |
| 80 | class RealDoUpgrade : public DoUpgrade { |
| 81 | public: |
| 82 | - RealDoUpgrade(Wire *w, Progress *p, bool r) : |
| 83 | + RealDoUpgrade(Wire *w, Progress *p, bool r, int start, int end) : |
| 84 | wire(w), progress(p), sequenceError(-1), reprogram(r), |
| 85 | lastType(NSLU2Protocol::InvalidType) { |
| 86 | if (reprogram) { |
| 87 | @@ -105,6 +105,8 @@ namespace NSLU2Upgrade { |
| 88 | NSLU2Protocol::UpgradeStartPacket packet(seq); |
| 89 | wire->Send(packet.PacketBuffer(), packet.PacketLength()); |
| 90 | } |
| 91 | + BaseAddress = start; |
| 92 | + EndAddress = end; |
| 93 | } |
| 94 | |
| 95 | virtual ~RealDoUpgrade() { |
| 96 | @@ -205,8 +207,8 @@ namespace NSLU2Upgrade { |
| 97 | |
| 98 | }; |
| 99 | |
| 100 | - DoUpgrade *DoUpgrade::MakeDoUpgrade(Wire *wire, Progress *progress, bool reprogram) { |
| 101 | - return new RealDoUpgrade(wire, progress, reprogram); |
| 102 | + DoUpgrade *DoUpgrade::MakeDoUpgrade(Wire *wire, Progress *progress, bool reprogram, int start, int end) { |
| 103 | + return new RealDoUpgrade(wire, progress, reprogram, start, end); |
| 104 | } |
| 105 | }; |
| 106 | |
| 107 | @@ -421,13 +423,18 @@ void NSLU2Upgrade::RealDoUpgrade::Upgrad |
| 108 | /* Simple upgrade programs only the addresses beyound BaseAddress, |
| 109 | * reprogram overwrites the whole flash. |
| 110 | */ |
| 111 | - if (!reprogram && address < NSLU2Protocol::BaseAddress) { |
| 112 | + if (!reprogram && address < BaseAddress) { |
| 113 | length += address; |
| 114 | - if (length <= NSLU2Protocol::BaseAddress) |
| 115 | + if (length <= BaseAddress) |
| 116 | return; /* nothing to do. */ |
| 117 | - address = NSLU2Protocol::BaseAddress; |
| 118 | + address = BaseAddress; |
| 119 | length -= address; |
| 120 | } |
| 121 | + if (!reprogram && address + length > EndAddress) { |
| 122 | + if (address >= EndAddress) |
| 123 | + return; /* nothing to do. */ |
| 124 | + length -= EndAddress - address; |
| 125 | + } |
| 126 | |
| 127 | #if 1 |
| 128 | /* Skip blocks of 255 valued bytes - the erase clears the flash to this |
| 129 | @@ -495,11 +502,11 @@ void NSLU2Upgrade::RealDoUpgrade::Verify |
| 130 | Finish(); |
| 131 | |
| 132 | /* Verify never verifies anything below BaseAddress. */ |
| 133 | - if (address < NSLU2Protocol::BaseAddress) { |
| 134 | + if (address < BaseAddress) { |
| 135 | length += address; |
| 136 | - if (length <= NSLU2Protocol::BaseAddress) |
| 137 | + if (length <= BaseAddress) |
| 138 | return; /* nothing to do. */ |
| 139 | - address = NSLU2Protocol::BaseAddress; |
| 140 | + address = BaseAddress; |
| 141 | length -= address; |
| 142 | } |
| 143 | |
| 144 | --- a/nslu2_upgrade.h |
| 145 | +++ b/nslu2_upgrade.h |
| 146 | @@ -206,6 +206,8 @@ namespace NSLU2Upgrade { |
| 147 | |
| 148 | class DoUpgrade { |
| 149 | public: |
| 150 | + int BaseAddress; |
| 151 | + int EndAddress; |
| 152 | virtual ~DoUpgrade() { |
| 153 | } |
| 154 | |
| 155 | @@ -228,7 +230,7 @@ namespace NSLU2Upgrade { |
| 156 | virtual void Reboot(void) = 0; |
| 157 | /* Reboot the NSLU2. */ |
| 158 | |
| 159 | - static DoUpgrade *MakeDoUpgrade(Wire *wire, Progress *progress, bool reprogram); |
| 160 | + static DoUpgrade *MakeDoUpgrade(Wire *wire, Progress *progress, bool reprogram, int start, int end); |
| 161 | /* Instantiate a real DoUpgrade, returns NULL if the object |
| 162 | * cannot be instantiated. |
| 163 | * |
| 164 | --- a/upslug2.cc |
| 165 | +++ b/upslug2.cc |
| 166 | @@ -21,8 +21,8 @@ |
| 167 | |
| 168 | class ProgressBar : public UpSlug2::CharacterProgressBar<80> { |
| 169 | public: |
| 170 | - ProgressBar(bool reprogram, const unsigned char *t) : |
| 171 | - UpSlug2::CharacterProgressBar<80>(reprogram, 64), |
| 172 | + ProgressBar(bool reprogram, const unsigned char *t, int start, int end) : |
| 173 | + UpSlug2::CharacterProgressBar<80>(reprogram, 64, start, end), |
| 174 | target(t), displayed(false), ticker(0) { |
| 175 | } |
| 176 | |
| 177 | @@ -95,7 +95,7 @@ private: |
| 178 | else if (seen == -1) { |
| 179 | seen = 0; |
| 180 | if (!reprogram) |
| 181 | - sent -= NSLU2Protocol::BaseAddress; |
| 182 | + sent -= NSLU2Protocol::FlashSize - (EndAddress - BaseAddress); |
| 183 | } else |
| 184 | sent -= seen; |
| 185 | |
| 186 | @@ -423,7 +423,7 @@ int main(int argc, char **argv) { |
| 187 | { 0, 0, 0, 0 } |
| 188 | }; |
| 189 | |
| 190 | - do switch (getopt_long(argc, argv, "he:d:t:f:vUni:Ck:r:R:j:p:P:T:F:E:", options, 0)) { |
| 191 | + do switch (getopt_long(argc, argv, "he:d:t:f:vUni:Ck:r:R:j:op:P:T:F:E:", options, 0)) { |
| 192 | case -1: if (optind < argc) { |
| 193 | std::fprintf(stderr, "%s: unrecognised option\n", argv[optind]); |
| 194 | std::exit(1); |
| 195 | @@ -523,16 +523,22 @@ done: |
| 196 | |
| 197 | if (mac && got_kernel) { |
| 198 | Pointer<NSLU2Upgrade::Wire> wire(NSLU2Upgrade::Wire::MakeWire(device, fromMac, mac, euid)); |
| 199 | - ProgressBar progress(reprogram, mac); |
| 200 | + int BaseAddress = NSLU2Protocol::BaseAddress; |
| 201 | + int EndAddress = NSLU2Protocol::FlashSize; |
| 202 | |
| 203 | if (full_image) { /* complete image. */ |
| 204 | /* The full image case allows a complete reprogram. */ |
| 205 | + NSLU2Image::Image *image_p; |
| 206 | Pointer<NSLU2Image::Image> image( |
| 207 | NSLU2Image::Image::MakeImage( |
| 208 | reprogram, full_image)); |
| 209 | + image_p = image.p; |
| 210 | + image_p->GetBoundaries(BaseAddress, EndAddress); |
| 211 | + ProgressBar progress(reprogram, mac, BaseAddress, EndAddress); |
| 212 | Pointer<NSLU2Upgrade::DoUpgrade> upgrade( |
| 213 | NSLU2Upgrade::DoUpgrade::MakeDoUpgrade( |
| 214 | - wire.p, &progress, reprogram)); |
| 215 | + wire.p, &progress, reprogram, |
| 216 | + BaseAddress, EndAddress)); |
| 217 | progress.FirstDisplay(); |
| 218 | Upgrade(upgrade.p, image.p, no_upgrade, no_verify); |
| 219 | progress.EndDisplay(); |
| 220 | @@ -551,9 +557,11 @@ done: |
| 221 | fis_payload, |
| 222 | product_id, protocol_id, |
| 223 | firmware_version, extra_version)); |
| 224 | + ProgressBar progress(reprogram, mac, BaseAddress, EndAddress); |
| 225 | Pointer<NSLU2Upgrade::DoUpgrade> upgrade( |
| 226 | NSLU2Upgrade::DoUpgrade::MakeDoUpgrade( |
| 227 | - wire.p, &progress, false)); |
| 228 | + wire.p, &progress, false, |
| 229 | + BaseAddress, EndAddress)); |
| 230 | progress.FirstDisplay(); |
| 231 | Upgrade(upgrade.p, image.p, no_upgrade, no_verify); |
| 232 | progress.EndDisplay(); |
| 233 | --- a/upslug2_progress.h |
| 234 | +++ b/upslug2_progress.h |
| 235 | @@ -161,15 +161,19 @@ namespace UpSlug2 { |
| 236 | Timedout, /* *: timeout on a sent packet for this address. */ |
| 237 | NumberOfStates |
| 238 | } Status; |
| 239 | - |
| 240 | + int BaseAddress; |
| 241 | + int EndAddress; |
| 242 | + |
| 243 | /* reprogram says whether this is a full reprogram (the entire |
| 244 | * flash will be erased) or not (the leading, RedBoot, SysConf |
| 245 | * partitions are not erased). |
| 246 | * resolution should be about 6 for a command line (character) |
| 247 | * progress bar and 8 for a GUI (pixel) progress bar. |
| 248 | */ |
| 249 | - ProgressBar(bool r) : |
| 250 | + ProgressBar(bool r, int start, int end) : |
| 251 | reprogram(r), timeout(false), retransmit(false), status(Init) { |
| 252 | + BaseAddress = start; |
| 253 | + EndAddress = end; |
| 254 | } |
| 255 | |
| 256 | /* lowWaterMark..(highWaterMark-1) bytes are in state 'st', |
| 257 | @@ -179,8 +183,8 @@ namespace UpSlug2 { |
| 258 | /* These initial settings cover the majority of cases |
| 259 | * correctly. |
| 260 | */ |
| 261 | - lowWaterMark = reprogram ? 0 : NSLU2Protocol::BaseAddress; |
| 262 | - highWaterMark = status >= st ? NSLU2Protocol::FlashSize-1 : 0; |
| 263 | + lowWaterMark = reprogram ? 0 : BaseAddress; |
| 264 | + highWaterMark = status >= st ? EndAddress-1 : 0; |
| 265 | switch (st) { |
| 266 | case Init: |
| 267 | /* Everything has an initial value... */ |
| 268 | @@ -286,9 +290,9 @@ namespace UpSlug2 { |
| 269 | */ |
| 270 | template <int characters> class CharacterProgressBar : public ProgressBar { |
| 271 | public: |
| 272 | - CharacterProgressBar(bool reprogram, int n, const char ind[NumberOfStates] = 0) : |
| 273 | + CharacterProgressBar(bool reprogram, int n, int start, int end, const char ind[NumberOfStates] = 0) : |
| 274 | numberOfCharacters(n > characters || n < 1 ? characters : n), |
| 275 | - ProgressBar(reprogram) { |
| 276 | + ProgressBar(reprogram, start, end) { |
| 277 | if (ind) |
| 278 | std::memcpy(indicators, ind, NumberOfStates); |
| 279 | else |
| 280 | |