1 // SPDX-License-Identifier: GPL-2.0-or-later
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> *
8 * Partially based on drivers/mtd/nand_ids.c from Linux. *
9 ***************************************************************************/
18 #include <target/target.h>
20 COMMAND_HANDLER(handle_nand_list_command
)
22 struct nand_device
*p
;
26 command_print(CMD
, "no NAND flash devices configured");
30 for (p
= nand_devices
, i
= 0; p
; p
= p
->next
, i
++) {
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
);
39 command_print(CMD
, "#%i: not probed", i
);
45 COMMAND_HANDLER(handle_nand_info_command
)
54 return ERROR_COMMAND_SYNTAX_ERROR
;
60 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], i
);
65 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], first
);
66 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], last
);
70 struct nand_device
*p
;
71 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
72 if (retval
!= ERROR_OK
)
76 command_print(CMD
, "#%s: not probed", CMD_ARGV
[0]);
80 if (first
>= p
->num_blocks
)
81 first
= p
->num_blocks
- 1;
83 if (last
>= p
->num_blocks
)
84 last
= p
->num_blocks
- 1;
87 "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
90 p
->manufacturer
->name
,
95 for (j
= first
; j
<= last
; j
++) {
96 char *erase_state
, *bad_state
;
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";
103 erase_state
= "erase state unknown";
105 if (p
->blocks
[j
].is_bad
== 0)
107 else if (p
->blocks
[j
].is_bad
== 1)
108 bad_state
= " (marked bad)";
110 bad_state
= " (block condition unknown)";
113 "\t#%i: 0x%8.8" PRIx32
" (%" PRIu32
"kB) %s%s",
116 p
->blocks
[j
].size
/ 1024,
124 COMMAND_HANDLER(handle_nand_probe_command
)
127 return ERROR_COMMAND_SYNTAX_ERROR
;
129 struct nand_device
*p
;
130 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
131 if (retval
!= ERROR_OK
)
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
);
143 COMMAND_HANDLER(handle_nand_erase_command
)
145 if (CMD_ARGC
!= 1 && CMD_ARGC
!= 3)
146 return ERROR_COMMAND_SYNTAX_ERROR
;
148 struct nand_device
*p
;
149 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
150 if (retval
!= ERROR_OK
)
153 unsigned long offset
;
154 unsigned long length
;
156 /* erase specified part of the chip; or else everything */
158 unsigned long size
= p
->erase_size
* p
->num_blocks
;
160 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[1], offset
);
161 if ((offset
% p
->erase_size
) != 0 || offset
>= size
)
162 return ERROR_COMMAND_SYNTAX_ERROR
;
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
;
169 offset
/= p
->erase_size
;
170 length
/= p
->erase_size
;
173 length
= p
->num_blocks
;
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
);
187 COMMAND_HANDLER(handle_nand_check_bad_blocks_command
)
192 if ((CMD_ARGC
< 1) || (CMD_ARGC
> 3) || (CMD_ARGC
== 2))
193 return ERROR_COMMAND_SYNTAX_ERROR
;
195 struct nand_device
*p
;
196 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
197 if (retval
!= ERROR_OK
)
201 unsigned long offset
;
202 unsigned long length
;
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
;
209 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[2], length
);
210 if (length
% p
->erase_size
)
211 return ERROR_COMMAND_SYNTAX_ERROR
;
214 length
/= p
->erase_size
;
217 last
= offset
+ length
;
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");
229 COMMAND_HANDLER(handle_nand_write_command
)
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
)
238 uint32_t total_bytes
= s
.size
;
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
);
246 s
.size
-= bytes_read
;
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
);
257 s
.address
+= s
.page_size
;
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
));
269 COMMAND_HANDLER(handle_nand_verify_command
)
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
)
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
)
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
);
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
);
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
);
314 file
.size
-= bytes_read
;
315 dev
.address
+= nand
->page_size
;
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
));
325 return nand_fileio_cleanup(&dev
);
328 COMMAND_HANDLER(handle_nand_dump_command
)
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
)
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
);
349 fileio_write(s
.fileio
, s
.page_size
, s
.page
, &size_written
);
352 fileio_write(s
.fileio
, s
.oob_size
, s
.oob
, &size_written
);
354 s
.size
-= nand
->page_size
;
355 s
.address
+= nand
->page_size
;
358 retval
= fileio_size(s
.fileio
, &filesize
);
359 if (retval
!= ERROR_OK
)
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
));
370 COMMAND_HANDLER(handle_nand_raw_access_command
)
372 if ((CMD_ARGC
< 1) || (CMD_ARGC
> 2))
373 return ERROR_COMMAND_SYNTAX_ERROR
;
375 struct nand_device
*p
;
376 int retval
= CALL_COMMAND_HANDLER(nand_command_get_device
, 0, &p
);
377 if (retval
!= ERROR_OK
)
381 command_print(CMD
, "#%s: not probed", CMD_ARGV
[0]);
386 COMMAND_PARSE_ENABLE(CMD_ARGV
[1], p
->use_raw
);
388 const char *msg
= p
->use_raw
? "enabled" : "disabled";
389 command_print(CMD
, "raw access is %s", msg
);
394 static const struct command_registration nand_exec_command_handlers
[] = {
397 .handler
= handle_nand_list_command
,
398 .mode
= COMMAND_EXEC
,
399 .help
= "list configured NAND flash devices",
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",
411 .handler
= handle_nand_probe_command
,
412 .mode
= COMMAND_EXEC
,
414 .help
= "identify NAND flash device",
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",
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",
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",
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",
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",
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",
461 COMMAND_REGISTRATION_DONE
464 static int nand_init(struct command_context
*cmd_ctx
)
469 return register_commands(cmd_ctx
, "nand", nand_exec_command_handlers
);
472 COMMAND_HANDLER(handle_nand_init_command
)
475 return ERROR_COMMAND_SYNTAX_ERROR
;
477 static bool nand_initialized
;
478 if (nand_initialized
) {
479 LOG_INFO("'nand init' has already been called");
482 nand_initialized
= true;
484 LOG_DEBUG("Initializing NAND devices...");
485 return nand_init(CMD_CTX
);
488 static int nand_list_walker(struct nand_flash_controller
*c
, void *x
)
490 struct command_invocation
*cmd
= x
;
491 command_print(cmd
, " %s", c
->name
);
495 COMMAND_HANDLER(handle_nand_list_drivers
)
497 command_print(CMD
, "Available NAND flash controller drivers:");
498 return nand_driver_walk(&nand_list_walker
, CMD
);
501 static COMMAND_HELPER(create_nand_device
, const char *bank_name
,
502 struct nand_flash_controller
*controller
)
504 struct nand_device
*c
;
505 struct target
*target
;
509 return ERROR_COMMAND_SYNTAX_ERROR
;
510 target
= get_target(CMD_ARGV
[1]);
512 LOG_ERROR("invalid target %s", CMD_ARGV
[1]);
513 return ERROR_COMMAND_ARGUMENT_INVALID
;
516 if (controller
->commands
) {
517 retval
= register_commands(CMD_CTX
, NULL
, controller
->commands
);
518 if (retval
!= ERROR_OK
)
521 c
= malloc(sizeof(struct nand_device
));
523 LOG_ERROR("End of memory");
527 c
->name
= strdup(bank_name
);
529 c
->controller
= controller
;
530 c
->controller_priv
= NULL
;
531 c
->manufacturer
= NULL
;
534 c
->address_cycles
= 0;
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",
548 if (!controller
->usage
)
549 LOG_DEBUG("'%s' driver usage field missing", controller
->name
);
556 COMMAND_HANDLER(handle_nand_device_command
)
559 return ERROR_COMMAND_SYNTAX_ERROR
;
561 /* save name and increment (for compatibility) with drivers */
562 const char *bank_name
= *CMD_ARGV
++;
565 const char *driver_name
= CMD_ARGV
[0];
566 struct nand_flash_controller
*controller
;
567 controller
= nand_driver_find_by_name(CMD_ARGV
[0]);
569 LOG_ERROR("No valid NAND flash driver found (%s)", driver_name
);
570 return CALL_COMMAND_HANDLER(handle_nand_list_drivers
);
572 return CALL_COMMAND_HANDLER(create_nand_device
, bank_name
, controller
);
575 static const struct command_registration nand_config_command_handlers
[] = {
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 ...]",
585 .handler
= &handle_nand_list_drivers
,
587 .help
= "lists available NAND drivers",
592 .mode
= COMMAND_CONFIG
,
593 .handler
= &handle_nand_init_command
,
594 .help
= "initialize NAND devices",
597 COMMAND_REGISTRATION_DONE
600 static const struct command_registration nand_command_handlers
[] = {
604 .help
= "NAND flash command group",
606 .chain
= nand_config_command_handlers
,
608 COMMAND_REGISTRATION_DONE
611 int nand_register_commands(struct command_context
*cmd_ctx
)
613 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)