aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorXiaolei Li <xiaolei.li@mediatek.com>2018-04-10 15:36:55 +0800
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2018-04-10 15:38:56 +0200
commita10353584f93334b5687c598a15260c0fc5b8d3e (patch)
treecb2916f76ba8c9cbe131b7cf632027891f94d964 /lib
parent044ed4c0dd788f980a3a1a6fc6bf855a239f12e5 (diff)
libmtd: Add support to access OOB available size
This patch exposes OOB available size to user. Then user can use OOB free area according to OOB available size. Steps to get OOB available size: First, access /sys/class/mtd/mtdX/oobavail. If not exist, then try to get ecc layout by ioctl "ECCGETLAYOUT". If none of them work, set OOB available size to 0. Signed-off-by: Xiaolei Li <xiaolei.li@mediatek.com> Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib')
-rw-r--r--lib/libmtd.c14
-rw-r--r--lib/libmtd_int.h5
-rw-r--r--lib/libmtd_legacy.c43
3 files changed, 62 insertions, 0 deletions
diff --git a/lib/libmtd.c b/lib/libmtd.c
index 86c89ae..7382229 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -614,6 +614,10 @@ libmtd_t libmtd_open(void)
if (!lib->mtd_oob_size)
goto out_error;
+ lib->mtd_oobavail = mkpath(lib->mtd, MTD_OOBAVAIL);
+ if (!lib->mtd_oobavail)
+ goto out_error;
+
lib->mtd_region_cnt = mkpath(lib->mtd, MTD_REGION_CNT);
if (!lib->mtd_region_cnt)
goto out_error;
@@ -637,6 +641,7 @@ void libmtd_close(libmtd_t desc)
free(lib->mtd_flags);
free(lib->mtd_region_cnt);
free(lib->mtd_oob_size);
+ free(lib->mtd_oobavail);
free(lib->mtd_subpage_size);
free(lib->mtd_min_io_size);
free(lib->mtd_size);
@@ -769,6 +774,15 @@ int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd)
return -1;
if (dev_read_pos_int(lib->mtd_oob_size, mtd_num, &mtd->oob_size))
return -1;
+ if (dev_read_pos_int(lib->mtd_oobavail, mtd_num, &mtd->oobavail)) {
+ /*
+ * Fail to access oobavail sysfs file,
+ * try ioctl ECCGETLAYOUT. */
+ mtd->oobavail = legacy_get_mtd_oobavail1(mtd_num);
+ /* Set 0 as default if can not get valid ecc layout */
+ if (mtd->oobavail < 0)
+ mtd->oobavail = 0;
+ }
if (dev_read_pos_int(lib->mtd_region_cnt, mtd_num, &mtd->region_cnt))
return -1;
if (dev_read_hex_int(lib->mtd_flags, mtd_num, &ret))
diff --git a/lib/libmtd_int.h b/lib/libmtd_int.h
index 03b0863..c0514d2 100644
--- a/lib/libmtd_int.h
+++ b/lib/libmtd_int.h
@@ -44,6 +44,7 @@ extern "C" {
#define MTD_MIN_IO_SIZE "writesize"
#define MTD_SUBPAGE_SIZE "subpagesize"
#define MTD_OOB_SIZE "oobsize"
+#define MTD_OOBAVAIL "oobavail"
#define MTD_REGION_CNT "numeraseregions"
#define MTD_FLAGS "flags"
@@ -63,6 +64,7 @@ extern "C" {
* @mtd_min_io_size: minimum I/O unit size file pattern
* @mtd_subpage_size: sub-page size file pattern
* @mtd_oob_size: MTD device OOB size file pattern
+ * @mtd_oobavail: MTD device free OOB size file pattern
* @mtd_region_cnt: count of additional erase regions file pattern
* @mtd_flags: MTD device flags file pattern
* @sysfs_supported: non-zero if sysfs is supported by MTD
@@ -92,6 +94,7 @@ struct libmtd
char *mtd_min_io_size;
char *mtd_subpage_size;
char *mtd_oob_size;
+ char *mtd_oobavail;
char *mtd_region_cnt;
char *mtd_flags;
unsigned int sysfs_supported:1;
@@ -103,6 +106,8 @@ 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_mtd_oobavail(const char *node);
+int legacy_get_mtd_oobavail1(int mtd_num);
#ifdef __cplusplus
}
diff --git a/lib/libmtd_legacy.c b/lib/libmtd_legacy.c
index 46f51fd..e1ab48e 100644
--- a/lib/libmtd_legacy.c
+++ b/lib/libmtd_legacy.c
@@ -215,6 +215,46 @@ int legacy_mtd_get_info(struct mtd_info *info)
return 0;
}
+int legacy_get_mtd_oobavail(const char *node)
+{
+ struct stat st;
+ struct nand_ecclayout_user usrlay;
+ int fd, ret;
+
+ if (stat(node, &st))
+ return sys_errmsg("cannot open \"%s\"", node);
+
+ if (!S_ISCHR(st.st_mode)) {
+ errno = EINVAL;
+ return errmsg("\"%s\" is not a character device", node);
+ }
+
+ fd = open(node, O_RDONLY);
+ if (fd == -1)
+ return sys_errmsg("cannot open \"%s\"", node);
+
+ ret = ioctl(fd, ECCGETLAYOUT, &usrlay);
+ if (ret < 0) {
+ sys_errmsg("ECCGETLAYOUT ioctl request failed");
+ goto out_close;
+ }
+
+ ret = usrlay.oobavail;
+
+out_close:
+ close(fd);
+
+ return ret;
+}
+
+int legacy_get_mtd_oobavail1(int mtd_num)
+{
+ char node[sizeof(MTD_DEV_PATT) + 20];
+
+ sprintf(node, MTD_DEV_PATT, mtd_num);
+ return legacy_get_mtd_oobavail(node);
+}
+
/**
* legacy_get_dev_info - legacy version of 'mtd_get_dev_info()'.
* @node: name of the MTD device node
@@ -335,6 +375,9 @@ int legacy_get_dev_info(const char *node, struct mtd_dev_info *mtd)
close(fd);
+ ret = legacy_get_mtd_oobavail(node);
+ mtd->oobavail = ret > 0 ? ret : 0;
+
/*
* Unfortunately, the device name is not available via ioctl, and
* we have to parse /proc/mtd to get it.