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> *
6 * Partially based on drivers/mtd/nand_ids.c from Linux. *
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. *
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. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20 ***************************************************************************/
29 #include <target/target.h>
32 extern struct nand_device
*nand_devices
;
34 COMMAND_HANDLER(handle_nand_list_command
)
36 struct nand_device
*p
;
40 command_print(CMD_CTX
, "no NAND flash devices configured");
44 for (p
= nand_devices
, i
= 0; p
; p
= p
->next
, i
++) {
46 command_print(CMD_CTX
, "#%i: %s (%s) "
47 "pagesize: %i, buswidth: %i,\n\t"
48 "blocksize: %i, blocks: %i",
49 i
, p
->device
->name
, p
->manufacturer
->name
,
50 p
->page_size
, p
->bus_width
,
51 p
->erase_size
, p
->num_blocks
);
53 command_print(CMD_CTX
, "#%i: not probed", i
);
59 COMMAND_HANDLER(handle_nand_info_command
)
68 return ERROR_COMMAND_SYNTAX_ERROR
;
74 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], i
);
79 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], first
);
80 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], last
);
84 struct nand_device
*p
;
85 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
86 if (ERROR_OK
!= retval
)
89 if (NULL
== p
->device
) {
90 command_print(CMD_CTX
, "#%s: not probed", CMD_ARGV
[0]);
94 if (first
>= p
->num_blocks
)
95 first
= p
->num_blocks
- 1;
97 if (last
>= p
->num_blocks
)
98 last
= p
->num_blocks
- 1;
100 command_print(CMD_CTX
,
101 "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
104 p
->manufacturer
->name
,
109 for (j
= first
; j
<= last
; j
++) {
110 char *erase_state
, *bad_state
;
112 if (p
->blocks
[j
].is_erased
== 0)
113 erase_state
= "not erased";
114 else if (p
->blocks
[j
].is_erased
== 1)
115 erase_state
= "erased";
117 erase_state
= "erase state unknown";
119 if (p
->blocks
[j
].is_bad
== 0)
121 else if (p
->blocks
[j
].is_bad
== 1)
122 bad_state
= " (marked bad)";
124 bad_state
= " (block condition unknown)";
126 command_print(CMD_CTX
,
127 "\t#%i: 0x%8.8" PRIx32
" (%" PRId32
"kB) %s%s",
130 p
->blocks
[j
].size
/ 1024,
138 COMMAND_HANDLER(handle_nand_probe_command
)
141 return ERROR_COMMAND_SYNTAX_ERROR
;
143 struct nand_device
*p
;
144 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
145 if (ERROR_OK
!= retval
)
148 retval
= nand_probe(p
);
149 if (retval
== ERROR_OK
) {
150 command_print(CMD_CTX
, "NAND flash device '%s (%s)' found",
151 p
->device
->name
, p
->manufacturer
->name
);
157 COMMAND_HANDLER(handle_nand_erase_command
)
159 if (CMD_ARGC
!= 1 && CMD_ARGC
!= 3)
160 return ERROR_COMMAND_SYNTAX_ERROR
;
162 struct nand_device
*p
;
163 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
164 if (ERROR_OK
!= retval
)
167 unsigned long offset
;
168 unsigned long length
;
170 /* erase specified part of the chip; or else everything */
172 unsigned long size
= p
->erase_size
* p
->num_blocks
;
174 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[1], offset
);
175 if ((offset
% p
->erase_size
) != 0 || offset
>= size
)
176 return ERROR_COMMAND_SYNTAX_ERROR
;
178 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[2], length
);
179 if ((length
== 0) || (length
% p
->erase_size
) != 0
180 || (length
+ offset
) > size
)
181 return ERROR_COMMAND_SYNTAX_ERROR
;
183 offset
/= p
->erase_size
;
184 length
/= p
->erase_size
;
187 length
= p
->num_blocks
;
190 retval
= nand_erase(p
, offset
, offset
+ length
- 1);
191 if (retval
== ERROR_OK
) {
192 command_print(CMD_CTX
, "erased blocks %lu to %lu "
193 "on NAND flash device #%s '%s'",
194 offset
, offset
+ length
- 1,
195 CMD_ARGV
[0], p
->device
->name
);
201 COMMAND_HANDLER(handle_nand_check_bad_blocks_command
)
206 if ((CMD_ARGC
< 1) || (CMD_ARGC
> 3) || (CMD_ARGC
== 2))
207 return ERROR_COMMAND_SYNTAX_ERROR
;
209 struct nand_device
*p
;
210 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
211 if (ERROR_OK
!= retval
)
215 unsigned long offset
;
216 unsigned long length
;
218 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[1], offset
);
219 if (offset
% p
->erase_size
)
220 return ERROR_COMMAND_SYNTAX_ERROR
;
221 offset
/= p
->erase_size
;
223 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[2], length
);
224 if (length
% p
->erase_size
)
225 return ERROR_COMMAND_SYNTAX_ERROR
;
228 length
/= p
->erase_size
;
231 last
= offset
+ length
;
234 retval
= nand_build_bbt(p
, first
, last
);
235 if (retval
== ERROR_OK
) {
236 command_print(CMD_CTX
, "checked NAND flash device for bad blocks, "
237 "use \"nand info\" command to list blocks");
243 COMMAND_HANDLER(handle_nand_write_command
)
245 struct nand_device
*nand
= NULL
;
246 struct nand_fileio_state s
;
247 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
248 &s
, &nand
, FILEIO_READ
, false, true);
249 if (ERROR_OK
!= retval
)
252 uint32_t total_bytes
= s
.size
;
254 int bytes_read
= nand_fileio_read(nand
, &s
);
255 if (bytes_read
<= 0) {
256 command_print(CMD_CTX
, "error while reading file");
257 return nand_fileio_cleanup(&s
);
259 s
.size
-= bytes_read
;
261 retval
= nand_write_page(nand
, s
.address
/ nand
->page_size
,
262 s
.page
, s
.page_size
, s
.oob
, s
.oob_size
);
263 if (ERROR_OK
!= retval
) {
264 command_print(CMD_CTX
, "failed writing file %s "
265 "to NAND flash %s at offset 0x%8.8" PRIx32
,
266 CMD_ARGV
[1], CMD_ARGV
[0], s
.address
);
267 return nand_fileio_cleanup(&s
);
269 s
.address
+= s
.page_size
;
272 if (nand_fileio_finish(&s
) == ERROR_OK
) {
273 command_print(CMD_CTX
, "wrote file %s to NAND flash %s up to "
274 "offset 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)",
275 CMD_ARGV
[1], CMD_ARGV
[0], s
.address
, duration_elapsed(&s
.bench
),
276 duration_kbps(&s
.bench
, total_bytes
));
281 COMMAND_HANDLER(handle_nand_verify_command
)
283 struct nand_device
*nand
= NULL
;
284 struct nand_fileio_state file
;
285 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
286 &file
, &nand
, FILEIO_READ
, false, true);
287 if (ERROR_OK
!= retval
)
290 struct nand_fileio_state dev
;
291 nand_fileio_init(&dev
);
292 dev
.address
= file
.address
;
293 dev
.size
= file
.size
;
294 dev
.oob_format
= file
.oob_format
;
295 retval
= nand_fileio_start(CMD_CTX
, nand
, NULL
, FILEIO_NONE
, &dev
);
296 if (ERROR_OK
!= retval
)
299 while (file
.size
> 0) {
300 retval
= nand_read_page(nand
, dev
.address
/ dev
.page_size
,
301 dev
.page
, dev
.page_size
, dev
.oob
, dev
.oob_size
);
302 if (ERROR_OK
!= retval
) {
303 command_print(CMD_CTX
, "reading NAND flash page failed");
304 nand_fileio_cleanup(&dev
);
305 nand_fileio_cleanup(&file
);
309 int bytes_read
= nand_fileio_read(nand
, &file
);
310 if (bytes_read
<= 0) {
311 command_print(CMD_CTX
, "error while reading file");
312 nand_fileio_cleanup(&dev
);
313 nand_fileio_cleanup(&file
);
317 if ((dev
.page
&& memcmp(dev
.page
, file
.page
, dev
.page_size
)) ||
318 (dev
.oob
&& memcmp(dev
.oob
, file
.oob
, dev
.oob_size
))) {
319 command_print(CMD_CTX
, "NAND flash contents differ "
320 "at 0x%8.8" PRIx32
, dev
.address
);
321 nand_fileio_cleanup(&dev
);
322 nand_fileio_cleanup(&file
);
326 file
.size
-= bytes_read
;
327 dev
.address
+= nand
->page_size
;
330 if (nand_fileio_finish(&file
) == ERROR_OK
) {
331 command_print(CMD_CTX
, "verified file %s in NAND flash %s "
332 "up to offset 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)",
333 CMD_ARGV
[1], CMD_ARGV
[0], dev
.address
, duration_elapsed(&file
.bench
),
334 duration_kbps(&file
.bench
, dev
.size
));
337 return nand_fileio_cleanup(&dev
);
340 COMMAND_HANDLER(handle_nand_dump_command
)
343 struct nand_device
*nand
= NULL
;
344 struct nand_fileio_state s
;
345 int retval
= CALL_COMMAND_HANDLER(nand_fileio_parse_args
,
346 &s
, &nand
, FILEIO_WRITE
, true, false);
347 if (ERROR_OK
!= retval
)
352 retval
= nand_read_page(nand
, s
.address
/ nand
->page_size
,
353 s
.page
, s
.page_size
, s
.oob
, s
.oob_size
);
354 if (ERROR_OK
!= retval
) {
355 command_print(CMD_CTX
, "reading NAND flash page failed");
356 nand_fileio_cleanup(&s
);
361 fileio_write(s
.fileio
, s
.page_size
, s
.page
, &size_written
);
364 fileio_write(s
.fileio
, s
.oob_size
, s
.oob
, &size_written
);
366 s
.size
-= nand
->page_size
;
367 s
.address
+= nand
->page_size
;
370 retval
= fileio_size(s
.fileio
, &filesize
);
371 if (retval
!= ERROR_OK
)
374 if (nand_fileio_finish(&s
) == ERROR_OK
) {
375 command_print(CMD_CTX
, "dumped %zu bytes in %fs (%0.3f KiB/s)",
376 filesize
, duration_elapsed(&s
.bench
),
377 duration_kbps(&s
.bench
, filesize
));
382 COMMAND_HANDLER(handle_nand_raw_access_command
)
384 if ((CMD_ARGC
< 1) || (CMD_ARGC
> 2))
385 return ERROR_COMMAND_SYNTAX_ERROR
;
387 struct nand_device
*p
;
388 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
389 if (ERROR_OK
!= retval
)
392 if (NULL
== p
->device
) {
393 command_print(CMD_CTX
, "#%s: not probed", CMD_ARGV
[0]);
398 COMMAND_PARSE_ENABLE(CMD_ARGV
[1], p
->use_raw
);
400 const char *msg
= p
->use_raw
? "enabled" : "disabled";
401 command_print(CMD_CTX
, "raw access is %s", msg
);
406 static const struct command_registration nand_exec_command_handlers
[] = {
409 .handler
= handle_nand_list_command
,
410 .mode
= COMMAND_EXEC
,
411 .help
= "list configured NAND flash devices",
415 .handler
= handle_nand_info_command
,
416 .mode
= COMMAND_EXEC
,
417 .usage
= "[banknum | first_bank_num last_bank_num]",
418 .help
= "print info about one or more NAND flash devices",
422 .handler
= handle_nand_probe_command
,
423 .mode
= COMMAND_EXEC
,
425 .help
= "identify NAND flash device",
428 .name
= "check_bad_blocks",
429 .handler
= handle_nand_check_bad_blocks_command
,
430 .mode
= COMMAND_EXEC
,
431 .usage
= "bank_id [offset length]",
432 .help
= "check all or part of NAND flash device for bad blocks",
436 .handler
= handle_nand_erase_command
,
437 .mode
= COMMAND_EXEC
,
438 .usage
= "bank_id [offset length]",
439 .help
= "erase all or subset of blocks on NAND flash device",
443 .handler
= handle_nand_dump_command
,
444 .mode
= COMMAND_EXEC
,
445 .usage
= "bank_id filename offset length "
446 "['oob_raw'|'oob_only']",
447 .help
= "dump from NAND flash device",
451 .handler
= handle_nand_verify_command
,
452 .mode
= COMMAND_EXEC
,
453 .usage
= "bank_id filename offset "
454 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
455 .help
= "verify NAND flash device",
459 .handler
= handle_nand_write_command
,
460 .mode
= COMMAND_EXEC
,
461 .usage
= "bank_id filename offset "
462 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
463 .help
= "write to NAND flash device",
466 .name
= "raw_access",
467 .handler
= handle_nand_raw_access_command
,
468 .mode
= COMMAND_EXEC
,
469 .usage
= "bank_id ['enable'|'disable']",
470 .help
= "raw access to NAND flash device",
472 COMMAND_REGISTRATION_DONE
475 static int nand_init(struct command_context
*cmd_ctx
)
479 struct command
*parent
= command_find_in_context(cmd_ctx
, "nand");
480 return register_commands(cmd_ctx
, parent
, nand_exec_command_handlers
);
483 COMMAND_HANDLER(handle_nand_init_command
)
486 return ERROR_COMMAND_SYNTAX_ERROR
;
488 static bool nand_initialized
;
489 if (nand_initialized
) {
490 LOG_INFO("'nand init' has already been called");
493 nand_initialized
= true;
495 LOG_DEBUG("Initializing NAND devices...");
496 return nand_init(CMD_CTX
);
499 static int nand_list_walker(struct nand_flash_controller
*c
, void *x
)
501 struct command_context
*cmd_ctx
= x
;
502 command_print(cmd_ctx
, " %s", c
->name
);
506 COMMAND_HANDLER(handle_nand_list_drivers
)
508 command_print(CMD_CTX
, "Available NAND flash controller drivers:");
509 return nand_driver_walk(&nand_list_walker
, CMD_CTX
);
512 static COMMAND_HELPER(create_nand_device
, const char *bank_name
,
513 struct nand_flash_controller
*controller
)
515 struct nand_device
*c
;
516 struct target
*target
;
520 return ERROR_COMMAND_SYNTAX_ERROR
;
521 target
= get_target(CMD_ARGV
[1]);
523 LOG_ERROR("invalid target %s", CMD_ARGV
[1]);
524 return ERROR_COMMAND_ARGUMENT_INVALID
;
527 if (NULL
!= controller
->commands
) {
528 retval
= register_commands(CMD_CTX
, NULL
,
529 controller
->commands
);
530 if (ERROR_OK
!= retval
)
533 c
= malloc(sizeof(struct nand_device
));
535 LOG_ERROR("End of memory");
539 c
->name
= strdup(bank_name
);
541 c
->controller
= controller
;
542 c
->controller_priv
= NULL
;
543 c
->manufacturer
= NULL
;
546 c
->address_cycles
= 0;
551 retval
= CALL_COMMAND_HANDLER(controller
->nand_device_command
, c
);
552 if (ERROR_OK
!= retval
) {
553 LOG_ERROR("'%s' driver rejected nand flash. Usage: %s",
560 if (controller
->usage
== NULL
)
561 LOG_DEBUG("'%s' driver usage field missing", controller
->name
);
568 COMMAND_HANDLER(handle_nand_device_command
)
571 return ERROR_COMMAND_SYNTAX_ERROR
;
573 /* save name and increment (for compatibility) with drivers */
574 const char *bank_name
= *CMD_ARGV
++;
577 const char *driver_name
= CMD_ARGV
[0];
578 struct nand_flash_controller
*controller
;
579 controller
= nand_driver_find_by_name(CMD_ARGV
[0]);
580 if (NULL
== controller
) {
581 LOG_ERROR("No valid NAND flash driver found (%s)", driver_name
);
582 return CALL_COMMAND_HANDLER(handle_nand_list_drivers
);
584 return CALL_COMMAND_HANDLER(create_nand_device
, bank_name
, controller
);
587 static const struct command_registration nand_config_command_handlers
[] = {
590 .handler
= &handle_nand_device_command
,
591 .mode
= COMMAND_CONFIG
,
592 .help
= "defines a new NAND bank",
593 .usage
= "bank_id driver target [driver_options ...]",
597 .handler
= &handle_nand_list_drivers
,
599 .help
= "lists available NAND drivers",
604 .mode
= COMMAND_CONFIG
,
605 .handler
= &handle_nand_init_command
,
606 .help
= "initialize NAND devices",
609 COMMAND_REGISTRATION_DONE
612 static const struct command_registration nand_command_handlers
[] = {
616 .help
= "NAND flash command group",
618 .chain
= nand_config_command_handlers
,
620 COMMAND_REGISTRATION_DONE
623 int nand_register_commands(struct command_context
*cmd_ctx
)
625 return register_commands(cmd_ctx
, NULL
, nand_command_handlers
);
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)