@@ -35,6 +35,34 @@ static const char * _err2str(uint8_t _error){
3535 return (" UNKNOWN" );
3636}
3737
38+ static bool _partitionIsBootable (const esp_partition_t * partition){
39+ uint8_t buf[4 ];
40+ if (!partition){
41+ return false ;
42+ }
43+ if (!ESP.flashRead (partition->address , (uint32_t *)buf, 4 )) {
44+ return false ;
45+ }
46+
47+ if (buf[0 ] != ESP_IMAGE_HEADER_MAGIC) {
48+ return false ;
49+ }
50+ return true ;
51+ }
52+
53+ static bool _enablePartition (const esp_partition_t * partition){
54+ uint8_t buf[4 ];
55+ if (!partition){
56+ return false ;
57+ }
58+ if (!ESP.flashRead (partition->address , (uint32_t *)buf, 4 )) {
59+ return false ;
60+ }
61+ buf[0 ] = ESP_IMAGE_HEADER_MAGIC;
62+
63+ return ESP.flashWrite (partition->address , (uint32_t *)buf, 4 );
64+ }
65+
3866UpdateClass::UpdateClass ()
3967: _error(0 )
4068, _buffer(0 )
@@ -56,6 +84,22 @@ void UpdateClass::_reset() {
5684 _command = U_FLASH;
5785}
5886
87+ bool UpdateClass::canRollBack (){
88+ if (_buffer){ // Update is running
89+ return false ;
90+ }
91+ const esp_partition_t * partition = esp_ota_get_next_update_partition (NULL );
92+ return _partitionIsBootable (partition);
93+ }
94+
95+ bool UpdateClass::rollBack (){
96+ if (_buffer){ // Update is running
97+ return false ;
98+ }
99+ const esp_partition_t * partition = esp_ota_get_next_update_partition (NULL );
100+ return _partitionIsBootable (partition) && !esp_ota_set_boot_partition (partition);
101+ }
102+
59103bool UpdateClass::begin (size_t size, int command) {
60104 if (_size > 0 ){
61105 log_w (" already running" );
@@ -121,6 +165,17 @@ void UpdateClass::abort(){
121165}
122166
123167bool UpdateClass::_writeBuffer (){
168+ // first bytes of new firmware
169+ if (!_progress && _command == U_FLASH){
170+ // check magic
171+ if (_buffer[0 ] != ESP_IMAGE_HEADER_MAGIC){
172+ _abort (UPDATE_ERROR_MAGIC_BYTE);
173+ return false ;
174+ }
175+ // remove magic byte from the firmware now and write it upon success
176+ // this ensures that partially written firmware will not be bootable
177+ _buffer[0 ] = 0xFF ;
178+ }
124179 if (!ESP.flashEraseSector ((_partition->address + _progress)/SPI_FLASH_SEC_SIZE)){
125180 _abort (UPDATE_ERROR_ERASE);
126181 return false ;
@@ -129,6 +184,10 @@ bool UpdateClass::_writeBuffer(){
129184 _abort (UPDATE_ERROR_WRITE);
130185 return false ;
131186 }
187+ // restore magic or md5 will fail
188+ if (!_progress && _command == U_FLASH){
189+ _buffer[0 ] = ESP_IMAGE_HEADER_MAGIC;
190+ }
132191 _md5.add (_buffer, _bufferLen);
133192 _progress += _bufferLen;
134193 _bufferLen = 0 ;
@@ -150,24 +209,19 @@ bool UpdateClass::_verifyHeader(uint8_t data) {
150209
151210bool UpdateClass::_verifyEnd () {
152211 if (_command == U_FLASH) {
153- uint8_t buf[4 ];
154- if (!ESP.flashRead (_partition->address , (uint32_t *)buf, 4 )) {
212+ if (!_partitionIsBootable (_partition)) {
155213 _abort (UPDATE_ERROR_READ);
156214 return false ;
157215 }
158216
159- if (buf[0 ] != ESP_IMAGE_HEADER_MAGIC) {
160- _abort (UPDATE_ERROR_MAGIC_BYTE);
161- return false ;
162- }
163-
164217 if (esp_ota_set_boot_partition (_partition)){
165218 _abort (UPDATE_ERROR_ACTIVATE);
166219 return false ;
167220 }
168221 _reset ();
169222 return true ;
170223 } else if (_command == U_SPIFFS) {
224+ _reset ();
171225 return true ;
172226 }
173227 return false ;
0 commit comments