diff options
-rw-r--r-- | include/libmtd.h | 15 | ||||
-rw-r--r-- | include/mtd/mtd-abi.h | 122 | ||||
-rw-r--r-- | lib/libmtd.c | 86 | ||||
-rw-r--r-- | nanddump.c | 2 | ||||
-rw-r--r-- | nandwrite.c | 144 | ||||
-rw-r--r-- | ubi-utils/ubiformat.c | 6 |
6 files changed, 245 insertions, 130 deletions
diff --git a/include/libmtd.h b/include/libmtd.h index 9efccbc..07c304a 100644 --- a/include/libmtd.h +++ b/include/libmtd.h @@ -255,19 +255,26 @@ int mtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs, /** * mtd_write - write data to an MTD device. + * @desc: MTD library descriptor * @mtd: MTD device description object * @fd: MTD device node file descriptor * @eb: eraseblock to write to * @offs: offset withing the eraseblock to write to - * @buf: buffer to write - * @len: how many bytes to write + * @data: data buffer to write + * @len: how many data bytes to write + * @oob: OOB buffer to write + * @ooblen: how many OOB bytes to write + * @mode: write mode (e.g., %MTD_OOB_PLACE, %MTD_OOB_RAW) * * This function writes @len bytes of data to eraseblock @eb and offset @offs * of the MTD device defined by @mtd. Returns %0 in case of success and %-1 in * case of failure. + * + * Can only write to a single page at a time if writing to OOB. */ -int mtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs, - void *buf, int len); +int mtd_write(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb, + int offs, void *data, int len, void *oob, int ooblen, + uint8_t mode); /** * mtd_read_oob - read out-of-band area. diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index a86364a..4de167b 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h @@ -45,6 +45,51 @@ struct mtd_oob_buf64 { __u64 usr_ptr; }; +/** + * MTD operation modes + * + * @MTD_OPS_PLACE_OOB: OOB data are placed at the given offset (default) + * @MTD_OPS_AUTO_OOB: OOB data are automatically placed at the free areas + * which are defined by the internal ecclayout + * @MTD_OPS_RAW: data are transferred as-is, with no error correction; + * this mode implies %MTD_OPS_PLACE_OOB + * + * These modes can be passed to ioctl(MEMWRITE) and are also used internally. + * See notes on "MTD file modes" for discussion on %MTD_OPS_RAW vs. + * %MTD_FILE_MODE_RAW. + */ +enum { + MTD_OPS_PLACE_OOB = 0, + MTD_OPS_AUTO_OOB = 1, + MTD_OPS_RAW = 2, +}; + +/** + * struct mtd_write_req - data structure for requesting a write operation + * + * @start: start address + * @len: length of data buffer + * @ooblen: length of OOB buffer + * @usr_data: user-provided data buffer + * @usr_oob: user-provided OOB buffer + * @mode: MTD mode (see "MTD operation modes") + * @padding: reserved, must be set to 0 + * + * This structure supports ioctl(MEMWRITE) operations, allowing data and/or OOB + * writes in various modes. To write to OOB-only, set @usr_data == NULL, and to + * write data-only, set @usr_oob == NULL. However, setting both @usr_data and + * @usr_oob to NULL is not allowed. + */ +struct mtd_write_req { + __u64 start; + __u64 len; + __u64 ooblen; + __u64 usr_data; + __u64 usr_oob; + __u8 mode; + __u8 padding[7]; +}; + #define MTD_ABSENT 0 #define MTD_RAM 1 #define MTD_ROM 2 @@ -59,13 +104,13 @@ struct mtd_oob_buf64 { #define MTD_NO_ERASE 0x1000 /* No erase necessary */ #define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */ -// Some common devices / combinations of capabilities +/* Some common devices / combinations of capabilities */ #define MTD_CAP_ROM 0 #define MTD_CAP_RAM (MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE) #define MTD_CAP_NORFLASH (MTD_WRITEABLE | MTD_BIT_WRITEABLE) #define MTD_CAP_NANDFLASH (MTD_WRITEABLE) -/* ECC byte placement */ +/* Obsolete ECC byte placement modes (used with obsolete MEMGETOOBSEL) */ #define MTD_NANDECC_OFF 0 // Switch off ECC (Not recommended) #define MTD_NANDECC_PLACE 1 // Use the given placement in the structure (YAFFS1 legacy mode) #define MTD_NANDECC_AUTOPLACE 2 // Use the default placement scheme @@ -80,21 +125,18 @@ struct mtd_oob_buf64 { struct mtd_info_user { __u8 type; __u32 flags; - __u32 size; // Total size of the MTD + __u32 size; /* Total size of the MTD */ __u32 erasesize; __u32 writesize; - __u32 oobsize; // Amount of OOB data per block (e.g. 16) - /* The below two fields are obsolete and broken, do not use them - * (TODO: remove at some point) */ - __u32 ecctype; - __u32 eccsize; + __u32 oobsize; /* Amount of OOB data per block (e.g. 16) */ + __u64 padding; /* Old obsolete field; do not use */ }; struct region_info_user { __u32 offset; /* At which this region starts, - * from the beginning of the MTD */ - __u32 erasesize; /* For this region */ - __u32 numblocks; /* Number of blocks in this region */ + * from the beginning of the MTD */ + __u32 erasesize; /* For this region */ + __u32 numblocks; /* Number of blocks in this region */ __u32 regionindex; }; @@ -104,29 +146,61 @@ struct otp_info { __u32 locked; }; +/* + * Note, the following ioctl existed in the past and was removed: + * #define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo) + * Try to avoid adding a new ioctl with the same ioctl number. + */ + +/* Get basic MTD characteristics info (better to use sysfs) */ #define MEMGETINFO _IOR('M', 1, struct mtd_info_user) +/* Erase segment of MTD */ #define MEMERASE _IOW('M', 2, struct erase_info_user) +/* Write out-of-band data from MTD */ #define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf) +/* Read out-of-band data from MTD */ #define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf) +/* Lock a chip (for MTD that supports it) */ #define MEMLOCK _IOW('M', 5, struct erase_info_user) +/* Unlock a chip (for MTD that supports it) */ #define MEMUNLOCK _IOW('M', 6, struct erase_info_user) +/* Get the number of different erase regions */ #define MEMGETREGIONCOUNT _IOR('M', 7, int) +/* Get information about the erase region for a specific index */ #define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) -#define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo) +/* Get info about OOB modes (e.g., RAW, PLACE, AUTO) - legacy interface */ #define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo) +/* Check if an eraseblock is bad */ #define MEMGETBADBLOCK _IOW('M', 11, __kernel_loff_t) +/* Mark an eraseblock as bad */ #define MEMSETBADBLOCK _IOW('M', 12, __kernel_loff_t) +/* Set OTP (One-Time Programmable) mode (factory vs. user) */ #define OTPSELECT _IOR('M', 13, int) +/* Get number of OTP (One-Time Programmable) regions */ #define OTPGETREGIONCOUNT _IOW('M', 14, int) +/* Get all OTP (One-Time Programmable) info about MTD */ #define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) +/* Lock a given range of user data (must be in mode %MTD_FILE_MODE_OTP_USER) */ #define OTPLOCK _IOR('M', 16, struct otp_info) +/* Get ECC layout (deprecated) */ #define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout_user) +/* Get statistics about corrected/uncorrected errors */ #define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) +/* Set MTD mode on a per-file-descriptor basis (see "MTD file modes") */ #define MTDFILEMODE _IO('M', 19) +/* Erase segment of MTD (supports 64-bit address) */ #define MEMERASE64 _IOW('M', 20, struct erase_info_user64) +/* Write data to OOB (64-bit version) */ #define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64) +/* Read data from OOB (64-bit version) */ #define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64) +/* Check if chip is locked (for MTD that supports it) */ #define MEMISLOCKED _IOR('M', 23, struct erase_info_user) +/* + * Most generic write interface; can write in-band and/or out-of-band in various + * modes (see "struct mtd_write_req") + */ +#define MEMWRITE _IOWR('M', 24, struct mtd_write_req) /* * Obsolete legacy interface. Keep it in order not to break userspace @@ -177,13 +251,27 @@ struct mtd_ecc_stats { }; /* - * Read/write file modes for access to MTD + * MTD file modes - for read/write access to MTD + * + * @MTD_FILE_MODE_NORMAL: OTP disabled, ECC enabled + * @MTD_FILE_MODE_OTP_FACTORY: OTP enabled in factory mode + * @MTD_FILE_MODE_OTP_USER: OTP enabled in user mode + * @MTD_FILE_MODE_RAW: OTP disabled, ECC disabled + * + * These modes can be set via ioctl(MTDFILEMODE). The mode mode will be retained + * separately for each open file descriptor. + * + * Note: %MTD_FILE_MODE_RAW provides the same functionality as %MTD_OPS_RAW - + * raw access to the flash, without error correction or autoplacement schemes. + * Wherever possible, the MTD_OPS_* mode will override the MTD_FILE_MODE_* mode + * (e.g., when using ioctl(MEMWRITE)), but in some cases, the MTD_FILE_MODE is + * used out of necessity (e.g., `write()', ioctl(MEMWRITEOOB64)). */ enum mtd_file_modes { - MTD_MODE_NORMAL = MTD_OTP_OFF, - MTD_MODE_OTP_FACTORY = MTD_OTP_FACTORY, - MTD_MODE_OTP_USER = MTD_OTP_USER, - MTD_MODE_RAW, + MTD_FILE_MODE_NORMAL = MTD_OTP_OFF, + MTD_FILE_MODE_OTP_FACTORY = MTD_OTP_FACTORY, + MTD_FILE_MODE_OTP_USER = MTD_OTP_USER, + MTD_FILE_MODE_RAW, }; #endif /* __MTD_ABI_H__ */ diff --git a/lib/libmtd.c b/lib/libmtd.c index c34874e..1b16de5 100644 --- a/lib/libmtd.c +++ b/lib/libmtd.c @@ -970,7 +970,8 @@ int mtd_torture(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb) /* Write a pattern and check it */ memset(buf, patterns[i], mtd->eb_size); - err = mtd_write(mtd, fd, eb, 0, buf, mtd->eb_size); + err = mtd_write(desc, mtd, fd, eb, 0, buf, mtd->eb_size, NULL, + 0, 0); if (err) goto out; @@ -1070,11 +1071,49 @@ int mtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs, return 0; } -int mtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs, - void *buf, int len) +static int legacy_auto_oob_layout(const struct mtd_dev_info *mtd, int fd, + int ooblen, void *oob) { + struct nand_oobinfo old_oobinfo; + int start, len; + uint8_t *tmp_buf; + + /* Read the current oob info */ + if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo)) + return sys_errmsg("MEMGETOOBSEL failed"); + + tmp_buf = malloc(ooblen); + memcpy(tmp_buf, oob, ooblen); + + /* + * We use autoplacement and have the oobinfo with the autoplacement + * information from the kernel available + */ + if (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) { + int i, tags_pos = 0; + 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]; + memcpy(oob + start, tmp_buf + tags_pos, len); + tags_pos += len; + } + } else { + /* Set at least the ecc byte positions to 0xff */ + start = old_oobinfo.eccbytes; + len = mtd->oob_size - start; + memcpy(oob + start, tmp_buf + start, len); + } + + return 0; +} + +int mtd_write(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb, + int offs, void *data, int len, void *oob, int ooblen, + uint8_t mode) { int ret; off_t seek; + struct mtd_write_req ops; ret = mtd_valid_erase_block(mtd, eb); if (ret) @@ -1099,16 +1138,41 @@ int mtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs, return -1; } - /* Seek to the beginning of the eraseblock */ + /* Calculate seek address */ seek = (off_t)eb * mtd->eb_size + offs; - if (lseek(fd, seek, SEEK_SET) != seek) - return sys_errmsg("cannot seek mtd%d to offset %llu", - mtd->mtd_num, (unsigned long long)seek); - ret = write(fd, buf, len); - if (ret != len) - return sys_errmsg("cannot write %d bytes to mtd%d (eraseblock %d, offset %d)", - len, mtd->mtd_num, eb, offs); + ops.start = seek; + ops.len = len; + ops.ooblen = ooblen; + ops.usr_data = (uint64_t)(unsigned long)data; + ops.usr_oob = (uint64_t)(unsigned long)oob; + ops.mode = mode; + + ret = ioctl(fd, MEMWRITE, &ops); + if (ret == 0) + return 0; + else if (errno != ENOTTY) + return mtd_ioctl_error(mtd, eb, "MEMWRITE"); + + /* Fall back to old methods if necessary */ + if (oob) { + if (mode == MTD_OPS_AUTO_OOB) + if (legacy_auto_oob_layout(mtd, fd, ooblen, oob)) + return -1; + if (mtd_write_oob(desc, mtd, fd, seek, ooblen, oob) < 0) + return sys_errmsg("cannot write to OOB"); + } + if (data) { + /* Seek to the beginning of the eraseblock */ + if (lseek(fd, seek, SEEK_SET) != seek) + return sys_errmsg("cannot seek mtd%d to offset %llu", + mtd->mtd_num, (unsigned long long)seek); + ret = write(fd, data, len); + if (ret != len) + return sys_errmsg("cannot write %d bytes to mtd%d " + "(eraseblock %d, offset %d)", + len, mtd->mtd_num, eb, offs); + } return 0; } @@ -336,7 +336,7 @@ int main(int argc, char * const argv[]) readbuf = xmalloc(sizeof(readbuf) * mtd.min_io_size); if (noecc) { - if (ioctl(fd, MTDFILEMODE, MTD_MODE_RAW) != 0) { + if (ioctl(fd, MTDFILEMODE, MTD_FILE_MODE_RAW) != 0) { perror("MTDFILEMODE"); goto closeall; } 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; diff --git a/ubi-utils/ubiformat.c b/ubi-utils/ubiformat.c index c396b09..a265a9a 100644 --- a/ubi-utils/ubiformat.c +++ b/ubi-utils/ubiformat.c @@ -537,7 +537,8 @@ static int flash_image(libmtd_t libmtd, const struct mtd_dev_info *mtd, new_len = drop_ffs(mtd, buf, mtd->eb_size); - err = mtd_write(mtd, args.node_fd, eb, 0, buf, new_len); + err = mtd_write(libmtd, mtd, args.node_fd, eb, 0, buf, new_len, + NULL, 0, 0); if (err) { sys_errmsg("cannot write eraseblock %d", eb); @@ -647,7 +648,8 @@ static int format(libmtd_t libmtd, const struct mtd_dev_info *mtd, fflush(stdout); } - err = mtd_write(mtd, args.node_fd, eb, 0, hdr, write_size); + err = mtd_write(libmtd, mtd, args.node_fd, eb, 0, hdr, + write_size, NULL, 0, 0); if (err) { if (!args.quiet && !args.verbose) printf("\n"); |