further ota code sanitization (delete update.cpp/.h)
This commit is contained in:
		
							parent
							
								
									26ea8621c2
								
							
						
					
					
						commit
						3d93a44c96
					
				| @ -4,8 +4,8 @@ | |||||||
| #ifdef USE_OTA | #ifdef USE_OTA | ||||||
| 
 | 
 | ||||||
| #include "globals.h" | #include "globals.h" | ||||||
| #include "update.h" |  | ||||||
| #include "battery.h" | #include "battery.h" | ||||||
|  | #include <Update.h> | ||||||
| #include <WiFi.h> | #include <WiFi.h> | ||||||
| #include <WiFiClientSecure.h> | #include <WiFiClientSecure.h> | ||||||
| #include <BintrayClient.h> | #include <BintrayClient.h> | ||||||
|  | |||||||
							
								
								
									
										181
									
								
								include/update.h
									
									
									
									
									
								
							
							
						
						
									
										181
									
								
								include/update.h
									
									
									
									
									
								
							| @ -1,181 +0,0 @@ | |||||||
| #ifndef ESP8266UPDATER_H |  | ||||||
| #define ESP8266UPDATER_H |  | ||||||
| 
 |  | ||||||
| #include <Arduino.h> |  | ||||||
| #include <MD5Builder.h> |  | ||||||
| #include <functional> |  | ||||||
| #include "esp_partition.h" |  | ||||||
| 
 |  | ||||||
| #define UPDATE_ERROR_OK                 (0) |  | ||||||
| #define UPDATE_ERROR_WRITE              (1) |  | ||||||
| #define UPDATE_ERROR_ERASE              (2) |  | ||||||
| #define UPDATE_ERROR_READ               (3) |  | ||||||
| #define UPDATE_ERROR_SPACE              (4) |  | ||||||
| #define UPDATE_ERROR_SIZE               (5) |  | ||||||
| #define UPDATE_ERROR_STREAM             (6) |  | ||||||
| #define UPDATE_ERROR_MD5                (7) |  | ||||||
| #define UPDATE_ERROR_MAGIC_BYTE         (8) |  | ||||||
| #define UPDATE_ERROR_ACTIVATE           (9) |  | ||||||
| #define UPDATE_ERROR_NO_PARTITION       (10) |  | ||||||
| #define UPDATE_ERROR_BAD_ARGUMENT       (11) |  | ||||||
| #define UPDATE_ERROR_ABORT              (12) |  | ||||||
| 
 |  | ||||||
| #define UPDATE_SIZE_UNKNOWN 0xFFFFFFFF |  | ||||||
| 
 |  | ||||||
| #define U_FLASH   0 |  | ||||||
| #define U_SPIFFS  100 |  | ||||||
| #define U_AUTH    200 |  | ||||||
| 
 |  | ||||||
| class UpdateClass { |  | ||||||
|   public: |  | ||||||
|     typedef std::function<void(size_t, size_t)> THandlerFunction_Progress; |  | ||||||
| 
 |  | ||||||
|     UpdateClass(); |  | ||||||
| 
 |  | ||||||
|     /*
 |  | ||||||
|       This callback will be called when Update is receiving data |  | ||||||
|     */ |  | ||||||
|     UpdateClass& onProgress(THandlerFunction_Progress fn); |  | ||||||
| 
 |  | ||||||
|     /*
 |  | ||||||
|       Call this to check the space needed for the update |  | ||||||
|       Will return false if there is not enough space |  | ||||||
|     */ |  | ||||||
|     bool begin(size_t size=UPDATE_SIZE_UNKNOWN, int command = U_FLASH); |  | ||||||
| 
 |  | ||||||
|     /*
 |  | ||||||
|       Writes a buffer to the flash and increments the address |  | ||||||
|       Returns the amount written |  | ||||||
|     */ |  | ||||||
|     size_t write(uint8_t *data, size_t len); |  | ||||||
| 
 |  | ||||||
|     /*
 |  | ||||||
|       Writes the remaining bytes from the Stream to the flash |  | ||||||
|       Uses readBytes() and sets UPDATE_ERROR_STREAM on timeout |  | ||||||
|       Returns the bytes written |  | ||||||
|       Should be equal to the remaining bytes when called |  | ||||||
|       Usable for slow streams like Serial |  | ||||||
|     */ |  | ||||||
|     size_t writeStream(Stream &data); |  | ||||||
| 
 |  | ||||||
|     /*
 |  | ||||||
|       If all bytes are written |  | ||||||
|       this call will write the config to eboot |  | ||||||
|       and return true |  | ||||||
|       If there is already an update running but is not finished and !evenIfRemainanig |  | ||||||
|       or there is an error |  | ||||||
|       this will clear everything and return false |  | ||||||
|       the last error is available through getError() |  | ||||||
|       evenIfRemaining is helpfull when you update without knowing the final size first |  | ||||||
|     */ |  | ||||||
|     bool end(bool evenIfRemaining = false); |  | ||||||
| 
 |  | ||||||
|     /*
 |  | ||||||
|       Aborts the running update |  | ||||||
|     */ |  | ||||||
|     void abort(); |  | ||||||
| 
 |  | ||||||
|     /*
 |  | ||||||
|       Prints the last error to an output stream |  | ||||||
|     */ |  | ||||||
|     void printError(Stream &out); |  | ||||||
| 
 |  | ||||||
|     /*
 |  | ||||||
|       sets the expected MD5 for the firmware (hexString) |  | ||||||
|     */ |  | ||||||
|     bool setMD5(const char * expected_md5); |  | ||||||
| 
 |  | ||||||
|     /*
 |  | ||||||
|       returns the MD5 String of the sucessfully ended firmware |  | ||||||
|     */ |  | ||||||
|     String md5String(void){ return _md5.toString(); } |  | ||||||
| 
 |  | ||||||
|     /*
 |  | ||||||
|       populated the result with the md5 bytes of the sucessfully ended firmware |  | ||||||
|     */ |  | ||||||
|     void md5(uint8_t * result){ return _md5.getBytes(result); } |  | ||||||
| 
 |  | ||||||
|     //Helpers
 |  | ||||||
|     uint8_t getError(){ return _error; } |  | ||||||
|     void clearError(){ _error = UPDATE_ERROR_OK; } |  | ||||||
|     bool hasError(){ return _error != UPDATE_ERROR_OK; } |  | ||||||
|     bool isRunning(){ return _size > 0; } |  | ||||||
|     bool isFinished(){ return _progress == _size; } |  | ||||||
|     size_t size(){ return _size; } |  | ||||||
|     size_t progress(){ return _progress; } |  | ||||||
|     size_t remaining(){ return _size - _progress; } |  | ||||||
| 
 |  | ||||||
|     /*
 |  | ||||||
|       Template to write from objects that expose |  | ||||||
|       available() and read(uint8_t*, size_t) methods |  | ||||||
|       faster than the writeStream method |  | ||||||
|       writes only what is available |  | ||||||
|     */ |  | ||||||
|     template<typename T> |  | ||||||
|     size_t write(T &data){ |  | ||||||
|       size_t written = 0; |  | ||||||
|       if (hasError() || !isRunning()) |  | ||||||
|         return 0; |  | ||||||
| 
 |  | ||||||
|       size_t available = data.available(); |  | ||||||
|       while(available) { |  | ||||||
|         if(_bufferLen + available > remaining()){ |  | ||||||
|           available = remaining() - _bufferLen; |  | ||||||
|         } |  | ||||||
|         if(_bufferLen + available > 4096) { |  | ||||||
|           size_t toBuff = 4096 - _bufferLen; |  | ||||||
|           data.read(_buffer + _bufferLen, toBuff); |  | ||||||
|           _bufferLen += toBuff; |  | ||||||
|           if(!_writeBuffer()) |  | ||||||
|             return written; |  | ||||||
|           written += toBuff; |  | ||||||
|         } else { |  | ||||||
|           data.read(_buffer + _bufferLen, available); |  | ||||||
|           _bufferLen += available; |  | ||||||
|           written += available; |  | ||||||
|           if(_bufferLen == remaining()) { |  | ||||||
|             if(!_writeBuffer()) { |  | ||||||
|               return written; |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|         if(remaining() == 0) |  | ||||||
|           return written; |  | ||||||
|         available = data.available(); |  | ||||||
|       } |  | ||||||
|       return written; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /*
 |  | ||||||
|       check if there is a firmware on the other OTA partition that you can bootinto |  | ||||||
|     */ |  | ||||||
|     bool canRollBack(); |  | ||||||
|     /*
 |  | ||||||
|       set the other OTA partition as bootable (reboot to enable) |  | ||||||
|     */ |  | ||||||
|     bool rollBack(); |  | ||||||
| 
 |  | ||||||
|   private: |  | ||||||
|     void _reset(); |  | ||||||
|     void _abort(uint8_t err); |  | ||||||
|     bool _writeBuffer(); |  | ||||||
|     bool _verifyHeader(uint8_t data); |  | ||||||
|     bool _verifyEnd(); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     uint8_t _error; |  | ||||||
|     uint8_t *_buffer; |  | ||||||
|     size_t _bufferLen; |  | ||||||
|     size_t _size; |  | ||||||
|     THandlerFunction_Progress _progress_callback; |  | ||||||
|     uint32_t _progress; |  | ||||||
|     uint32_t _command; |  | ||||||
|     const esp_partition_t* _partition; |  | ||||||
| 
 |  | ||||||
|     String _target_md5; |  | ||||||
|     MD5Builder _md5; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| extern UpdateClass Update; |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| @ -84,7 +84,7 @@ void start_ota_update() { | |||||||
|       ESP_LOGI(TAG, "Connected to %s", WIFI_SSID); |       ESP_LOGI(TAG, "Connected to %s", WIFI_SSID); | ||||||
|       display(1, "OK", "WiFi connected"); |       display(1, "OK", "WiFi connected"); | ||||||
|       // do a number of tries to update firmware limited by OTA_MAX_TRY
 |       // do a number of tries to update firmware limited by OTA_MAX_TRY
 | ||||||
|       while ( j--) { |       while (j--) { | ||||||
|         ESP_LOGI(TAG, |         ESP_LOGI(TAG, | ||||||
|                  "Starting OTA update, attempt %u of %u. This will take some " |                  "Starting OTA update, attempt %u of %u. This will take some " | ||||||
|                  "time to complete...", |                  "time to complete...", | ||||||
| @ -92,8 +92,8 @@ void start_ota_update() { | |||||||
|         ret = do_ota_update(); |         ret = do_ota_update(); | ||||||
|         if (ret) |         if (ret) | ||||||
|           goto end; // update successful
 |           goto end; // update successful
 | ||||||
|       } |       } // update not successful
 | ||||||
|       goto end; // update not successful
 |       goto end;  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -263,6 +263,8 @@ bool do_ota_update() { | |||||||
| 
 | 
 | ||||||
|   display(4, "**", "writing..."); |   display(4, "**", "writing..."); | ||||||
| 
 | 
 | ||||||
|  |   // set server connection timeout and open server connection
 | ||||||
|  |   client.setTimeout(RESPONSE_TIMEOUT_MS); | ||||||
|   written = Update.writeStream(client); |   written = Update.writeStream(client); | ||||||
| 
 | 
 | ||||||
|   if (written == contentLength) { |   if (written == contentLength) { | ||||||
|  | |||||||
							
								
								
									
										354
									
								
								src/update.cpp
									
									
									
									
									
								
							
							
						
						
									
										354
									
								
								src/update.cpp
									
									
									
									
									
								
							| @ -1,354 +0,0 @@ | |||||||
| /*
 |  | ||||||
| 
 |  | ||||||
| this file copied from esp32-arduino library and patched, see PR |  | ||||||
| https://github.com/espressif/arduino-esp32/pull/1886
 |  | ||||||
| 
 |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| #include "update.h" |  | ||||||
| #include "Arduino.h" |  | ||||||
| #include "esp_spi_flash.h" |  | ||||||
| #include "esp_ota_ops.h" |  | ||||||
| #include "esp_image_format.h" |  | ||||||
| 
 |  | ||||||
| static const char * _err2str(uint8_t _error){ |  | ||||||
|     if(_error == UPDATE_ERROR_OK){ |  | ||||||
|         return ("No Error"); |  | ||||||
|     } else if(_error == UPDATE_ERROR_WRITE){ |  | ||||||
|         return ("Flash Write Failed"); |  | ||||||
|     } else if(_error == UPDATE_ERROR_ERASE){ |  | ||||||
|         return ("Flash Erase Failed"); |  | ||||||
|     } else if(_error == UPDATE_ERROR_READ){ |  | ||||||
|         return ("Flash Read Failed"); |  | ||||||
|     } else if(_error == UPDATE_ERROR_SPACE){ |  | ||||||
|         return ("Not Enough Space"); |  | ||||||
|     } else if(_error == UPDATE_ERROR_SIZE){ |  | ||||||
|         return ("Bad Size Given"); |  | ||||||
|     } else if(_error == UPDATE_ERROR_STREAM){ |  | ||||||
|         return ("Stream Read Timeout"); |  | ||||||
|     } else if(_error == UPDATE_ERROR_MD5){ |  | ||||||
|         return ("MD5 Check Failed"); |  | ||||||
|     } else if(_error == UPDATE_ERROR_MAGIC_BYTE){ |  | ||||||
|         return ("Wrong Magic Byte"); |  | ||||||
|     } else if(_error == UPDATE_ERROR_ACTIVATE){ |  | ||||||
|         return ("Could Not Activate The Firmware"); |  | ||||||
|     } else if(_error == UPDATE_ERROR_NO_PARTITION){ |  | ||||||
|         return ("Partition Could Not be Found"); |  | ||||||
|     } else if(_error == UPDATE_ERROR_BAD_ARGUMENT){ |  | ||||||
|         return ("Bad Argument"); |  | ||||||
|     } else if(_error == UPDATE_ERROR_ABORT){ |  | ||||||
|         return ("Aborted"); |  | ||||||
|     } |  | ||||||
|     return ("UNKNOWN"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _partitionIsBootable(const esp_partition_t* partition){ |  | ||||||
|     uint8_t buf[4]; |  | ||||||
|     if(!partition){ |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if(!ESP.flashRead(partition->address, (uint32_t*)buf, 4)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(buf[0] != ESP_IMAGE_HEADER_MAGIC) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _enablePartition(const esp_partition_t* partition){ |  | ||||||
|     uint8_t buf[4]; |  | ||||||
|     if(!partition){ |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if(!ESP.flashRead(partition->address, (uint32_t*)buf, 4)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     buf[0] = ESP_IMAGE_HEADER_MAGIC; |  | ||||||
| 
 |  | ||||||
|     return ESP.flashWrite(partition->address, (uint32_t*)buf, 4); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| UpdateClass::UpdateClass() |  | ||||||
| : _error(0) |  | ||||||
| , _buffer(0) |  | ||||||
| , _bufferLen(0) |  | ||||||
| , _size(0) |  | ||||||
| , _progress_callback(NULL) |  | ||||||
| , _progress(0) |  | ||||||
| , _command(U_FLASH) |  | ||||||
| , _partition(NULL) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| UpdateClass& UpdateClass::onProgress(THandlerFunction_Progress fn) { |  | ||||||
|     _progress_callback = fn; |  | ||||||
|     return *this; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void UpdateClass::_reset() { |  | ||||||
|     if (_buffer) |  | ||||||
|         delete[] _buffer; |  | ||||||
|     _buffer = 0; |  | ||||||
|     _bufferLen = 0; |  | ||||||
|     _progress = 0; |  | ||||||
|     _size = 0; |  | ||||||
|     _command = U_FLASH; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool UpdateClass::canRollBack(){ |  | ||||||
|     if(_buffer){ //Update is running
 |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     const esp_partition_t* partition = esp_ota_get_next_update_partition(NULL); |  | ||||||
|     return _partitionIsBootable(partition); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool UpdateClass::rollBack(){ |  | ||||||
|     if(_buffer){ //Update is running
 |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     const esp_partition_t* partition = esp_ota_get_next_update_partition(NULL); |  | ||||||
|     return _partitionIsBootable(partition) && !esp_ota_set_boot_partition(partition); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool UpdateClass::begin(size_t size, int command) { |  | ||||||
|     if(_size > 0){ |  | ||||||
|         log_w("already running"); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     _reset(); |  | ||||||
|     _error = 0; |  | ||||||
| 
 |  | ||||||
|     if(size == 0) { |  | ||||||
|         _error = UPDATE_ERROR_SIZE; |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (command == U_FLASH) { |  | ||||||
|         _partition = esp_ota_get_next_update_partition(NULL); |  | ||||||
|         if(!_partition){ |  | ||||||
|             _error = UPDATE_ERROR_NO_PARTITION; |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|         log_d("OTA Partition: %s", _partition->label); |  | ||||||
|     } |  | ||||||
|     else if (command == U_SPIFFS) { |  | ||||||
|         _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL); |  | ||||||
|         if(!_partition){ |  | ||||||
|             _error = UPDATE_ERROR_NO_PARTITION; |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|         _error = UPDATE_ERROR_BAD_ARGUMENT; |  | ||||||
|         log_e("bad command %u", command); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(size == UPDATE_SIZE_UNKNOWN){ |  | ||||||
|         size = _partition->size; |  | ||||||
|     } else if(size > _partition->size){ |  | ||||||
|         _error = UPDATE_ERROR_SIZE; |  | ||||||
|         log_e("too large %u > %u", size, _partition->size); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     //initialize
 |  | ||||||
|     _buffer = (uint8_t*)malloc(SPI_FLASH_SEC_SIZE); |  | ||||||
|     if(!_buffer){ |  | ||||||
|         log_e("malloc failed"); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     _size = size; |  | ||||||
|     _command = command; |  | ||||||
|     _md5.begin(); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void UpdateClass::_abort(uint8_t err){ |  | ||||||
|     _reset(); |  | ||||||
|     _error = err; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void UpdateClass::abort(){ |  | ||||||
|     _abort(UPDATE_ERROR_ABORT); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool UpdateClass::_writeBuffer(){ |  | ||||||
|     //first bytes of new firmware
 |  | ||||||
|     if(!_progress && _command == U_FLASH){ |  | ||||||
|         //check magic
 |  | ||||||
|         if(_buffer[0] != ESP_IMAGE_HEADER_MAGIC){ |  | ||||||
|             _abort(UPDATE_ERROR_MAGIC_BYTE); |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|         //remove magic byte from the firmware now and write it upon success
 |  | ||||||
|         //this ensures that partially written firmware will not be bootable
 |  | ||||||
|         _buffer[0] = 0xFF; |  | ||||||
|     } |  | ||||||
|     if(!ESP.flashEraseSector((_partition->address + _progress)/SPI_FLASH_SEC_SIZE)){ |  | ||||||
|         _abort(UPDATE_ERROR_ERASE); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!ESP.flashWrite(_partition->address + _progress, (uint32_t*)_buffer, _bufferLen)) { |  | ||||||
|         _abort(UPDATE_ERROR_WRITE); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     //restore magic or md5 will fail
 |  | ||||||
|     if(!_progress && _command == U_FLASH){ |  | ||||||
|         _buffer[0] = ESP_IMAGE_HEADER_MAGIC; |  | ||||||
|     } |  | ||||||
|     _md5.add(_buffer, _bufferLen); |  | ||||||
|     _progress += _bufferLen; |  | ||||||
|     _bufferLen = 0; |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool UpdateClass::_verifyHeader(uint8_t data) { |  | ||||||
|     if(_command == U_FLASH) { |  | ||||||
|         if(data != ESP_IMAGE_HEADER_MAGIC) { |  | ||||||
|             _abort(UPDATE_ERROR_MAGIC_BYTE); |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|         return true; |  | ||||||
|     } else if(_command == U_SPIFFS) { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool UpdateClass::_verifyEnd() { |  | ||||||
|     if(_command == U_FLASH) { |  | ||||||
|         if(!_enablePartition(_partition) || !_partitionIsBootable(_partition)) { |  | ||||||
|             _abort(UPDATE_ERROR_READ); |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if(esp_ota_set_boot_partition(_partition)){ |  | ||||||
|             _abort(UPDATE_ERROR_ACTIVATE); |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|         _reset(); |  | ||||||
|         return true; |  | ||||||
|     } else if(_command == U_SPIFFS) { |  | ||||||
|         _reset(); |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool UpdateClass::setMD5(const char * expected_md5){ |  | ||||||
|     if(strlen(expected_md5) != 32) |  | ||||||
|     { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     _target_md5 = expected_md5; |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool UpdateClass::end(bool evenIfRemaining){ |  | ||||||
|     if(hasError() || _size == 0){ |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(!isFinished() && !evenIfRemaining){ |  | ||||||
|         log_e("premature end: res:%u, pos:%u/%u\n", getError(), progress(), _size); |  | ||||||
|         _abort(UPDATE_ERROR_ABORT); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(evenIfRemaining) { |  | ||||||
|         if(_bufferLen > 0) { |  | ||||||
|             _writeBuffer(); |  | ||||||
|         } |  | ||||||
|         _size = progress(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     _md5.calculate(); |  | ||||||
|     if(_target_md5.length()) { |  | ||||||
|         if(_target_md5 != _md5.toString()){ |  | ||||||
|             _abort(UPDATE_ERROR_MD5); |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return _verifyEnd(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| size_t UpdateClass::write(uint8_t *data, size_t len) { |  | ||||||
|     if(hasError() || !isRunning()){ |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(len > remaining()){ |  | ||||||
|         _abort(UPDATE_ERROR_SPACE); |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     size_t left = len; |  | ||||||
| 
 |  | ||||||
|     while((_bufferLen + left) > SPI_FLASH_SEC_SIZE) { |  | ||||||
|         size_t toBuff = SPI_FLASH_SEC_SIZE - _bufferLen; |  | ||||||
|         memcpy(_buffer + _bufferLen, data + (len - left), toBuff); |  | ||||||
|         _bufferLen += toBuff; |  | ||||||
|         if(!_writeBuffer()){ |  | ||||||
|             return len - left; |  | ||||||
|         } |  | ||||||
|         left -= toBuff; |  | ||||||
|     } |  | ||||||
|     memcpy(_buffer + _bufferLen, data + (len - left), left); |  | ||||||
|     _bufferLen += left; |  | ||||||
|     if(_bufferLen == remaining()){ |  | ||||||
|         if(!_writeBuffer()){ |  | ||||||
|             return len - left; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     return len; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| size_t UpdateClass::writeStream(Stream &data) { |  | ||||||
|     data.setTimeout(20000); |  | ||||||
|     size_t written = 0; |  | ||||||
|     size_t toRead = 0; |  | ||||||
|     if(hasError() || !isRunning()) |  | ||||||
|         return 0; |  | ||||||
| 
 |  | ||||||
|     if(!_verifyHeader(data.peek())) { |  | ||||||
|         _reset(); |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
|     if (_progress_callback) { |  | ||||||
|         _progress_callback(0, _size); |  | ||||||
|     } |  | ||||||
|     while(remaining()) { |  | ||||||
|         toRead = data.readBytes(_buffer + _bufferLen,  (SPI_FLASH_SEC_SIZE - _bufferLen)); |  | ||||||
|         if(toRead == 0) { //Timeout
 |  | ||||||
|             delay(100); |  | ||||||
|             toRead = data.readBytes(_buffer + _bufferLen, (SPI_FLASH_SEC_SIZE - _bufferLen)); |  | ||||||
|             if(toRead == 0) { //Timeout
 |  | ||||||
|                 _abort(UPDATE_ERROR_STREAM); |  | ||||||
|                 return written; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         _bufferLen += toRead; |  | ||||||
|         if((_bufferLen == remaining() || _bufferLen == SPI_FLASH_SEC_SIZE) && !_writeBuffer()) |  | ||||||
|             return written; |  | ||||||
|         written += toRead; |  | ||||||
|         if(_progress_callback) { |  | ||||||
|             _progress_callback(_progress, _size); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     if(_progress_callback) { |  | ||||||
|         _progress_callback(_size, _size); |  | ||||||
|     } |  | ||||||
|     return written; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void UpdateClass::printError(Stream &out){ |  | ||||||
|     out.println(_err2str(_error)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| UpdateClass Update; |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user