2 * Rick Bronson and Pantelis Antoniou
7 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
12 #include <asm/byteorder.h>
14 #ifdef CONFIG_SHOW_BOOT_PROGRESS
15 # include <status_led.h>
16 # define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
18 # define SHOW_BOOT_PROGRESS(arg)
21 #include <jffs2/jffs2.h>
24 extern nand_info_t nand_info[]; /* info for NAND chips */
26 static int nand_dump_oob(nand_info_t *nand, ulong off)
31 static int nand_dump(nand_info_t *nand, ulong off)
36 buf = malloc(nand->oobblock + nand->oobsize);
38 puts("No memory for page buffer\n");
41 off &= ~(nand->oobblock - 1);
42 i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
44 printf("Error (%d) reading page %08x\n", i, off);
48 printf("Page %08x dump:\n", off);
49 i = nand->oobblock >> 4; p = buf;
51 printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
52 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
53 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
54 p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
58 i = nand->oobsize >> 3;
60 printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
61 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
69 /* ------------------------------------------------------------------------- */
72 arg_off_size(int argc, char *argv[], ulong *off, ulong *size, ulong totsize)
77 #if defined(CONFIG_JFFS2_NAND) && defined(CFG_JFFS_CUSTOM_PART)
78 if (argc >= 1 && strcmp(argv[0], "partition") == 0) {
80 struct part_info *part;
86 partstr = getenv("partition");
89 part_num = (int)simple_strtoul(partstr, NULL, 10);
93 part = jffs2_part_info(part_num);
95 printf("\nInvalid partition %d\n", part_num);
99 *off = (ulong)part->offset;
104 *off = (ulong)simple_strtoul(argv[0], NULL, 16);
109 *size = (ulong)simple_strtoul(argv[1], NULL, 16);
111 *size = totsize - *off;
117 int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
120 ulong addr, off, size;
124 /* at least two arguments please */
130 if (strcmp(cmd, "info") == 0) {
133 for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
134 if (nand_info[i].name)
135 printf("Device %d: %s\n", i, nand_info[i].name);
140 if (strcmp(cmd, "device") == 0) {
143 if ((nand_curr_device < 0) ||
144 (nand_curr_device >= CFG_MAX_NAND_DEVICE))
145 puts("\nno devices available\n");
147 printf("\nDevice %d: %s\n", nand_curr_device,
148 nand_info[nand_curr_device].name);
151 dev = (int)simple_strtoul(argv[2], NULL, 10);
152 if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
153 puts("No such device\n");
156 printf("Device %d: %s", dev, nand_info[dev].name);
157 puts("... is now current device\n");
158 nand_curr_device = dev;
162 if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
163 strncmp(cmd, "dump", 4) != 0 &&
164 strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0
165 #ifdef CONFIG_MTD_NAND_UNSAFE
166 && strcmp(cmd, "scrub") != 0 && strcmp(cmd, "biterr") != 0
167 && strcmp(cmd, "markbad") != 0
172 /* the following commands operate on the current device */
173 if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
174 !nand_info[nand_curr_device].name) {
175 puts("\nno devices available\n");
178 nand = &nand_info[nand_curr_device];
180 if (strcmp(cmd, "bad") == 0) {
181 printf("\nDevice %d bad blocks:\n", nand_curr_device);
182 for (off = 0; off < nand->size; off += nand->erasesize)
183 if (nand_block_isbad(nand, off))
184 printf(" %08x\n", off);
188 if (strcmp(cmd, "erase") == 0
189 #ifdef CONFIG_MTD_NAND_UNSAFE
190 || strcmp(cmd, "scrub") == 0
194 #ifdef CONFIG_MTD_NAND_UNSAFE
195 i = strcmp(cmd, "scrub") == 0; /* 1 scrub, 0 = erase */
198 arg_off_size(argc - 2, argv + 2, &off, &size, nand->size);
199 if (off == 0 && size == 0)
202 printf("\nNAND %s: device %d offset 0x%x, size 0x%x ",
203 #ifdef CONFIG_MTD_NAND_UNSAFE
207 nand_curr_device, off, size);
209 #ifdef CONFIG_MTD_NAND_UNSAFE
211 ret = nand_scrub(nand, off, size);
214 ret = nand_erase(nand, off, size);
216 printf("%s\n", ret ? "ERROR" : "OK");
218 return ret == 0 ? 0 : 1;
221 if (strncmp(cmd, "dump", 4) == 0) {
225 s = strchr(cmd, '.');
226 off = (int)simple_strtoul(argv[2], NULL, 16);
228 if (s != NULL && strcmp(s, ".oob") == 0)
229 ret = nand_dump_oob(nand, off);
231 ret = nand_dump(nand, off);
233 return ret == 0 ? 1 : 0;
238 if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
242 s = strchr(cmd, '.');
245 if (strcmp(s, ".jffs2") == 0 || strcmp(s, ".e") == 0
250 addr = (ulong)simple_strtoul(argv[2], NULL, 16);
252 arg_off_size(argc - 3, argv + 3, &off, &size, nand->size);
253 if (off == 0 && size == 0)
256 i = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
257 printf("\nNAND %s: device %d offset %u, size %u ... ",
258 i ? "read" : "write", nand_curr_device, off, size);
261 ret = nand_read(nand, off, &size, (u_char *)addr);
263 ret = nand_write(nand, off, &size, (u_char *)addr);
265 printf(" %d bytes %s: %s\n", size,
266 i ? "read" : "written", ret ? "ERROR" : "OK");
268 return ret == 0 ? 0 : 1;
270 #ifdef CONFIG_MTD_NAND_UNSAFE
271 if (strcmp(cmd, "markbad") == 0 || strcmp(cmd, "biterr") == 0) {
275 i = strcmp(cmd, "biterr") == 0;
277 off = (int)simple_strtoul(argv[2], NULL, 16);
280 ret = nand_make_bit_error(nand, off);
282 ret = nand_mark_bad(nand, off);
284 return ret == 0 ? 0 : 1;
289 printf("Usage:\n%s\n", cmdtp->usage);
293 U_BOOT_CMD(nand, 5, 1, do_nand,
294 "nand - NAND sub-system\n",
295 "info - show available NAND devices\n"
296 "nand device [dev] - show or set current device\n"
297 "nand read[.jffs2] - addr off size\n"
298 "nand write[.jffs2] - addr off size - read/write `size' bytes starting\n"
299 " at offset `off' to/from memory address `addr'\n"
300 "nand erase [clean] [off size] - erase `size' bytes from\n"
301 " offset `off' (entire device if not specified)\n"
302 "nand bad - show bad blocks\n"
303 "nand dump[.oob] off - dump page\n"
304 "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
305 "nand markbad off - mark bad block at offset (UNSAFE)\n"
306 "nand biterr off - make a bit error at offset (UNSAFE)\n");
308 int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
310 char *boot_device = NULL;
314 ulong addr, cnt, offset = 0;
320 addr = CFG_LOAD_ADDR;
321 boot_device = getenv("bootdevice");
324 addr = simple_strtoul(argv[1], NULL, 16);
325 boot_device = getenv("bootdevice");
328 addr = simple_strtoul(argv[1], NULL, 16);
329 boot_device = argv[2];
332 addr = simple_strtoul(argv[1], NULL, 16);
333 boot_device = argv[2];
334 offset = simple_strtoul(argv[3], NULL, 16);
337 printf("Usage:\n%s\n", cmdtp->usage);
338 SHOW_BOOT_PROGRESS(-1);
343 puts("\n** No boot device **\n");
344 SHOW_BOOT_PROGRESS(-1);
348 dev = simple_strtoul(boot_device, &ep, 16);
350 if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
351 printf("\n** Device %d not available\n", dev);
352 SHOW_BOOT_PROGRESS(-1);
356 nand = &nand_info[dev];
357 printf("\nLoading from device %d: %s (offset 0x%lx)\n",
358 dev, nand->name, offset);
360 cnt = nand->oobblock;
361 r = nand_read(nand, offset, &cnt, (u_char *) addr);
363 printf("** Read error on %d\n", dev);
364 SHOW_BOOT_PROGRESS(-1);
368 hdr = (image_header_t *) addr;
370 if (ntohl(hdr->ih_magic) != IH_MAGIC) {
371 printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
372 SHOW_BOOT_PROGRESS(-1);
376 print_image_hdr(hdr);
378 cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t));
380 r = nand_read(nand, offset, &cnt, (u_char *) addr);
382 printf("** Read error on %d\n", dev);
383 SHOW_BOOT_PROGRESS(-1);
387 /* Loading ok, update default load address */
391 /* Check if we should attempt an auto-start */
392 if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
394 extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
396 local_args[0] = argv[0];
397 local_args[1] = NULL;
399 printf("Automatic boot of image at addr 0x%08lx ...\n", addr);
401 do_bootm(cmdtp, 0, 1, local_args);
407 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
408 "nboot - boot from NAND device\n", "loadAddr dev\n");
411 #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */