CFI CORE: bug-fix protect single sector
[openocd.git] / src / flash / nor / core.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
3 * Copyright (C) 2007,2008 Ø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 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 #include <flash/common.h>
27 #include <flash/nor/core.h>
28 #include <flash/nor/imp.h>
29 #include <target/image.h>
30
31
32 /**
33 * @file
34 * Upper level of NOR flash framework.
35 * The lower level interfaces are to drivers. These upper level ones
36 * primarily support access from Tcl scripts or from GDB.
37 */
38
39 struct flash_bank *flash_banks;
40
41 int flash_driver_erase(struct flash_bank *bank, int first, int last)
42 {
43 int retval;
44
45 retval = bank->driver->erase(bank, first, last);
46 if (retval != ERROR_OK)
47 {
48 LOG_ERROR("failed erasing sectors %d to %d (%d)", first, last, retval);
49 }
50
51 return retval;
52 }
53
54 int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
55 {
56 int retval;
57 bool updated = false;
58
59 /* NOTE: "first == last" means protect just that sector */
60
61 /* callers may not supply illegal parameters ... */
62 if (first < 0 || first > last || last >= bank->num_sectors)
63 return ERROR_FAIL;
64
65 /* force "set" to 0/1 */
66 set = !!set;
67
68 /*
69 * Filter out what trivial nonsense we can, so drivers don't have to.
70 *
71 * Don't tell drivers to change to the current state... it's needless,
72 * and reducing the amount of work to be done (potentially to nothing)
73 * speeds at least some things up.
74 */
75 scan:
76 for (int i = first; i <= last; i++) {
77 struct flash_sector *sector = bank->sectors + i;
78
79 /* Only filter requests to protect the already-protected, or
80 * to unprotect the already-unprotected. Changing from the
81 * unknown state (-1) to a known one is unwise but allowed;
82 * protection status is best checked first.
83 */
84 if (sector->is_protected != set)
85 continue;
86
87 /* Shrink this range of sectors from the start; don't overrun
88 * the end. Also shrink from the end; don't overun the start.
89 *
90 * REVISIT we could handle discontiguous regions by issuing
91 * more than one driver request. How much would that matter?
92 */
93 if (i == first) {
94 updated = true;
95 first++;
96 } else if (i == last) {
97 updated = true;
98 last--;
99 }
100 }
101
102 /* updating the range affects the tests in the scan loop above; so
103 * re-scan, to make sure we didn't miss anything.
104 */
105 if (updated) {
106 updated = false;
107 goto scan;
108 }
109
110 /* Single sector, already protected? Nothing to do! */
111 if (first > last)
112 return ERROR_OK;
113
114
115 retval = bank->driver->protect(bank, set, first, last);
116 if (retval != ERROR_OK)
117 {
118 LOG_ERROR("failed setting protection for areas %d to %d (%d)", first, last, retval);
119 }
120
121 return retval;
122 }
123
124 int flash_driver_write(struct flash_bank *bank,
125 uint8_t *buffer, uint32_t offset, uint32_t count)
126 {
127 int retval;
128
129 retval = bank->driver->write(bank, buffer, offset, count);
130 if (retval != ERROR_OK)
131 {
132 LOG_ERROR("error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32 " (%d)",
133 bank->base, offset, retval);
134 }
135
136 return retval;
137 }
138
139 void flash_bank_add(struct flash_bank *bank)
140 {
141 /* put flash bank in linked list */
142 unsigned bank_num = 0;
143 if (flash_banks)
144 {
145 /* find last flash bank */
146 struct flash_bank *p = flash_banks;
147 while (NULL != p->next)
148 {
149 bank_num += 1;
150 p = p->next;
151 }
152 p->next = bank;
153 bank_num += 1;
154 }
155 else
156 flash_banks = bank;
157
158 bank->bank_number = bank_num;
159 }
160
161 struct flash_bank *flash_bank_list(void)
162 {
163 return flash_banks;
164 }
165
166 struct flash_bank *get_flash_bank_by_num_noprobe(int num)
167 {
168 struct flash_bank *p;
169 int i = 0;
170
171 for (p = flash_banks; p; p = p->next)
172 {
173 if (i++ == num)
174 {
175 return p;
176 }
177 }
178 LOG_ERROR("flash bank %d does not exist", num);
179 return NULL;
180 }
181
182 int flash_get_bank_count(void)
183 {
184 struct flash_bank *p;
185 int i = 0;
186 for (p = flash_banks; p; p = p->next)
187 {
188 i++;
189 }
190 return i;
191 }
192
193 struct flash_bank *get_flash_bank_by_name(const char *name)
194 {
195 unsigned requested = get_flash_name_index(name);
196 unsigned found = 0;
197
198 struct flash_bank *bank;
199 for (bank = flash_banks; NULL != bank; bank = bank->next)
200 {
201 if (strcmp(bank->name, name) == 0)
202 return bank;
203 if (!flash_driver_name_matches(bank->driver->name, name))
204 continue;
205 if (++found < requested)
206 continue;
207 return bank;
208 }
209 return NULL;
210 }
211
212 struct flash_bank *get_flash_bank_by_num(int num)
213 {
214 struct flash_bank *p = get_flash_bank_by_num_noprobe(num);
215 int retval;
216
217 if (p == NULL)
218 return NULL;
219
220 retval = p->driver->auto_probe(p);
221
222 if (retval != ERROR_OK)
223 {
224 LOG_ERROR("auto_probe failed %d\n", retval);
225 return NULL;
226 }
227 return p;
228 }
229
230 /* lookup flash bank by address */
231 struct flash_bank *get_flash_bank_by_addr(struct target *target, uint32_t addr)
232 {
233 struct flash_bank *c;
234
235 /* cycle through bank list */
236 for (c = flash_banks; c; c = c->next)
237 {
238 int retval;
239 retval = c->driver->auto_probe(c);
240
241 if (retval != ERROR_OK)
242 {
243 LOG_ERROR("auto_probe failed %d\n", retval);
244 return NULL;
245 }
246 /* check whether address belongs to this flash bank */
247 if ((addr >= c->base) && (addr <= c->base + (c->size - 1)) && target == c->target)
248 return c;
249 }
250 LOG_ERROR("No flash at address 0x%08" PRIx32 "\n", addr);
251 return NULL;
252 }
253
254 int default_flash_mem_blank_check(struct flash_bank *bank)
255 {
256 struct target *target = bank->target;
257 const int buffer_size = 1024;
258 int i;
259 uint32_t nBytes;
260 int retval = ERROR_OK;
261
262 if (bank->target->state != TARGET_HALTED)
263 {
264 LOG_ERROR("Target not halted");
265 return ERROR_TARGET_NOT_HALTED;
266 }
267
268 uint8_t *buffer = malloc(buffer_size);
269
270 for (i = 0; i < bank->num_sectors; i++)
271 {
272 uint32_t j;
273 bank->sectors[i].is_erased = 1;
274
275 for (j = 0; j < bank->sectors[i].size; j += buffer_size)
276 {
277 uint32_t chunk;
278 chunk = buffer_size;
279 if (chunk > (j - bank->sectors[i].size))
280 {
281 chunk = (j - bank->sectors[i].size);
282 }
283
284 retval = target_read_memory(target, bank->base + bank->sectors[i].offset + j, 4, chunk/4, buffer);
285 if (retval != ERROR_OK)
286 {
287 goto done;
288 }
289
290 for (nBytes = 0; nBytes < chunk; nBytes++)
291 {
292 if (buffer[nBytes] != 0xFF)
293 {
294 bank->sectors[i].is_erased = 0;
295 break;
296 }
297 }
298 }
299 }
300
301 done:
302 free(buffer);
303
304 return retval;
305 }
306
307 int default_flash_blank_check(struct flash_bank *bank)
308 {
309 struct target *target = bank->target;
310 int i;
311 int retval;
312 int fast_check = 0;
313 uint32_t blank;
314
315 if (bank->target->state != TARGET_HALTED)
316 {
317 LOG_ERROR("Target not halted");
318 return ERROR_TARGET_NOT_HALTED;
319 }
320
321 for (i = 0; i < bank->num_sectors; i++)
322 {
323 uint32_t address = bank->base + bank->sectors[i].offset;
324 uint32_t size = bank->sectors[i].size;
325
326 if ((retval = target_blank_check_memory(target, address, size, &blank)) != ERROR_OK)
327 {
328 fast_check = 0;
329 break;
330 }
331 if (blank == 0xFF)
332 bank->sectors[i].is_erased = 1;
333 else
334 bank->sectors[i].is_erased = 0;
335 fast_check = 1;
336 }
337
338 if (!fast_check)
339 {
340 LOG_USER("Running slow fallback erase check - add working memory");
341 return default_flash_mem_blank_check(bank);
342 }
343
344 return ERROR_OK;
345 }
346
347 /* Manipulate given flash region, selecting the bank according to target
348 * and address. Maps an address range to a set of sectors, and issues
349 * the callback() on that set ... e.g. to erase or unprotect its members.
350 *
351 * (Note a current bad assumption: that protection operates on the same
352 * size sectors as erase operations use.)
353 *
354 * The "pad_reason" parameter is a kind of boolean: when it's NULL, the
355 * range must fit those sectors exactly. This is clearly safe; it can't
356 * erase data which the caller said to leave alone, for example. If it's
357 * non-NULL, rather than failing, extra data in the first and/or last
358 * sectors will be added to the range, and that reason string is used when
359 * warning about those additions.
360 */
361 static int flash_iterate_address_range(struct target *target,
362 char *pad_reason, uint32_t addr, uint32_t length,
363 int (*callback)(struct flash_bank *bank, int first, int last))
364 {
365 struct flash_bank *c;
366 uint32_t last_addr = addr + length; /* first address AFTER end */
367 int first = -1;
368 int last = -1;
369 int i;
370
371 if ((c = get_flash_bank_by_addr(target, addr)) == NULL)
372 return ERROR_FLASH_DST_OUT_OF_BANK; /* no corresponding bank found */
373
374 if (c->size == 0 || c->num_sectors == 0)
375 {
376 LOG_ERROR("Bank is invalid");
377 return ERROR_FLASH_BANK_INVALID;
378 }
379
380 if (length == 0)
381 {
382 /* special case, erase whole bank when length is zero */
383 if (addr != c->base)
384 {
385 LOG_ERROR("Whole bank access must start at beginning of bank.");
386 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
387 }
388
389 return callback(c, 0, c->num_sectors - 1);
390 }
391
392 /* check whether it all fits in this bank */
393 if (addr + length - 1 > c->base + c->size - 1)
394 {
395 LOG_ERROR("Flash access does not fit into bank.");
396 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
397 }
398
399 /** @todo: handle erasures that cross into adjacent banks */
400
401 addr -= c->base;
402 last_addr -= c->base;
403
404 for (i = 0; i < c->num_sectors; i++)
405 {
406 struct flash_sector *f = c->sectors + i;
407 uint32_t end = f->offset + f->size;
408
409 /* start only on a sector boundary */
410 if (first < 0) {
411 /* scanned past the first sector? */
412 if (addr < f->offset)
413 break;
414
415 /* is this the first sector? */
416 if (addr == f->offset)
417 first = i;
418
419 /* Does this need head-padding? If so, pad and warn;
420 * or else force an error.
421 *
422 * Such padding can make trouble, since *WE* can't
423 * ever know if that data was in use. The warning
424 * should help users sort out messes later.
425 */
426 else if (addr < end && pad_reason) {
427 /* FIXME say how many bytes (e.g. 80 KB) */
428 LOG_WARNING("Adding extra %s range, "
429 "%#8.8x to %#8.8x",
430 pad_reason,
431 (unsigned) f->offset,
432 (unsigned) addr - 1);
433 first = i;
434 } else
435 continue;
436 }
437
438 /* is this (also?) the last sector? */
439 if (last_addr == end) {
440 last = i;
441 break;
442 }
443
444 /* Does this need tail-padding? If so, pad and warn;
445 * or else force an error.
446 */
447 if (last_addr < end && pad_reason) {
448 /* FIXME say how many bytes (e.g. 80 KB) */
449 LOG_WARNING("Adding extra %s range, "
450 "%#8.8x to %#8.8x",
451 pad_reason,
452 (unsigned) last_addr,
453 (unsigned) end - 1);
454 last = i;
455 break;
456 }
457
458 /* MUST finish on a sector boundary */
459 if (last_addr <= f->offset)
460 break;
461 }
462
463 /* invalid start or end address? */
464 if (first == -1 || last == -1) {
465 LOG_ERROR("address range 0x%8.8x .. 0x%8.8x "
466 "is not sector-aligned",
467 (unsigned) (c->base + addr),
468 (unsigned) (c->base + last_addr - 1));
469 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
470 }
471
472 /* The NOR driver may trim this range down, based on what
473 * sectors are already erased/unprotected. GDB currently
474 * blocks such optimizations.
475 */
476 return callback(c, first, last);
477 }
478
479 int flash_erase_address_range(struct target *target,
480 bool pad, uint32_t addr, uint32_t length)
481 {
482 return flash_iterate_address_range(target, pad ? "erase" : NULL,
483 addr, length, &flash_driver_erase);
484 }
485
486 static int flash_driver_unprotect(struct flash_bank *bank, int first, int last)
487 {
488 return flash_driver_protect(bank, 0, first, last);
489 }
490
491 static int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length)
492 {
493 /* By default, pad to sector boundaries ... the real issue here
494 * is that our (only) caller *permanently* removes protection,
495 * and doesn't restore it.
496 */
497 return flash_iterate_address_range(target, "unprotect",
498 addr, length, &flash_driver_unprotect);
499 }
500
501 int flash_write_unlock(struct target *target, struct image *image,
502 uint32_t *written, int erase, bool unlock)
503 {
504 int retval = ERROR_OK;
505
506 int section;
507 uint32_t section_offset;
508 struct flash_bank *c;
509 int *padding;
510
511 /* REVISIT do_pad should perhaps just be another parameter.
512 * GDB wouldn't ever need it, since it erases separately.
513 * But "flash write_image" commands might want that option.
514 */
515 bool do_pad = false;
516
517 section = 0;
518 section_offset = 0;
519
520 if (written)
521 *written = 0;
522
523 if (erase)
524 {
525 /* assume all sectors need erasing - stops any problems
526 * when flash_write is called multiple times */
527
528 flash_set_dirty();
529 }
530
531 /* allocate padding array */
532 padding = calloc(image->num_sections, sizeof(*padding));
533
534 /* loop until we reach end of the image */
535 while (section < image->num_sections)
536 {
537 uint32_t buffer_size;
538 uint8_t *buffer;
539 int section_first;
540 int section_last;
541 uint32_t run_address = image->sections[section].base_address + section_offset;
542 uint32_t run_size = image->sections[section].size - section_offset;
543 int pad_bytes = 0;
544
545 if (image->sections[section].size == 0)
546 {
547 LOG_WARNING("empty section %d", section);
548 section++;
549 section_offset = 0;
550 continue;
551 }
552
553 /* find the corresponding flash bank */
554 if ((c = get_flash_bank_by_addr(target, run_address)) == NULL)
555 {
556 section++; /* and skip it */
557 section_offset = 0;
558 continue;
559 }
560
561 /* collect consecutive sections which fall into the same bank */
562 section_first = section;
563 section_last = section;
564 padding[section] = 0;
565 while ((run_address + run_size - 1 < c->base + c->size - 1)
566 && (section_last + 1 < image->num_sections))
567 {
568 if (image->sections[section_last + 1].base_address < (run_address + run_size))
569 {
570 LOG_DEBUG("section %d out of order "
571 "(surprising, but supported)",
572 section_last + 1);
573 /* REVISIT this can break with autoerase ...
574 * clobbering data after it's written.
575 */
576 break;
577 }
578
579 /* FIXME This needlessly touches sectors BETWEEN the
580 * sections it's writing. Without auto erase, it just
581 * writes ones. That WILL INVALIDATE data in cases
582 * like Stellaris Tempest chips, corrupting internal
583 * ECC codes; and at least FreeScale suggests issues
584 * with that approach (in HC11 documentation).
585 *
586 * With auto erase enabled, data in those sectors will
587 * be needlessly destroyed; and some of the limited
588 * number of flash erase cycles will be wasted...
589 *
590 * In both cases, the extra writes slow things down.
591 */
592
593 /* if we have multiple sections within our image,
594 * flash programming could fail due to alignment issues
595 * attempt to rebuild a consecutive buffer for the flash loader */
596 pad_bytes = (image->sections[section_last + 1].base_address) - (run_address + run_size);
597 if ((run_address + run_size + pad_bytes) > (c->base + c->size))
598 break;
599 padding[section_last] = pad_bytes;
600 run_size += image->sections[++section_last].size;
601 run_size += pad_bytes;
602
603 LOG_INFO("Padding image section %d with %d bytes", section_last-1, pad_bytes);
604 }
605
606 /* fit the run into bank constraints */
607 if (run_address + run_size - 1 > c->base + c->size - 1)
608 {
609 /* REVISIT isn't this superfluous, given the while()
610 * loop conditions above??
611 */
612 LOG_WARNING("writing %d bytes only - as image section is %d bytes and bank is only %d bytes", \
613 (int)(c->base + c->size - run_address), (int)(run_size), (int)(c->size));
614 run_size = c->base + c->size - run_address;
615 }
616
617 /* If we're applying any sector automagic, then pad this
618 * (maybe-combined) segment to the end of its last sector.
619 */
620 if (unlock || erase) {
621 int sector;
622 uint32_t offset_start = run_address - c->base;
623 uint32_t offset_end = offset_start + run_size;
624 uint32_t end = offset_end, delta;
625
626 for (sector = 0; sector < c->num_sectors; sector++) {
627 end = c->sectors[sector].offset
628 + c->sectors[sector].size;
629 if (offset_end <= end)
630 break;
631 }
632
633 delta = end - offset_end;
634 padding[section_last] += delta;
635 run_size += delta;
636 }
637
638 /* allocate buffer */
639 buffer = malloc(run_size);
640 buffer_size = 0;
641
642 /* read sections to the buffer */
643 while (buffer_size < run_size)
644 {
645 size_t size_read;
646
647 size_read = run_size - buffer_size;
648 if (size_read > image->sections[section].size - section_offset)
649 size_read = image->sections[section].size - section_offset;
650
651 if ((retval = image_read_section(image, section, section_offset,
652 size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0)
653 {
654 free(buffer);
655 free(padding);
656 return retval;
657 }
658
659 /* see if we need to pad the section */
660 while (padding[section]--)
661 (buffer + buffer_size)[size_read++] = 0xff;
662
663 buffer_size += size_read;
664 section_offset += size_read;
665
666 if (section_offset >= image->sections[section].size)
667 {
668 section++;
669 section_offset = 0;
670 }
671 }
672
673 retval = ERROR_OK;
674
675 if (unlock)
676 {
677 retval = flash_unlock_address_range(target, run_address, run_size);
678 }
679 if (retval == ERROR_OK)
680 {
681 if (erase)
682 {
683 /* calculate and erase sectors */
684 retval = flash_erase_address_range(target,
685 do_pad, run_address, run_size);
686 }
687 }
688
689 if (retval == ERROR_OK)
690 {
691 /* write flash sectors */
692 retval = flash_driver_write(c, buffer, run_address - c->base, run_size);
693 }
694
695 free(buffer);
696
697 if (retval != ERROR_OK)
698 {
699 free(padding);
700 return retval; /* abort operation */
701 }
702
703 if (written != NULL)
704 *written += run_size; /* add run size to total written counter */
705 }
706
707 free(padding);
708
709 return retval;
710 }
711
712 int flash_write(struct target *target, struct image *image,
713 uint32_t *written, int erase)
714 {
715 return flash_write_unlock(target, image, written, erase, false);
716 }
717
718 /**
719 * Invalidates cached flash state which a target can change as it runs.
720 *
721 * @param target The target being resumed
722 *
723 * OpenOCD caches some flash state for brief periods. For example, a sector
724 * that is protected must be unprotected before OpenOCD tries to write it,
725 * Also, a sector that's not erased must be erased before it's written.
726 *
727 * As a rule, OpenOCD and target firmware can both modify the flash, so when
728 * a target starts running, OpenOCD needs to invalidate its cached state.
729 */
730 void nor_resume(struct target *target)
731 {
732 struct flash_bank *bank;
733
734 for (bank = flash_banks; bank; bank = bank->next) {
735 int i;
736
737 if (bank->target != target)
738 continue;
739
740 for (i = 0; i < bank->num_sectors; i++) {
741 struct flash_sector *sector = bank->sectors + i;
742
743 sector->is_erased = -1;
744 sector->is_protected = -1;
745 }
746 }
747 }

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)