diff options
Diffstat (limited to 'nandwrite.c')
-rw-r--r-- | nandwrite.c | 144 |
1 files changed, 49 insertions, 95 deletions
diff --git a/nandwrite.c b/nandwrite.c index 066ef55..a42f7c9 100644 --- a/nandwrite.c +++ b/nandwrite.c @@ -49,12 +49,12 @@ static void display_help(void) "Usage: nandwrite [OPTION] MTD_DEVICE [INPUTFILE|-]\n" "Writes to the specified MTD device.\n" "\n" +" -a, --autoplace Use auto OOB layout\n" " -m, --markbad Mark blocks bad if write fails\n" " -n, --noecc Write without ecc\n" " -N, --noskipbad Write without bad block skipping\n" " -o, --oob Image contains oob data\n" " -O, --onlyoob Image contains oob data and only write the oob part\n" -" -r, --raw Image contains the raw oob data dumped by nanddump\n" " -s addr, --start=addr Set start address (default is 0)\n" " -p, --pad Pad to page size\n" " -b, --blockalign=1|2|4 Set multiple of eraseblocks to align to\n" @@ -86,10 +86,10 @@ static const char *mtd_device, *img; static long long mtdoffset = 0; static bool quiet = false; static bool writeoob = false; -static bool rawoob = false; static bool onlyoob = false; static bool markbad = false; static bool noecc = false; +static bool autoplace = false; static bool noskipbad = false; static bool pad = false; static int blockalign = 1; /* default to using actual block size */ @@ -100,7 +100,7 @@ static void process_options(int argc, char * const argv[]) for (;;) { int option_index = 0; - static const char *short_options = "b:mnNoOpqrs:"; + static const char *short_options = "b:mnNoOpqs:a"; static const struct option long_options[] = { {"help", no_argument, 0, 0}, {"version", no_argument, 0, 0}, @@ -112,8 +112,8 @@ static void process_options(int argc, char * const argv[]) {"onlyoob", no_argument, 0, 'O'}, {"pad", no_argument, 0, 'p'}, {"quiet", no_argument, 0, 'q'}, - {"raw", no_argument, 0, 'r'}, {"start", required_argument, 0, 's'}, + {"autoplace", no_argument, 0, 'a'}, {0, 0, 0, 0}, }; @@ -156,16 +156,15 @@ static void process_options(int argc, char * const argv[]) case 'p': pad = true; break; - case 'r': - rawoob = true; - writeoob = true; - break; case 's': mtdoffset = simple_strtoll(optarg, &error); break; case 'b': blockalign = atoi(optarg); break; + case 'a': + autoplace = true; + break; case '?': error++; break; @@ -180,6 +179,12 @@ static void process_options(int argc, char * const argv[]) errmsg_die("Can't specify negative blockalign with option -b:" " %d", blockalign); + if (autoplace && noecc) + errmsg_die("Autoplacement and no-ECC are mutually exclusive"); + + if (!onlyoob && (pad && writeoob)) + errmsg_die("Can't pad when oob data is present"); + argc -= optind; argv += optind; @@ -233,30 +238,23 @@ int main(int argc, char * const argv[]) /* points to the current page inside filebuf */ unsigned char *writebuf = NULL; /* points to the OOB for the current page in filebuf */ - unsigned char *oobreadbuf = NULL; unsigned char *oobbuf = NULL; libmtd_t mtd_desc; int ebsize_aligned; + uint8_t write_mode; process_options(argc, argv); - if (!onlyoob && (pad && writeoob)) { - fprintf(stderr, "Can't pad when oob data is present.\n"); - exit(EXIT_FAILURE); - } - /* Open the device */ - if ((fd = open(mtd_device, O_RDWR)) == -1) { - perror(mtd_device); - exit(EXIT_FAILURE); - } + if ((fd = open(mtd_device, O_RDWR)) == -1) + sys_errmsg_die("%s", mtd_device); mtd_desc = libmtd_open(); if (!mtd_desc) - return errmsg("can't initialize libmtd"); + errmsg_die("can't initialize libmtd"); /* Fill in MTD device capability structure */ if (mtd_get_dev_info(mtd_desc, mtd_device, &mtd) < 0) - return errmsg("mtd_get_dev_info failed"); + errmsg_die("mtd_get_dev_info failed"); /* * Pretend erasesize is specified number of blocks - to match jffs2 @@ -265,24 +263,27 @@ int main(int argc, char * const argv[]) */ ebsize_aligned = mtd.eb_size * blockalign; - if (mtdoffset & (mtd.min_io_size - 1)) { - fprintf(stderr, "The start address is not page-aligned !\n" - "The pagesize of this NAND Flash is 0x%x.\n", - mtd.min_io_size); - close(fd); - exit(EXIT_FAILURE); - } + if (mtdoffset & (mtd.min_io_size - 1)) + errmsg_die("The start address is not page-aligned !\n" + "The pagesize of this NAND Flash is 0x%x.\n", + mtd.min_io_size); + + /* Select OOB write mode */ + if (noecc) + write_mode = MTD_OPS_RAW; + else if (autoplace) + write_mode = MTD_OPS_AUTO_OOB; + else + write_mode = MTD_OPS_PLACE_OOB; if (noecc) { - ret = ioctl(fd, MTDFILEMODE, MTD_MODE_RAW); + ret = ioctl(fd, MTDFILEMODE, MTD_FILE_MODE_RAW); if (ret) { switch (errno) { case ENOTTY: errmsg_die("ioctl MTDFILEMODE is missing"); default: - perror("MTDFILEMODE"); - close(fd); - exit(EXIT_FAILURE); + sys_errmsg_die("MTDFILEMODE"); } } } @@ -331,7 +332,7 @@ int main(int argc, char * const argv[]) fprintf(stderr, "Image %d bytes, NAND page %d bytes, OOB area %d" " bytes, device size %lld bytes\n", imglen, pagelen, mtd.oob_size, mtd.size); - perror("Input file does not fit into device"); + sys_errmsg("Input file does not fit into device"); goto closeall; } @@ -345,9 +346,6 @@ int main(int argc, char * const argv[]) filebuf = xmalloc(filebuf_max); erase_buffer(filebuf, filebuf_max); - oobbuf = xmalloc(mtd.oob_size); - erase_buffer(oobbuf, mtd.oob_size); - /* * Get data from input and write to the device while there is * still input to read and we are still within the device @@ -460,16 +458,16 @@ int main(int argc, char * const argv[]) } if (writeoob) { - oobreadbuf = writebuf + mtd.min_io_size; + oobbuf = writebuf + mtd.min_io_size; /* Read more data for the OOB from the input if there isn't enough in the buffer */ - if ((oobreadbuf + mtd.oob_size) > (filebuf + filebuf_len)) { + if ((oobbuf + mtd.oob_size) > (filebuf + filebuf_len)) { int readlen = mtd.oob_size; - int alreadyread = (filebuf + filebuf_len) - oobreadbuf; + int alreadyread = (filebuf + filebuf_len) - oobbuf; int tinycnt = alreadyread; while (tinycnt < readlen) { - cnt = read(ifd, oobreadbuf + tinycnt, readlen - tinycnt); + cnt = read(ifd, oobbuf + tinycnt, readlen - tinycnt); if (cnt == 0) { /* EOF */ break; } else if (cnt < 0) { @@ -494,57 +492,17 @@ int main(int argc, char * const argv[]) imglen = 0; } } - - if (!noecc) { - int start, len; - struct nand_oobinfo old_oobinfo; - - /* Read the current oob info */ - if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo) != 0) { - perror("MEMGETOOBSEL"); - close(fd); - exit(EXIT_FAILURE); - } - - /* - * We use autoplacement and have the oobinfo with the autoplacement - * information from the kernel available - * - * Modified to support out of order oobfree segments, - * such as the layout used by diskonchip.c - */ - if (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) { - int i, tags_pos = 0, tmp_ofs; - for (i = 0; old_oobinfo.oobfree[i][1]; i++) { - /* Set the reserved bytes to 0xff */ - start = old_oobinfo.oobfree[i][0]; - len = old_oobinfo.oobfree[i][1]; - tmp_ofs = rawoob ? start : tags_pos; - memcpy(oobbuf + start, oobreadbuf + tmp_ofs, len); - tags_pos += len; - } - } else { - /* Set at least the ecc byte positions to 0xff */ - start = old_oobinfo.eccbytes; - len = mtd.oob_size - start; - memcpy(oobbuf + start, - oobreadbuf + start, - len); - } - } else { - memcpy(oobbuf, oobreadbuf, mtd.oob_size); - } - /* Write OOB data first, as ecc will be placed in there */ - if (mtd_write_oob(mtd_desc, &mtd, fd, mtdoffset, - mtd.oob_size, oobbuf)) { - sys_errmsg("%s: MTD writeoob failure", mtd_device); - goto closeall; - } } - /* Write out the Page data */ - if (!onlyoob && mtd_write(&mtd, fd, mtdoffset / mtd.eb_size, mtdoffset % mtd.eb_size, - writebuf, mtd.min_io_size)) { + /* Write out data */ + ret = mtd_write(mtd_desc, &mtd, fd, mtdoffset / mtd.eb_size, + mtdoffset % mtd.eb_size, + onlyoob ? NULL : writebuf, + onlyoob ? 0 : mtd.min_io_size, + writeoob ? oobbuf : NULL, + writeoob ? mtd.oob_size : 0, + write_mode); + if (ret) { int i; if (errno != EIO) { sys_errmsg("%s: MTD write failure", mtd_device); @@ -588,15 +546,11 @@ closeall: close(ifd); libmtd_close(mtd_desc); free(filebuf); - free(oobbuf); close(fd); - if (failed - || ((ifd != STDIN_FILENO) && (imglen > 0)) - || (writebuf < (filebuf + filebuf_len))) { - perror("Data was only partially written due to error\n"); - exit(EXIT_FAILURE); - } + if (failed || ((ifd != STDIN_FILENO) && (imglen > 0)) + || (writebuf < (filebuf + filebuf_len))) + sys_errmsg_die("Data was only partially written due to error"); /* Return happy */ return EXIT_SUCCESS; |