nand: when verify failed, it didn't return an error
[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 KiB/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 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 nand_fileio_cleanup(&file);
346 return retval;
347 }
348
349 int bytes_read = nand_fileio_read(nand, &file);
350 if (bytes_read <= 0)
351 {
352 command_print(CMD_CTX, "error while reading file");
353 nand_fileio_cleanup(&dev);
354 nand_fileio_cleanup(&file);
355 return ERROR_FAIL;
356 }
357
358 if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) ||
359 (dev.oob && memcmp(dev.oob, file.oob, dev.oob_size)) )
360 {
361 command_print(CMD_CTX, "NAND flash contents differ "
362 "at 0x%8.8" PRIx32, dev.address);
363 nand_fileio_cleanup(&dev);
364 nand_fileio_cleanup(&file);
365 return ERROR_FAIL;
366 }
367
368 file.size -= bytes_read;
369 dev.address += nand->page_size;
370 }
371
372 if (nand_fileio_finish(&file) == ERROR_OK)
373 {
374 command_print(CMD_CTX, "verified file %s in NAND flash %s "
375 "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
376 CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench),
377 duration_kbps(&file.bench, dev.size));
378 }
379
380 return nand_fileio_cleanup(&dev);
381 }
382
383 COMMAND_HANDLER(handle_nand_dump_command)
384 {
385 struct nand_device *nand = NULL;
386 struct nand_fileio_state s;
387 int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
388 &s, &nand, FILEIO_WRITE, true, false);
389 if (ERROR_OK != retval)
390 return retval;
391
392 while (s.size > 0)
393 {
394 size_t size_written;
395 retval = nand_read_page(nand, s.address / nand->page_size,
396 s.page, s.page_size, s.oob, s.oob_size);
397 if (ERROR_OK != retval)
398 {
399 command_print(CMD_CTX, "reading NAND flash page failed");
400 nand_fileio_cleanup(&s);
401 return retval;
402 }
403
404 if (NULL != s.page)
405 fileio_write(&s.fileio, s.page_size, s.page, &size_written);
406
407 if (NULL != s.oob)
408 fileio_write(&s.fileio, s.oob_size, s.oob, &size_written);
409
410 s.size -= nand->page_size;
411 s.address += nand->page_size;
412 }
413
414 if (nand_fileio_finish(&s) == ERROR_OK)
415 {
416 command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f KiB/s)",
417 (long)s.fileio.size, duration_elapsed(&s.bench),
418 duration_kbps(&s.bench, s.fileio.size));
419 }
420 return ERROR_OK;
421 }
422
423 COMMAND_HANDLER(handle_nand_raw_access_command)
424 {
425 if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
426 {
427 return ERROR_COMMAND_SYNTAX_ERROR;
428 }
429
430 struct nand_device *p;
431 int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
432 if (ERROR_OK != retval)
433 return retval;
434
435 if (NULL == p->device)
436 {
437 command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
438 return ERROR_OK;
439 }
440
441 if (CMD_ARGC == 2)
442 COMMAND_PARSE_ENABLE(CMD_ARGV[1], p->use_raw);
443
444 const char *msg = p->use_raw ? "enabled" : "disabled";
445 command_print(CMD_CTX, "raw access is %s", msg);
446
447 return ERROR_OK;
448 }
449
450 static const struct command_registration nand_exec_command_handlers[] = {
451 {
452 .name = "list",
453 .handler = handle_nand_list_command,
454 .mode = COMMAND_EXEC,
455 .help = "list configured NAND flash devices",
456 },
457 {
458 .name = "info",
459 .handler = handle_nand_info_command,
460 .mode = COMMAND_EXEC,
461 .usage = "[banknum | first_bank_num last_bank_num]",
462 .help = "print info about one or more NAND flash devices",
463 },
464 {
465 .name = "probe",
466 .handler = handle_nand_probe_command,
467 .mode = COMMAND_EXEC,
468 .usage = "bank_id",
469 .help = "identify NAND flash device",
470 },
471 {
472 .name = "check_bad_blocks",
473 .handler = handle_nand_check_bad_blocks_command,
474 .mode = COMMAND_EXEC,
475 .usage = "bank_id [offset length]",
476 .help = "check all or part of NAND flash device for bad blocks",
477 },
478 {
479 .name = "erase",
480 .handler = handle_nand_erase_command,
481 .mode = COMMAND_EXEC,
482 .usage = "bank_id [offset length]",
483 .help = "erase all or subset of blocks on NAND flash device",
484 },
485 {
486 .name = "dump",
487 .handler = handle_nand_dump_command,
488 .mode = COMMAND_EXEC,
489 .usage = "bank_id filename offset length "
490 "['oob_raw'|'oob_only']",
491 .help = "dump from NAND flash device",
492 },
493 {
494 .name = "verify",
495 .handler = handle_nand_verify_command,
496 .mode = COMMAND_EXEC,
497 .usage = "bank_id filename offset "
498 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
499 .help = "verify NAND flash device",
500 },
501 {
502 .name = "write",
503 .handler = handle_nand_write_command,
504 .mode = COMMAND_EXEC,
505 .usage = "bank_id filename offset "
506 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
507 .help = "write to NAND flash device",
508 },
509 {
510 .name = "raw_access",
511 .handler = handle_nand_raw_access_command,
512 .mode = COMMAND_EXEC,
513 .usage = "bank_id ['enable'|'disable']",
514 .help = "raw access to NAND flash device",
515 },
516 COMMAND_REGISTRATION_DONE
517 };
518
519 static int nand_init(struct command_context *cmd_ctx)
520 {
521 if (!nand_devices)
522 return ERROR_OK;
523 struct command *parent = command_find_in_context(cmd_ctx, "nand");
524 return register_commands(cmd_ctx, parent, nand_exec_command_handlers);
525 }
526
527 COMMAND_HANDLER(handle_nand_init_command)
528 {
529 if (CMD_ARGC != 0)
530 return ERROR_COMMAND_SYNTAX_ERROR;
531
532 static bool nand_initialized = false;
533 if (nand_initialized)
534 {
535 LOG_INFO("'nand init' has already been called");
536 return ERROR_OK;
537 }
538 nand_initialized = true;
539
540 LOG_DEBUG("Initializing NAND devices...");
541 return nand_init(CMD_CTX);
542 }
543
544 static int nand_list_walker(struct nand_flash_controller *c, void *x)
545 {
546 struct command_context *cmd_ctx = (struct command_context *)x;
547 command_print(cmd_ctx, " %s", c->name);
548 return ERROR_OK;
549 }
550
551 COMMAND_HANDLER(handle_nand_list_drivers)
552 {
553 command_print(CMD_CTX, "Available NAND flash controller drivers:");
554 return nand_driver_walk(&nand_list_walker, CMD_CTX);
555 }
556
557 static COMMAND_HELPER(create_nand_device, const char *bank_name,
558 struct nand_flash_controller *controller)
559 {
560 if (NULL != controller->commands)
561 {
562 int retval = register_commands(CMD_CTX, NULL,
563 controller->commands);
564 if (ERROR_OK != retval)
565 return retval;
566 }
567 struct nand_device *c = malloc(sizeof(struct nand_device));
568
569 c->name = strdup(bank_name);
570 c->controller = controller;
571 c->controller_priv = NULL;
572 c->manufacturer = NULL;
573 c->device = NULL;
574 c->bus_width = 0;
575 c->address_cycles = 0;
576 c->page_size = 0;
577 c->use_raw = 0;
578 c->next = NULL;
579
580 int retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
581 if (ERROR_OK != retval)
582 {
583 LOG_ERROR("'%s' driver rejected nand flash", controller->name);
584 free(c);
585 return ERROR_OK;
586 }
587
588 nand_device_add(c);
589
590 return ERROR_OK;
591 }
592
593 COMMAND_HANDLER(handle_nand_device_command)
594 {
595 if (CMD_ARGC < 1)
596 {
597 LOG_ERROR("incomplete nand device configuration");
598 return ERROR_FLASH_BANK_INVALID;
599 }
600
601 // save name and increment (for compatibility) with drivers
602 const char *bank_name = *CMD_ARGV++;
603 CMD_ARGC--;
604
605 const char *driver_name = CMD_ARGV[0];
606 struct nand_flash_controller *controller;
607 controller = nand_driver_find_by_name(CMD_ARGV[0]);
608 if (NULL == controller)
609 {
610 LOG_ERROR("No valid NAND flash driver found (%s)", driver_name);
611 return CALL_COMMAND_HANDLER(handle_nand_list_drivers);
612 }
613 return CALL_COMMAND_HANDLER(create_nand_device, bank_name, controller);
614 }
615
616 static const struct command_registration nand_config_command_handlers[] = {
617 {
618 .name = "device",
619 .handler = &handle_nand_device_command,
620 .mode = COMMAND_CONFIG,
621 .help = "defines a new NAND bank",
622 .usage = "bank_id driver target [driver_options ...]",
623 },
624 {
625 .name = "drivers",
626 .handler = &handle_nand_list_drivers,
627 .mode = COMMAND_ANY,
628 .help = "lists available NAND drivers",
629 },
630 {
631 .name = "init",
632 .mode = COMMAND_CONFIG,
633 .handler = &handle_nand_init_command,
634 .help = "initialize NAND devices",
635 },
636 COMMAND_REGISTRATION_DONE
637 };
638 static const struct command_registration nand_command_handlers[] = {
639 {
640 .name = "nand",
641 .mode = COMMAND_ANY,
642 .help = "NAND flash command group",
643 .chain = nand_config_command_handlers,
644 },
645 COMMAND_REGISTRATION_DONE
646 };
647
648 int nand_register_commands(struct command_context *cmd_ctx)
649 {
650 return register_commands(cmd_ctx, NULL, nand_command_handlers);
651 }
652
653

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)