summaryrefslogtreecommitdiff
path: root/ubi-utils
diff options
context:
space:
mode:
Diffstat (limited to 'ubi-utils')
-rw-r--r--ubi-utils/include/libubi.h30
-rw-r--r--ubi-utils/src/libubi.c127
-rw-r--r--ubi-utils/src/libubi_int.h1
3 files changed, 145 insertions, 13 deletions
diff --git a/ubi-utils/include/libubi.h b/ubi-utils/include/libubi.h
index f52904d..64b5eed 100644
--- a/ubi-utils/include/libubi.h
+++ b/ubi-utils/include/libubi.h
@@ -44,6 +44,7 @@ typedef void * libubi_t;
* (%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
* @vid_hdr_offset: VID header offset (%0 means default offset and this is what
* most of the users want)
*/
@@ -51,6 +52,7 @@ struct ubi_attach_request
{
int dev_num;
int mtd_num;
+ const char *dev;
int vid_hdr_offset;
};
@@ -219,6 +221,23 @@ int ubi_attach_mtd(libubi_t desc, const char *node,
struct ubi_attach_request *req);
/**
+ * ubi_attach - attach an MTD device by its node path.
+ * @desc: UBI library descriptor
+ * @node: name of the UBI control character device node
+ * @req: MTD attach request
+ *
+ * This function creates new UBI device by attaching an MTD device described by
+ * @req. If @req->dev is given it should contain path to the MTD device node.
+ * Otherwise functionality is similar than in function 'ubi_attach_mtd()' where
+ * @req->mtd_num is used.
+ *
+ * Returns %0 in case of success and %-1 in case of failure (errno is set). The
+ * newly created UBI device number is returned in @req->dev_num.
+ */
+int ubi_attach(libubi_t desc, const char *node,
+ struct ubi_attach_request *req);
+
+/**
* ubi_detach_mtd - detach an MTD device.
* @desc: UBI library descriptor
* @node: name of the UBI control character device node
@@ -231,6 +250,17 @@ int ubi_attach_mtd(libubi_t desc, const char *node,
int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num);
/**
+ * ubi_detach - detach an MTD device by its node path.
+ * @desc: UBI library descriptor
+ * @node: name of the UBI control character device node
+ * @dev: path to an MTD device node
+ *
+ * This function detaches an MTD device @dev from UBI. Returns zero in case of
+ * success and %-1 in case of failure.
+ */
+int ubi_detach(libubi_t desc, const char *node, const char *dev);
+
+/**
* ubi_remove_dev - remove an UBI device.
* @desc: UBI library descriptor
* @node: name of the UBI control character device node
diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c
index fd97774..2f19bd7 100644
--- a/ubi-utils/src/libubi.c
+++ b/ubi-utils/src/libubi.c
@@ -677,35 +677,120 @@ void libubi_close(libubi_t desc)
free(lib);
}
-int ubi_attach_mtd(libubi_t desc, const char *node,
- struct ubi_attach_request *req)
+/**
+ * do_attach - perform the actual attach operation.
+ * @node: name of the UBI control character device node
+ * @r: attach request
+ *
+ * This function performs the actual UBI attach operation. Returns %0 in case of
+ * success and %-1 in case of failure. @r->ubi_num contains newly created UBI
+ * device number.
+ */
+static int do_attach(const char *node, const struct ubi_attach_req *r)
{
int fd, ret;
- struct ubi_attach_req r;
-
- memset(&r, 0, sizeof(struct ubi_attach_req));
-
- desc = desc;
- r.ubi_num = req->dev_num;
- r.mtd_num = req->mtd_num;
- r.vid_hdr_offset = req->vid_hdr_offset;
fd = open(node, O_RDONLY);
if (fd == -1)
return sys_errmsg("cannot open \"%s\"", node);
- ret = ioctl(fd, UBI_IOCATT, &r);
+ ret = ioctl(fd, UBI_IOCATT, r);
close(fd);
if (ret == -1)
return -1;
- req->dev_num = r.ubi_num;
-
#ifdef UDEV_SETTLE_HACK
// if (system("udevsettle") == -1)
// return -1;
usleep(100000);
#endif
+ return ret;
+}
+
+int ubi_attach_mtd(libubi_t desc, const char *node,
+ struct ubi_attach_request *req)
+{
+ struct ubi_attach_req r;
+ int ret;
+
+ (void)desc;
+
+ memset(&r, 0, sizeof(struct ubi_attach_req));
+ r.ubi_num = req->dev_num;
+ r.mtd_num = req->mtd_num;
+ r.vid_hdr_offset = req->vid_hdr_offset;
+
+ ret = do_attach(node, &r);
+ if (ret == 0)
+ req->dev_num = r.ubi_num;
+
+ return ret;
+}
+
+#ifndef MTD_CHAR_MAJOR
+/*
+ * This is taken from kernel <linux/mtd/mtd.h> and is unlikely to change anytime
+ * soon.
+ */
+#define MTD_CHAR_MAJOR 90
+#endif
+
+/**
+ * dev_to_mtdnum - converts device node to MTD number.
+ * @dev: path to device node to convert
+ *
+ * This function converts given @dev to MTD device number. @dev should contain
+ * path to the MTD device node. Returns MTD device number in case of success and
+ * %-1 in case of failure (errno is set).
+ */
+static int dev_to_mtdnum(const char *dev)
+{
+ int major, minor;
+ struct stat sb;
+
+ if (stat(dev, &sb) < 0)
+ return sys_errmsg("cannot stat \"%s\"", dev);
+
+ if (!S_ISCHR(sb.st_mode)) {
+ errno = EINVAL;
+ return sys_errmsg("\"%s\" is not a character device", dev);
+ }
+
+ major = major(sb.st_rdev);
+ minor = minor(sb.st_rdev);
+
+ if (major != MTD_CHAR_MAJOR) {
+ errno = EINVAL;
+ return sys_errmsg("\"%s\" is not an MTD device", dev);
+ }
+
+ return minor / 2;
+}
+
+int ubi_attach(libubi_t desc, const char *node, struct ubi_attach_request *req)
+{
+ struct ubi_attach_req r;
+ int ret;
+
+ if (!req->dev)
+ /* Fallback to opening by mtd_num */
+ return ubi_attach_mtd(desc, node, req);
+
+ memset(&r, 0, sizeof(struct ubi_attach_req));
+ r.ubi_num = req->dev_num;
+ r.vid_hdr_offset = req->vid_hdr_offset;
+
+ /*
+ * User has passed path to device node. Lets find out MTD device number
+ * of the device and pass it to the kernel.
+ */
+ r.mtd_num = dev_to_mtdnum(req->dev);
+ if (r.mtd_num == -1)
+ return -1;
+
+ ret = do_attach(node, &r);
+ if (ret == 0)
+ req->dev_num = r.ubi_num;
return ret;
}
@@ -723,6 +808,22 @@ int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num)
return ubi_remove_dev(desc, node, ubi_dev);
}
+int ubi_detach(libubi_t desc, const char *node, const char *dev)
+{
+ int mtd_num;
+
+ if (!dev) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ mtd_num = dev_to_mtdnum(dev);
+ if (mtd_num == -1)
+ return -1;
+
+ return ubi_detach_mtd(desc, node, mtd_num);
+}
+
int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev)
{
int fd, ret;
diff --git a/ubi-utils/src/libubi_int.h b/ubi-utils/src/libubi_int.h
index 6d17d57..c3aa37a 100644
--- a/ubi-utils/src/libubi_int.h
+++ b/ubi-utils/src/libubi_int.h
@@ -83,6 +83,7 @@ extern "C" {
* handling
* @dev_max_vols: maximum volumes number count sysfs path pattern
* @dev_min_io_size: minimum I/O unit size sysfs path pattern
+ * @dev_mtd_num: MTD device number
* @ubi_vol: UBI volume sysfs directory pattern
* @vol_type: volume type sysfs path pattern
* @vol_dev: volume major/minor numbers file pattern