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

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)