aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/common.c46
-rw-r--r--lib/libmtd.c70
-rw-r--r--lib/libmtd_int.h1
-rw-r--r--lib/libmtd_legacy.c38
-rw-r--r--lib/libubi.c2
5 files changed, 155 insertions, 2 deletions
diff --git a/lib/common.c b/lib/common.c
index 8041878..e278593 100644
--- a/lib/common.c
+++ b/lib/common.c
@@ -33,6 +33,9 @@
#include <stdlib.h>
#include <unistd.h>
#include "common.h"
+#include "libmtd.h"
+
+#define MTD_DEV_PATT "/dev/mtd%d"
/**
* get_multiplier - convert size specifier to an integer multiplier.
@@ -162,3 +165,46 @@ int util_srand(void)
srand(seed);
return 0;
}
+
+/**
+ * mtd_find_dev_node - Find the device node for an MTD
+ * @id: Identifier for the MTD. this can be the device node itself, or
+ * "mtd:<name>" to look up MTD by name
+ *
+ * This is a helper function to convert MTD device identifiers into their
+ * device node.
+ *
+ * Returns a pointer to a string containing the device node that must be
+ * free'd, or NULL on failure.
+ */
+char *mtd_find_dev_node(const char *id)
+{
+ struct mtd_dev_info info;
+ struct libmtd_t *lib_mtd;
+ char *node;
+ int ret;
+
+ if (strncmp(id, "mtd:", 4)) {
+ /* Assume @id is the device node */
+ return strdup(id);
+ }
+
+ /* Search for MTD matching name */
+ id += 4;
+
+ lib_mtd = libmtd_open();
+ if (!lib_mtd)
+ return NULL;
+
+ ret = mtd_get_dev_info2(lib_mtd, id, &info);
+ libmtd_close(lib_mtd);
+ if (ret < 0)
+ return NULL;
+
+ node = malloc(strlen(MTD_DEV_PATT) + 20);
+ if (!node)
+ return NULL;
+
+ sprintf(node, MTD_DEV_PATT, info.mtd_num);
+ return node;
+}
diff --git a/lib/libmtd.c b/lib/libmtd.c
index a363e56..f588e09 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -427,7 +427,7 @@ static int type_str2int(const char *str)
/**
* dev_node2num - find MTD device number by its character device node.
* @lib: MTD library descriptor
- * @node: name of the MTD device node
+ * @node: path of the MTD device node
* @mtd_num: MTD device number is returned here
*
* This function returns %0 in case of success and %-1 in case of failure.
@@ -477,6 +477,58 @@ static int dev_node2num(struct libmtd *lib, const char *node, int *mtd_num)
}
/**
+ * dev_name2num - find MTD device number by its MTD name
+ * @lib: MTD library descriptor
+ * @name: name of the MTD device
+ * @mtd_num: MTD device number is returned here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int dev_name2num(struct libmtd *lib, const char *name, int *mtd_num)
+{
+ struct mtd_info info;
+ char name2[MTD_NAME_MAX + 1];
+ int i, mtd_num_tmp = -1;
+
+ if (mtd_get_info((libmtd_t *)lib, &info))
+ return -1;
+
+ for (i = info.lowest_mtd_num; i <= info.highest_mtd_num; i++) {
+ int ret;
+
+ ret = dev_read_data(lib->mtd_name, i, name2,
+ MTD_NAME_MAX + 1);
+ if (ret < 0) {
+ if (errno == ENOENT)
+ continue;
+ if (!errno)
+ break;
+ return -1;
+ }
+ name2[ret - 1] = '\0';
+
+ if (!strcmp(name, name2)) {
+ // Device name collision
+ if (mtd_num_tmp >= 0) {
+ errmsg("Multiple MTD's found matching name %s", name);
+ errno = ENODEV;
+ return -1;
+ }
+
+ mtd_num_tmp = i;
+ }
+ }
+
+ if (mtd_num_tmp < 0) {
+ errno = ENODEV;
+ return -1;
+ }
+
+ *mtd_num = mtd_num_tmp;
+ return 0;
+}
+
+/**
* sysfs_is_supported - check whether the MTD sub-system supports MTD.
* @lib: MTD library descriptor
*
@@ -792,7 +844,7 @@ int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd)
return -1;
mtd->writable = !!(ret & MTD_WRITEABLE);
- if (ret & MTD_NO_ERASE)
+ if ((ret & MTD_NO_ERASE) && (mtd->eb_size == 0))
mtd->eb_cnt = 1;
else
mtd->eb_cnt = mtd->size / mtd->eb_size;
@@ -817,6 +869,20 @@ int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd)
return mtd_get_dev_info1(desc, mtd_num, mtd);
}
+int mtd_get_dev_info2(libmtd_t desc, const char *name, struct mtd_dev_info *mtd)
+{
+ int mtd_num;
+ struct libmtd *lib = (struct libmtd *)desc;
+
+ if (!lib->sysfs_supported)
+ return legacy_get_dev_info2(name, mtd);
+
+ if (dev_name2num(lib, name, &mtd_num))
+ return -1;
+
+ return mtd_get_dev_info1(desc, mtd_num, mtd);
+}
+
static inline int mtd_ioctl_error(const struct mtd_dev_info *mtd, int eb,
const char *sreq)
{
diff --git a/lib/libmtd_int.h b/lib/libmtd_int.h
index c0514d2..79200f7 100644
--- a/lib/libmtd_int.h
+++ b/lib/libmtd_int.h
@@ -106,6 +106,7 @@ int legacy_dev_present(int mtd_num);
int legacy_mtd_get_info(struct mtd_info *info);
int legacy_get_dev_info(const char *node, struct mtd_dev_info *mtd);
int legacy_get_dev_info1(int dev_num, struct mtd_dev_info *mtd);
+int legacy_get_dev_info2(const char *name, struct mtd_dev_info *mtd);
int legacy_get_mtd_oobavail(const char *node);
int legacy_get_mtd_oobavail1(int mtd_num);
diff --git a/lib/libmtd_legacy.c b/lib/libmtd_legacy.c
index 4eb4a70..e0ecf49 100644
--- a/lib/libmtd_legacy.c
+++ b/lib/libmtd_legacy.c
@@ -428,3 +428,41 @@ int legacy_get_dev_info1(int mtd_num, struct mtd_dev_info *mtd)
sprintf(node, MTD_DEV_PATT, mtd_num);
return legacy_get_dev_info(node, mtd);
}
+
+/**
+ * legacy_get_dev_info2 - legacy version of `mtd_get_dev_info2()`
+ * @name: name of the MTD device
+ * @mtd: the MTD device information is returned here
+ *
+ * This function is similar to 'mtd_get_dev_info2()' and has the same
+ * conventions.
+ */
+int legacy_get_dev_info2(const char *name, struct mtd_dev_info *mtd)
+{
+ struct proc_parse_info pi;
+ int ret, mtd_num = -1;
+
+ ret = proc_parse_start(&pi);
+ if (ret)
+ return -1;
+
+ while (proc_parse_next(&pi)) {
+ if (!strcmp(name, pi.name)) {
+ // Device name collision
+ if (mtd_num >= 0) {
+ errmsg("Multiple MTD's found matching name %s", name);
+ errno = ENODEV;
+ return -1;
+ }
+
+ mtd_num = pi.mtd_num;
+ }
+ }
+
+ if (mtd_num < 0) {
+ errno = ENODEV;
+ return -1;
+ }
+
+ return legacy_get_dev_info1(mtd_num, mtd);
+}
diff --git a/lib/libubi.c b/lib/libubi.c
index baaca2f..6b57e50 100644
--- a/lib/libubi.c
+++ b/lib/libubi.c
@@ -767,6 +767,8 @@ int ubi_attach(libubi_t desc, const char *node, struct ubi_attach_request *req)
r.ubi_num = req->dev_num;
r.mtd_num = req->mtd_num;
r.vid_hdr_offset = req->vid_hdr_offset;
+ r.disable_fm = req->disable_fm ? 1 : 0;
+ r.need_resv_pool = req->need_resv_pool ? 1 : 0;
if (req->max_beb_per1024) {
/*