summaryrefslogtreecommitdiff
path: root/ubi-utils/src
diff options
context:
space:
mode:
authorMika Westerberg <ext-mika.1.westerberg@nokia.com>2010-02-01 10:03:47 +0100
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-02-18 15:42:50 +0200
commita341ac7d0d5c23dd859136018ea6f7ecdc5f65e8 (patch)
tree77109fbb3de946d5c507f29688af50a8aba6c1af /ubi-utils/src
parentacabf7fcea06b7a2926837523561861ed14cab31 (diff)
libubi: add support to attach/detach by MTD device path
struct ubi_attach_request now has additional field 'dev' that can contain path to the MTD device node in the filesystem. Also there are two new functions that are able to handle path to the MTD device node: ubi_attach() - attach MTD device by number or by path ubi_detach() - detach MTD device by path ubi_attach() works like ubi_attach_mtd() when it is passed empty req->dev, otherwise it looks up correct MTD device number based on the given device node path. Signed-off-by: Mika Westerberg <ext-mika.1.westerberg@nokia.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'ubi-utils/src')
-rw-r--r--ubi-utils/src/libubi.c127
-rw-r--r--ubi-utils/src/libubi_int.h1
2 files changed, 115 insertions, 13 deletions
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