diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2010-06-14 13:25:07 +0300 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2010-06-14 13:54:31 +0300 |
commit | 5e77e9d5a72d4f7bafc74373d5e44a106a369ceb (patch) | |
tree | 3e5e47d7ba2487a409f53a3f27456723ca86dfda /ubi-utils | |
parent | 8b1c9cad58f5e2055646b57245fc72cca398c264 (diff) |
libmtd: add mtd_write_img
Add another helper interface which can be used to write an image
to an mtd device.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'ubi-utils')
-rw-r--r-- | ubi-utils/include/libmtd.h | 15 | ||||
-rw-r--r-- | ubi-utils/include/libubi.h | 4 | ||||
-rw-r--r-- | ubi-utils/src/libmtd.c | 104 |
3 files changed, 120 insertions, 3 deletions
diff --git a/ubi-utils/include/libmtd.h b/ubi-utils/include/libmtd.h index c8b44e8..dd82b72 100644 --- a/ubi-utils/include/libmtd.h +++ b/ubi-utils/include/libmtd.h @@ -214,6 +214,21 @@ int mtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs, void *buf, int len); /** + * mtd_write_img - write a file to MTD device. + * @mtd: MTD device description object + * @fd: MTD device node file descriptor + * @eb: eraseblock to write to + * @offs: offset withing the eraseblock to write to + * @img_name: the file to write + * + * This function writes an image @img_name the MTD device defined by @mtd. @eb + * and @offs are the starting eraseblock and offset on the MTD device. Returns + * %0 in case of success and %-1 in case of failure. + */ +int mtd_write_img(const struct mtd_dev_info *mtd, int fd, int eb, int offs, + const char *img_name); + +/** * mtd_probe_node - test MTD node. * @desc: MTD library descriptor * @node: the node to test diff --git a/ubi-utils/include/libubi.h b/ubi-utils/include/libubi.h index f029a8d..ffc4be9 100644 --- a/ubi-utils/include/libubi.h +++ b/ubi-utils/include/libubi.h @@ -43,8 +43,8 @@ typedef void * libubi_t; * @dev_num: number to assign to the newly created UBI device * (%UBI_DEV_NUM_AUTO should be used to automatically assign the * number) - * @mtd_num: MTD device number to attach - * @dev: path to device node to attach + * @mtd_num: MTD device number to attach (used if @dev is %NULL) + * @dev: path to MTD device node to attach * @vid_hdr_offset: VID header offset (%0 means default offset and this is what * most of the users want) */ diff --git a/ubi-utils/src/libmtd.c b/ubi-utils/src/libmtd.c index 249fa23..011327d 100644 --- a/ubi-utils/src/libmtd.c +++ b/ubi-utils/src/libmtd.c @@ -981,7 +981,6 @@ int mtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs, errno = EINVAL; return -1; } - if (offs % mtd->subpage_size) { errmsg("write offset %d is not aligned to mtd%d min. I/O size %d", offs, mtd->dev_num, mtd->subpage_size); @@ -1009,6 +1008,109 @@ int mtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs, return 0; } +int mtd_write_img(const struct mtd_dev_info *mtd, int fd, int eb, int offs, + const char *img_name) +{ + int tmp, ret, in_fd, len, written = 0; + off_t seek; + struct stat st; + char *buf; + + if (eb < 0 || eb >= mtd->eb_cnt) { + errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks", + eb, mtd->dev_num, mtd->eb_cnt); + errno = EINVAL; + return -1; + } + if (offs < 0 || offs >= mtd->eb_size) { + errmsg("bad offset %d, mtd%d eraseblock size is %d", + offs, mtd->dev_num, mtd->eb_size); + errno = EINVAL; + return -1; + } + if (offs % mtd->subpage_size) { + errmsg("write offset %d is not aligned to mtd%d min. I/O size %d", + offs, mtd->dev_num, mtd->subpage_size); + errno = EINVAL; + return -1; + } + + in_fd = open(img_name, O_RDONLY); + if (in_fd == -1) + return sys_errmsg("cannot open %s", img_name); + + if (fstat(in_fd, &st)) { + sys_errmsg("cannot stat %s", img_name); + goto out_close; + } + + len = st.st_size; + if (len % mtd->subpage_size) { + errmsg("size of \"%s\" is %d byte, which is not aligned to " + "mtd%d min. I/O size %d", img_name, len, mtd->dev_num, + mtd->subpage_size); + errno = EINVAL; + goto out_close; + } + tmp = (offs + len + mtd->eb_size - 1) / mtd->eb_size; + if (eb + tmp > mtd->eb_cnt) { + errmsg("\"%s\" image size is %d bytes, mtd%d size is %d " + "eraseblocks, the image does not fit if we write it " + "starting from eraseblock %d, offset %d", + img_name, len, mtd->dev_num, mtd->eb_cnt, eb, offs); + errno = EINVAL; + goto out_close; + } + + /* Seek to the beginning of the eraseblock */ + seek = (off_t)eb * mtd->eb_size + offs; + if (lseek(fd, seek, SEEK_SET) != seek) { + sys_errmsg("cannot seek mtd%d to offset %llu", + mtd->dev_num, (unsigned long long)seek); + goto out_close; + } + + buf = malloc(mtd->eb_size); + if (!buf) { + sys_errmsg("cannot allocate %d bytes of memory", mtd->eb_size); + goto out_close; + } + + while (written < len) { + int rd = 0; + + do { + ret = read(in_fd, buf, mtd->eb_size - offs - rd); + if (ret == -1) { + sys_errmsg("cannot read from %s", img_name); + goto out_free; + } + rd += ret; + } while (ret && rd < mtd->eb_size - offs); + + ret = write(fd, buf, rd); + if (ret != rd) { + sys_errmsg("cannot write %d bytes to mtd%d (eraseblock %d, offset %d)", + len, mtd->dev_num, eb, offs); + goto out_free; + } + + offs = 0; + eb += 1; + written += rd; + } + + free(buf); + close(in_fd); + return 0; + +out_free: + free(buf); +out_close: + close(in_fd); + return -1; +} + int mtd_probe_node(libmtd_t desc, const char *node) { struct stat st; |