diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 2c35597d4..a0e5c6f41 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -177,26 +177,7 @@ uint32_t EspClass::getFlashChipSize(void) uint8_t * bytes = (uint8_t *) &data; // read first 4 byte (magic byte + flash config) if(spi_flash_read(0x0000, &data, 4) == SPI_FLASH_RESULT_OK) { - switch((bytes[3] & 0xf0) >> 4) { - case 0x0: // 4 Mbit (512KB) - return (512_kB); - case 0x1: // 2 MBit (256KB) - return (256_kB); - case 0x2: // 8 MBit (1MB) - return (1_MB); - case 0x3: // 16 MBit (2MB) - return (2_MB); - case 0x4: // 32 MBit (4MB) - return (4_MB); - case 0x5: // 64 MBit (8MB) - return (8_MB); - case 0x6: // 128 MBit (16MB) - return (16_MB); - case 0x7: // 256 MBit (32MB) - return (32_MB); - default: // fail? - return 0; - } + return magicFlashChipSize((bytes[3] & 0xf0) >> 4); } return 0; } @@ -207,18 +188,7 @@ uint32_t EspClass::getFlashChipSpeed(void) uint8_t * bytes = (uint8_t *) &data; // read first 4 byte (magic byte + flash config) if(spi_flash_read(0x0000, &data, 4) == SPI_FLASH_RESULT_OK) { - switch(bytes[3] & 0x0F) { - case 0x0: // 40 MHz - return (40_MHz); - case 0x1: // 26 MHz - return (26_MHz); - case 0x2: // 20 MHz - return (20_MHz); - case 0xf: // 80 MHz - return (80_MHz); - default: // fail? - return 0; - } + return magicFlashChipSpeed(bytes[3] & 0x0F); } return 0; } @@ -230,10 +200,53 @@ FlashMode_t EspClass::getFlashChipMode(void) uint8_t * bytes = (uint8_t *) &data; // read first 4 byte (magic byte + flash config) if(spi_flash_read(0x0000, &data, 4) == SPI_FLASH_RESULT_OK) { - mode = (FlashMode_t) bytes[2]; - if(mode > FM_DOUT) { - mode = FM_UNKNOWN; - } + mode = magicFlashChipMode(bytes[2]); + } + return mode; +} + +uint32_t EspClass::magicFlashChipSize(uint8_t byte) { + switch(byte & 0x0F) { + case 0x0: // 4 Mbit (512KB) + return (512_kB); + case 0x1: // 2 MBit (256KB) + return (256_kB); + case 0x2: // 8 MBit (1MB) + return (1_MB); + case 0x3: // 16 MBit (2MB) + return (2_MB); + case 0x4: // 32 MBit (4MB) + return (4_MB); + case 0x5: // 64 MBit (8MB) + return (8_MB); + case 0x6: // 128 MBit (16MB) + return (16_MB); + case 0x7: // 256 MBit (32MB) + return (32_MB); + default: // fail? + return 0; + } +} + +uint32_t EspClass::magicFlashChipSpeed(uint8_t byte) { + switch(byte & 0x0F) { + case 0x0: // 40 MHz + return (40_MHz); + case 0x1: // 26 MHz + return (26_MHz); + case 0x2: // 20 MHz + return (20_MHz); + case 0xf: // 80 MHz + return (80_MHz); + default: // fail? + return 0; + } +} + +FlashMode_t EspClass::magicFlashChipMode(uint8_t byte) { + FlashMode_t mode = (FlashMode_t) byte; + if(mode > FM_DOUT) { + mode = FM_UNKNOWN; } return mode; } diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index 4201ec47d..f04dd0e4d 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -117,6 +117,10 @@ class EspClass { FlashMode_t getFlashChipMode(); uint32_t getFlashChipSizeByChipId(); + uint32_t magicFlashChipSize(uint8_t byte); + uint32_t magicFlashChipSpeed(uint8_t byte); + FlashMode_t magicFlashChipMode(uint8_t byte); + bool checkFlashConfig(bool needsEquals = false); bool flashEraseSector(uint32_t sector); diff --git a/libraries/ESP8266WiFi/src/WiFiClient.cpp b/libraries/ESP8266WiFi/src/WiFiClient.cpp index d881c4a87..672fff4b2 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClient.cpp @@ -239,6 +239,27 @@ int WiFiClient::peek() return _client->peek(); } +size_t WiFiClient::peekBytes(uint8_t *buffer, size_t length) { + size_t count = 0; + + if(!_client) { + return 0; + } + + _startMillis = millis(); + while((available() < (int) length) && ((millis() - _startMillis) < _timeout)) { + yield(); + } + + if(available() < (int) length) { + count = available(); + } else { + count = length; + } + + return _client->peekBytes((char *)buffer, count); +} + void WiFiClient::flush() { if (_client) diff --git a/libraries/ESP8266WiFi/src/WiFiClient.h b/libraries/ESP8266WiFi/src/WiFiClient.h index 3c4ebde2e..62436b512 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.h +++ b/libraries/ESP8266WiFi/src/WiFiClient.h @@ -56,6 +56,10 @@ public: virtual int read(); virtual int read(uint8_t *buf, size_t size); virtual int peek(); + virtual size_t peekBytes(uint8_t *buffer, size_t length); + size_t peekBytes(char *buffer, size_t length) { + return peekBytes((uint8_t *) buffer, length); + } virtual void flush(); virtual void stop(); virtual uint8_t connected(); diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp index a35a25ad0..4299ddb8f 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp @@ -133,6 +133,17 @@ public: return _read_ptr[0]; } + size_t peekBytes(char *dst, size_t size) { + if(!_available) { + if(!_readAll()) + return -1; + } + + size_t will_copy = (_available < size) ? _available : size; + memcpy(dst, _read_ptr, will_copy); + return will_copy; + } + int available() { auto cb = _available; if (cb == 0) { @@ -278,6 +289,27 @@ int WiFiClientSecure::peek() { return _ssl->peek(); } +size_t WiFiClientSecure::peekBytes(uint8_t *buffer, size_t length) { + size_t count = 0; + + if(!_ssl) { + return 0; + } + + _startMillis = millis(); + while((available() < (int) length) && ((millis() - _startMillis) < _timeout)) { + yield(); + } + + if(available() < (int) length) { + count = available(); + } else { + count = length; + } + + return _ssl->peekBytes((char *)buffer, count); +} + int WiFiClientSecure::available() { if (!_ssl) return 0; diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecure.h b/libraries/ESP8266WiFi/src/WiFiClientSecure.h index 07b111e1a..d1234a621 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecure.h +++ b/libraries/ESP8266WiFi/src/WiFiClientSecure.h @@ -46,6 +46,7 @@ public: int available() override; int read() override; int peek() override; + size_t peekBytes(uint8_t *buffer, size_t length) override; void stop() override; void setCertificate(const uint8_t* cert_data, size_t size); diff --git a/libraries/ESP8266WiFi/src/include/ClientContext.h b/libraries/ESP8266WiFi/src/include/ClientContext.h index 2c26de832..65cbc2a24 100644 --- a/libraries/ESP8266WiFi/src/include/ClientContext.h +++ b/libraries/ESP8266WiFi/src/include/ClientContext.h @@ -179,6 +179,20 @@ class ClientContext { return reinterpret_cast(_rx_buf->payload)[_rx_buf_offset]; } + size_t peekBytes(char *dst, size_t size) { + if(!_rx_buf) return 0; + + size_t max_size = _rx_buf->tot_len - _rx_buf_offset; + size = (size < max_size) ? size : max_size; + + DEBUGV(":pd %d, %d, %d\r\n", size, _rx_buf->tot_len, _rx_buf_offset); + size_t buf_size = _rx_buf->len - _rx_buf_offset; + size_t copy_size = (size < buf_size) ? size : buf_size; + DEBUGV(":rpi %d, %d\r\n", buf_size, copy_size); + os_memcpy(dst, reinterpret_cast(_rx_buf->payload) + _rx_buf_offset, copy_size); + return copy_size; + } + void flush() { if(!_rx_buf) { return; diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index bb1bbfd9d..f45846440 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -124,6 +124,12 @@ String ESP8266HTTPUpdate::getLastErrorString(void) { return String("Forbidden (403)"); case HTTP_UE_SERVER_WRONG_HTTP_CODE: return String("Wrong HTTP code"); + case HTTP_UE_SERVER_FAULTY_MD5: + return String("Faulty MD5"); + case HTTP_UE_BIN_VERIFY_HEADER_FAILED: + return String("Verify bin header failed"); + case HTTP_UE_BIN_FOR_WRONG_FLASH: + return String("bin for wrong flash size"); } return String(); @@ -232,6 +238,33 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate flash...\n"); } + uint8_t buf[4]; + if(tcp->peekBytes(&buf[0], 4) != 4) { + DEBUG_HTTP_UPDATE("[httpUpdate] peekBytes magic header failed\n"); + lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; + http->end(); + return HTTP_UPDATE_FAILED; + } + + // check for valid first magic byte + if(buf[0] != 0xE9) { + DEBUG_HTTP_UPDATE("[httpUpdate] magic header not starts with 0xE9\n"); + lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; + http->end(); + return HTTP_UPDATE_FAILED; + + } + + uint32_t bin_flash_size = ESP.magicFlashChipSize((buf[3] & 0xf0) >> 4); + + // check if new bin fits to SPI flash + if(bin_flash_size > ESP.getFlashChipRealSize()) { + DEBUG_HTTP_UPDATE("[httpUpdate] magic header, new bin not fits SPI Flash\n"); + lastError = HTTP_UE_BIN_FOR_WRONG_FLASH; + http->end(); + return HTTP_UPDATE_FAILED; + } + if(runUpdate(*tcp, len, http->header("x-MD5"), command)) { ret = HTTP_UPDATE_OK; DEBUG_HTTP_UPDATE("[httpUpdate] Update ok\n"); diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h index 36ef5b5a2..ddfefb44b 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h @@ -39,12 +39,14 @@ #endif /// note we use HTTP client errors too so we start at 100 -#define HTTP_UE_TOO_LESS_SPACE (-100) -#define HTTP_UE_SERVER_NOT_REPORT_SIZE (-101) -#define HTTP_UE_SERVER_FILE_NOT_FOUND (-102) -#define HTTP_UE_SERVER_FORBIDDEN (-103) -#define HTTP_UE_SERVER_WRONG_HTTP_CODE (-104) -#define HTTP_UE_SERVER_FAULTY_MD5 (-105) +#define HTTP_UE_TOO_LESS_SPACE (-100) +#define HTTP_UE_SERVER_NOT_REPORT_SIZE (-101) +#define HTTP_UE_SERVER_FILE_NOT_FOUND (-102) +#define HTTP_UE_SERVER_FORBIDDEN (-103) +#define HTTP_UE_SERVER_WRONG_HTTP_CODE (-104) +#define HTTP_UE_SERVER_FAULTY_MD5 (-105) +#define HTTP_UE_BIN_VERIFY_HEADER_FAILED (-106) +#define HTTP_UE_BIN_FOR_WRONG_FLASH (-107) typedef enum { HTTP_UPDATE_FAILED,