23
23
24
24
#include <zephyr/kernel.h>
25
25
#include <zephyr/device.h>
26
+ #include <zephyr/devicetree.h>
26
27
#include <stddef.h>
27
28
#include <string.h>
28
29
#include <errno.h>
@@ -34,6 +35,16 @@ LOG_MODULE_REGISTER(flash_esp32, CONFIG_FLASH_LOG_LEVEL);
34
35
35
36
#define FLASH_SEM_TIMEOUT (k_is_in_isr() ? K_NO_WAIT : K_FOREVER)
36
37
38
+ #ifdef CONFIG_ESP32_EFUSE_VIRTUAL_KEEP_IN_FLASH
39
+ #define ENCRYPTION_IS_VIRTUAL (!efuse_hal_flash_encryption_enabled())
40
+ #else
41
+ #define ENCRYPTION_IS_VIRTUAL 0
42
+ #endif
43
+
44
+ #ifndef ALIGN_OFFSET
45
+ #define ALIGN_OFFSET (num , align ) ((num) & ((align) - 1))
46
+ #endif
47
+
37
48
struct flash_esp32_dev_config {
38
49
spi_dev_t * controller ;
39
50
};
@@ -76,6 +87,227 @@ static inline void flash_esp32_sem_give(const struct device *dev)
76
87
#include <stdint.h>
77
88
#include <string.h>
78
89
90
+ #ifndef CONFIG_MCUBOOT
91
+ static int flash_esp32_read_check_enc (off_t address , void * buffer , size_t length )
92
+ {
93
+ int ret = 0 ;
94
+
95
+ if (esp_flash_encryption_enabled ()) {
96
+ LOG_DBG ("Flash read ENCRYPTED - address 0x%lx size 0x%x" , address , length );
97
+ ret = esp_flash_read_encrypted (NULL , address , buffer , length );
98
+ } else {
99
+ LOG_DBG ("Flash read RAW - address 0x%lx size 0x%x" , address , length );
100
+ ret = esp_flash_read (NULL , buffer , address , length );
101
+ }
102
+
103
+ if (ret != 0 ) {
104
+ LOG_ERR ("Flash read error: %d" , ret );
105
+ return - EIO ;
106
+ }
107
+
108
+ return 0 ;
109
+ }
110
+
111
+ static int flash_esp32_write_check_enc (off_t address , const void * buffer , size_t length )
112
+ {
113
+ int ret = 0 ;
114
+
115
+ if (esp_flash_encryption_enabled () && !ENCRYPTION_IS_VIRTUAL ) {
116
+ LOG_DBG ("Flash write ENCRYPTED - address 0x%lx size 0x%x" , address , length );
117
+ ret = esp_flash_write_encrypted (NULL , address , buffer , length );
118
+ } else {
119
+ LOG_DBG ("Flash write RAW - address 0x%lx size 0x%x" , address , length );
120
+ ret = esp_flash_write (NULL , buffer , address , length );
121
+ }
122
+
123
+ if (ret != 0 ) {
124
+ LOG_ERR ("Flash write error: %d" , ret );
125
+ return - EIO ;
126
+ }
127
+
128
+ return 0 ;
129
+ }
130
+
131
+ #ifdef CONFIG_ESP_FLASH_ENCRYPTION
132
+ #define FLASH_BUFFER_SIZE 32
133
+
134
+ static bool aligned_flash_write (size_t dest_addr , const void * src , size_t size , bool erase );
135
+ static bool aligned_flash_erase (size_t addr , size_t size );
136
+
137
+ /* Auxiliar buffer to store the sector that will be partially written */
138
+ static uint8_t write_aux_buf [FLASH_SECTOR_SIZE ] = {0 };
139
+
140
+ /* Auxiliar buffer to store the sector that will be partially erased */
141
+ static uint8_t erase_aux_buf [FLASH_SECTOR_SIZE ] = {0 };
142
+
143
+ static bool aligned_flash_write (size_t dest_addr , const void * src , size_t size , bool erase )
144
+ {
145
+ bool flash_encryption_enabled = esp_flash_encryption_enabled ();
146
+
147
+ /* When flash encryption is enabled, write alignment is 32 bytes, however to avoid
148
+ * inconsistences the region may be erased right before writing, thus the alignment
149
+ * is set to the erase required alignment (FLASH_SECTOR_SIZE).
150
+ * When flash encryption is not enabled, regular write alignment is 4 bytes.
151
+ */
152
+ size_t alignment = flash_encryption_enabled ? (erase ? FLASH_SECTOR_SIZE : 32 ) : 4 ;
153
+
154
+ if (IS_ALIGNED (dest_addr , alignment ) && IS_ALIGNED ((uintptr_t )src , 4 ) &&
155
+ IS_ALIGNED (size , alignment )) {
156
+ /* A single write operation is enough when all parameters are aligned */
157
+
158
+ if (flash_encryption_enabled && erase ) {
159
+ if (esp_flash_erase_region (NULL , dest_addr , size ) != ESP_OK ) {
160
+ LOG_ERR ("%s: Flash erase failed at 0x%08lx" , __func__ ,
161
+ (uintptr_t )dest_addr );
162
+ return false;
163
+ }
164
+ }
165
+ return flash_esp32_write_check_enc (dest_addr , (void * )src , size ) == ESP_OK ;
166
+ }
167
+
168
+ LOG_DBG ("%s: forcing unaligned write dest_addr: 0x%08lx src: 0x%08lx size: 0x%x erase: %c" ,
169
+ __func__ , (uintptr_t )dest_addr , (uintptr_t )src , size , erase ? 't' : 'f' );
170
+
171
+ size_t write_addr = dest_addr ;
172
+ size_t bytes_remaining = size ;
173
+ size_t src_offset = 0 ;
174
+
175
+ while (bytes_remaining > 0 ) {
176
+ size_t aligned_curr_addr = ROUND_DOWN (write_addr , alignment );
177
+ size_t curr_buf_off = write_addr - aligned_curr_addr ;
178
+ size_t chunk_len = MIN (bytes_remaining , FLASH_SECTOR_SIZE - curr_buf_off );
179
+
180
+ /* Read data before modifying */
181
+ if (flash_esp32_read_check_enc (aligned_curr_addr , write_aux_buf ,
182
+ ROUND_UP (chunk_len , alignment )) != ESP_OK ) {
183
+ LOG_ERR ("%s: Flash read failed at 0x%08lx" , __func__ ,
184
+ (uintptr_t )aligned_curr_addr );
185
+ return false;
186
+ }
187
+
188
+ /* Erase if needed */
189
+ if (flash_encryption_enabled && erase ) {
190
+ if (esp_flash_erase_region (NULL , aligned_curr_addr ,
191
+ ROUND_UP (chunk_len , FLASH_SECTOR_SIZE )) !=
192
+ ESP_OK ) {
193
+ LOG_ERR ("%s: Flash erase failed at 0x%08lx" , __func__ ,
194
+ (uintptr_t )aligned_curr_addr );
195
+ return false;
196
+ }
197
+ }
198
+
199
+ /* Merge data into buffer */
200
+ memcpy (& write_aux_buf [curr_buf_off ], & ((const uint8_t * )src )[src_offset ],
201
+ chunk_len );
202
+
203
+ /* Write back aligned chunk */
204
+ if (flash_esp32_write_check_enc (aligned_curr_addr , write_aux_buf ,
205
+ ROUND_UP (chunk_len , alignment )) != ESP_OK ) {
206
+ LOG_ERR ("%s: Flash write failed at 0x%08lx" , __func__ ,
207
+ (uintptr_t )aligned_curr_addr );
208
+ return false;
209
+ }
210
+
211
+ write_addr += chunk_len ;
212
+ src_offset += chunk_len ;
213
+ bytes_remaining -= chunk_len ;
214
+ }
215
+
216
+ return true;
217
+ }
218
+
219
+ static bool erase_partial_sector (size_t addr , size_t sector_size , size_t erase_start ,
220
+ size_t erase_end )
221
+ {
222
+ /* Read full sector before erasing */
223
+ if (flash_esp32_read_check_enc (addr , erase_aux_buf , sector_size ) != ESP_OK ) {
224
+ LOG_ERR ("%s: Flash read failed at 0x%08lx" , __func__ , (uintptr_t )addr );
225
+ return false;
226
+ }
227
+ /* Erase full sector */
228
+ if (esp_flash_erase_region (NULL , addr , sector_size ) != ESP_OK ) {
229
+ LOG_ERR ("%s: Flash erase failed at 0x%08lx" , __func__ , (uintptr_t )addr );
230
+ return false;
231
+ }
232
+ /* Write back preserved head data up to erase_start */
233
+ if (erase_start > 0 ) {
234
+ if (!aligned_flash_write (addr , erase_aux_buf , erase_start , false)) {
235
+ LOG_ERR ("%s: Flash write failed at 0x%08lx" , __func__ , (uintptr_t )addr );
236
+ return false;
237
+ }
238
+ }
239
+ /* Write back preserved tail data from erase_end up to sector end */
240
+ if (erase_end < sector_size ) {
241
+ if (!aligned_flash_write (addr + erase_end , & erase_aux_buf [erase_end ],
242
+ sector_size - erase_end , false)) {
243
+ LOG_ERR ("%s: Flash write failed at 0x%08lx" , __func__ ,
244
+ (uintptr_t )(addr + erase_end ));
245
+ return false;
246
+ }
247
+ }
248
+ return true;
249
+ }
250
+
251
+ static bool aligned_flash_erase (size_t addr , size_t size )
252
+ {
253
+ if (IS_ALIGNED (addr , FLASH_SECTOR_SIZE ) && IS_ALIGNED (size , FLASH_SECTOR_SIZE )) {
254
+ /* A single erase operation is enough when all parameters are aligned */
255
+ return esp_flash_erase_region (NULL , addr , size ) == ESP_OK ;
256
+ }
257
+
258
+ const size_t sector_size = FLASH_SECTOR_SIZE ;
259
+ const size_t start_addr = ROUND_DOWN (addr , sector_size );
260
+ const size_t end_addr = ROUND_UP (addr + size , sector_size );
261
+ const size_t total_len = end_addr - start_addr ;
262
+
263
+ LOG_DBG ("%s: forcing unaligned erase on sector Offset: "
264
+ "0x%08lx Length: 0x%x total_len: 0x%x" ,
265
+ __func__ , (uintptr_t )addr , (int )size , total_len );
266
+
267
+ size_t current_addr = start_addr ;
268
+
269
+ while (current_addr < end_addr ) {
270
+ bool preserve_head = (addr > current_addr );
271
+ bool preserve_tail = ((addr + size ) < (current_addr + sector_size ));
272
+
273
+ if (preserve_head || preserve_tail ) {
274
+ size_t erase_start = preserve_head ? (addr - current_addr ) : 0 ;
275
+ size_t erase_end =
276
+ MIN (current_addr + sector_size , addr + size ) - current_addr ;
277
+
278
+ LOG_DBG ("%s: partial sector erase from: 0x%08lx to: 0x%08lx Length: 0x%x" ,
279
+ __func__ , (uintptr_t )(current_addr + erase_start ),
280
+ (uintptr_t )(current_addr + erase_end ), erase_end - erase_start );
281
+
282
+ if (!erase_partial_sector (current_addr , sector_size , erase_start ,
283
+ erase_end )) {
284
+ return false;
285
+ }
286
+
287
+ current_addr += sector_size ;
288
+ } else {
289
+ /* Full sector erase is safe, erase the next consecutive full sectors */
290
+ size_t contiguous_size =
291
+ ROUND_DOWN (addr + size , sector_size ) - current_addr ;
292
+
293
+ LOG_DBG ("%s: sectors erased from: 0x%08lx length: 0x%x" , __func__ ,
294
+ (uintptr_t )current_addr , contiguous_size );
295
+
296
+ if (esp_flash_erase_region (NULL , current_addr , contiguous_size ) != ESP_OK ) {
297
+ LOG_ERR ("%s: Flash erase failed at 0x%08lx" , __func__ ,
298
+ (uintptr_t )current_addr );
299
+ return false;
300
+ }
301
+
302
+ current_addr += contiguous_size ;
303
+ }
304
+ }
305
+
306
+ return true;
307
+ }
308
+ #endif /* CONFIG_ESP_FLASH_ENCRYPTION */
309
+ #endif /* !CONFIG_MCUBOOT */
310
+
79
311
#ifdef CONFIG_MCUBOOT
80
312
#define READ_BUFFER_SIZE 32
81
313
static bool flash_esp32_is_aligned (off_t address , void * buffer , size_t length )
@@ -143,11 +375,7 @@ static int flash_esp32_read(const struct device *dev, off_t address, void *buffe
143
375
#else
144
376
flash_esp32_sem_take (dev );
145
377
146
- if (esp_flash_encryption_enabled ()) {
147
- ret = esp_flash_read_encrypted (NULL , address , buffer , length );
148
- } else {
149
- ret = esp_flash_read (NULL , buffer , address , length );
150
- }
378
+ ret = flash_esp32_read_check_enc (address , buffer , length );
151
379
152
380
flash_esp32_sem_give (dev );
153
381
#endif
@@ -179,12 +407,24 @@ static int flash_esp32_write(const struct device *dev,
179
407
#else
180
408
flash_esp32_sem_take (dev );
181
409
410
+ #ifdef CONFIG_ESP_FLASH_ENCRYPTION
411
+ bool erase = false;
412
+
182
413
if (esp_flash_encryption_enabled ()) {
183
- ret = esp_flash_write_encrypted (NULL , address , buffer , length );
184
- } else {
185
- ret = esp_flash_write (NULL , buffer , address , length );
414
+ /* Ensuring flash region has been erased before writing in order to
415
+ * avoid inconsistences when hardware flash encryption is enabled.
416
+ */
417
+ erase = true;
186
418
}
187
419
420
+ if (!aligned_flash_write (address , buffer , length , erase )) {
421
+ LOG_ERR ("%s: Flash erase before write failed" , __func__ );
422
+ ret = -1 ;
423
+ }
424
+ #else
425
+ ret = flash_esp32_write_check_enc (address , buffer , length );
426
+ #endif
427
+
188
428
flash_esp32_sem_give (dev );
189
429
#endif
190
430
@@ -204,7 +444,44 @@ static int flash_esp32_erase(const struct device *dev, off_t start, size_t len)
204
444
ret = esp_rom_flash_erase_range (start , len );
205
445
#else
206
446
flash_esp32_sem_take (dev );
447
+
448
+ #ifdef CONFIG_ESP_FLASH_ENCRYPTION
449
+ if (!aligned_flash_erase (start , len )) {
450
+ ret = - EIO ;
451
+ }
452
+
453
+ if (esp_flash_encryption_enabled ()) {
454
+ uint8_t erased_val_buf [FLASH_BUFFER_SIZE ];
455
+ uint32_t bytes_remaining = len ;
456
+ uint32_t offset = start ;
457
+ uint32_t bytes_written = MIN (sizeof (erased_val_buf ), len );
458
+
459
+ memset (erased_val_buf ,
460
+ flash_get_parameters (dev )-> erase_value , sizeof (erased_val_buf ));
461
+
462
+ /* When hardware flash encryption is enabled, force expected erased
463
+ * value (0xFF) into flash when erasing a region.
464
+ *
465
+ * This is handled on this implementation because MCUboot's state
466
+ * machine relies on erased valued data (0xFF) readed from a
467
+ * previously erased region that was not written yet, however when
468
+ * hardware flash encryption is enabled, the flash read always
469
+ * decrypts whats being read from flash, thus a region that was
470
+ * erased would not be read as what MCUboot expected (0xFF).
471
+ */
472
+ while (bytes_remaining != 0 ) {
473
+ if (!aligned_flash_write (offset , erased_val_buf , bytes_written , false)) {
474
+ LOG_ERR ("%s: Flash erase failed" , __func__ );
475
+ return -1 ;
476
+ }
477
+ offset += bytes_written ;
478
+ bytes_remaining -= bytes_written ;
479
+ }
480
+ }
481
+ #else
207
482
ret = esp_flash_erase_region (NULL , start , len );
483
+ #endif
484
+
208
485
flash_esp32_sem_give (dev );
209
486
#endif
210
487
if (ret != 0 ) {
0 commit comments