SWUpdate library to be used with RPC.
Fork of SWUpdate by
SWUpdate.cpp@3:c69fff55fc60, 2014-06-14 (annotated)
- Committer:
- WiredHome
- Date:
- Sat Jun 14 18:18:28 2014 +0000
- Revision:
- 3:c69fff55fc60
- Parent:
- 1:208de08b1a19
- Child:
- 7:a7efbae7e02e
Updated documentation to support integrity checking.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
WiredHome | 0:e221363f7942 | 1 | |
WiredHome | 0:e221363f7942 | 2 | // Software Update via Ethernet from forum - |
WiredHome | 0:e221363f7942 | 3 | // http://mbed.org/forum/mbed/topic/1183/ |
WiredHome | 1:208de08b1a19 | 4 | // |
WiredHome | 0:e221363f7942 | 5 | #include "mbed.h" |
WiredHome | 0:e221363f7942 | 6 | #include "SWUpdate.h" |
WiredHome | 0:e221363f7942 | 7 | #include "HTTPClient.h" |
WiredHome | 0:e221363f7942 | 8 | #include "HTTPText.h" |
WiredHome | 0:e221363f7942 | 9 | #include "HTTPFile.h" |
WiredHome | 0:e221363f7942 | 10 | #include <stdio.h> |
WiredHome | 0:e221363f7942 | 11 | |
WiredHome | 0:e221363f7942 | 12 | extern "C" void mbed_reset(); |
WiredHome | 0:e221363f7942 | 13 | |
WiredHome | 0:e221363f7942 | 14 | #define DEBUG "SWup" |
WiredHome | 0:e221363f7942 | 15 | #include <cstdio> |
WiredHome | 0:e221363f7942 | 16 | #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) |
WiredHome | 0:e221363f7942 | 17 | #define DBG(x, ...) std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 0:e221363f7942 | 18 | #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 0:e221363f7942 | 19 | #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 0:e221363f7942 | 20 | #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 0:e221363f7942 | 21 | #else |
WiredHome | 0:e221363f7942 | 22 | #define DBG(x, ...) |
WiredHome | 0:e221363f7942 | 23 | #define WARN(x, ...) |
WiredHome | 0:e221363f7942 | 24 | #define ERR(x, ...) |
WiredHome | 0:e221363f7942 | 25 | #define INFO(x, ...) |
WiredHome | 0:e221363f7942 | 26 | #endif |
WiredHome | 0:e221363f7942 | 27 | |
WiredHome | 3:c69fff55fc60 | 28 | static bool PassesIntegrityCheck(const char * fname, int cksum, int fsize) { |
WiredHome | 3:c69fff55fc60 | 29 | int res = false; // assume things go wrong... |
WiredHome | 3:c69fff55fc60 | 30 | int newCksum = 0; |
WiredHome | 3:c69fff55fc60 | 31 | int newFSize = 0; |
WiredHome | 3:c69fff55fc60 | 32 | FILE *fh = fopen(fname, "rb"); |
WiredHome | 3:c69fff55fc60 | 33 | INFO("IntegrityCheck(%s,%d,%d)", fname, cksum, fsize); |
WiredHome | 3:c69fff55fc60 | 34 | if (fh) { |
WiredHome | 3:c69fff55fc60 | 35 | char buf; |
WiredHome | 3:c69fff55fc60 | 36 | while (fread(&buf, 1, 1, fh)) { |
WiredHome | 3:c69fff55fc60 | 37 | newCksum = (newCksum + buf) & 0xFFFF; |
WiredHome | 3:c69fff55fc60 | 38 | newFSize++; |
WiredHome | 3:c69fff55fc60 | 39 | } |
WiredHome | 3:c69fff55fc60 | 40 | fclose(fh); |
WiredHome | 3:c69fff55fc60 | 41 | INFO(" Check(...,%d,%d)", newCksum, newFSize); |
WiredHome | 3:c69fff55fc60 | 42 | if (newCksum == cksum && newFSize == fsize) |
WiredHome | 3:c69fff55fc60 | 43 | res = true; |
WiredHome | 3:c69fff55fc60 | 44 | } else { |
WiredHome | 3:c69fff55fc60 | 45 | WARN("failed to open %s.", fname); |
WiredHome | 3:c69fff55fc60 | 46 | } |
WiredHome | 3:c69fff55fc60 | 47 | return res; |
WiredHome | 1:208de08b1a19 | 48 | } |
WiredHome | 1:208de08b1a19 | 49 | |
WiredHome | 0:e221363f7942 | 50 | bool SoftwareUpdate(const char *url, const char * name, Reboot_T reboot) { |
WiredHome | 0:e221363f7942 | 51 | HTTPClient http; |
WiredHome | 0:e221363f7942 | 52 | //http.setTimeout( 15000 ); |
WiredHome | 0:e221363f7942 | 53 | char fqurl[150]; // fully qualified url |
WiredHome | 0:e221363f7942 | 54 | char verfn[32]; // local version file |
WiredHome | 0:e221363f7942 | 55 | char fwfn[32]; |
WiredHome | 0:e221363f7942 | 56 | bool result = false; // many things can go wrong, assume failure |
WiredHome | 0:e221363f7942 | 57 | char buf[50]; |
WiredHome | 0:e221363f7942 | 58 | |
WiredHome | 0:e221363f7942 | 59 | INFO("SoftwareUpdate(%s,%s)", url, name); |
WiredHome | 0:e221363f7942 | 60 | snprintf(verfn, 32, "/local/%s.ver", name); |
WiredHome | 0:e221363f7942 | 61 | |
WiredHome | 0:e221363f7942 | 62 | /* Read installed version string */ |
WiredHome | 0:e221363f7942 | 63 | int inst_ver = -1; |
WiredHome | 0:e221363f7942 | 64 | FILE *fv = fopen(verfn, "r"); |
WiredHome | 0:e221363f7942 | 65 | if (fv) { |
WiredHome | 0:e221363f7942 | 66 | fscanf(fv, "%d", &inst_ver); |
WiredHome | 0:e221363f7942 | 67 | fclose(fv); |
WiredHome | 0:e221363f7942 | 68 | } |
WiredHome | 0:e221363f7942 | 69 | INFO(" Installed version: %d", inst_ver); |
WiredHome | 0:e221363f7942 | 70 | |
WiredHome | 0:e221363f7942 | 71 | /* Download latest version string */ |
WiredHome | 0:e221363f7942 | 72 | HTTPText server_ver("test message"); |
WiredHome | 0:e221363f7942 | 73 | snprintf(fqurl, 150, "%s/%s.txt", url, name); |
WiredHome | 0:e221363f7942 | 74 | HTTPResult r = http.get(fqurl, buf, sizeof(buf)); |
WiredHome | 0:e221363f7942 | 75 | if (r == HTTP_OK) { |
WiredHome | 0:e221363f7942 | 76 | int latest_ver = -1; |
WiredHome | 3:c69fff55fc60 | 77 | int cksum = 0; |
WiredHome | 3:c69fff55fc60 | 78 | int fsize = 0; |
WiredHome | 3:c69fff55fc60 | 79 | int parseCount; |
WiredHome | 0:e221363f7942 | 80 | INFO(" read {%s}", buf); |
WiredHome | 3:c69fff55fc60 | 81 | parseCount = sscanf(buf, "%d,%d,%d", &latest_ver, &cksum, &fsize); |
WiredHome | 3:c69fff55fc60 | 82 | if (parseCount == 3) { |
WiredHome | 3:c69fff55fc60 | 83 | INFO(" web version: %d", latest_ver); |
WiredHome | 3:c69fff55fc60 | 84 | INFO(" checksum: %d", cksum); |
WiredHome | 3:c69fff55fc60 | 85 | INFO(" file size: %d", fsize); |
WiredHome | 3:c69fff55fc60 | 86 | if (inst_ver != latest_ver) { |
WiredHome | 3:c69fff55fc60 | 87 | INFO(" Downloading firmware ver %d ...", latest_ver); |
WiredHome | 3:c69fff55fc60 | 88 | sprintf(fwfn, "/local/%s%d.BIN", name, latest_ver); |
WiredHome | 3:c69fff55fc60 | 89 | snprintf(fqurl, 150, "%s/%s.bin", url, name); |
WiredHome | 3:c69fff55fc60 | 90 | |
WiredHome | 3:c69fff55fc60 | 91 | HTTPFile latest(fwfn); |
WiredHome | 3:c69fff55fc60 | 92 | r = http.get(fqurl, &latest); |
WiredHome | 3:c69fff55fc60 | 93 | if (r == HTTP_OK) { |
WiredHome | 3:c69fff55fc60 | 94 | // Check the integrity of the freshly downloaded file, |
WiredHome | 3:c69fff55fc60 | 95 | // before swapping out the old version. |
WiredHome | 3:c69fff55fc60 | 96 | // ... to appear here ... |
WiredHome | 3:c69fff55fc60 | 97 | if (PassesIntegrityCheck(fwfn, cksum, fsize)) { |
WiredHome | 3:c69fff55fc60 | 98 | sprintf(fwfn, "/local/%s%d.BIN", name, inst_ver); |
WiredHome | 3:c69fff55fc60 | 99 | INFO(" Firmware downloaded, removing old version (%s).", fwfn); |
WiredHome | 3:c69fff55fc60 | 100 | if (remove(fwfn)) { |
WiredHome | 3:c69fff55fc60 | 101 | ERR(" *** Failed to remove old version. ***"); |
WiredHome | 3:c69fff55fc60 | 102 | } |
WiredHome | 3:c69fff55fc60 | 103 | INFO("Updating stored version number."); |
WiredHome | 3:c69fff55fc60 | 104 | fv = fopen(verfn, "w"); |
WiredHome | 3:c69fff55fc60 | 105 | if (fv) { |
WiredHome | 3:c69fff55fc60 | 106 | int fr = fputs(buf, fv); |
WiredHome | 3:c69fff55fc60 | 107 | if (fr < 0) { |
WiredHome | 3:c69fff55fc60 | 108 | ERR("Failed (%d) to update stored version number.", fr); |
WiredHome | 3:c69fff55fc60 | 109 | fclose( fv ); |
WiredHome | 3:c69fff55fc60 | 110 | } else { |
WiredHome | 3:c69fff55fc60 | 111 | fclose( fv ); |
WiredHome | 3:c69fff55fc60 | 112 | if (reboot == AUTO_REBOOT) { |
WiredHome | 3:c69fff55fc60 | 113 | WARN("Resetting...\n"); |
WiredHome | 3:c69fff55fc60 | 114 | wait_ms(200); |
WiredHome | 3:c69fff55fc60 | 115 | mbed_reset(); |
WiredHome | 3:c69fff55fc60 | 116 | } |
WiredHome | 3:c69fff55fc60 | 117 | result = true; |
WiredHome | 3:c69fff55fc60 | 118 | } |
WiredHome | 1:208de08b1a19 | 119 | } else { |
WiredHome | 3:c69fff55fc60 | 120 | WARN("Failed to update local version info in %s.", verfn); |
WiredHome | 1:208de08b1a19 | 121 | } |
WiredHome | 0:e221363f7942 | 122 | } else { |
WiredHome | 3:c69fff55fc60 | 123 | WARN("New file {%s} did not pass integrity check.", fwfn); |
WiredHome | 0:e221363f7942 | 124 | } |
WiredHome | 1:208de08b1a19 | 125 | } else { |
WiredHome | 3:c69fff55fc60 | 126 | WARN("Failed to download lastest firmware."); |
WiredHome | 0:e221363f7942 | 127 | } |
WiredHome | 0:e221363f7942 | 128 | } else { |
WiredHome | 3:c69fff55fc60 | 129 | WARN("Only %d parameters found in online version file.", parseCount); |
WiredHome | 0:e221363f7942 | 130 | } |
WiredHome | 0:e221363f7942 | 131 | } |
WiredHome | 0:e221363f7942 | 132 | } else { |
WiredHome | 1:208de08b1a19 | 133 | WARN("Failed to download online firmware version number."); |
WiredHome | 0:e221363f7942 | 134 | } |
WiredHome | 0:e221363f7942 | 135 | return result; |
WiredHome | 0:e221363f7942 | 136 | } |