aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@intel.com>2011-11-18 23:53:11 +0200
committerArtem Bityutskiy <Artem.Bityutskiy@intel.com>2011-11-18 23:53:11 +0200
commitf8aa6922dde02835ba97e84be41f387cdd38ec7d (patch)
tree171914942c226c733a9781cd8b0ca4ebeba3233d
parent97bb4aa681f4df5e784c1f8a8db049a95a0d65c6 (diff)
parent0970bf408707d610e88abb069b123e267aeb42f8 (diff)
Merge branch 'brian'v1.4.7
-rw-r--r--include/libmtd.h15
-rw-r--r--include/mtd/mtd-abi.h122
-rw-r--r--lib/libmtd.c86
-rw-r--r--nanddump.c2
-rw-r--r--nandwrite.c144
-rw-r--r--ubi-utils/ubiformat.c6
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;
}
diff --git a/nanddump.c b/nanddump.c
index 7a24c0d..be458c6 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -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");