707dcff181a21e0bfa6a48648cf3480e253a7c4b
[openocd.git] / src / flash / nor / core.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
3 * Copyright (C) 2007-2010 Øyvind Harboe <oyvind.harboe@zylin.com> *
4 * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
5 * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
6 * Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20 ***************************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <flash/common.h>
26 #include <flash/nor/core.h>
27 #include <flash/nor/imp.h>
28 #include <target/image.h>
29
30 /**
31 * @file
32 * Upper level of NOR flash framework.
33 * The lower level interfaces are to drivers. These upper level ones
34 * primarily support access from Tcl scripts or from GDB.
35 */
36
37 static struct flash_bank *flash_banks;
38
39 int flash_driver_erase(struct flash_bank *bank, int first, int last)
40 {
41 int retval;
42
43 retval = bank->driver->erase(bank, first, last);
44 if (retval != ERROR_OK)
45 LOG_ERROR("failed erasing sectors %d to %d", first, last);
46
47 return retval;
48 }
49
50 int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
51 {
52 int retval;
53 int num_blocks;
54
55 if (bank->num_prot_blocks)
56 num_blocks = bank->num_prot_blocks;
57 else
58 num_blocks = bank->num_sectors;
59
60
61 /* callers may not supply illegal parameters ... */
62 if (first < 0 || first > last || last >= num_blocks) {
63 LOG_ERROR("illegal protection block range");
64 return ERROR_FAIL;
65 }
66
67 /* force "set" to 0/1 */
68 set = !!set;
69
70 /* DANGER!
71 *
72 * We must not use any cached information about protection state!!!!
73 *
74 * There are a million things that could change the protect state:
75 *
76 * the target could have reset, power cycled, been hot plugged,
77 * the application could have run, etc.
78 *
79 * Drivers only receive valid protection block range.
80 */
81 retval = bank->driver->protect(bank, set, first, last);
82 if (retval != ERROR_OK)
83 LOG_ERROR("failed setting protection for blocks %d to %d", first, last);
84
85 return retval;
86 }
87
88 int flash_driver_write(struct flash_bank *bank,
89 uint8_t *buffer, uint32_t offset, uint32_t count)
90 {
91 int retval;
92
93 retval = bank->driver->write(bank, buffer, offset, count);
94 if (retval != ERROR_OK) {
95 LOG_ERROR(
96 "error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
97 bank->base,
98 offset);
99 }
100
101 return retval;
102 }
103
104 int flash_driver_read(struct flash_bank *bank,
105 uint8_t *buffer, uint32_t offset, uint32_t count)
106 {
107 int retval;
108
109 LOG_DEBUG("call flash_driver_read()");
110
111 retval = bank->driver->read(bank, buffer, offset, count);
112 if (retval != ERROR_OK) {
113 LOG_ERROR(
114 "error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
115 bank->base,
116 offset);
117 }
118
119 return retval;
120 }
121
122 int default_flash_read(struct flash_bank *bank,
123 uint8_t *buffer, uint32_t offset, uint32_t count)
124 {
125 return target_read_buffer(bank->target, offset + bank->base, count, buffer);
126 }
127
128 void flash_bank_add(struct flash_bank *bank)
129 {
130 /* put flash bank in linked list */
131 unsigned bank_num = 0;
132 if (flash_banks) {
133 /* find last flash bank */
134 struct flash_bank *p = flash_banks;
135 while (NULL != p->next) {
136 bank_num += 1;
137 p = p->next;
138 }
139 p->next = bank;
140 bank_num += 1;
141 } else
142 flash_banks = bank;
143
144 bank->bank_number = bank_num;
145 }
146
147 struct flash_bank *flash_bank_list(void)
148 {
149 return flash_banks;
150 }
151
152 struct flash_bank *get_flash_bank_by_num_noprobe(int num)
153 {
154 struct flash_bank *p;
155 int i = 0;
156
157 for (p = flash_banks; p; p = p->next) {
158 if (i++ == num)
159 return p;
160 }
161 LOG_ERROR("flash bank %d does not exist", num);
162 return NULL;
163 }
164
165 int flash_get_bank_count(void)
166 {
167 struct flash_bank *p;
168 int i = 0;
169 for (p = flash_banks; p; p = p->next)
170 i++;
171 return i;
172 }
173
174 void default_flash_free_driver_priv(struct flash_bank *bank)
175 {
176 free(bank->driver_priv);
177 bank->driver_priv = NULL;
178 }
179
180 void flash_free_all_banks(void)
181 {
182 struct flash_bank *bank = flash_banks;
183 while (bank) {
184 struct flash_bank *next = bank->next;
185 if (bank->driver->free_driver_priv)
186 bank->driver->free_driver_priv(bank);
187 else
188 LOG_WARNING("Flash driver of %s does not support free_driver_priv()", bank->name);
189
190 free(bank->name);
191 free(bank->sectors);
192 free(bank->prot_blocks);
193 free(bank);
194 bank = next;
195 }
196 flash_banks = NULL;
197 }
198
199 struct flash_bank *get_flash_bank_by_name_noprobe(const char *name)
200 {
201 unsigned requested = get_flash_name_index(name);
202 unsigned found = 0;
203
204 struct flash_bank *bank;
205 for (bank = flash_banks; NULL != bank; bank = bank->next) {
206 if (strcmp(bank->name, name) == 0)
207 return bank;
208 if (!flash_driver_name_matches(bank->driver->name, name))
209 continue;
210 if (++found < requested)
211 continue;
212 return bank;
213 }
214 return NULL;
215 }
216
217 int get_flash_bank_by_name(const char *name, struct flash_bank **bank_result)
218 {
219 struct flash_bank *bank;
220 int retval;
221
222 bank = get_flash_bank_by_name_noprobe(name);
223 if (bank != NULL) {
224 retval = bank->driver->auto_probe(bank);
225
226 if (retval != ERROR_OK) {
227 LOG_ERROR("auto_probe failed");
228 return retval;
229 }
230 }
231
232 *bank_result = bank;
233 return ERROR_OK;
234 }
235
236 int get_flash_bank_by_num(int num, struct flash_bank **bank)
237 {
238 struct flash_bank *p = get_flash_bank_by_num_noprobe(num);
239 int retval;
240
241 if (p == NULL)
242 return ERROR_FAIL;
243
244 retval = p->driver->auto_probe(p);
245
246 if (retval != ERROR_OK) {
247 LOG_ERROR("auto_probe failed");
248 return retval;
249 }
250 *bank = p;
251 return ERROR_OK;
252 }
253
254 /* lookup flash bank by address, bank not found is success, but
255 * result_bank is set to NULL. */
256 int get_flash_bank_by_addr(struct target *target,
257 uint32_t addr,
258 bool check,
259 struct flash_bank **result_bank)
260 {
261 struct flash_bank *c;
262
263 /* cycle through bank list */
264 for (c = flash_banks; c; c = c->next) {
265 if (c->target != target)
266 continue;
267
268 int retval;
269 retval = c->driver->auto_probe(c);
270
271 if (retval != ERROR_OK) {
272 LOG_ERROR("auto_probe failed");
273 return retval;
274 }
275 /* check whether address belongs to this flash bank */
276 if ((addr >= c->base) && (addr <= c->base + (c->size - 1))) {
277 *result_bank = c;
278 return ERROR_OK;
279 }
280 }
281 *result_bank = NULL;
282 if (check) {
283 LOG_ERROR("No flash at address 0x%08" PRIx32, addr);
284 return ERROR_FAIL;
285 }
286 return ERROR_OK;
287 }
288
289 static int default_flash_mem_blank_check(struct flash_bank *bank)
290 {
291 struct target *target = bank->target;
292 const int buffer_size = 1024;
293 int i;
294 uint32_t nBytes;
295 int retval = ERROR_OK;
296
297 if (bank->target->state != TARGET_HALTED) {
298 LOG_ERROR("Target not halted");
299 return ERROR_TARGET_NOT_HALTED;
300 }
301
302 uint8_t *buffer = malloc(buffer_size);
303
304 for (i = 0; i < bank->num_sectors; i++) {
305 uint32_t j;
306 bank->sectors[i].is_erased = 1;
307
308 for (j = 0; j < bank->sectors[i].size; j += buffer_size) {
309 uint32_t chunk;
310 chunk = buffer_size;
311 if (chunk > (j - bank->sectors[i].size))
312 chunk = (j - bank->sectors[i].size);
313
314 retval = target_read_memory(target,
315 bank->base + bank->sectors[i].offset + j,
316 4,
317 chunk/4,
318 buffer);
319 if (retval != ERROR_OK)
320 goto done;
321
322 for (nBytes = 0; nBytes < chunk; nBytes++) {
323 if (buffer[nBytes] != bank->erased_value) {
324 bank->sectors[i].is_erased = 0;
325 break;
326 }
327 }
328 }
329 }
330
331 done:
332 free(buffer);
333
334 return retval;
335 }
336
337 int default_flash_blank_check(struct flash_bank *bank)
338 {
339 struct target *target = bank->target;
340 int i;
341 int retval;
342
343 if (bank->target->state != TARGET_HALTED) {
344 LOG_ERROR("Target not halted");
345 return ERROR_TARGET_NOT_HALTED;
346 }
347
348 struct target_memory_check_block *block_array;
349 block_array = malloc(bank->num_sectors * sizeof(struct target_memory_check_block));
350 if (block_array == NULL)
351 return default_flash_mem_blank_check(bank);
352
353 for (i = 0; i < bank->num_sectors; i++) {
354 block_array[i].address = bank->base + bank->sectors[i].offset;
355 block_array[i].size = bank->sectors[i].size;
356 block_array[i].result = UINT32_MAX; /* erase state unknown */
357 }
358
359 bool fast_check = true;
360 for (i = 0; i < bank->num_sectors; ) {
361 retval = target_blank_check_memory(target,
362 block_array + i, bank->num_sectors - i,
363 bank->erased_value);
364 if (retval < 1) {
365 /* Run slow fallback if the first run gives no result
366 * otherwise use possibly incomplete results */
367 if (i == 0)
368 fast_check = false;
369 break;
370 }
371 i += retval; /* add number of blocks done this round */
372 }
373
374 if (fast_check) {
375 for (i = 0; i < bank->num_sectors; i++)
376 bank->sectors[i].is_erased = block_array[i].result;
377 retval = ERROR_OK;
378 } else {
379 LOG_USER("Running slow fallback erase check - add working memory");
380 retval = default_flash_mem_blank_check(bank);
381 }
382 free(block_array);
383
384 return retval;
385 }
386
387 /* Manipulate given flash region, selecting the bank according to target
388 * and address. Maps an address range to a set of sectors, and issues
389 * the callback() on that set ... e.g. to erase or unprotect its members.
390 *
391 * Parameter iterate_protect_blocks switches iteration of protect block
392 * instead of erase sectors. If there is no protect blocks array, sectors
393 * are used in iteration, so compatibility for old flash drivers is retained.
394 *
395 * The "pad_reason" parameter is a kind of boolean: when it's NULL, the
396 * range must fit those sectors exactly. This is clearly safe; it can't
397 * erase data which the caller said to leave alone, for example. If it's
398 * non-NULL, rather than failing, extra data in the first and/or last
399 * sectors will be added to the range, and that reason string is used when
400 * warning about those additions.
401 */
402 static int flash_iterate_address_range_inner(struct target *target,
403 char *pad_reason, uint32_t addr, uint32_t length,
404 bool iterate_protect_blocks,
405 int (*callback)(struct flash_bank *bank, int first, int last))
406 {
407 struct flash_bank *c;
408 struct flash_sector *block_array;
409 uint32_t last_addr = addr + length; /* first address AFTER end */
410 int first = -1;
411 int last = -1;
412 int i;
413 int num_blocks;
414
415 int retval = get_flash_bank_by_addr(target, addr, true, &c);
416 if (retval != ERROR_OK)
417 return retval;
418
419 if (c->size == 0 || c->num_sectors == 0) {
420 LOG_ERROR("Bank is invalid");
421 return ERROR_FLASH_BANK_INVALID;
422 }
423
424 if (length == 0) {
425 /* special case, erase whole bank when length is zero */
426 if (addr != c->base) {
427 LOG_ERROR("Whole bank access must start at beginning of bank.");
428 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
429 }
430
431 return callback(c, 0, c->num_sectors - 1);
432 }
433
434 /* check whether it all fits in this bank */
435 if (addr + length - 1 > c->base + c->size - 1) {
436 LOG_ERROR("Flash access does not fit into bank.");
437 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
438 }
439
440 if (c->prot_blocks == NULL || c->num_prot_blocks == 0) {
441 /* flash driver does not define protect blocks, use sectors instead */
442 iterate_protect_blocks = false;
443 }
444
445 if (iterate_protect_blocks) {
446 block_array = c->prot_blocks;
447 num_blocks = c->num_prot_blocks;
448 } else {
449 block_array = c->sectors;
450 num_blocks = c->num_sectors;
451 }
452
453 addr -= c->base;
454 last_addr -= c->base;
455
456 for (i = 0; i < num_blocks; i++) {
457 struct flash_sector *f = &block_array[i];
458 uint32_t end = f->offset + f->size;
459
460 /* start only on a sector boundary */
461 if (first < 0) {
462 /* scanned past the first sector? */
463 if (addr < f->offset)
464 break;
465
466 /* is this the first sector? */
467 if (addr == f->offset)
468 first = i;
469
470 /* Does this need head-padding? If so, pad and warn;
471 * or else force an error.
472 *
473 * Such padding can make trouble, since *WE* can't
474 * ever know if that data was in use. The warning
475 * should help users sort out messes later.
476 */
477 else if (addr < end && pad_reason) {
478 /* FIXME say how many bytes (e.g. 80 KB) */
479 LOG_WARNING("Adding extra %s range, "
480 "%#8.8x to %#8.8x",
481 pad_reason,
482 (unsigned) f->offset,
483 (unsigned) addr - 1);
484 first = i;
485 } else
486 continue;
487 }
488
489 /* is this (also?) the last sector? */
490 if (last_addr == end) {
491 last = i;
492 break;
493 }
494
495 /* Does this need tail-padding? If so, pad and warn;
496 * or else force an error.
497 */
498 if (last_addr < end && pad_reason) {
499 /* FIXME say how many bytes (e.g. 80 KB) */
500 LOG_WARNING("Adding extra %s range, "
501 "%#8.8x to %#8.8x",
502 pad_reason,
503 (unsigned) last_addr,
504 (unsigned) end - 1);
505 last = i;
506 break;
507 }
508
509 /* MUST finish on a sector boundary */
510 if (last_addr <= f->offset)
511 break;
512 }
513
514 /* invalid start or end address? */
515 if (first == -1 || last == -1) {
516 LOG_ERROR("address range 0x%8.8x .. 0x%8.8x "
517 "is not sector-aligned",
518 (unsigned) (c->base + addr),
519 (unsigned) (c->base + last_addr - 1));
520 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
521 }
522
523 /* The NOR driver may trim this range down, based on what
524 * sectors are already erased/unprotected. GDB currently
525 * blocks such optimizations.
526 */
527 return callback(c, first, last);
528 }
529
530 /* The inner fn only handles a single bank, we could be spanning
531 * multiple chips.
532 */
533 static int flash_iterate_address_range(struct target *target,
534 char *pad_reason, uint32_t addr, uint32_t length,
535 bool iterate_protect_blocks,
536 int (*callback)(struct flash_bank *bank, int first, int last))
537 {
538 struct flash_bank *c;
539 int retval = ERROR_OK;
540
541 /* Danger! zero-length iterations means entire bank! */
542 do {
543 retval = get_flash_bank_by_addr(target, addr, true, &c);
544 if (retval != ERROR_OK)
545 return retval;
546
547 uint32_t cur_length = length;
548 /* check whether it all fits in this bank */
549 if (addr + length - 1 > c->base + c->size - 1) {
550 LOG_DEBUG("iterating over more than one flash bank.");
551 cur_length = c->base + c->size - addr;
552 }
553 retval = flash_iterate_address_range_inner(target,
554 pad_reason, addr, cur_length,
555 iterate_protect_blocks,
556 callback);
557 if (retval != ERROR_OK)
558 break;
559
560 length -= cur_length;
561 addr += cur_length;
562 } while (length > 0);
563
564 return retval;
565 }
566
567 int flash_erase_address_range(struct target *target,
568 bool pad, uint32_t addr, uint32_t length)
569 {
570 return flash_iterate_address_range(target, pad ? "erase" : NULL,
571 addr, length, false, &flash_driver_erase);
572 }
573
574 static int flash_driver_unprotect(struct flash_bank *bank, int first, int last)
575 {
576 return flash_driver_protect(bank, 0, first, last);
577 }
578
579 int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length)
580 {
581 /* By default, pad to sector boundaries ... the real issue here
582 * is that our (only) caller *permanently* removes protection,
583 * and doesn't restore it.
584 */
585 return flash_iterate_address_range(target, "unprotect",
586 addr, length, true, &flash_driver_unprotect);
587 }
588
589 static int compare_section(const void *a, const void *b)
590 {
591 struct imagesection *b1, *b2;
592 b1 = *((struct imagesection **)a);
593 b2 = *((struct imagesection **)b);
594
595 if (b1->base_address == b2->base_address)
596 return 0;
597 else if (b1->base_address > b2->base_address)
598 return 1;
599 else
600 return -1;
601 }
602
603 int flash_write_unlock(struct target *target, struct image *image,
604 uint32_t *written, int erase, bool unlock)
605 {
606 int retval = ERROR_OK;
607
608 int section;
609 uint32_t section_offset;
610 struct flash_bank *c;
611 int *padding;
612
613 section = 0;
614 section_offset = 0;
615
616 if (written)
617 *written = 0;
618
619 if (erase) {
620 /* assume all sectors need erasing - stops any problems
621 * when flash_write is called multiple times */
622
623 flash_set_dirty();
624 }
625
626 /* allocate padding array */
627 padding = calloc(image->num_sections, sizeof(*padding));
628
629 /* This fn requires all sections to be in ascending order of addresses,
630 * whereas an image can have sections out of order. */
631 struct imagesection **sections = malloc(sizeof(struct imagesection *) *
632 image->num_sections);
633 int i;
634 for (i = 0; i < image->num_sections; i++)
635 sections[i] = &image->sections[i];
636
637 qsort(sections, image->num_sections, sizeof(struct imagesection *),
638 compare_section);
639
640 /* loop until we reach end of the image */
641 while (section < image->num_sections) {
642 uint32_t buffer_size;
643 uint8_t *buffer;
644 int section_last;
645 target_addr_t run_address = sections[section]->base_address + section_offset;
646 uint32_t run_size = sections[section]->size - section_offset;
647 int pad_bytes = 0;
648
649 if (sections[section]->size == 0) {
650 LOG_WARNING("empty section %d", section);
651 section++;
652 section_offset = 0;
653 continue;
654 }
655
656 /* find the corresponding flash bank */
657 retval = get_flash_bank_by_addr(target, run_address, false, &c);
658 if (retval != ERROR_OK)
659 goto done;
660 if (c == NULL) {
661 LOG_WARNING("no flash bank found for address " TARGET_ADDR_FMT, run_address);
662 section++; /* and skip it */
663 section_offset = 0;
664 continue;
665 }
666
667 /* collect consecutive sections which fall into the same bank */
668 section_last = section;
669 padding[section] = 0;
670 while ((run_address + run_size - 1 < c->base + c->size - 1) &&
671 (section_last + 1 < image->num_sections)) {
672 /* sections are sorted */
673 assert(sections[section_last + 1]->base_address >= c->base);
674 if (sections[section_last + 1]->base_address >= (c->base + c->size)) {
675 /* Done with this bank */
676 break;
677 }
678
679 /* FIXME This needlessly touches sectors BETWEEN the
680 * sections it's writing. Without auto erase, it just
681 * writes ones. That WILL INVALIDATE data in cases
682 * like Stellaris Tempest chips, corrupting internal
683 * ECC codes; and at least FreeScale suggests issues
684 * with that approach (in HC11 documentation).
685 *
686 * With auto erase enabled, data in those sectors will
687 * be needlessly destroyed; and some of the limited
688 * number of flash erase cycles will be wasted...
689 *
690 * In both cases, the extra writes slow things down.
691 */
692
693 /* if we have multiple sections within our image,
694 * flash programming could fail due to alignment issues
695 * attempt to rebuild a consecutive buffer for the flash loader */
696 target_addr_t run_next_addr = run_address + run_size;
697 if (sections[section_last + 1]->base_address < run_next_addr) {
698 LOG_ERROR("Section at " TARGET_ADDR_FMT
699 " overlaps section ending at " TARGET_ADDR_FMT,
700 sections[section_last + 1]->base_address,
701 run_next_addr);
702 LOG_ERROR("Flash write aborted.");
703 retval = ERROR_FAIL;
704 goto done;
705 }
706
707 pad_bytes = sections[section_last + 1]->base_address - run_next_addr;
708 padding[section_last] = pad_bytes;
709 run_size += sections[++section_last]->size;
710 run_size += pad_bytes;
711
712 if (pad_bytes > 0)
713 LOG_INFO("Padding image section %d with %d bytes",
714 section_last-1,
715 pad_bytes);
716 }
717
718 if (run_address + run_size - 1 > c->base + c->size - 1) {
719 /* If we have more than one flash chip back to back, then we limit
720 * the current write operation to the current chip.
721 */
722 LOG_DEBUG("Truncate flash run size to the current flash chip.");
723
724 run_size = c->base + c->size - run_address;
725 assert(run_size > 0);
726 }
727
728 /* If we're applying any sector automagic, then pad this
729 * (maybe-combined) segment to the end of its last sector.
730 */
731 if (unlock || erase) {
732 int sector;
733 uint32_t offset_start = run_address - c->base;
734 uint32_t offset_end = offset_start + run_size;
735 uint32_t end = offset_end, delta;
736
737 for (sector = 0; sector < c->num_sectors; sector++) {
738 end = c->sectors[sector].offset
739 + c->sectors[sector].size;
740 if (offset_end <= end)
741 break;
742 }
743
744 delta = end - offset_end;
745 padding[section_last] += delta;
746 run_size += delta;
747 }
748
749 /* allocate buffer */
750 buffer = malloc(run_size);
751 if (buffer == NULL) {
752 LOG_ERROR("Out of memory for flash bank buffer");
753 retval = ERROR_FAIL;
754 goto done;
755 }
756 buffer_size = 0;
757
758 /* read sections to the buffer */
759 while (buffer_size < run_size) {
760 size_t size_read;
761
762 size_read = run_size - buffer_size;
763 if (size_read > sections[section]->size - section_offset)
764 size_read = sections[section]->size - section_offset;
765
766 /* KLUDGE!
767 *
768 * #¤%#"%¤% we have to figure out the section # from the sorted
769 * list of pointers to sections to invoke image_read_section()...
770 */
771 intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections;
772 int t_section_num = diff / sizeof(struct imagesection);
773
774 LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, "
775 "section_offset = %d, buffer_size = %d, size_read = %d",
776 (int)section, (int)t_section_num, (int)section_offset,
777 (int)buffer_size, (int)size_read);
778 retval = image_read_section(image, t_section_num, section_offset,
779 size_read, buffer + buffer_size, &size_read);
780 if (retval != ERROR_OK || size_read == 0) {
781 free(buffer);
782 goto done;
783 }
784
785 /* see if we need to pad the section */
786 while (padding[section]--)
787 (buffer + buffer_size)[size_read++] = c->default_padded_value;
788
789 buffer_size += size_read;
790 section_offset += size_read;
791
792 if (section_offset >= sections[section]->size) {
793 section++;
794 section_offset = 0;
795 }
796 }
797
798 retval = ERROR_OK;
799
800 if (unlock)
801 retval = flash_unlock_address_range(target, run_address, run_size);
802 if (retval == ERROR_OK) {
803 if (erase) {
804 /* calculate and erase sectors */
805 retval = flash_erase_address_range(target,
806 true, run_address, run_size);
807 }
808 }
809
810 if (retval == ERROR_OK) {
811 /* write flash sectors */
812 retval = flash_driver_write(c, buffer, run_address - c->base, run_size);
813 }
814
815 free(buffer);
816
817 if (retval != ERROR_OK) {
818 /* abort operation */
819 goto done;
820 }
821
822 if (written != NULL)
823 *written += run_size; /* add run size to total written counter */
824 }
825
826 done:
827 free(sections);
828 free(padding);
829
830 return retval;
831 }
832
833 int flash_write(struct target *target, struct image *image,
834 uint32_t *written, int erase)
835 {
836 return flash_write_unlock(target, image, written, erase, false);
837 }
838
839 struct flash_sector *alloc_block_array(uint32_t offset, uint32_t size, int num_blocks)
840 {
841 int i;
842
843 struct flash_sector *array = calloc(num_blocks, sizeof(struct flash_sector));
844 if (array == NULL)
845 return NULL;
846
847 for (i = 0; i < num_blocks; i++) {
848 array[i].offset = offset;
849 array[i].size = size;
850 array[i].is_erased = -1;
851 array[i].is_protected = -1;
852 offset += size;
853 }
854
855 return array;
856 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)