esp_efuse_utility.c 18 KB

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