1 // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 #include <stdio.h>
15 #include "esp_system.h"
16 #include "esp_log.h"
17 #include "WL_Flash.h"
18 #include <stdlib.h>
19 #include "crc32.h"
20 #include <string.h>
21 #include <stddef.h>
22 
23 static const char *TAG = "wl_flash";
24 #ifndef WL_CFG_CRC_CONST
25 #define WL_CFG_CRC_CONST UINT32_MAX
26 #endif // WL_CFG_CRC_CONST
27 
28 #define WL_RESULT_CHECK(result) \
29     if (result != ESP_OK) { \
30         ESP_LOGE(TAG,"%s(%d): result = 0x%08x", __FUNCTION__, __LINE__, result); \
31         return (result); \
32     }
33 
34 #ifndef _MSC_VER // MSVS has different format for this define
35 static_assert(sizeof(wl_state_t) % 32 == 0, "wl_state_t structure size must be multiple of flash encryption unit size");
36 #endif // _MSC_VER
37 
38 
WL_Flash()39 WL_Flash::WL_Flash()
40 {
41 }
42 
~WL_Flash()43 WL_Flash::~WL_Flash()
44 {
45     free(this->temp_buff);
46 }
47 
config(wl_config_t * cfg,Flash_Access * flash_drv)48 esp_err_t WL_Flash::config(wl_config_t *cfg, Flash_Access *flash_drv)
49 {
50     ESP_LOGV(TAG, "%s start_addr=0x%08x, full_mem_size=0x%08x, page_size=0x%08x, sector_size=0x%08x, updaterate=0x%08x, wr_size=0x%08x, version=0x%08x, temp_buff_size=0x%08x", __func__,
51              (uint32_t) cfg->start_addr,
52              cfg->full_mem_size,
53              cfg->page_size,
54              cfg->sector_size,
55              cfg->updaterate,
56              cfg->wr_size,
57              cfg->version,
58              (uint32_t) cfg->temp_buff_size);
59 
60     cfg->crc = crc32::crc32_le(WL_CFG_CRC_CONST, (const unsigned char *)cfg, offsetof(wl_config_t, crc));
61     esp_err_t result = ESP_OK;
62     memcpy(&this->cfg, cfg, sizeof(wl_config_t));
63     if (this->cfg.temp_buff_size < this->cfg.wr_size) {
64         this->cfg.temp_buff_size = this->cfg.wr_size;
65     }
66     this->configured = false;
67     if (cfg == NULL) {
68         result = ESP_ERR_INVALID_ARG;
69     }
70     this->flash_drv = flash_drv;
71     if (flash_drv == NULL) {
72         result = ESP_ERR_INVALID_ARG;
73     }
74     if ((this->cfg.sector_size % this->cfg.temp_buff_size) != 0) {
75         result = ESP_ERR_INVALID_ARG;
76     }
77     if (this->cfg.page_size < this->cfg.sector_size) {
78         result = ESP_ERR_INVALID_ARG;
79     }
80     WL_RESULT_CHECK(result);
81 
82     this->state_size = this->cfg.sector_size;
83     if (this->state_size < (sizeof(wl_state_t) + (this->cfg.full_mem_size / this->cfg.sector_size)*this->cfg.wr_size)) {
84         this->state_size = ((sizeof(wl_state_t) + (this->cfg.full_mem_size / this->cfg.sector_size) * this->cfg.wr_size) + this->cfg.sector_size - 1) / this->cfg.sector_size;
85         this->state_size = this->state_size * this->cfg.sector_size;
86     }
87     this->cfg_size = (sizeof(wl_config_t) + this->cfg.sector_size - 1) / this->cfg.sector_size;
88     this->cfg_size = cfg_size * this->cfg.sector_size;
89 
90     this->addr_cfg = this->cfg.start_addr + this->cfg.full_mem_size - this->cfg_size;
91     this->addr_state1 = this->cfg.start_addr + this->cfg.full_mem_size - this->state_size * 2 - this->cfg_size; // allocate data at the end of memory
92     this->addr_state2 = this->cfg.start_addr + this->cfg.full_mem_size - this->state_size * 1 - this->cfg_size; // allocate data at the end of memory
93 
94     ptrdiff_t flash_sz = ((this->cfg.full_mem_size - this->state_size * 2 - this->cfg_size) / this->cfg.page_size - 1) * this->cfg.page_size; // -1 remove dummy block
95     this->flash_size = ((this->cfg.full_mem_size - this->state_size * 2 - this->cfg_size) / this->cfg.page_size - 1) * this->cfg.page_size; // -1 remove dummy block
96 
97     ESP_LOGD(TAG, "%s - config result: state_size=0x%08x, cfg_size=0x%08x, addr_cfg=0x%08x, addr_state1=0x%08x, addr_state2=0x%08x, flash_size=0x%08x", __func__,
98              (uint32_t) this->state_size,
99              (uint32_t) this->cfg_size,
100              (uint32_t) this->addr_cfg,
101              (uint32_t) this->addr_state1,
102              (uint32_t) this->addr_state2,
103              (uint32_t) this->flash_size
104             );
105     if (flash_sz <= 0) {
106         result = ESP_ERR_INVALID_ARG;
107     }
108     WL_RESULT_CHECK(result);
109 
110     this->temp_buff = (uint8_t *)malloc(this->cfg.temp_buff_size);
111     if (this->temp_buff == NULL) {
112         result = ESP_ERR_NO_MEM;
113     }
114     WL_RESULT_CHECK(result);
115     this->configured = true;
116     return ESP_OK;
117 }
118 
init()119 esp_err_t WL_Flash::init()
120 {
121     esp_err_t result = ESP_OK;
122     if (this->configured == false) {
123         ESP_LOGW(TAG, "WL_Flash: not configured, call config() first");
124         return ESP_ERR_INVALID_STATE;
125     }
126     // If flow will be interrupted by error, then this flag will be false
127     this->initialized = false;
128     // Init states if it is first time...
129     this->flash_drv->read(this->addr_state1, &this->state, sizeof(wl_state_t));
130     wl_state_t sa_copy;
131     wl_state_t *state_copy = &sa_copy;
132     result = this->flash_drv->read(this->addr_state2, state_copy, sizeof(wl_state_t));
133     WL_RESULT_CHECK(result);
134 
135     int check_size = WL_STATE_CRC_LEN_V2;
136     // Chech CRC and recover state
137     uint32_t crc1 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, check_size);
138     uint32_t crc2 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)state_copy, check_size);
139 
140     ESP_LOGD(TAG, "%s - config ID=%i, stored ID=%i, access_count=%i, block_size=%i, max_count=%i, pos=%i, move_count=0x%8.8X",
141              __func__,
142              this->cfg.version,
143              this->state.version,
144              this->state.access_count,
145              this->state.block_size,
146              this->state.max_count,
147              this->state.pos,
148              this->state.move_count);
149 
150     ESP_LOGD(TAG, "%s starts: crc1= 0x%08x, crc2 = 0x%08x, this->state.crc= 0x%08x, state_copy->crc= 0x%08x, version=%i, read_version=%i", __func__, crc1, crc2, this->state.crc, state_copy->crc, this->cfg.version, this->state.version);
151     if ((crc1 == this->state.crc) && (crc2 == state_copy->crc)) {
152         // The state is OK. Check the ID
153         if (this->state.version != this->cfg.version) {
154             result = this->initSections();
155             WL_RESULT_CHECK(result);
156             result = this->recoverPos();
157             WL_RESULT_CHECK(result);
158         } else {
159             if (crc1 != crc2) {// we did not update second structure.
160                 result = this->flash_drv->erase_range(this->addr_state2, this->state_size);
161                 WL_RESULT_CHECK(result);
162                 result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
163                 WL_RESULT_CHECK(result);
164                 for (size_t i = 0; i < ((this->cfg.full_mem_size / this->cfg.sector_size)*this->cfg.wr_size); i++) {
165                     bool pos_bits;
166                     result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
167                     WL_RESULT_CHECK(result);
168                     pos_bits = this->OkBuffSet(i);
169                     if (pos_bits == true) {
170                         //this->fillOkBuff(i);
171                         result = this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
172                         WL_RESULT_CHECK(result);
173                     }
174                 }
175             }
176             ESP_LOGD(TAG, "%s: crc1=0x%08x, crc2 = 0x%08x, result= 0x%08x", __func__, crc1, crc2, (uint32_t)result);
177             result = this->recoverPos();
178             WL_RESULT_CHECK(result);
179         }
180     } else if ((crc1 != this->state.crc) && (crc2 != state_copy->crc)) { // This is just new flash or new version
181         // Check if this is new version or just new instance of WL
182         ESP_LOGD(TAG, "%s: try to update version - crc1= 0x%08x, crc2 = 0x%08x, result= 0x%08x", __func__, (uint32_t)crc1, (uint32_t)crc2, (uint32_t)result);
183         result = this->updateVersion();
184         if (result == ESP_FAIL) {
185             ESP_LOGD(TAG, "%s: init flash sections", __func__);
186             result = this->initSections();
187             WL_RESULT_CHECK(result);
188         }
189         result = this->recoverPos();
190         WL_RESULT_CHECK(result);
191     } else {
192         // recover broken state
193         if (crc1 == this->state.crc) {// we have to recover state 2
194             result = this->flash_drv->erase_range(this->addr_state2, this->state_size);
195             WL_RESULT_CHECK(result);
196             result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
197             WL_RESULT_CHECK(result);
198             for (size_t i = 0; i < ((this->cfg.full_mem_size / this->cfg.sector_size) * this->cfg.wr_size); i++) {
199                 bool pos_bits;
200                 result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
201                 WL_RESULT_CHECK(result);
202                 pos_bits = this->OkBuffSet(i);
203                 if (pos_bits == true) {
204                     result = this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
205                     WL_RESULT_CHECK(result);
206                 }
207             }
208             result = this->flash_drv->read(this->addr_state2, &this->state, sizeof(wl_state_t));
209             WL_RESULT_CHECK(result);
210         } else { // we have to recover state 1
211             result = this->flash_drv->erase_range(this->addr_state1, this->state_size);
212             WL_RESULT_CHECK(result);
213             result = this->flash_drv->write(this->addr_state1, state_copy, sizeof(wl_state_t));
214             WL_RESULT_CHECK(result);
215             for (size_t i = 0; i < ((this->cfg.full_mem_size / this->cfg.sector_size) * this->cfg.wr_size); i++) {
216                 bool pos_bits;
217                 result = this->flash_drv->read(this->addr_state2 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
218 
219                 WL_RESULT_CHECK(result);
220                 pos_bits = this->OkBuffSet(i);
221                 if (pos_bits == true) {
222                     result = this->flash_drv->write(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
223                     WL_RESULT_CHECK(result);
224                 }
225             }
226             result = this->flash_drv->read(this->addr_state1, &this->state, sizeof(wl_state_t));
227             WL_RESULT_CHECK(result);
228             this->state.pos = this->state.max_pos - 1;
229         }
230         // done. We have recovered the state
231         // If we have a new configuration, we will overwrite it
232         if (this->state.version != this->cfg.version) {
233             result = this->initSections();
234             WL_RESULT_CHECK(result);
235         }
236     }
237     if (result != ESP_OK) {
238         this->initialized = false;
239         ESP_LOGE(TAG, "%s: returned 0x%08x", __func__, (uint32_t)result);
240         return result;
241     }
242     this->initialized = true;
243     ESP_LOGD(TAG, "%s - move_count= 0x%08x", __func__, (uint32_t)this->state.move_count);
244     return ESP_OK;
245 }
246 
recoverPos()247 esp_err_t WL_Flash::recoverPos()
248 {
249     esp_err_t result = ESP_OK;
250     size_t position = 0;
251     ESP_LOGV(TAG, "%s start", __func__);
252     for (size_t i = 0; i < this->state.max_pos; i++) {
253         bool pos_bits;
254         position = i;
255         result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
256         pos_bits = this->OkBuffSet(i);
257         WL_RESULT_CHECK(result);
258         ESP_LOGV(TAG, "%s - check pos: result=0x%08x, position= %i, pos_bits= 0x%08x", __func__, (uint32_t)result, (uint32_t)position, (uint32_t)pos_bits);
259         if (pos_bits == false) {
260             break; // we have found position
261         }
262     }
263 
264     this->state.pos = position;
265     if (this->state.pos == this->state.max_pos) {
266         this->state.pos--;
267     }
268     ESP_LOGD(TAG, "%s - this->state.pos= 0x%08x, position= 0x%08x, result= 0x%08x, max_pos= 0x%08x", __func__, (uint32_t)this->state.pos, (uint32_t)position, (uint32_t)result, (uint32_t)this->state.max_pos);
269     ESP_LOGV(TAG, "%s done", __func__);
270     return result;
271 }
272 
initSections()273 esp_err_t WL_Flash::initSections()
274 {
275     esp_err_t result = ESP_OK;
276     this->state.pos = 0;
277     this->state.access_count = 0;
278     this->state.move_count = 0;
279     // max count
280     this->state.max_count = this->flash_size / this->state_size * this->cfg.updaterate;
281     if (this->cfg.updaterate != 0) {
282         this->state.max_count = this->cfg.updaterate;
283     }
284     this->state.version = this->cfg.version;
285     this->state.block_size = this->cfg.page_size;
286     this->state.device_id = esp_random();
287     memset(this->state.reserved, 0, sizeof(this->state.reserved));
288 
289     this->state.max_pos = 1 + this->flash_size / this->cfg.page_size;
290 
291     this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, WL_STATE_CRC_LEN_V2);
292 
293     result = this->flash_drv->erase_range(this->addr_state1, this->state_size);
294     WL_RESULT_CHECK(result);
295     result = this->flash_drv->write(this->addr_state1, &this->state, sizeof(wl_state_t));
296     WL_RESULT_CHECK(result);
297     // write state copy
298     result = this->flash_drv->erase_range(this->addr_state2, this->state_size);
299     WL_RESULT_CHECK(result);
300     result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
301     WL_RESULT_CHECK(result);
302 
303     result = this->flash_drv->erase_range(this->addr_cfg, this->cfg_size);
304     WL_RESULT_CHECK(result);
305     result = this->flash_drv->write(this->addr_cfg, &this->cfg, sizeof(wl_config_t));
306     WL_RESULT_CHECK(result);
307 
308     ESP_LOGD(TAG, "%s - this->state->max_count= 0x%08x, this->state->max_pos= 0x%08x", __func__, this->state.max_count, this->state.max_pos);
309     ESP_LOGD(TAG, "%s - result= 0x%08x", __func__, result);
310     return result;
311 }
312 
updateVersion()313 esp_err_t WL_Flash::updateVersion()
314 {
315     esp_err_t result = ESP_OK;
316 
317     result = this->updateV1_V2();
318     if (result == ESP_OK) {
319         return result;
320     }
321     // check next version
322     return result;
323 }
324 
updateV1_V2()325 esp_err_t WL_Flash::updateV1_V2()
326 {
327     esp_err_t result = ESP_OK;
328     // Check crc for old version and old version
329     ESP_LOGV(TAG, "%s start", __func__);
330     int check_size = WL_STATE_CRC_LEN_V1;
331     // Chech CRC and recover state
332     uint32_t crc1 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, check_size);
333     wl_state_t sa_copy;
334     wl_state_t *state_copy = &sa_copy;
335     result = this->flash_drv->read(this->addr_state2, state_copy, sizeof(wl_state_t));
336     WL_RESULT_CHECK(result);
337     uint32_t crc2 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)state_copy, check_size);
338 
339     // For V1 crc in place of device_id and version
340     uint32_t v1_crc1 = this->state.device_id;
341     uint32_t v1_crc2 = state_copy->device_id;
342 
343     ESP_LOGD(TAG, "%s - process crc1=0x%08x, crc2=0x%08x, v1_crc1=0x%08x, v1_crc2=0x%08x, version=%i", __func__, crc1, crc2, v1_crc1, v1_crc2, this->state.version);
344 
345     if ((crc1 == v1_crc1) && (crc2 == v1_crc2) && (v1_crc1 == v1_crc2) && (this->state.version == 1) && (state_copy->version == 1)) {
346         // Here we have to update all internal structures
347         ESP_LOGI(TAG, "%s Update from V1 to V2, crc=0x%08x, ", __func__, crc1);
348         uint32_t pos = 0;
349 
350         for (size_t i = 0; i < this->state.max_pos; i++) {
351             uint8_t pos_bits;
352             result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, &pos_bits, 1);
353             WL_RESULT_CHECK(result);
354             ESP_LOGV(TAG, "%s- result= 0x%08x, pos= %i, pos_bits= 0x%08x", __func__, (uint32_t)result, (uint32_t)pos, (uint32_t)pos_bits);
355             pos = i;
356             if (pos_bits == 0xff) {
357                 break; // we have found position
358             }
359         }
360         ESP_LOGI(TAG, "%s max_pos=%i, pos=%i, state.ver=%i, state2.ver=%i", __func__, (uint32_t)this->state.max_pos, (uint32_t)pos, (uint32_t)this->state.version, (uint32_t)state_copy->version);
361         if (pos == this->state.max_pos) {
362             pos--;
363         }
364         WL_RESULT_CHECK(result);
365 
366         this->state.version = 2;
367         this->state.pos = 0;
368         this->state.device_id = esp_random();
369         memset(this->state.reserved, 0, sizeof(this->state.reserved));
370         this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, WL_STATE_CRC_LEN_V2);
371 
372         result = this->flash_drv->erase_range(this->addr_state1, this->state_size);
373         WL_RESULT_CHECK(result);
374         result = this->flash_drv->write(this->addr_state1, &this->state, sizeof(wl_state_t));
375         WL_RESULT_CHECK(result);
376 
377         memset(this->temp_buff, 0, this->cfg.wr_size);
378         for (uint32_t i = 0 ; i <= pos; i++) {
379             this->fillOkBuff(i);
380             result = this->flash_drv->write(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
381             WL_RESULT_CHECK(result);
382         }
383 
384         result = this->flash_drv->erase_range(this->addr_state2, this->state_size);
385         WL_RESULT_CHECK(result);
386         result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
387         WL_RESULT_CHECK(result);
388         ESP_LOGD(TAG, "%s - move_count= 0x%08x, pos= 0x%08x", __func__, this->state.move_count, this->state.pos);
389 
390         memset(this->temp_buff, 0, this->cfg.wr_size);
391         for (uint32_t i = 0 ; i <= pos; i++) {
392             this->fillOkBuff(i);
393             result = this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
394             WL_RESULT_CHECK(result);
395         }
396         this->state.pos = pos;
397         return result;
398     }
399 
400     return ESP_FAIL;
401 }
402 
fillOkBuff(int n)403 void WL_Flash::fillOkBuff(int n)
404 {
405     uint32_t *buff = (uint32_t *)this->temp_buff;
406 
407     for (int i = 0 ; i < 4 ; i++) {
408         buff[i] = this->state.device_id + n * 4 + i;
409         buff[i] = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&buff[i], sizeof(uint32_t));
410     }
411 }
412 
OkBuffSet(int n)413 bool WL_Flash::OkBuffSet(int n)
414 {
415     bool result = true;
416     uint32_t *data_buff = (uint32_t *)this->temp_buff;
417     for (int i = 0 ; i < 4 ; i++) {
418         uint32_t data = this->state.device_id + n * 4 + i;
419         uint32_t crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&data, sizeof(uint32_t));
420         if (crc != data_buff[i]) {
421             result = false;
422         }
423     }
424     return result;
425 }
426 
427 
updateWL()428 esp_err_t WL_Flash::updateWL()
429 {
430     esp_err_t result = ESP_OK;
431     this->state.access_count++;
432     if (this->state.access_count < this->state.max_count) {
433         return result;
434     }
435     // Here we have to move the block and increase the state
436     this->state.access_count = 0;
437     ESP_LOGV(TAG, "%s - access_count= 0x%08x, pos= 0x%08x", __func__, this->state.access_count, this->state.pos);
438     // copy data to dummy block
439     size_t data_addr = this->state.pos + 1; // next block, [pos+1] copy to [pos]
440     if (data_addr >= this->state.max_pos) {
441         data_addr = 0;
442     }
443     data_addr = this->cfg.start_addr + data_addr * this->cfg.page_size;
444     this->dummy_addr = this->cfg.start_addr + this->state.pos * this->cfg.page_size;
445     result = this->flash_drv->erase_range(this->dummy_addr, this->cfg.page_size);
446     if (result != ESP_OK) {
447         ESP_LOGE(TAG, "%s - erase wl dummy sector result= 0x%08x", __func__, result);
448         this->state.access_count = this->state.max_count - 1; // we will update next time
449         return result;
450     }
451 
452     size_t copy_count = this->cfg.page_size / this->cfg.temp_buff_size;
453     for (size_t i = 0; i < copy_count; i++) {
454         result = this->flash_drv->read(data_addr + i * this->cfg.temp_buff_size, this->temp_buff, this->cfg.temp_buff_size);
455         if (result != ESP_OK) {
456             ESP_LOGE(TAG, "%s - not possible to read buffer, will try next time, result= 0x%08x", __func__, result);
457             this->state.access_count = this->state.max_count - 1; // we will update next time
458             return result;
459         }
460         result = this->flash_drv->write(this->dummy_addr + i * this->cfg.temp_buff_size, this->temp_buff, this->cfg.temp_buff_size);
461         if (result != ESP_OK) {
462             ESP_LOGE(TAG, "%s - not possible to write buffer, will try next time, result= 0x%08x", __func__, result);
463             this->state.access_count = this->state.max_count - 1; // we will update next time
464             return result;
465         }
466     }
467     // done... block moved.
468     // Here we will update structures...
469     // Update bits and save to flash:
470     uint32_t byte_pos = this->state.pos * this->cfg.wr_size;
471     this->fillOkBuff(this->state.pos);
472     // write state to mem. We updating only affected bits
473     result |= this->flash_drv->write(this->addr_state1 + sizeof(wl_state_t) + byte_pos, this->temp_buff, this->cfg.wr_size);
474     if (result != ESP_OK) {
475         ESP_LOGE(TAG, "%s - update position 1 result= 0x%08x", __func__, result);
476         this->state.access_count = this->state.max_count - 1; // we will update next time
477         return result;
478     }
479     this->fillOkBuff(this->state.pos);
480     result |= this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + byte_pos, this->temp_buff, this->cfg.wr_size);
481     if (result != ESP_OK) {
482         ESP_LOGE(TAG, "%s - update position 2 result= 0x%08x", __func__, result);
483         this->state.access_count = this->state.max_count - 1; // we will update next time
484         return result;
485     }
486 
487     this->state.pos++;
488     if (this->state.pos >= this->state.max_pos) {
489         this->state.pos = 0;
490         // one loop more
491         this->state.move_count++;
492         if (this->state.move_count >= (this->state.max_pos - 1)) {
493             this->state.move_count = 0;
494         }
495         // write main state
496         this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, WL_STATE_CRC_LEN_V2);
497 
498         result = this->flash_drv->erase_range(this->addr_state1, this->state_size);
499         WL_RESULT_CHECK(result);
500         result = this->flash_drv->write(this->addr_state1, &this->state, sizeof(wl_state_t));
501         WL_RESULT_CHECK(result);
502         result = this->flash_drv->erase_range(this->addr_state2, this->state_size);
503         WL_RESULT_CHECK(result);
504         result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
505         WL_RESULT_CHECK(result);
506         ESP_LOGD(TAG, "%s - move_count= 0x%08x, pos= 0x%08x, ", __func__, this->state.move_count, this->state.pos);
507     }
508     // Save structures to the flash... and check result
509     if (result == ESP_OK) {
510         ESP_LOGV(TAG, "%s - result= 0x%08x", __func__, result);
511     } else {
512         ESP_LOGE(TAG, "%s - result= 0x%08x", __func__, result);
513     }
514     return result;
515 }
516 
calcAddr(size_t addr)517 size_t WL_Flash::calcAddr(size_t addr)
518 {
519     size_t result = (this->flash_size - this->state.move_count * this->cfg.page_size + addr) % this->flash_size;
520     size_t dummy_addr = this->state.pos * this->cfg.page_size;
521     if (result < dummy_addr) {
522     } else {
523         result += this->cfg.page_size;
524     }
525     ESP_LOGV(TAG, "%s - addr= 0x%08x -> result= 0x%08x, dummy_addr= 0x%08x", __func__, (uint32_t) addr, (uint32_t) result, (uint32_t)dummy_addr);
526     return result;
527 }
528 
529 
chip_size()530 size_t WL_Flash::chip_size()
531 {
532     if (!this->configured) {
533         return 0;
534     }
535     return this->flash_size;
536 }
sector_size()537 size_t WL_Flash::sector_size()
538 {
539     if (!this->configured) {
540         return 0;
541     }
542     return this->cfg.sector_size;
543 }
544 
545 
erase_sector(size_t sector)546 esp_err_t WL_Flash::erase_sector(size_t sector)
547 {
548     esp_err_t result = ESP_OK;
549     if (!this->initialized) {
550         return ESP_ERR_INVALID_STATE;
551     }
552     ESP_LOGD(TAG, "%s - sector= 0x%08x", __func__, (uint32_t) sector);
553     result = this->updateWL();
554     WL_RESULT_CHECK(result);
555     size_t virt_addr = this->calcAddr(sector * this->cfg.sector_size);
556     result = this->flash_drv->erase_sector((this->cfg.start_addr + virt_addr) / this->cfg.sector_size);
557     WL_RESULT_CHECK(result);
558     return result;
559 }
erase_range(size_t start_address,size_t size)560 esp_err_t WL_Flash::erase_range(size_t start_address, size_t size)
561 {
562     esp_err_t result = ESP_OK;
563     if (!this->initialized) {
564         return ESP_ERR_INVALID_STATE;
565     }
566     ESP_LOGD(TAG, "%s - start_address= 0x%08x, size= 0x%08x", __func__, (uint32_t) start_address, (uint32_t) size);
567     size_t erase_count = (size + this->cfg.sector_size - 1) / this->cfg.sector_size;
568     size_t start_sector = start_address / this->cfg.sector_size;
569     for (size_t i = 0; i < erase_count; i++) {
570         result = this->erase_sector(start_sector + i);
571         WL_RESULT_CHECK(result);
572     }
573     ESP_LOGV(TAG, "%s - result= 0x%08x", __func__, result);
574     return result;
575 }
576 
write(size_t dest_addr,const void * src,size_t size)577 esp_err_t WL_Flash::write(size_t dest_addr, const void *src, size_t size)
578 {
579     esp_err_t result = ESP_OK;
580     if (!this->initialized) {
581         return ESP_ERR_INVALID_STATE;
582     }
583     ESP_LOGD(TAG, "%s - dest_addr= 0x%08x, size= 0x%08x", __func__, (uint32_t) dest_addr, (uint32_t) size);
584     uint32_t count = (size - 1) / this->cfg.page_size;
585     for (size_t i = 0; i < count; i++) {
586         size_t virt_addr = this->calcAddr(dest_addr + i * this->cfg.page_size);
587         result = this->flash_drv->write(this->cfg.start_addr + virt_addr, &((uint8_t *)src)[i * this->cfg.page_size], this->cfg.page_size);
588         WL_RESULT_CHECK(result);
589     }
590     size_t virt_addr_last = this->calcAddr(dest_addr + count * this->cfg.page_size);
591     result = this->flash_drv->write(this->cfg.start_addr + virt_addr_last, &((uint8_t *)src)[count * this->cfg.page_size], size - count * this->cfg.page_size);
592     WL_RESULT_CHECK(result);
593     return result;
594 }
595 
read(size_t src_addr,void * dest,size_t size)596 esp_err_t WL_Flash::read(size_t src_addr, void *dest, size_t size)
597 {
598     esp_err_t result = ESP_OK;
599     if (!this->initialized) {
600         return ESP_ERR_INVALID_STATE;
601     }
602     ESP_LOGD(TAG, "%s - src_addr= 0x%08x, size= 0x%08x", __func__, (uint32_t) src_addr, (uint32_t) size);
603     uint32_t count = (size - 1) / this->cfg.page_size;
604     for (size_t i = 0; i < count; i++) {
605         size_t virt_addr = this->calcAddr(src_addr + i * this->cfg.page_size);
606         ESP_LOGV(TAG, "%s - real_addr= 0x%08x, size= 0x%08x", __func__, (uint32_t) (this->cfg.start_addr + virt_addr), (uint32_t) size);
607         result = this->flash_drv->read(this->cfg.start_addr + virt_addr, &((uint8_t *)dest)[i * this->cfg.page_size], this->cfg.page_size);
608         WL_RESULT_CHECK(result);
609     }
610     size_t virt_addr_last = this->calcAddr(src_addr + count * this->cfg.page_size);
611     result = this->flash_drv->read(this->cfg.start_addr + virt_addr_last, &((uint8_t *)dest)[count * this->cfg.page_size], size - count * this->cfg.page_size);
612     WL_RESULT_CHECK(result);
613     return result;
614 }
615 
get_drv()616 Flash_Access *WL_Flash::get_drv()
617 {
618     return this->flash_drv;
619 }
get_cfg()620 wl_config_t *WL_Flash::get_cfg()
621 {
622     return &this->cfg;
623 }
624 
flush()625 esp_err_t WL_Flash::flush()
626 {
627     esp_err_t result = ESP_OK;
628     this->state.access_count = this->state.max_count - 1;
629     result = this->updateWL();
630     ESP_LOGD(TAG, "%s - result= 0x%08x, move_count= 0x%08x", __func__, result, this->state.move_count);
631     return result;
632 }
633