NAND: Misleading report of erased blocks
[fw/openocd] / 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 - 1,
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