cmd_nand_new.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. #include <common.h>
  2. #if (CONFIG_COMMANDS & CFG_CMD_NAND) && defined CONFIG_NEW_NAND_CODE
  3. #include <command.h>
  4. #include <watchdog.h>
  5. #include <malloc.h>
  6. #include <asm/byteorder.h>
  7. #ifdef CONFIG_SHOW_BOOT_PROGRESS
  8. # include <status_led.h>
  9. # define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
  10. #else
  11. # define SHOW_BOOT_PROGRESS(arg)
  12. #endif
  13. #include <jffs2/jffs2.h>
  14. #include <nand.h>
  15. extern nand_info_t nand_info[]; /* info for NAND chips */
  16. static int nand_dump_oob(nand_info_t *nand, ulong off)
  17. {
  18. return 0;
  19. }
  20. static int nand_dump(nand_info_t *nand, ulong off)
  21. {
  22. int i;
  23. u_char *buf, *p;
  24. buf = malloc(nand->oobblock + nand->oobsize);
  25. if (!buf) {
  26. puts("No memory for page buffer\n");
  27. return 1;
  28. }
  29. off &= ~(nand->oobblock - 1);
  30. i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
  31. if (i < 0) {
  32. printf("Error (%d) reading page %08x\n", i, off);
  33. free(buf);
  34. return 1;
  35. }
  36. printf("Page %08x dump:\n", off);
  37. i = nand->oobblock >> 4; p = buf;
  38. while (i--) {
  39. printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
  40. " %02x %02x %02x %02x %02x %02x %02x %02x\n",
  41. p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
  42. p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
  43. p += 16;
  44. }
  45. puts("OOB:\n");
  46. i = nand->oobsize >> 3;
  47. while (i--) {
  48. printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
  49. p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
  50. p += 8;
  51. }
  52. free(buf);
  53. return 0;
  54. }
  55. /* ------------------------------------------------------------------------- */
  56. static void
  57. arg_off_size(int argc, char *argv[], ulong *off, ulong *size, ulong totsize)
  58. {
  59. *off = 0;
  60. *size = 0;
  61. #if defined(CONFIG_JFFS2_NAND) && defined(CFG_JFFS_CUSTOM_PART)
  62. if (argc >= 1 && strcmp(argv[0], "partition") == 0) {
  63. int part_num;
  64. struct part_info *part;
  65. const char *partstr;
  66. if (argc >= 2)
  67. partstr = argv[1];
  68. else
  69. partstr = getenv("partition");
  70. if (partstr)
  71. part_num = (int)simple_strtoul(partstr, NULL, 10);
  72. else
  73. part_num = 0;
  74. part = jffs2_part_info(part_num);
  75. if (part == NULL) {
  76. printf("\nInvalid partition %d\n", part_num);
  77. return;
  78. }
  79. *size = part->size;
  80. *off = (ulong)part->offset;
  81. } else
  82. #endif
  83. {
  84. if (argc >= 1)
  85. *off = (ulong)simple_strtoul(argv[0], NULL, 16);
  86. else
  87. *off = 0;
  88. if (argc >= 2)
  89. *size = (ulong)simple_strtoul(argv[1], NULL, 16);
  90. else
  91. *size = totsize - *off;
  92. }
  93. }
  94. int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
  95. {
  96. int i, dev, ret;
  97. ulong addr, off, size;
  98. char *cmd, *s;
  99. nand_info_t *nand;
  100. /* at least two arguments please */
  101. if (argc < 2)
  102. goto usage;
  103. cmd = argv[1];
  104. if (strcmp(cmd, "info") == 0) {
  105. putc('\n');
  106. for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
  107. if (nand_info[i].name)
  108. printf("Device %d: %s\n", i, nand_info[i].name);
  109. }
  110. return 0;
  111. }
  112. if (strcmp(cmd, "device") == 0) {
  113. if (argc < 3) {
  114. if ((nand_curr_device < 0) ||
  115. (nand_curr_device >= CFG_MAX_NAND_DEVICE))
  116. puts("\nno devices available\n");
  117. else
  118. printf("\nDevice %d: %s\n", nand_curr_device,
  119. nand_info[nand_curr_device].name);
  120. return 0;
  121. }
  122. dev = (int)simple_strtoul(argv[2], NULL, 10);
  123. if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
  124. puts("No such device\n");
  125. return 1;
  126. }
  127. printf("Device %d: %s", dev, nand_info[dev].name);
  128. puts("... is now current device\n");
  129. nand_curr_device = dev;
  130. return 0;
  131. }
  132. if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
  133. strncmp(cmd, "dump", 4) != 0 &&
  134. strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0)
  135. goto usage;
  136. /* the following commands operate on the current device */
  137. if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
  138. !nand_info[nand_curr_device].name) {
  139. puts("\nno devices available\n");
  140. return 1;
  141. }
  142. nand = &nand_info[nand_curr_device];
  143. if (strcmp(cmd, "bad") == 0) {
  144. printf("\nDevice %d bad blocks:\n", nand_curr_device);
  145. for (off = 0; off < nand->size; off += nand->erasesize)
  146. if (nand_block_isbad(nand, off))
  147. printf(" %08x\n", off);
  148. return 0;
  149. }
  150. if (strcmp(cmd, "erase") == 0) {
  151. arg_off_size(argc - 2, argv + 2, &off, &size, nand->size);
  152. if (off == 0 && size == 0)
  153. return 1;
  154. printf("\nNAND erase: device %d offset 0x%x, size 0x%x ",
  155. nand_curr_device, off, size);
  156. ret = nand_erase(nand, off, size);
  157. printf("%s\n", ret ? "ERROR" : "OK");
  158. return ret == 0 ? 0 : 1;
  159. }
  160. if (strncmp(cmd, "dump", 4) == 0) {
  161. if (argc < 3)
  162. goto usage;
  163. s = strchr(cmd, '.');
  164. off = (int)simple_strtoul(argv[2], NULL, 16);
  165. if (s != NULL && strcmp(s, ".oob") == 0)
  166. ret = nand_dump_oob(nand, off);
  167. else
  168. ret = nand_dump(nand, off);
  169. return ret == 0 ? 1 : 0;
  170. }
  171. /* read write */
  172. if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
  173. if (argc < 4)
  174. goto usage;
  175. /*
  176. s = strchr(cmd, '.');
  177. clean = CLEAN_NONE;
  178. if (s != NULL) {
  179. if (strcmp(s, ".jffs2") == 0 || strcmp(s, ".e") == 0
  180. || strcmp(s, ".i"))
  181. clean = CLEAN_JFFS2;
  182. }
  183. */
  184. addr = (ulong)simple_strtoul(argv[2], NULL, 16);
  185. arg_off_size(argc - 3, argv + 3, &off, &size, nand->size);
  186. if (off == 0 && size == 0)
  187. return 1;
  188. i = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
  189. printf("\nNAND %s: device %d offset %u, size %u ... ",
  190. i ? "read" : "write", nand_curr_device, off, size);
  191. if (i)
  192. ret = nand_read(nand, off, &size, (u_char *)addr);
  193. else
  194. ret = nand_write(nand, off, &size, (u_char *)addr);
  195. printf(" %d bytes %s: %s\n", size,
  196. i ? "read" : "written", ret ? "ERROR" : "OK");
  197. return ret == 0 ? 0 : 1;
  198. }
  199. usage:
  200. printf("Usage:\n%s\n", cmdtp->usage);
  201. return 1;
  202. }
  203. U_BOOT_CMD(nand, 5, 1, do_nand,
  204. "nand - NAND sub-system\n",
  205. "info - show available NAND devices\n"
  206. "nand device [dev] - show or set current device\n"
  207. "nand read[.jffs2] - addr off size\n"
  208. "nand write[.jffs2] - addr off size - read/write `size' bytes starting\n"
  209. " at offset `off' to/from memory address `addr'\n"
  210. "nand erase [clean] [off size] - erase `size' bytes from\n"
  211. " offset `off' (entire device if not specified)\n"
  212. "nand bad - show bad blocks\n"
  213. "nand dump[.oob] off - dump page\n"
  214. "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
  215. "nand markbad off - mark bad block at offset (UNSAFE)\n"
  216. "nand biterr off - make a bit error at offset (UNSAFE)\n");
  217. int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
  218. {
  219. char *boot_device = NULL;
  220. char *ep;
  221. int dev;
  222. int r;
  223. ulong addr, cnt, offset = 0;
  224. image_header_t *hdr;
  225. nand_info_t *nand;
  226. switch (argc) {
  227. case 1:
  228. addr = CFG_LOAD_ADDR;
  229. boot_device = getenv("bootdevice");
  230. break;
  231. case 2:
  232. addr = simple_strtoul(argv[1], NULL, 16);
  233. boot_device = getenv("bootdevice");
  234. break;
  235. case 3:
  236. addr = simple_strtoul(argv[1], NULL, 16);
  237. boot_device = argv[2];
  238. break;
  239. case 4:
  240. addr = simple_strtoul(argv[1], NULL, 16);
  241. boot_device = argv[2];
  242. offset = simple_strtoul(argv[3], NULL, 16);
  243. break;
  244. default:
  245. printf("Usage:\n%s\n", cmdtp->usage);
  246. SHOW_BOOT_PROGRESS(-1);
  247. return 1;
  248. }
  249. if (!boot_device) {
  250. puts("\n** No boot device **\n");
  251. SHOW_BOOT_PROGRESS(-1);
  252. return 1;
  253. }
  254. dev = simple_strtoul(boot_device, &ep, 16);
  255. if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
  256. printf("\n** Device %d not available\n", dev);
  257. SHOW_BOOT_PROGRESS(-1);
  258. return 1;
  259. }
  260. nand = &nand_info[dev];
  261. printf("\nLoading from device %d: %s (offset 0x%lx)\n",
  262. dev, nand->name, offset);
  263. cnt = nand->oobblock;
  264. r = nand_read(nand, offset, &cnt, (u_char *) addr);
  265. if (r) {
  266. printf("** Read error on %d\n", dev);
  267. SHOW_BOOT_PROGRESS(-1);
  268. return 1;
  269. }
  270. hdr = (image_header_t *) addr;
  271. if (ntohl(hdr->ih_magic) != IH_MAGIC) {
  272. printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
  273. SHOW_BOOT_PROGRESS(-1);
  274. return 1;
  275. }
  276. print_image_hdr(hdr);
  277. cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t));
  278. r = nand_read(nand, offset, &cnt, (u_char *) addr);
  279. if (r) {
  280. printf("** Read error on %d\n", dev);
  281. SHOW_BOOT_PROGRESS(-1);
  282. return 1;
  283. }
  284. /* Loading ok, update default load address */
  285. load_addr = addr;
  286. /* Check if we should attempt an auto-start */
  287. if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
  288. char *local_args[2];
  289. extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
  290. local_args[0] = argv[0];
  291. local_args[1] = NULL;
  292. printf("Automatic boot of image at addr 0x%08lx ...\n", addr);
  293. do_bootm(cmdtp, 0, 1, local_args);
  294. return 1;
  295. }
  296. return 0;
  297. }
  298. U_BOOT_CMD(nboot, 4, 1, do_nandboot,
  299. "nboot - boot from NAND device\n", "loadAddr dev\n");
  300. #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */