1 /*
2  * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "esp_efuse_utility.h"
8 
9 #include "soc/efuse_periph.h"
10 #include "esp_log.h"
11 #include "esp_rom_sys.h"
12 #include "assert.h"
13 #include "sdkconfig.h"
14 #include <sys/param.h>
15 
16 static const char *TAG = "efuse";
17 
18 // This counter is used to implement independent read access for efuses.
19 // During the read operation, the counter should be unchanged and even.
20 // If it is not so, we must repeat the read to make sure that the burn operation does not affect the read data.
21 static volatile unsigned s_burn_counter = 0;
22 
23 // Array for emulate efuse registers.
24 #ifdef CONFIG_EFUSE_VIRTUAL
25 uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK];
26 
27 #ifndef BOOTLOADER_BUILD
28 #ifndef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
29 /* Call the update function to seed virtual efuses during initialization */
30 void esp_efuse_utility_update_virt_blocks(void);
31 #endif // CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
32 #endif // NOT BOOTLOADER_BUILD
33 
34 #endif // CONFIG_EFUSE_VIRTUAL
35 
36 extern const esp_efuse_range_addr_t range_read_addr_blocks[];
37 extern const esp_efuse_range_addr_t range_write_addr_blocks[];
38 
39 static int get_reg_num(int bit_start, int bit_count, int i_reg);
40 static int get_starting_bit_num_in_reg(int bit_start, int i_reg);
41 static uint32_t get_mask(unsigned int bit_count, unsigned int shift);
42 static int get_count_bits_in_reg(int bit_start, int bit_count, int i_reg);
43 static void write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t value);
44 static uint32_t fill_reg(int bit_start_in_reg, int bit_count_in_reg, uint8_t* blob, int* filled_bits_blob);
45 static uint32_t set_cnt_in_reg(int bit_start_in_reg, int bit_count_used_in_reg, uint32_t reg_masked, size_t* cnt);
46 static bool check_range_of_bits(esp_efuse_block_t blk, int offset_in_bits, int size_bits);
47 
48 // This function processes the field by calling the passed function.
esp_efuse_utility_process(const esp_efuse_desc_t * field[],void * ptr,size_t ptr_size_bits,efuse_func_proc_t func_proc)49 esp_err_t esp_efuse_utility_process(const esp_efuse_desc_t* field[], void* ptr, size_t ptr_size_bits, efuse_func_proc_t func_proc)
50 {
51     esp_err_t err = ESP_OK;
52     int bits_counter = 0;
53 
54     // get and check size.
55     int field_len = esp_efuse_get_field_size(field);
56     int req_size = (ptr_size_bits == 0) ? field_len : MIN(ptr_size_bits, field_len);
57 
58     int i = 0;
59     unsigned count_before = s_burn_counter;
60     while (err == ESP_OK && req_size > bits_counter && field[i] != NULL) {
61         if (check_range_of_bits(field[i]->efuse_block, field[i]->bit_start, field[i]->bit_count) == false) {
62             ESP_EARLY_LOGE(TAG, "Range of data does not match the coding scheme");
63             err = ESP_ERR_CODING;
64         }
65         int i_reg = 0;
66         int num_reg;
67         while (err == ESP_OK && req_size > bits_counter &&
68                 (num_reg = get_reg_num(field[i]->bit_start, field[i]->bit_count, i_reg)) != -1) {
69 
70             int start_bit = get_starting_bit_num_in_reg(field[i]->bit_start, i_reg);
71             int num_bits = get_count_bits_in_reg(field[i]->bit_start, field[i]->bit_count, i_reg);
72             if ((bits_counter + num_bits) > req_size) { // Limits the length of the field.
73                 num_bits = req_size - bits_counter;
74             }
75             ESP_EARLY_LOGD(TAG, "In EFUSE_BLK%d__DATA%d_REG is used %d bits starting with %d bit",
76                     (int)field[i]->efuse_block, num_reg, num_bits, start_bit);
77             err = func_proc(num_reg, field[i]->efuse_block, start_bit, num_bits, ptr, &bits_counter);
78             ++i_reg;
79         }
80         i++;
81     }
82     unsigned count_after = s_burn_counter;
83     if (err == ESP_OK &&
84         (func_proc == esp_efuse_utility_fill_buff || func_proc == esp_efuse_utility_count_once) && // these functions are used for read APIs: read_field_blob and read_field_cnt
85         (count_before != count_after || (count_after & 1) == 1)) {
86         err = ESP_ERR_DAMAGED_READING;
87     }
88     assert(bits_counter <= req_size);
89     return err;
90 }
91 
92 
93 // Read efuse register and write this value to array.
esp_efuse_utility_fill_buff(unsigned int num_reg,esp_efuse_block_t efuse_block,int bit_start,int bit_count,void * arr_out,int * bits_counter)94 esp_err_t esp_efuse_utility_fill_buff(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* arr_out, int* bits_counter)
95 {
96     uint8_t* blob = (uint8_t *) arr_out;
97     uint32_t reg = esp_efuse_utility_read_reg(efuse_block, num_reg);
98     uint64_t reg_of_aligned_bits = (reg >> bit_start) & get_mask(bit_count, 0);
99 
100     int shift_bit = (*bits_counter) % 8;
101     if (shift_bit != 0) {
102         blob[(*bits_counter) / 8] |= (uint8_t)(reg_of_aligned_bits << shift_bit);
103         shift_bit = ((8 - shift_bit) < bit_count) ? (8 - shift_bit) : bit_count;
104         (*bits_counter) += shift_bit;
105         bit_count -= shift_bit;
106     }
107 
108     int sum_shift = 0;
109     while (bit_count > 0) {
110         sum_shift += shift_bit;
111         blob[(*bits_counter) / 8] |= (uint8_t)(reg_of_aligned_bits >> sum_shift);
112         shift_bit = (bit_count > 8) ? 8 : bit_count;
113         (*bits_counter) += shift_bit;
114         bit_count -= shift_bit;
115     };
116     return ESP_OK;
117 }
118 
119 // Count a set bits.
esp_efuse_utility_count_once(unsigned int num_reg,esp_efuse_block_t efuse_block,int bit_start,int bit_count,void * out_cnt,int * bits_counter)120 esp_err_t esp_efuse_utility_count_once(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* out_cnt, int* bits_counter)
121 {
122     uint32_t reg = esp_efuse_utility_read_reg(efuse_block, num_reg);
123     *((size_t *)out_cnt) += __builtin_popcount(reg & get_mask(bit_count, bit_start)); // Returns the number of 1-bits in reg.
124     *bits_counter += bit_count;
125     return ESP_OK;
126 }
127 
128 // Fill registers from array for writing.
esp_efuse_utility_write_blob(unsigned int num_reg,esp_efuse_block_t efuse_block,int bit_start,int bit_count,void * arr_in,int * bits_counter)129 esp_err_t esp_efuse_utility_write_blob(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* arr_in, int* bits_counter)
130 {
131     uint32_t reg_to_write = fill_reg(bit_start, bit_count, (uint8_t *)arr_in, bits_counter);
132     return esp_efuse_utility_write_reg(efuse_block, num_reg, reg_to_write);
133 }
134 
135 // fill registers with the required number of bits for writing.
esp_efuse_utility_write_cnt(unsigned int num_reg,esp_efuse_block_t efuse_block,int bit_start,int bit_count,void * cnt,int * bits_counter)136 esp_err_t esp_efuse_utility_write_cnt(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* cnt, int* bits_counter)
137 {
138     esp_err_t err = ESP_OK;
139     uint32_t reg = esp_efuse_utility_read_reg(efuse_block, num_reg);
140     size_t* set_bits = (size_t*)cnt;
141     uint32_t mask = get_mask(bit_count, bit_start);
142     uint32_t reg_masked_bits = reg & mask;
143     if ((reg_masked_bits ^ mask) != 0) {// register has free bits to set them to 1?
144         uint32_t reg_to_write = set_cnt_in_reg(bit_start, bit_count, reg_masked_bits, set_bits);
145         write_reg(efuse_block, num_reg, reg_to_write);
146     }
147     *bits_counter += bit_count;
148     if ((*set_bits) == 0) {
149         err = ESP_OK_EFUSE_CNT;
150     }
151     return err;
152 }
153 
154 // Reset efuse write registers
esp_efuse_utility_reset(void)155 void esp_efuse_utility_reset(void)
156 {
157     ++s_burn_counter;
158     esp_efuse_utility_clear_program_registers();
159     ++s_burn_counter;
160     for (int num_block = EFUSE_BLK0; num_block < EFUSE_BLK_MAX; num_block++) {
161         for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
162             REG_WRITE(addr_wr_block, 0);
163         }
164     }
165 }
166 
esp_efuse_utility_debug_dump_pending(void)167 void esp_efuse_utility_debug_dump_pending(void)
168 {
169     for (int num_block = 0; num_block < EFUSE_BLK_MAX; num_block++) {
170         for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
171             if (REG_READ(addr_wr_block) != 0) {
172                 esp_efuse_utility_debug_dump_single_block(num_block, false);
173                 break;
174             }
175         }
176     }
177 }
178 
esp_efuse_utility_burn_efuses(void)179 esp_err_t esp_efuse_utility_burn_efuses(void)
180 {
181     ++s_burn_counter;
182 #ifdef CONFIG_EFUSE_VIRTUAL_LOG_ALL_WRITES
183     ESP_EARLY_LOGW(TAG, "Burn:");
184     esp_efuse_utility_debug_dump_pending();
185 #endif
186     esp_err_t err = esp_efuse_utility_burn_chip();
187     ++s_burn_counter;
188     return err;
189 }
190 
191 // Erase the virt_blocks array.
esp_efuse_utility_erase_virt_blocks(void)192 void esp_efuse_utility_erase_virt_blocks(void)
193 {
194 #ifdef CONFIG_EFUSE_VIRTUAL
195     memset(virt_blocks, 0, sizeof(virt_blocks));
196 #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
197     esp_efuse_utility_write_efuses_to_flash();
198 #endif
199 #endif // CONFIG_EFUSE_VIRTUAL
200 }
201 
202 // Fills the virt_blocks array by values from efuse_Rdata.
esp_efuse_utility_update_virt_blocks(void)203 void esp_efuse_utility_update_virt_blocks(void)
204 {
205 #ifdef CONFIG_EFUSE_VIRTUAL
206 #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
207     if (!esp_efuse_utility_load_efuses_from_flash()) {
208 #else
209     if (1) {
210 #endif
211         ESP_EARLY_LOGW(TAG, "[Virtual] Loading virtual efuse blocks from real efuses");
212         for (int num_block = EFUSE_BLK0; num_block < EFUSE_BLK_MAX; num_block++) {
213             int subblock = 0;
214             for (uint32_t addr_rd_block = range_read_addr_blocks[num_block].start; addr_rd_block <= range_read_addr_blocks[num_block].end; addr_rd_block += 4) {
215                 virt_blocks[num_block][subblock++] = REG_READ(addr_rd_block);
216             }
217             ESP_EARLY_LOGD(TAG, "[Virtual] virt_blocks[%d] is filled by EFUSE_BLOCK%d", num_block, num_block);
218         }
219 #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
220         esp_efuse_utility_write_efuses_to_flash();
221 #endif
222     }
223 #else
224     ESP_EARLY_LOGI(TAG, "Emulate efuse is disabled");
225 #endif
226 }
227 
228 // Prints efuse values for a single block
229 void esp_efuse_utility_debug_dump_single_block(int num_block, bool from_read)
230 {
231     esp_rom_printf("%d) ", num_block);
232     int num_reg = 0;
233     if (from_read) {
234         for (uint32_t addr_rd_block = range_read_addr_blocks[num_block].start; addr_rd_block <= range_read_addr_blocks[num_block].end; addr_rd_block += 4, num_reg++) {
235 #ifdef CONFIG_EFUSE_VIRTUAL
236             esp_rom_printf("0x%08x ", virt_blocks[num_block][num_reg]);
237 #else
238             esp_rom_printf("0x%08x ", REG_READ(addr_rd_block));
239             (void) num_reg;
240 #endif
241         }
242     } else {
243         for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4, num_reg++) {
244             esp_rom_printf("0x%08x ", REG_READ(addr_wr_block));
245         }
246     }
247     esp_rom_printf("\n");
248 }
249 
250 // Prints efuse values for all registers.
251 void esp_efuse_utility_debug_dump_blocks(void)
252 {
253     esp_rom_printf("EFUSE_BLKx:\n");
254     for (int num_block = EFUSE_BLK0; num_block < EFUSE_BLK_MAX; num_block++) {
255         esp_efuse_utility_debug_dump_single_block(num_block, true);
256     }
257     esp_rom_printf("\n");
258 }
259 
260 // returns the number of array elements for placing these bits in an array with the length of each element equal to size_of_base.
261 int esp_efuse_utility_get_number_of_items(int bits, int size_of_base)
262 {
263     return  bits / size_of_base + (bits % size_of_base > 0 ? 1 : 0);
264 }
265 
266 // Writing efuse register with checking of repeated programming of programmed bits.
267 esp_err_t esp_efuse_utility_write_reg(esp_efuse_block_t efuse_block, unsigned int num_reg, uint32_t reg_to_write)
268 {
269     esp_err_t err = ESP_OK;
270     uint32_t reg = esp_efuse_utility_read_reg(efuse_block, num_reg);
271     if (reg & reg_to_write) {
272         ESP_EARLY_LOGE(TAG, "Repeated programming of programmed bits is strictly forbidden 0x%08x", reg & reg_to_write);
273         err = ESP_ERR_EFUSE_REPEATED_PROG;
274     } else {
275         write_reg(efuse_block, num_reg, reg_to_write);
276     }
277     return err;
278 }
279 
280 // Reading efuse register.
281 uint32_t esp_efuse_utility_read_reg(esp_efuse_block_t blk, unsigned int num_reg)
282 {
283     assert(blk >= 0 && blk < EFUSE_BLK_MAX);
284     assert(num_reg <= (range_read_addr_blocks[blk].end - range_read_addr_blocks[blk].start) / sizeof(uint32_t));
285     uint32_t value;
286 #ifdef CONFIG_EFUSE_VIRTUAL
287     value = virt_blocks[blk][num_reg];
288 #else
289     value = REG_READ(range_read_addr_blocks[blk].start + num_reg * 4);
290 #endif
291     return value;
292 }
293 
294 // Private functions
295 
296 // writing efuse register.
297 static void write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t value)
298 {
299     assert(blk >= 0 && blk < EFUSE_BLK_MAX);
300     assert(num_reg <= (range_read_addr_blocks[blk].end - range_read_addr_blocks[blk].start) / sizeof(uint32_t));
301 
302     uint32_t addr_wr_reg = range_write_addr_blocks[blk].start + num_reg * 4;
303     uint32_t reg_to_write = REG_READ(addr_wr_reg) | value;
304     // The register can be written in parts so we combine the new value with the one already available.
305     REG_WRITE(addr_wr_reg, reg_to_write);
306 }
307 
308 // return mask with required the number of ones with shift.
309 static uint32_t get_mask(unsigned int bit_count, unsigned int shift)
310 {
311     uint32_t mask;
312     if (bit_count != 32) {
313         mask = (1 << bit_count) - 1;
314     } else {
315         mask = 0xFFFFFFFF;
316     }
317     return mask << shift;
318 }
319 
320 // return the register number in the array. return -1 if all registers for field was selected.
321 static int get_reg_num(int bit_start, int bit_count, int i_reg)
322 {
323     int num_reg = i_reg + bit_start / 32;
324 
325     if (num_reg > (bit_start + bit_count - 1) / 32) {
326         return -1;
327     }
328 
329     return num_reg;
330 }
331 
332 // returns the starting bit number in the register.
333 static int get_starting_bit_num_in_reg(int bit_start, int i_reg)
334 {
335     return (i_reg == 0) ? bit_start % 32 : 0;
336 }
337 
338 // Returns the number of bits in the register.
339 static int get_count_bits_in_reg(int bit_start, int bit_count, int i_reg)
340 {
341     int ret_count = 0;
342     int num_reg = 0;
343     int last_used_bit = (bit_start + bit_count - 1);
344     for (int num_bit = bit_start; num_bit <= last_used_bit; ++num_bit) {
345         ++ret_count;
346         if ((((num_bit + 1) % 32) == 0) || (num_bit == last_used_bit)) {
347             if (i_reg == num_reg++) {
348                 return ret_count;
349             }
350             ret_count = 0;
351         }
352     }
353     return 0;
354 }
355 
356 // fill efuse register from array.
357 static uint32_t fill_reg(int bit_start_in_reg, int bit_count_in_reg, uint8_t* blob, int* filled_bits_blob)
358 {
359     uint32_t reg_to_write = 0;
360     uint32_t temp_blob_32;
361     int shift_bit = (*filled_bits_blob) % 8;
362     if (shift_bit != 0) {
363         temp_blob_32 = blob[(*filled_bits_blob) / 8] >> shift_bit;
364         shift_bit = ((8 - shift_bit) < bit_count_in_reg) ? (8 - shift_bit) : bit_count_in_reg;
365         reg_to_write = temp_blob_32 & get_mask(shift_bit, 0);
366         (*filled_bits_blob) += shift_bit;
367         bit_count_in_reg -= shift_bit;
368     }
369 
370     int shift_reg = shift_bit;
371     while (bit_count_in_reg > 0) {
372         temp_blob_32 = blob[(*filled_bits_blob) / 8];
373         shift_bit = (bit_count_in_reg > 8) ? 8 : bit_count_in_reg;
374         reg_to_write |= (temp_blob_32 & get_mask(shift_bit, 0)) << shift_reg;
375         (*filled_bits_blob) += shift_bit;
376         bit_count_in_reg -= shift_bit;
377         shift_reg += 8;
378     };
379     return reg_to_write << bit_start_in_reg;
380 }
381 
382 // sets a required count of bits as "1".
383 static uint32_t set_cnt_in_reg(int bit_start_in_reg, int bit_count_used_in_reg, uint32_t reg_masked, size_t* cnt)
384 {
385     assert((bit_start_in_reg + bit_count_used_in_reg) <= 32);
386     uint32_t reg_to_write = 0;
387     for (int i = bit_start_in_reg; i < bit_start_in_reg + bit_count_used_in_reg; ++i) {
388         if ((reg_masked & (1 << i)) == 0) {
389             reg_to_write |= (1 << i);
390             if (--(*cnt) == 0) {
391                 break;
392             }
393         }
394     }
395     return reg_to_write;
396 }
397 
398 // check range of bits for any coding scheme.
399 static bool check_range_of_bits(esp_efuse_block_t blk, int offset_in_bits, int size_bits)
400 {
401     int max_num_bit = offset_in_bits + size_bits;
402     if (max_num_bit > 256) {
403         return false;
404     } else {
405         ESP_EFUSE_FIELD_CORRESPONDS_CODING_SCHEME(blk, max_num_bit);
406     }
407     return true;
408 }
409 
410 uint32_t esp_efuse_utility_get_read_register_address(esp_efuse_block_t block)
411 {
412     assert(block < EFUSE_BLK_MAX);
413 #ifdef CONFIG_EFUSE_VIRTUAL
414     return (uint32_t)&virt_blocks[block][0];
415 #else
416     return range_read_addr_blocks[block].start;
417 #endif
418 
419 }
420 
421 #if defined(BOOTLOADER_BUILD) && defined(CONFIG_EFUSE_VIRTUAL) && !defined(CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH)
422 void esp_efuse_init_virtual_mode_in_ram(void)
423 {
424     esp_efuse_utility_update_virt_blocks();
425 }
426 #endif
427 
428 #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
429 
430 #include "../bootloader_flash/include/bootloader_flash_priv.h"
431 
432 static uint32_t esp_efuse_flash_offset = 0;
433 static uint32_t esp_efuse_flash_size = 0;
434 
435 void esp_efuse_init_virtual_mode_in_flash(uint32_t offset, uint32_t size)
436 {
437     esp_efuse_flash_offset = offset;
438     esp_efuse_flash_size = size;
439     esp_efuse_utility_update_virt_blocks();
440     esp_efuse_utility_debug_dump_blocks();
441 }
442 
443 void esp_efuse_utility_erase_efuses_in_flash(void)
444 {
445     ESP_EARLY_LOGW(TAG, "[Virtual] Erasing eFuses in flash");
446 
447     if (esp_efuse_flash_offset == 0) {
448         ESP_EARLY_LOGE(TAG, "[Virtual] no efuse partition in partition_table? (Flash is not updated)");
449         abort();
450     }
451     esp_err_t err = bootloader_flash_erase_range(esp_efuse_flash_offset, esp_efuse_flash_size);
452     if (err != ESP_OK) {
453         ESP_EARLY_LOGE(TAG, "[Virtual] Failed to erase flash. err = 0x%x", err);
454         abort();
455     }
456 
457     ESP_EARLY_LOGW(TAG, "[Virtual] Erase complete");
458 }
459 
460 bool esp_efuse_utility_load_efuses_from_flash(void)
461 {
462     ESP_EARLY_LOGW(TAG, "[Virtual] try loading efuses from flash: 0x%x (offset)", esp_efuse_flash_offset);
463 
464     if (esp_efuse_flash_offset == 0) {
465         ESP_EARLY_LOGE(TAG, "[Virtual] no efuse partition in partition_table? (Flash is not updated)");
466         abort();
467     }
468     uint32_t efuses_in_flash[sizeof(virt_blocks)];
469 
470     esp_err_t err = bootloader_flash_read(esp_efuse_flash_offset, &efuses_in_flash, sizeof(efuses_in_flash), false);
471     if (err != ESP_OK) {
472         ESP_EARLY_LOGE(TAG, "[Virtual] Can not read eFuse partition from flash (err=0x%x)", err);
473         abort();
474     }
475 
476     for (unsigned i = 0; i < sizeof(virt_blocks); ++i) {
477         if (efuses_in_flash[i] != 0xFFFFFFFF) {
478             ESP_EARLY_LOGW(TAG, "[Virtual] Loading virtual efuse blocks from flash");
479             memcpy(virt_blocks, efuses_in_flash, sizeof(virt_blocks));
480             return true;
481         }
482     }
483 
484     ESP_EARLY_LOGW(TAG, "[Virtual] no efuses found in flash");
485 
486     return false;
487 }
488 
489 void esp_efuse_utility_write_efuses_to_flash(void)
490 {
491     if (esp_efuse_flash_offset == 0) {
492         ESP_EARLY_LOGE(TAG, "[Virtual] no efuse partition in partition_table? (Flash is not updated)");
493         abort();
494     }
495 
496     esp_err_t err = bootloader_flash_erase_range(esp_efuse_flash_offset, esp_efuse_flash_size);
497     if (err != ESP_OK) {
498         ESP_EARLY_LOGE(TAG, "[Virtual] Failed to erase flash. err = 0x%x", err);
499         abort();
500     }
501 
502     err = bootloader_flash_write(esp_efuse_flash_offset, &virt_blocks, sizeof(virt_blocks), false);
503     if (err != ESP_OK) {
504         ESP_EARLY_LOGE(TAG, "[Virtual] Failed to write eFuses to flash. err = 0x%x", err);
505         abort();
506     }
507 }
508 #endif // CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
509 
510 bool esp_efuse_utility_is_correct_written_data(esp_efuse_block_t block, unsigned r_data_len)
511 {
512     uint32_t* w_data = (uint32_t*)range_write_addr_blocks[block].start;
513     uint32_t* r_data = (uint32_t*)range_read_addr_blocks[block].start;
514 
515     bool correct_written_data = memcmp(w_data, r_data, r_data_len) == 0;
516     if (correct_written_data) {
517         ESP_LOGI(TAG, "BURN BLOCK%d - OK (write block == read block)", block);
518         return true;
519     }
520 
521     correct_written_data = true;
522     for (unsigned i = 0; i < r_data_len / 4; i++) {
523         if ((*(r_data + i) & *(w_data + i)) != *(w_data + i)) {
524             correct_written_data = false;
525             break;
526         }
527     }
528     if (correct_written_data) {
529         ESP_LOGI(TAG, "BURN BLOCK%d - OK (all write block bits are set)", block);
530     } else {
531         ESP_LOGE(TAG, "BURN BLOCK%d - ERROR (written bits != read bits)", block);
532     }
533     return correct_written_data;
534 }
535