@@ -35,6 +35,34 @@ static const char * _err2str(uint8_t _error){
35
35
return (" UNKNOWN" );
36
36
}
37
37
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
+
38
66
UpdateClass::UpdateClass ()
39
67
: _error(0 )
40
68
, _buffer(0 )
@@ -56,6 +84,22 @@ void UpdateClass::_reset() {
56
84
_command = U_FLASH;
57
85
}
58
86
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
+
59
103
bool UpdateClass::begin (size_t size, int command) {
60
104
if (_size > 0 ){
61
105
log_w (" already running" );
@@ -121,6 +165,17 @@ void UpdateClass::abort(){
121
165
}
122
166
123
167
bool 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
+ }
124
179
if (!ESP.flashEraseSector ((_partition->address + _progress)/SPI_FLASH_SEC_SIZE)){
125
180
_abort (UPDATE_ERROR_ERASE);
126
181
return false ;
@@ -129,6 +184,10 @@ bool UpdateClass::_writeBuffer(){
129
184
_abort (UPDATE_ERROR_WRITE);
130
185
return false ;
131
186
}
187
+ // restore magic or md5 will fail
188
+ if (!_progress && _command == U_FLASH){
189
+ _buffer[0 ] = ESP_IMAGE_HEADER_MAGIC;
190
+ }
132
191
_md5.add (_buffer, _bufferLen);
133
192
_progress += _bufferLen;
134
193
_bufferLen = 0 ;
@@ -150,24 +209,19 @@ bool UpdateClass::_verifyHeader(uint8_t data) {
150
209
151
210
bool UpdateClass::_verifyEnd () {
152
211
if (_command == U_FLASH) {
153
- uint8_t buf[4 ];
154
- if (!ESP.flashRead (_partition->address , (uint32_t *)buf, 4 )) {
212
+ if (!_partitionIsBootable (_partition)) {
155
213
_abort (UPDATE_ERROR_READ);
156
214
return false ;
157
215
}
158
216
159
- if (buf[0 ] != ESP_IMAGE_HEADER_MAGIC) {
160
- _abort (UPDATE_ERROR_MAGIC_BYTE);
161
- return false ;
162
- }
163
-
164
217
if (esp_ota_set_boot_partition (_partition)){
165
218
_abort (UPDATE_ERROR_ACTIVATE);
166
219
return false ;
167
220
}
168
221
_reset ();
169
222
return true ;
170
223
} else if (_command == U_SPIFFS) {
224
+ _reset ();
171
225
return true ;
172
226
}
173
227
return false ;
0 commit comments