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

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)