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

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)