📄 cmd_nand.c.l
字号:
679 * bad. This can be very handy if you are _sure_ that the block680 * is OK, say because you marked a good block bad to test bad681 * block handling and you are done testing, or if you have682 * accidentally marked blocks bad.683 *684 * Erasing factory marked bad blocks is a _bad_ idea. If the685 * erase succeeds there is no reliable way to find them again,686 * and attempting to program or erase bad blocks can affect687 * the data in _other_ (good) blocks.688 */689 #define ALLOW_ERASE_BAD_DEBUG 0690 691 #define CONFIG_MTD_NAND_ECC /* enable ECC */692 #define CONFIG_MTD_NAND_ECC_JFFS2693 694 /* bits for nand_legacy_rw() `cmd'; or together as needed */695 #define NANDRW_READ 0x01696 #define NANDRW_WRITE 0x00697 #define NANDRW_JFFS2 0x02698 #define NANDRW_JFFS2_SKIP 0x04699 700 /*701 * Imports from nand_legacy.c702 */703 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];704 extern int curr_device;705 extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs,706 size_t len, int clean);707 extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start,708 size_t len, size_t *retlen, u_char *buf);709 extern void nand_print(struct nand_chip *nand);710 extern void nand_print_bad(struct nand_chip *nand);711 extern int nand_read_oob(struct nand_chip *nand, size_t ofs,712 size_t len, size_t *retlen, u_char *buf);713 extern int nand_write_oob(struct nand_chip *nand, size_t ofs,714 size_t len, size_t *retlen, const u_char *buf);715 716 717 int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])718 {719 int rcode = 0;720 721 switch (argc) {722 case 0:723 case 1:724 printf ("Usage:\n%s\n", cmdtp->usage);725 return 1;726 case 2:727 if (strcmp(argv[1],"info") == 0) {728 int i;729 730 putc ('\n');731 732 for (i=0; i<CFG_MAX_NAND_DEVICE; ++i) {733 if(nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN)734 continue; /* list only known devices */735 printf ("Device %d: ", i);736 nand_print(&nand_dev_desc[i]);737 }738 return 0;739 740 } else if (strcmp(argv[1],"device") == 0) {741 if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {742 puts ("\nno devices available\n");743 return 1;744 }745 printf ("\nDevice %d: ", curr_device);746 nand_print(&nand_dev_desc[curr_device]);747 return 0;748 749 } else if (strcmp(argv[1],"bad") == 0) {750 if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {751 puts ("\nno devices available\n");752 return 1;753 }754 printf ("\nDevice %d bad blocks:\n", curr_device);755 nand_print_bad(&nand_dev_desc[curr_device]);756 return 0;757 758 }759 printf ("Usage:\n%s\n", cmdtp->usage);760 return 1;761 case 3:762 if (strcmp(argv[1],"device") == 0) {763 int dev = (int)simple_strtoul(argv[2], NULL, 10);764 765 printf ("\nDevice %d: ", dev);766 if (dev >= CFG_MAX_NAND_DEVICE) {767 puts ("unknown device\n");768 return 1;769 }770 nand_print(&nand_dev_desc[dev]);771 /*nand_print (dev);*/772 773 if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) {774 return 1;775 }776 777 curr_device = dev;778 779 puts ("... is now current device\n");780 781 return 0;782 }783 else if (strcmp(argv[1],"erase") == 0 && strcmp(argv[2], "clean") == 0) {784 struct nand_chip* nand = &nand_dev_desc[curr_device];785 ulong off = 0;786 ulong size = nand->totlen;787 int ret;788 789 printf ("\nNAND erase: device %d offset %ld, size %ld ... ",790 curr_device, off, size);791 792 ret = nand_legacy_erase (nand, off, size, 1);793 794 printf("%s\n", ret ? "ERROR" : "OK");795 796 return ret;797 }798 799 printf ("Usage:\n%s\n", cmdtp->usage);800 return 1;801 default:802 /* at least 4 args */803 804 if (strncmp(argv[1], "read", 4) == 0 ||805 strncmp(argv[1], "write", 5) == 0) {806 ulong addr = simple_strtoul(argv[2], NULL, 16);807 ulong off = simple_strtoul(argv[3], NULL, 16);808 ulong size = simple_strtoul(argv[4], NULL, 16);809 int cmd = (strncmp(argv[1], "read", 4) == 0) ?810 NANDRW_READ : NANDRW_WRITE;811 int ret, total;812 char* cmdtail = strchr(argv[1], '.');813 814 if (cmdtail && !strncmp(cmdtail, ".oob", 2)) {815 /* read out-of-band data */816 if (cmd & NANDRW_READ) {817 ret = nand_read_oob(nand_dev_desc + curr_device,818 off, size, (size_t *)&total,819 (u_char*)addr);820 }821 else {822 ret = nand_write_oob(nand_dev_desc + curr_device,823 off, size, (size_t *)&total,824 (u_char*)addr);825 }826 return ret;827 }828 else if (cmdtail && !strncmp(cmdtail, ".jffs2", 2))829 cmd |= NANDRW_JFFS2; /* skip bad blocks */830 else if (cmdtail && !strncmp(cmdtail, ".jffs2s", 2)) {831 cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */832 if (cmd & NANDRW_READ)833 cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */834 }835 #ifdef SXNI855T836 /* need ".e" same as ".j" for compatibility with older units */837 else if (cmdtail && !strcmp(cmdtail, ".e"))838 cmd |= NANDRW_JFFS2; /* skip bad blocks */839 #endif840 #ifdef CFG_NAND_SKIP_BAD_DOT_I841 /* need ".i" same as ".jffs2s" for compatibility with older units (esd) */842 /* ".i" for image -> read skips bad block (no 0xff) */843 else if (cmdtail && !strcmp(cmdtail, ".i")) {844 cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */845 if (cmd & NANDRW_READ)846 cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */847 }848 #endif /* CFG_NAND_SKIP_BAD_DOT_I */849 else if (cmdtail) {850 printf ("Usage:\n%s\n", cmdtp->usage);851 return 1;852 }853 854 printf ("\nNAND %s: device %d offset %ld, size %ld ...\n",855 (cmd & NANDRW_READ) ? "read" : "write",856 curr_device, off, size);857 858 ret = nand_legacy_rw(nand_dev_desc + curr_device, cmd, off, size,859 (size_t *)&total, (u_char*)addr);860 861 printf (" %d bytes %s: %s\n", total,862 (cmd & NANDRW_READ) ? "read" : "written",863 ret ? "ERROR" : "OK");864 865 return ret;866 } else if (strcmp(argv[1],"erase") == 0 &&867 (argc == 4 || strcmp("clean", argv[2]) == 0)) {868 int clean = argc == 5;869 ulong off = simple_strtoul(argv[2 + clean], NULL, 16);870 ulong size = simple_strtoul(argv[3 + clean], NULL, 16);871 int ret;872 873 printf ("\nNAND erase: device %d offset %ld, size %ld ...\n",874 curr_device, off, size);875 876 ret = nand_legacy_erase (nand_dev_desc + curr_device,877 off, size, clean);878 879 printf("%s\n", ret ? "ERROR" : "OK");880 881 return ret;882 } else {883 printf ("Usage:\n%s\n", cmdtp->usage);884 rcode = 1;885 }886 887 return rcode;888 }889 }890 891 U_BOOT_CMD(892 nand, 5, 1, do_nand,893 "nand - legacy NAND sub-system\n",894 "info - show available NAND devices\n"895 "nand device [dev] - show or set current device\n"896 "nand read[.jffs2[s]] addr off size\n"897 "nand write[.jffs2] addr off size - read/write `size' bytes starting\n"898 " at offset `off' to/from memory address `addr'\n"899 "nand erase [clean] [off size] - erase `size' bytes from\n"900 " offset `off' (entire device if not specified)\n"901 "nand bad - show bad blocks\n"902 "nand read.oob addr off size - read out-of-band data\n"903 "nand write.oob addr off size - read out-of-band data\n"904 );905 906 int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])907 {908 char *boot_device = NULL;909 char *ep;910 int dev;911 ulong cnt;912 ulong addr;913 ulong offset = 0;914 image_header_t *hdr;915 int rcode = 0;916 switch (argc) {917 case 1:918 addr = CFG_LOAD_ADDR;919 boot_device = getenv ("bootdevice");920 break;921 case 2:922 addr = simple_strtoul(argv[1], NULL, 16);923 boot_device = getenv ("bootdevice");924 break;925 case 3:926 addr = simple_strtoul(argv[1], NULL, 16);927 boot_device = argv[2];928 break;929 case 4:930 addr = simple_strtoul(argv[1], NULL, 16);931 boot_device = argv[2];932 offset = simple_strtoul(argv[3], NULL, 16);933 break;934 default:935 printf ("Usage:\n%s\n", cmdtp->usage);936 SHOW_BOOT_PROGRESS (-1);937 return 1;938 }939 940 if (!boot_device) {941 puts ("\n** No boot device **\n");942 SHOW_BOOT_PROGRESS (-1);943 return 1;944 }945 946 dev = simple_strtoul(boot_device, &ep, 16);947 948 if ((dev >= CFG_MAX_NAND_DEVICE) ||949 (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) {950 printf ("\n** Device %d not available\n", dev);951 SHOW_BOOT_PROGRESS (-1);952 return 1;953 }954 955 printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",956 dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,957 offset);958 959 if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset,960 SECTORSIZE, NULL, (u_char *)addr)) {961 printf ("** Read error on %d\n", dev);962 SHOW_BOOT_PROGRESS (-1);963 return 1;964 }965 966 hdr = (image_header_t *)addr;967 968 if (ntohl(hdr->ih_magic) == IH_MAGIC) {969 970 print_image_hdr (hdr);971 972 cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));973 cnt -= SECTORSIZE;974 } else {975 printf ("\n** Bad Magic Number 0x%x **\n", ntohl(hdr->ih_magic));976 SHOW_BOOT_PROGRESS (-1);977 return 1;978 }979 980 if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ,981 offset + SECTORSIZE, cnt, NULL,982 (u_char *)(addr+SECTORSIZE))) {983 printf ("** Read error on %d\n", dev);984 SHOW_BOOT_PROGRESS (-1);985 return 1;986 }987 988 /* Loading ok, update default load address */989 990 load_addr = addr;991 992 /* Check if we should attempt an auto-start */993 if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {994 char *local_args[2];995 extern int do_bootm (cmd_tbl_t *, int, int, char *[]);996 997 local_args[0] = argv[0];998 local_args[1] = NULL;999 1000 printf ("Automatic boot of image at addr 0x%08lx ...\n", addr);1001 1002 do_bootm (cmdtp, 0, 1, local_args);1003 rcode = 1;1004 }1005 return rcode;1006 }1007 1008 U_BOOT_CMD(1009 nboot, 4, 1, do_nandboot,1010 "nboot - boot from NAND device\n",1011 "loadAddr dev\n"1012 );1013 1014 #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */1015 1016 #endif /* CFG_NAND_LEGACY */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -