for all features, make sure
 CONFIG_MTD_UBI=y
 CONFIG_MTD_UBI_GLUEBI=y
 CONFIG_UBIFS_FS=y
are set on the target.
ubi helpers for fs-state, drafted as stand-alone user-land tool.
This depends on the bluebi-sysfs kernel patch to detect gluebi<->ubi
mapping, but works without that feature on systems without the patch
or without any gluebi support.

filesystem and volume information detection can now be carried out
by libblkid-tiny's ubifs support and easily be associated with the
matching ubi volumes.

root@OpenWrt:/# ubi
read-write UBI partition
 mtd device: '/dev/mtd1'
 ubi device: '/dev/ubi0'
=====
read-write volume
 ubi device: '/dev/ubi0_0'
 gluebi emumlated mtd device: '/dev/mtd2'
 volume name: 'rollback'
 parent ubi device name: '/dev/ubi0'
 parent mtd device: '/dev/mtd1'
=====
read-write volume
 ubi device: '/dev/ubi0_1'
 gluebi emumlated mtd device: '/dev/mtd3'
 volume name: 'factory'
 parent ubi device name: '/dev/ubi0'
 parent mtd device: '/dev/mtd1'
=====
read-write volume
 ubi device: '/dev/ubi0_2'
 gluebi emumlated mtd device: '/dev/mtd4'
 volume name: 'rootfs'
 parent ubi device name: '/dev/ubi0'
 parent mtd device: '/dev/mtd1'
=====
read-write volume
 ubi device: '/dev/ubi0_3'
 gluebi emumlated mtd device: '/dev/mtd5'
 volume name: 'rootfs_data'
 parent ubi device name: '/dev/ubi0'
 parent mtd device: '/dev/mtd1'
=====

root@OpenWrt:/# ubi /dev/ubi0_2
/dev/mtd1
/dev/ubi0
/dev/ubi0_2
/dev/mtd4

root@OpenWrt:/# ubi ubi0:rootfs
/dev/mtd1
/dev/ubi0
/dev/ubi0_2
/dev/mtd4

root@OpenWrt:/# ubi /dev/mtd1
/dev/ubi0

root@OpenWrt:/# ubi /dev/mtd3
/dev/ubi0_1

root@OpenWrt:/# ubi /dev/mtdblock5
/dev/ubi0_3
---
 package/utils/ubiprobe/Makefile     |  32 +++
 package/utils/ubiprobe/src/Makefile |   8 +
 package/utils/ubiprobe/src/ubi.c    | 486 ++++++++++++++++++++++++++++++++++++
 3 files changed, 526 insertions(+)
 create mode 100644 package/utils/ubiprobe/Makefile
 create mode 100644 package/utils/ubiprobe/src/Makefile
 create mode 100644 package/utils/ubiprobe/src/ubi.c

diff --git a/package/utils/ubiprobe/Makefile b/package/utils/ubiprobe/Makefile
new file mode 100644
index 0000000..622f631
--- /dev/null
+++ b/package/utils/ubiprobe/Makefile
@@ -0,0 +1,32 @@
+# Copyright (C) 2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ubiprobe
+PKG_RELEASE:=1
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ubiprobe
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=ubi probe tool
+  DEPENDS:=+libubox
+endef
+
+define Build/Prepare
+       mkdir -p $(PKG_BUILD_DIR)
+       $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Package/ubiprobe/install
+       $(INSTALL_DIR) $(1)/usr/bin/
+       $(INSTALL_BIN) $(PKG_BUILD_DIR)/ubi $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,ubiprobe))
diff --git a/package/utils/ubiprobe/src/Makefile 
b/package/utils/ubiprobe/src/Makefile
new file mode 100644
index 0000000..3c04b31
--- /dev/null
+++ b/package/utils/ubiprobe/src/Makefile
@@ -0,0 +1,8 @@
+ubi: ubi.o
+       $(CC) $(LDFLAGS) ubi.o -o ubi
+
+ubi.o: ubi.c
+       $(CC) $(CFLAGS) -c ubi.c
+
+clean:
+       rm *.o ubi
diff --git a/package/utils/ubiprobe/src/ubi.c b/package/utils/ubiprobe/src/ubi.c
new file mode 100644
index 0000000..bbf49c9
--- /dev/null
+++ b/package/utils/ubiprobe/src/ubi.c
@@ -0,0 +1,486 @@
+/*
+ * Copyright (C) 2014 OpenWrt.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+
+#include <libubox/list.h>
+
+/* FS_UBI and FS_UBIFS should be be added to the existing list */
+enum {
+       FS_NONE,
+       FS_UBI,
+       FS_UBIFS,
+};
+
+char *ubi_dir_name = "/sys/devices/virtual/ubi";
+char *mtd_dir_name = "/sys/devices/virtual/mtd";
+
+typedef struct volume volume_t;
+
+struct volume {
+       struct list_head list;
+       char            *volname;
+       char            *devname;
+       volume_t        *parent;
+       int             ubi_num;
+       int             ubi_volnum;
+       int             fs;
+       int             readonly;
+       int             mtdnum;
+       int             gluebimtdnum;
+};
+
+static struct list_head volume_list = LIST_HEAD_INIT(volume_list);
+
+unsigned int
+read_uint_from_file(char *dirname, char *filename, int *i)
+{
+       FILE *f;
+       char fname[128];
+       int ret = -1;
+
+       snprintf(fname, sizeof(fname), "%s/%s", dirname, filename);
+
+       f = fopen(fname, "r");
+       if (!f)
+               return ret;
+
+       if (fscanf(f, "%d", i) == 1)
+               ret = 0;
+
+       fclose(f);
+       return ret;
+}
+
+char
+*read_string_from_file(char *dirname, char *filename)
+{
+       FILE *f;
+       char fname[128];
+       char buf[128];
+       int ret = -1, i;
+       char *str;
+
+       snprintf(fname, sizeof(fname), "%s/%s", dirname, filename);
+
+       f = fopen(fname, "r");
+       if (!f)
+               return NULL;
+
+       if (fgets(buf, 128, f) == NULL)
+               return NULL;
+
+       i = strlen(buf);
+       do
+               buf[i--]='\0';
+       while (buf[i] == '\n');
+
+       str = strndup(buf, sizeof(buf));
+       fclose(f);
+       return str;
+}
+
+volume_t
+*ubi_probe_vol(int ubi_num, int volnum)
+{
+       int readonly = 0;
+       char voldir[40], voldev[32], *volname, *voltype;
+       int gluebinum;
+       volume_t *vol;
+
+       snprintf(voldir, sizeof(voldir), "%s/ubi%u/ubi%u_%u",
+               ubi_dir_name, ubi_num, ubi_num, volnum);
+
+       snprintf(voldev, sizeof(voldev), "/dev/ubi%u_%u",
+               ubi_num, volnum);
+
+       vol = malloc(sizeof(volume_t));
+       if (!vol)
+               return NULL;
+
+       vol->devname = strdup(voldev);
+       vol->mtdnum = -1;
+       vol->volname = read_string_from_file(voldir, "name");
+       vol->ubi_num = ubi_num;
+       vol->ubi_volnum = volnum;
+       /* gluebi fake-mtd partition should rather set this as parent */
+       vol->gluebimtdnum = -1;
+
+       voltype = read_string_from_file(voldir, "type");
+       if (voltype != NULL)
+               readonly = (strncmp(voltype, "dynamic", 7) != 0);
+       else
+               readonly = 0;
+
+       vol->readonly = readonly;
+
+       return vol;
+}
+
+volume_t
+*ubi_probe_part(unsigned int ubi_num)
+{
+       unsigned int i, volumes_count, mtd_num;
+       char devdir[80], mtddev[32], ubidev[32];
+       volume_t *mtdvol, *newvol;
+
+       snprintf(devdir, sizeof(devdir), "%s/ubi%u",
+               ubi_dir_name, ubi_num);
+
+       if (read_uint_from_file(devdir, "volumes_count", &volumes_count))
+               return NULL;
+
+       if (read_uint_from_file(devdir, "mtd_num", &mtd_num))
+               return NULL;
+
+       snprintf(mtddev, sizeof(mtddev), "/dev/mtd%u", mtd_num);
+       snprintf(ubidev, sizeof(ubidev), "/dev/ubi%u", ubi_num);
+
+       mtdvol = malloc(sizeof(volume_t));
+       mtdvol->devname = strdup(ubidev);
+       mtdvol->volname = NULL;
+       mtdvol->fs = FS_UBI;
+       mtdvol->parent = NULL; /* should be corresponding mtd volume */
+       mtdvol->readonly = 0; /* should be inherited from mtd volume */
+       mtdvol->ubi_num = ubi_num;
+       mtdvol->ubi_volnum = -1;
+       mtdvol->mtdnum = mtd_num;
+       /* see above */
+       mtdvol->gluebimtdnum = -1;
+
+       list_add_tail(&mtdvol->list, &volume_list);
+
+       /* probe volumes */
+       for (i=0;i<volumes_count;i++) {
+               newvol = ubi_probe_vol(ubi_num, i);
+               if (!newvol) break;
+               newvol->parent = mtdvol;
+               list_add_tail(&newvol->list, &volume_list);
+       }
+
+       return newvol;
+}
+
+volume_t
+*volume_lookup(unsigned int ubi_num, unsigned int vol_id)
+{
+       volume_t *vol;
+
+       list_for_each_entry(vol, &volume_list, list) {
+               if (vol->ubi_num == ubi_num && vol->ubi_volnum == vol_id)
+                       return vol;
+       }
+       return NULL;
+}
+
+int
+mtd_probe_gluebi(unsigned int mtd_num)
+{
+       char mtddevdir[80];
+       unsigned int ubi_num, vol_id;
+       volume_t *vol;
+
+       snprintf(mtddevdir, sizeof(mtddevdir), "%s/mtd%u", mtd_dir_name, 
mtd_num);
+
+       if (read_uint_from_file(mtddevdir, "gluebi_ubi_num", &ubi_num))
+               return -1;
+
+       if (read_uint_from_file(mtddevdir, "gluebi_vol_id", &vol_id))
+               return -1;
+
+       vol = volume_lookup(ubi_num, vol_id);
+       if (!vol)
+               return -1;
+
+       vol->gluebimtdnum = mtd_num;
+
+       return 0;
+}
+
+void
+ubi_probe()
+{
+       DIR *ubi_dir, *mtd_dir;
+       struct dirent *ubi_dirent, *mtd_dirent;
+       unsigned int ubi_num, mtd_num;
+       volume_t *newvol, *prevvol = NULL;
+       int numdevs = 0;
+       size_t len;
+
+       ubi_dir = opendir(ubi_dir_name);
+       /* check for os ubi support */
+       if (!ubi_dir)
+               return;
+
+       /* probe ubi devices and volumes */
+       while ((ubi_dirent = readdir(ubi_dir)) != NULL) {
+               if (ubi_dirent->d_name[0] == '.')
+                       continue;
+
+               sscanf(ubi_dirent->d_name, "ubi%u", &ubi_num);
+               ubi_probe_part(ubi_num);
+               numdevs++;
+       }
+       closedir(ubi_dir);
+
+       /* no need to probe for gluebi if there is no ubi */
+       if (numdevs <= 0)
+               return;
+
+       mtd_dir = opendir(mtd_dir_name);
+       /* check for os mtd support (ubi but no mtd?!) */
+       if (!mtd_dir)
+               return;
+
+       /* probe gluebi mtd devices */
+       while ((mtd_dirent = readdir(mtd_dir)) != NULL) {
+               len = strlen(mtd_dirent->d_name);
+               /* skip /dev/mtd/.* and /dev/mtd*ro entries */
+               if (mtd_dirent->d_name[0] == '.' ||
+                   mtd_dirent->d_name[len-1] == 'o')
+                       continue;
+
+               sscanf(mtd_dirent->d_name, "mtd%u", &mtd_num);
+               mtd_probe_gluebi(mtd_num);
+       }
+
+       closedir(mtd_dir);
+}
+
+volume_t
+*ubi_lookup(char *arg)
+{
+       unsigned int ubi_num, ubi_volnum;
+       char *tmp, *volname, *volnum_s;
+       volume_t *vol;
+
+       /* both /dev/ubi0 and /dev/ubi0_1 syntax */
+       if (strncmp("/dev/", arg, 5) == 0) {
+               list_for_each_entry(vol, &volume_list, list)
+                       if (vol->devname &&
+                          (strcmp(vol->devname, arg) == 0))
+                               return vol;
+       }
+
+       /* ubi0:rootfs on / type ubifs (rw,noatime) */
+       if (strncmp("ubi", arg, 3) == 0) {
+               volname = strchr(arg, ':');
+               volnum_s = strchr(arg, '_');
+               sscanf(arg, "ubi%u", &ubi_num);
+               if (volname && volname[0] != '\0') {
+                       volname++;
+                       list_for_each_entry(vol, &volume_list, list)
+                       if (ubi_num == vol->ubi_num && vol->volname &&
+                          (strcmp(vol->volname, volname) == 0))
+                               return vol;
+               } else if (volnum_s && volnum_s[0] != '\0') {
+                       volnum_s++;
+                       sscanf(volnum_s, "%u", &ubi_volnum);
+                       list_for_each_entry(vol, &volume_list, list)
+                       if (ubi_num == vol->ubi_num &&
+                           vol->ubi_volnum == ubi_volnum)
+                               return vol;
+               } else {
+                       list_for_each_entry(vol, &volume_list, list)
+                       if (ubi_num == vol->ubi_num &&
+                           vol->fs == FS_UBI)
+                               return vol;
+               }
+       }
+
+       /* volume name only, e.g. rootfs_data */
+       list_for_each_entry(vol, &volume_list, list)
+       if (vol->volname && (strcmp(vol->volname, arg) == 0))
+               return vol;
+
+       return NULL;
+}
+
+volume_t
+*mtd_lookup(char *arg)
+{
+       volume_t *vol;
+       char blockdev_s[40], mtddev_s[40];
+
+       list_for_each_entry(vol, &volume_list, list) {
+               if (vol->mtdnum >= 0 && vol->fs == FS_UBI) {
+                   snprintf(blockdev_s, sizeof(blockdev_s), "/dev/mtdblock%u", 
vol->mtdnum);
+                   snprintf(mtddev_s, sizeof(mtddev_s), "/dev/mtd%u", 
vol->mtdnum);
+                   if(strncmp(blockdev_s, arg, sizeof(blockdev_s)) == 0 ||
+                      strncmp(mtddev_s, arg, sizeof(mtddev_s)) == 0)
+                       return vol;
+               }
+       }
+       return NULL;
+}
+
+volume_t
+*gluebi_lookup(char *arg)
+{
+       volume_t *vol;
+       char blockdev_s[40], mtddev_s[40];
+
+       list_for_each_entry(vol, &volume_list, list) {
+               if (vol->gluebimtdnum >= 0) {
+                   snprintf(blockdev_s, sizeof(blockdev_s), "/dev/mtdblock%u", 
vol->gluebimtdnum);
+                   snprintf(mtddev_s, sizeof(mtddev_s), "/dev/mtd%u", 
vol->gluebimtdnum);
+                   if(strncmp(blockdev_s, arg, sizeof(blockdev_s)) == 0 ||
+                      strncmp(mtddev_s, arg, sizeof(mtddev_s)) == 0)
+                       return vol;
+               }
+       }
+       return NULL;
+}
+
+void
+gluebi_find_vol(char *arg)
+{
+       volume_t *vol = gluebi_lookup(arg);
+       if (!vol)
+               return;
+
+       if (vol->devname)
+               printf("%s\n", vol->devname);
+}
+
+void
+ubi_find_gluebi(char *arg)
+{
+       volume_t *vol = ubi_lookup(arg);
+       if (!vol)
+               return;
+
+       if (vol->gluebimtdnum >= 0)
+               printf("/dev/mtd%u\n", vol->gluebimtdnum);
+}
+
+void
+ubi_find_mtddev(char *arg)
+{
+       volume_t *vol = ubi_lookup(arg);
+       if (!vol)
+               return;
+
+       if (vol->mtdnum >= 0)
+               printf("/dev/mtd%u\n", vol->mtdnum);
+       else if (vol->parent && vol->parent->mtdnum >= 0)
+               printf("/dev/mtd%u\n", vol->parent->mtdnum);
+       return;
+}
+
+void
+ubi_find_voldev(char *arg)
+{
+       volume_t *vol = ubi_lookup(arg);
+       if (!vol)
+               return;
+
+       if (vol->devname && vol->fs != FS_UBI)
+               printf("%s\n", vol->devname);
+}
+
+void
+ubi_find_ubidev(char *arg)
+{
+       volume_t *vol = ubi_lookup(arg);
+       if (!vol)
+               return;
+
+       if (vol->devname && vol->fs == FS_UBI)
+               printf("%s\n", vol->devname);
+       else if (vol->parent && vol->parent->devname &&
+                 vol->parent->fs == FS_UBI )
+               printf("%s\n", vol->parent->devname);
+}
+
+
+void mtd_find_ubidev(char *arg)
+{
+       volume_t *vol = mtd_lookup(arg);
+       if (!vol)
+               return;
+
+       if (vol->devname)
+               printf("%s\n", vol->devname);
+}
+
+void
+ubi_print_volume(volume_t *vol)
+{
+       printf("read-%s", vol->readonly?"only ":"write ");
+
+       switch (vol->fs) {
+               case FS_UBI:
+                       printf("UBI partition\n");
+                       break;
+                       ;;
+               case FS_UBIFS:
+                       printf("UBIFS\n");
+                       break;
+                       ;;
+               default:
+                       printf("volume\n");
+       }
+
+       if (vol->mtdnum >= 0)
+               printf(" mtd device: '/dev/mtd%u'\n", vol->mtdnum);
+
+       if (vol->devname)
+               printf(" ubi device: '%s'\n", vol->devname);
+
+       if (vol->gluebimtdnum >= 0)
+               printf(" gluebi emumlated mtd device: '/dev/mtd%u'\n", 
vol->gluebimtdnum);
+
+       if (vol->volname)
+               printf(" volume name: '%s'\n", vol->volname);
+
+       if (vol->parent) {
+               if (vol->parent->devname)
+                       printf(" parent ubi device name: '%s'\n", 
vol->parent->devname);
+               if (vol->parent->mtdnum >= 0)
+                       printf(" parent mtd device: '/dev/mtd%u'\n", 
vol->parent->mtdnum);
+       }
+}
+
+void
+ubi_print_list()
+{
+       volume_t *vol;
+       list_for_each_entry(vol, &volume_list, list) {
+               ubi_print_volume(vol);
+               printf("=====\n");
+       }
+}
+
+int
+main(int args, char *argv[])
+{
+       ubi_probe();
+       if ( args < 2 ) {
+               ubi_print_list();
+       } else if ( args == 2 ) {
+               ubi_find_mtddev(argv[1]);
+               ubi_find_ubidev(argv[1]);
+               mtd_find_ubidev(argv[1]);
+               ubi_find_voldev(argv[1]);
+               gluebi_find_vol(argv[1]);
+               ubi_find_gluebi(argv[1]);
+       } else {
+               return 1;
+       }
+       return 0;
+}
-- 
1.9.0

Attachment: pgpig9RGyL2yc.pgp
Description: PGP signature

_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to