ARMv7-M: make DAP commands verify target is an ARMv7-M
[openocd.git] / src / flash / nand / tcl.c
1 /***************************************************************************
2 * Copyright (C) 2007 by Dominic Rath <Dominic.Rath@gmx.de> *
3 * Copyright (C) 2002 Thomas Gleixner <tglx@linutronix.de> *
4 * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
5 * *
6 * Partially based on drivers/mtd/nand_ids.c from Linux. *
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, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "core.h"
28 #include "imp.h"
29 #include "fileio.h"
30
31 // to be removed
32 extern struct nand_device *nand_devices;
33
34 COMMAND_HANDLER(handle_nand_list_command)
35 {
36 struct nand_device *p;
37 int i;
38
39 if (!nand_devices)
40 {
41 command_print(CMD_CTX, "no NAND flash devices configured");
42 return ERROR_OK;
43 }
44
45 for (p = nand_devices, i = 0; p; p = p->next, i++)
46 {
47 if (p->device)
48 command_print(CMD_CTX, "#%i: %s (%s) "
49 "pagesize: %i, buswidth: %i,\n\t"
50 "blocksize: %i, blocks: %i",
51 i, p->device->name, p->manufacturer->name,
52 p->page_size, p->bus_width,
53 p->erase_size, p->num_blocks);
54 else
55 command_print(CMD_CTX, "#%i: not probed", i);
56 }
57
58 return ERROR_OK;
59 }
60
61 COMMAND_HANDLER(handle_nand_info_command)
62 {
63 int i = 0;
64 int j = 0;
65 int first = -1;
66 int last = -1;
67
68 switch (CMD_ARGC) {
69 default:
70 return ERROR_COMMAND_SYNTAX_ERROR;
71 case 1:
72 first = 0;
73 last = INT32_MAX;
74 break;
75 case 2:
76 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i);
77 first = last = i;
78 i = 0;
79 break;
80 case 3:
81 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first);
82 COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last);
83 break;
84 }
85
86 struct nand_device *p;
87 int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
88 if (ERROR_OK != retval)
89 return retval;
90
91 if (NULL == p->device)
92 {
93 command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
94 return ERROR_OK;
95 }
96
97 if (first >= p->num_blocks)
98 first = p->num_blocks - 1;
99
100 if (last >= p->num_blocks)
101 last = p->num_blocks - 1;
102
103 command_print(CMD_CTX, "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
104 i++, p->device->name, p->manufacturer->name, p->page_size, p->bus_width, p->erase_size);
105
106 for (j = first; j <= last; j++)
107 {
108 char *erase_state, *bad_state;
109
110 if (p->blocks[j].is_erased == 0)
111 erase_state = "not erased";
112 else if (p->blocks[j].is_erased == 1)
113 erase_state = "erased";
114 else
115 erase_state = "erase state unknown";
116
117 if (p->blocks[j].is_bad == 0)
118 bad_state = "";
119 else if (p->blocks[j].is_bad == 1)
120 bad_state = " (marked bad)";
121 else
122 bad_state = " (block condition unknown)";
123
124 command_print(CMD_CTX,
125 "\t#%i: 0x%8.8" PRIx32 " (%" PRId32 "kB) %s%s",
126 j,
127 p->blocks[j].offset,
128 p->blocks[j].size / 1024,
129 erase_state,
130 bad_state);
131 }
132
133 return ERROR_OK;
134 }
135
136 COMMAND_HANDLER(handle_nand_probe_command)
137 {
138 if (CMD_ARGC != 1)
139 {
140 return ERROR_COMMAND_SYNTAX_ERROR;
141 }
142
143 struct nand_device *p;
144 int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
145 if (ERROR_OK != retval)
146 return retval;
147
148 if ((retval = nand_probe(p)) == ERROR_OK)
149 {
150 command_print(CMD_CTX, "NAND flash device '%s' found", p->device->name);
151 }
152 else if (retval == ERROR_NAND_OPERATION_FAILED)
153 {
154 command_print(CMD_CTX, "probing failed for NAND flash device");
155 }
156 else
157 {
158 command_print(CMD_CTX, "unknown error when probing NAND flash device");
159 }
160
161 return ERROR_OK;
162 }
163
164 COMMAND_HANDLER(handle_nand_erase_command)
165 {
166 if (CMD_ARGC != 1 && CMD_ARGC != 3)
167 {
168 return ERROR_COMMAND_SYNTAX_ERROR;
169
170 }
171
172 struct nand_device *p;
173 int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
174 if (ERROR_OK != retval)
175 return retval;
176
177 unsigned long offset;
178 unsigned long length;
179
180 /* erase specified part of the chip; or else everything */
181 if (CMD_ARGC == 3) {
182 unsigned long size = p->erase_size * p->num_blocks;
183
184 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset);
185 if ((offset % p->erase_size) != 0 || offset >= size)
186 return ERROR_INVALID_ARGUMENTS;
187
188 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
189 if ((length == 0) || (length % p->erase_size) != 0
190 || (length + offset) > size)
191 return ERROR_INVALID_ARGUMENTS;
192
193 offset /= p->erase_size;
194 length /= p->erase_size;
195 } else {
196 offset = 0;
197 length = p->num_blocks;
198 }
199
200 retval = nand_erase(p, offset, offset + length - 1);
201 if (retval == ERROR_OK)
202 {
203 command_print(CMD_CTX, "erased blocks %lu to %lu "
204 "on NAND flash device #%s '%s'",
205 offset, offset + length,
206 CMD_ARGV[0], p->device->name);
207 }
208 else if (retval == ERROR_NAND_OPERATION_FAILED)
209 {
210 command_print(CMD_CTX, "erase failed");
211 }
212 else
213 {
214 command_print(CMD_CTX, "unknown error when erasing NAND flash device");
215 }
216
217 return ERROR_OK;
218 }
219
220 COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
221 {
222 int first = -1;
223 int last = -1;
224
225 if ((CMD_ARGC < 1) || (CMD_ARGC > 3) || (CMD_ARGC == 2))
226 {
227 return ERROR_COMMAND_SYNTAX_ERROR;
228
229 }
230
231 struct nand_device *p;
232 int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
233 if (ERROR_OK != retval)
234 return retval;
235
236 if (CMD_ARGC == 3)
237 {
238 unsigned long offset;
239 unsigned long length;
240
241 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset);
242 if (offset % p->erase_size)
243 return ERROR_INVALID_ARGUMENTS;
244 offset /= p->erase_size;
245
246 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
247 if (length % p->erase_size)
248 return ERROR_INVALID_ARGUMENTS;
249
250 length -= 1;
251 length /= p->erase_size;
252
253 first = offset;
254 last = offset + length;
255 }
256
257 retval = nand_build_bbt(p, first, last);
258 if (retval == ERROR_OK)
259 {
260 command_print(CMD_CTX, "checked NAND flash device for bad blocks, "
261 "use \"nand info\" command to list blocks");
262 }
263 else if (retval == ERROR_NAND_OPERATION_FAILED)
264 {
265 command_print(CMD_CTX, "error when checking for bad blocks on "
266 "NAND flash device");
267 }
268 else
269 {
270 command_print(CMD_CTX, "unknown error when checking for bad "
271 "blocks on NAND flash device");
272 }
273
274 return ERROR_OK;
275 }
276
277 COMMAND_HANDLER(handle_nand_write_command)
278 {
279 struct nand_device *nand = NULL;
280 struct nand_fileio_state s;
281 int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
282 &s, &nand, FILEIO_READ, false, true);
283 if (ERROR_OK != retval)
284 return retval;
285
286 uint32_t total_bytes = s.size;
287 while (s.size > 0)
288 {
289 int bytes_read = nand_fileio_read(nand, &s);
290 if (bytes_read <= 0)
291 {
292 command_print(CMD_CTX, "error while reading file");
293 return nand_fileio_cleanup(&s);
294 }
295 s.size -= bytes_read;
296
297 retval = nand_write_page(nand, s.address / nand->page_size,
298 s.page, s.page_size, s.oob, s.oob_size);
299 if (ERROR_OK != retval)
300 {
301 command_print(CMD_CTX, "failed writing file %s "
302 "to NAND flash %s at offset 0x%8.8" PRIx32,
303 CMD_ARGV[1], CMD_ARGV[0], s.address);
304 return nand_fileio_cleanup(&s);
305 }
306 s.address += s.page_size;
307 }
308
309 if (nand_fileio_finish(&s))
310 {
311 command_print(CMD_CTX, "wrote file %s to NAND flash %s up to "
312 "offset 0x%8.8" PRIx32 " in %fs (%0.3f kb/s)",
313 CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench),
314 duration_kbps(&s.bench, total_bytes));
315 }
316 return ERROR_OK;
317 }
318
319 COMMAND_HANDLER(handle_nand_verify_command)
320 {
321 struct nand_device *nand = NULL;
322 struct nand_fileio_state file;
323 int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
324 &file, &nand, FILEIO_READ, false, true);
325 if (ERROR_OK != retval)
326 return retval;
327
328 struct nand_fileio_state dev;
329 nand_fileio_init(&dev);
330 dev.address = file.address;
331 dev.size = file.size;
332 dev.oob_format = file.oob_format;
333 retval = nand_fileio_start(CMD_CTX, nand, NULL, FILEIO_NONE, &dev);
334 if (ERROR_OK != retval)
335 return retval;
336
337 while (file.size > 0)
338 {
339 int retval = nand_read_page(nand, dev.address / dev.page_size,
340 dev.page, dev.page_size, dev.oob, dev.oob_size);
341 if (ERROR_OK != retval)
342 {
343 command_print(CMD_CTX, "reading NAND flash page failed");
344 nand_fileio_cleanup(&dev);
345 return nand_fileio_cleanup(&file);
346 }
347
348 int bytes_read = nand_fileio_read(nand, &file);
349 if (bytes_read <= 0)
350 {
351 command_print(CMD_CTX, "error while reading file");
352 nand_fileio_cleanup(&dev);
353 return nand_fileio_cleanup(&file);
354 }
355
356 if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) ||
357 (dev.oob && memcmp(dev.oob, file.oob, dev.oob_size)) )
358 {
359 command_print(CMD_CTX, "NAND flash contents differ "
360 "at 0x%8.8" PRIx32, dev.address);
361 nand_fileio_cleanup(&dev);
362 return nand_fileio_cleanup(&file);
363 }
364
365 file.size -= bytes_read;
366 dev.address += nand->page_size;
367 }
368
369 if (nand_fileio_finish(&file) == ERROR_OK)
370 {
371 command_print(CMD_CTX, "verified file %s in NAND flash %s "
372 "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f kb/s)",
373 CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench),
374 duration_kbps(&file.bench, dev.size));
375 }
376
377 return nand_fileio_cleanup(&dev);
378 }
379
380 COMMAND_HANDLER(handle_nand_dump_command)
381 {
382 struct nand_device *nand = NULL;
383 struct nand_fileio_state s;
384 int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
385 &s, &nand, FILEIO_WRITE, true, false);
386 if (ERROR_OK != retval)
387 return retval;
388
389 while (s.size > 0)
390 {
391 size_t size_written;
392 int retval = nand_read_page(nand, s.address / nand->page_size,
393 s.page, s.page_size, s.oob, s.oob_size);
394 if (ERROR_OK != retval)
395 {
396 command_print(CMD_CTX, "reading NAND flash page failed");
397 return nand_fileio_cleanup(&s);
398 }
399
400 if (NULL != s.page)
401 fileio_write(&s.fileio, s.page_size, s.page, &size_written);
402
403 if (NULL != s.oob)
404 fileio_write(&s.fileio, s.oob_size, s.oob, &size_written);
405
406 s.size -= nand->page_size;
407 s.address += nand->page_size;
408 }
409
410 if (nand_fileio_finish(&s) == ERROR_OK)
411 {
412 command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f kb/s)",
413 (long)s.fileio.size, duration_elapsed(&s.bench),
414 duration_kbps(&s.bench, s.fileio.size));
415 }
416 return ERROR_OK;
417 }
418
419 COMMAND_HANDLER(handle_nand_raw_access_command)
420 {
421 if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
422 {
423 return ERROR_COMMAND_SYNTAX_ERROR;
424 }
425
426 struct nand_device *p;
427 int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
428 if (ERROR_OK != retval)
429 return retval;
430
431 if (NULL == p->device)
432 {
433 command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
434 return ERROR_OK;
435 }
436
437 if (CMD_ARGC == 2)
438 COMMAND_PARSE_ENABLE(CMD_ARGV[1], p->use_raw);
439
440 const char *msg = p->use_raw ? "enabled" : "disabled";
441 command_print(CMD_CTX, "raw access is %s", msg);
442
443 return ERROR_OK;
444 }
445
446 static const struct command_registration nand_exec_command_handlers[] = {
447 {
448 .name = "list",
449 .handler = handle_nand_list_command,
450 .mode = COMMAND_EXEC,
451 .help = "list configured NAND flash devices",
452 },
453 {
454 .name = "info",
455 .handler = handle_nand_info_command,
456 .mode = COMMAND_EXEC,
457 .usage = "[banknum | first_bank_num last_bank_num]",
458 .help = "print info about one or more NAND flash devices",
459 },
460 {
461 .name = "probe",
462 .handler = handle_nand_probe_command,
463 .mode = COMMAND_EXEC,
464 .usage = "bank_id",
465 .help = "identify NAND flash device",
466 },
467 {
468 .name = "check_bad_blocks",
469 .handler = handle_nand_check_bad_blocks_command,
470 .mode = COMMAND_EXEC,
471 .usage = "bank_id [offset length]",
472 .help = "check all or part of NAND flash device for bad blocks",
473 },
474 {
475 .name = "erase",
476 .handler = handle_nand_erase_command,
477 .mode = COMMAND_EXEC,
478 .usage = "bank_id [offset length]",
479 .help = "erase all or subset of blocks on NAND flash device",
480 },
481 {
482 .name = "dump",
483 .handler = handle_nand_dump_command,
484 .mode = COMMAND_EXEC,
485 .usage = "bank_id filename offset length "
486 "['oob_raw'|'oob_only']",
487 .help = "dump from NAND flash device",
488 },
489 {
490 .name = "verify",
491 .handler = handle_nand_verify_command,
492 .mode = COMMAND_EXEC,
493 .usage = "bank_id filename offset "
494 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
495 .help = "verify NAND flash device",
496 },
497 {
498 .name = "write",
499 .handler = handle_nand_write_command,
500 .mode = COMMAND_EXEC,
501 .usage = "bank_id filename offset "
502 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
503 .help = "write to NAND flash device",
504 },
505 {
506 .name = "raw_access",
507 .handler = handle_nand_raw_access_command,
508 .mode = COMMAND_EXEC,
509 .usage = "bank_id ['enable'|'disable']",
510 .help = "raw access to NAND flash device",
511 },
512 COMMAND_REGISTRATION_DONE
513 };
514
515 int nand_init(struct command_context *cmd_ctx)
516 {
517 if (!nand_devices)
518 return ERROR_OK;
519 struct command *parent = command_find_in_context(cmd_ctx, "nand");
520 return register_commands(cmd_ctx, parent, nand_exec_command_handlers);
521 }
522
523 COMMAND_HANDLER(handle_nand_init_command)
524 {
525 if (CMD_ARGC != 0)
526 return ERROR_COMMAND_SYNTAX_ERROR;
527
528 static bool nand_initialized = false;
529 if (nand_initialized)
530 {
531 LOG_INFO("'nand init' has already been called");
532 return ERROR_OK;
533 }
534 nand_initialized = true;
535
536 LOG_DEBUG("Initializing NAND devices...");
537 return nand_init(CMD_CTX);
538 }
539 int nand_list_walker(struct nand_flash_controller *c, void *x)
540 {
541 struct command_context *cmd_ctx = (struct command_context *)x;
542 command_print(cmd_ctx, " %s", c->name);
543 return ERROR_OK;
544 }
545 COMMAND_HANDLER(handle_nand_list_drivers)
546 {
547 command_print(CMD_CTX, "Available NAND flash controller drivers:");
548 return nand_driver_walk(&nand_list_walker, CMD_CTX);
549 }
550
551 static COMMAND_HELPER(create_nand_device, const char *bank_name,
552 struct nand_flash_controller *controller)
553 {
554 if (NULL != controller->commands)
555 {
556 int retval = register_commands(CMD_CTX, NULL,
557 controller->commands);
558 if (ERROR_OK != retval)
559 return retval;
560 }
561 struct nand_device *c = malloc(sizeof(struct nand_device));
562
563 c->name = strdup(bank_name);
564 c->controller = controller;
565 c->controller_priv = NULL;
566 c->manufacturer = NULL;
567 c->device = NULL;
568 c->bus_width = 0;
569 c->address_cycles = 0;
570 c->page_size = 0;
571 c->use_raw = 0;
572 c->next = NULL;
573
574 int retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
575 if (ERROR_OK != retval)
576 {
577 LOG_ERROR("'%s' driver rejected nand flash", controller->name);
578 free(c);
579 return ERROR_OK;
580 }
581
582 nand_device_add(c);
583
584 return ERROR_OK;
585 }
586
587 COMMAND_HANDLER(handle_nand_device_command)
588 {
589 if (CMD_ARGC < 1)
590 {
591 LOG_ERROR("incomplete nand device configuration");
592 return ERROR_FLASH_BANK_INVALID;
593 }
594
595 // save name and increment (for compatibility) with drivers
596 const char *bank_name = *CMD_ARGV++;
597 CMD_ARGC--;
598
599 const char *driver_name = CMD_ARGV[0];
600 struct nand_flash_controller *controller;
601 controller = nand_driver_find_by_name(CMD_ARGV[0]);
602 if (NULL == controller)
603 {
604 LOG_ERROR("No valid NAND flash driver found (%s)", driver_name);
605 return CALL_COMMAND_HANDLER(handle_nand_list_drivers);
606 }
607 return CALL_COMMAND_HANDLER(create_nand_device, bank_name, controller);
608 }
609
610 static const struct command_registration nand_config_command_handlers[] = {
611 {
612 .name = "device",
613 .handler = &handle_nand_device_command,
614 .mode = COMMAND_CONFIG,
615 .help = "defines a new NAND bank",
616 .usage = "bank_id driver target [driver_options ...]",
617 },
618 {
619 .name = "drivers",
620 .handler = &handle_nand_list_drivers,
621 .mode = COMMAND_ANY,
622 .help = "lists available NAND drivers",
623 },
624 {
625 .name = "init",
626 .mode = COMMAND_CONFIG,
627 .handler = &handle_nand_init_command,
628 .help = "initialize NAND devices",
629 },
630 COMMAND_REGISTRATION_DONE
631 };
632 static const struct command_registration nand_command_handlers[] = {
633 {
634 .name = "nand",
635 .mode = COMMAND_ANY,
636 .help = "NAND flash command group",
637 .chain = nand_config_command_handlers,
638 },
639 COMMAND_REGISTRATION_DONE
640 };
641
642 int nand_register_commands(struct command_context *cmd_ctx)
643 {
644 return register_commands(cmd_ctx, NULL, nand_command_handlers);
645 }
646
647

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)