⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmd_nand.c

📁 嵌入式试验箱S3C2410的bootloader源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Driver for NAND support, Rick Bronson * borrowed heavily from: * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org> * * Added 16-bit nand support * (C) 2004 Texas Instruments */#include <common.h>#ifndef CFG_NAND_LEGACY/* * * New NAND support * */#include <common.h>#if (CONFIG_COMMANDS & CFG_CMD_NAND)#include <command.h>#include <watchdog.h>#include <malloc.h>#include <asm/byteorder.h>#ifdef CONFIG_SHOW_BOOT_PROGRESS# include <status_led.h># define SHOW_BOOT_PROGRESS(arg)    show_boot_progress(arg)#else# define SHOW_BOOT_PROGRESS(arg)#endif#include <jffs2/jffs2.h>#include <nand.h>#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)/* parition handling routines */int mtdparts_init(void);int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);int find_dev_and_part(const char *id, struct mtd_device **dev,        u8 *part_num, struct part_info **part);#endifextern nand_info_t nand_info[];       /* info for NAND chips */static int nand_dump_oob(nand_info_t *nand, ulong off){    return 0;}static int nand_dump(nand_info_t *nand, ulong off){    int i;    u_char *buf, *p;    buf = malloc(nand->oobblock + nand->oobsize);    if (!buf) {        puts("No memory for page buffer\n");        return 1;    }    off &= ~(nand->oobblock - 1);    i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);    if (i < 0) {        printf("Error (%d) reading page %08x\n", i, off);        free(buf);        return 1;    }    printf("Page %08x dump:\n", off);    i = nand->oobblock >> 4; p = buf;    while (i--) {        printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"            "  %02x %02x %02x %02x %02x %02x %02x %02x\n",            p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],            p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);        p += 16;    }    puts("OOB:\n");    i = nand->oobsize >> 3;    while (i--) {        printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",            p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);        p += 8;    }    free(buf);    return 0;}/* ------------------------------------------------------------------------- */static inline int str2long(char *p, ulong *num){    char *endptr;    *num = simple_strtoul(p, &endptr, 16);    return (*p != '\0' && *endptr == '\0') ? 1 : 0;}static intarg_off_size(int argc, char *argv[], nand_info_t *nand, ulong *off, ulong *size){    int idx = nand_curr_device;#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)    struct mtd_device *dev;    struct part_info *part;    u8 pnum;    if (argc >= 1 && !(str2long(argv[0], off))) {        if ((mtdparts_init() == 0) &&            (find_dev_and_part(argv[0], &dev, &pnum, &part) == 0)) {            if (dev->id->type != MTD_DEV_TYPE_NAND) {                puts("not a NAND device\n");                return -1;            }            *off = part->offset;            if (argc >= 2) {                if (!(str2long(argv[1], size))) {                    printf("'%s' is not a number\n", argv[1]);                    return -1;                }                if (*size > part->size)                    *size = part->size;            } else {                *size = part->size;            }            idx = dev->id->num;            *nand = nand_info[idx];            goto out;        }    }#endif    if (argc >= 1) {        if (!(str2long(argv[0], off))) {            printf("'%s' is not a number\n", argv[0]);            return -1;        }    } else {        *off = 0;    }    if (argc >= 2) {        if (!(str2long(argv[1], size))) {            printf("'%s' is not a number\n", argv[1]);            return -1;        }    } else {        *size = nand->size - *off;    }#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)out:#endif    printf("device %d ", idx);    if (*size == nand->size)        puts("whole chip\n");    else        printf("offset 0x%x, size 0x%x\n", *off, *size);    return 0;}int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){    int i, dev, ret;    ulong addr, off, size;    char *cmd, *s;    nand_info_t *nand;    int quiet = 0;    const char *quiet_str = getenv("quiet");    /* at least two arguments please */    if (argc < 2)        goto usage;    if (quiet_str)        quiet = simple_strtoul(quiet_str, NULL, 0) != 0;    cmd = argv[1];    if (strcmp(cmd, "info") == 0) {        putc('\n');        for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {            if (nand_info[i].name)                printf("Device %d: %s, sector size %lu KiB\n",                    i, nand_info[i].name,                    nand_info[i].erasesize >> 10);        }        return 0;    }    if (strcmp(cmd, "device") == 0) {        if (argc < 3) {            if ((nand_curr_device < 0) ||                (nand_curr_device >= CFG_MAX_NAND_DEVICE))                puts("\nno devices available\n");            else                printf("\nDevice %d: %s\n", nand_curr_device,                    nand_info[nand_curr_device].name);            return 0;        }        dev = (int)simple_strtoul(argv[2], NULL, 10);        if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {            puts("No such device\n");            return 1;        }        printf("Device %d: %s", dev, nand_info[dev].name);        puts("... is now current device\n");        nand_curr_device = dev;#ifdef CFG_NAND_SELECT_DEVICE        /*         * Select the chip in the board/cpu specific driver         */        board_nand_select_device(nand_info[dev].priv, dev);#endif        return 0;    }    if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&        strncmp(cmd, "dump", 4) != 0 &&        strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&        strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&        strcmp(cmd, "biterr") != 0 &&        strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 )        goto usage;    /* the following commands operate on the current device */    if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||        !nand_info[nand_curr_device].name) {        puts("\nno devices available\n");        return 1;    }    nand = &nand_info[nand_curr_device];    if (strcmp(cmd, "bad") == 0) {        printf("\nDevice %d bad blocks:\n", nand_curr_device);        for (off = 0; off < nand->size; off += nand->erasesize)            if (nand_block_isbad(nand, off))                printf("  %08x\n", off);        return 0;    }    /*     * Syntax is:     *   0    1     2       3    4     *   nand erase [clean] [off size]     */    if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) {        nand_erase_options_t opts;        /* "clean" at index 2 means request to write cleanmarker */        int clean = argc > 2 && !strcmp("clean", argv[2]);        int o = clean ? 3 : 2;        int scrub = !strcmp(cmd, "scrub");        printf("\nNAND %s: ", scrub ? "scrub" : "erase");        /* skip first two or three arguments, look for offset and size */        if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0)            return 1;        memset(&opts, 0, sizeof(opts));        opts.offset = off;        opts.length = size;        opts.jffs2  = clean;        opts.quiet  = quiet;        if (scrub) {            puts("Warning: "                 "scrub option will erase all factory set "                 "bad blocks!\n"                 "         "                 "There is no reliable way to recover them.\n"                 "         "                 "Use this command only for testing purposes "                 "if you\n"                 "         "                 "are sure of what you are doing!\n"                 "\nReally scrub this NAND flash? <y/N>\n");            if (getc() == 'y' && getc() == '\r') {                opts.scrub = 1;            } else {                puts("scrub aborted\n");                return -1;            }        }        ret = nand_erase_opts(nand, &opts);        printf("%s\n", ret ? "ERROR" : "OK");        return ret == 0 ? 0 : 1;    }    if (strncmp(cmd, "dump", 4) == 0) {        if (argc < 3)            goto usage;        s = strchr(cmd, '.');        off = (int)simple_strtoul(argv[2], NULL, 16);        if (s != NULL && strcmp(s, ".oob") == 0)            ret = nand_dump_oob(nand, off);        else            ret = nand_dump(nand, off);        return ret == 0 ? 1 : 0;    }    /* read write */    if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {        int read;        if (argc < 4)            goto usage;        addr = (ulong)simple_strtoul(argv[2], NULL, 16);        read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */        printf("\nNAND %s: ", read ? "read" : "write");        if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)            return 1;        s = strchr(cmd, '.');        if (s != NULL &&            (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) {            if (read) {                /* read */                nand_read_options_t opts;                memset(&opts, 0, sizeof(opts));                opts.buffer = (u_char*) addr;                opts.length = size;                opts.offset = off;                opts.quiet      = quiet;                ret = nand_read_opts(nand, &opts);            } else {                /* write */                nand_write_options_t opts;                memset(&opts, 0, sizeof(opts));                opts.buffer = (u_char*) addr;                opts.length = size;                opts.offset = off;                /* opts.forcejffs2 = 1; */                opts.pad    = 1;                opts.blockalign = 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -