block: allow block info /dev/ubi?_?
[project/fstools.git] / ubi.c
diff --git a/ubi.c b/ubi.c
index 7cb8d62..54f67b8 100644 (file)
--- a/ubi.c
+++ b/ubi.c
 #include <string.h>
 #include <unistd.h>
 
+#include <libubox/ulog.h>
+
 #include "libubi/libubi-tiny.h"
 
+static int print_usage(void)
+{
+       printf("ubi info\n");
+       printf("ubi detach kernel|rootfs\n");
+       printf("ubi kernel <image.kernel.ubi>\n");
+       printf("ubi rootfs <image.rootfs.ubi>\n");
+       printf("ubi overlay <image.rootfs-overlay.ubi>\n");
+
+       return -1;
+}
+
 static int mtd_find_index(char *name)
 {
        FILE *fp = fopen("/proc/mtd", "r");
@@ -68,31 +81,22 @@ static int ubi_find(libubi_t libubi, char *name, char *ret)
        int index = mtd_find_index(name);
        int ubi = 0;
 
-       if (index < 0)
-               return -1;
-
-       if (mtd_num2ubi_dev(libubi, index, &ubi)) {
-               fprintf(stderr, "failed to get ubi node for %s\n", name);
-               return -1;
-       }
-       sprintf(ret, "/dev/ubi%d", ubi);
+       while (ubi_dev_present(libubi, ubi))
+       {
+               struct ubi_dev_info info;
 
-       return 0;
-}
-
-static int ubi_find_mtd(libubi_t libubi, char *name, char *ret)
-{
-       struct ubi_dev_info info;
+               if (ubi_get_dev_info1(libubi, ubi++, &info))
+                       continue;
 
-       if (ubi_find(libubi, name, ret))
-               return -1;
+               if (info.mtd_num != index)
+                       continue;
 
-       if (ubi_get_dev_info(libubi, ret, &info))
-               return -1;
+               sprintf(ret, "/dev/ubi%d", info.dev_num);
 
-       sprintf(ret, "/dev/mtd%d", info.mtd_num);
+               return 0;
+       }
 
-       return 0;
+       return -1;
 }
 
 static int volume_find(libubi_t libubi, char *name, char *ret)
@@ -105,12 +109,12 @@ static int volume_find(libubi_t libubi, char *name, char *ret)
                return -1;
 
        if (mtd_num2ubi_dev(libubi, index, &ubi)) {
-               fprintf(stderr, "failed to get ubi node for %s\n", name);
+               ULOG_ERR("failed to get ubi node for %s\n", name);
                return -1;
        }
 
        if (ubi_get_vol_info1_nm(libubi, ubi, name, &vol)) {
-               fprintf(stderr, "failed to get ubi volume info for %s\n", name);
+               ULOG_ERR("failed to get ubi volume info for %s\n", name);
                return -1;
        }
 
@@ -119,75 +123,129 @@ static int volume_find(libubi_t libubi, char *name, char *ret)
        return 0;
 }
 
+static int main_detach(char *type)
+{
+       libubi_t libubi;
+       char mtd[64];
+       int err;
+
+       if (!strcmp(type, "kernel"))
+               err = mtd_find("kernel_ubi", mtd);
+       else if (!strcmp(type, "rootfs"))
+               err = mtd_find("rootfs_ubi", mtd);
+       else
+               return print_usage();
+
+       if (err) {
+               ULOG_ERR("MTD partition '%s_ubi' not found\n", type);
+               return -1;
+       }
+
+       libubi = libubi_open();
+       if (!libubi) {
+               ULOG_ERR("cannot open libubi");
+               return -1;
+       }
+
+       err = ubidetach(libubi, mtd);
+       if (err) {
+               ULOG_ERR("cannot detach \"%s\"", mtd);
+               return -1;
+       }
+
+       return 0;
+}
+
 static int main_image(char *partition, char *image, char *overlay)
 {
        libubi_t libubi;
+       struct stat s;
        int err;
        char mtd[64];
-       char part[64];
+       char _part[64];
        char node[64];
        char volume[64];
        char _data[64];
        char *data = NULL;
 
-       if (mtd_find(partition, part)) {
-               fprintf(stderr, "failed to find mtd partition %s\n", partition);
+       if (stat(image, &s)) {
+               ULOG_ERR("image not found %s\n", image);
                return -1;
        }
+
+       if (!strcmp(partition, "kernel"))
+               err = mtd_find("kernel", _part);
+       else
+               err = mtd_find("rootfs", _part);
+
        if (overlay && !mtd_find(overlay, _data))
                data = _data;
 
        libubi = libubi_open();
        if (!libubi) {
-               fprintf(stderr, "cannot open libubi");
-               return -1;
-       }
-
-       if (ubi_find_mtd(libubi, partition, mtd)) {
-               fprintf(stderr, "failed to find mtd parent %s\n", partition);
+               ULOG_ERR("cannot open libubi");
                return -1;
        }
 
-       if (ubi_find(libubi, partition, node)) {
-               fprintf(stderr, "failed to find ubi volume %s\n", partition);
+       if (!strcmp(partition, "kernel"))
+               err = mtd_find("kernel_ubi", mtd);
+       else
+               err = mtd_find("rootfs_ubi", mtd);
+       if (err) {
+               ULOG_ERR("MTD partition '%s_ubi' not found\n", partition);
                return -1;
        }
 
-       if (volume_find(libubi, partition, volume)) {
-               fprintf(stderr, "failed to find ubi volume %s\n", partition);
+       if (!strcmp(partition, "kernel"))
+               err = ubi_find(libubi, "kernel_ubi", node);
+       else
+               err = ubi_find(libubi, "rootfs_ubi", node);
+       if (err) {
+               ULOG_ERR("UBI volume '%s' not found\n", partition);
                return -1;
        }
 
        err = ubidetach(libubi, mtd);
        if (err) {
-               fprintf(stderr, "cannot detach \"%s\"", mtd);
+               ULOG_ERR("cannot detach \"%s\"", mtd);
                return -1;
        }
 
        err = ubiattach(libubi, mtd);
        if (err) {
-               fprintf(stderr, "cannot attach \"%s\"", mtd);
+               ULOG_ERR("cannot attach \"%s\"", mtd);
                return -1;
        }
 
        if (data) {
                err = ubirmvol(libubi, node, overlay);
                if (err) {
-                       fprintf(stderr, "cannot remove \"%s\"", node);
+                       ULOG_ERR("cannot remove \"%s\"", node);
                        return -1;
                }
        }
 
+       if (volume_find(libubi, partition, volume) < 0) {
+               ULOG_ERR("UBI volume '%s' not found\n", partition);
+               return -1;
+       }
+
+       err = ubirsvol(libubi, node, partition, s.st_size);
+       if (err) {
+               ULOG_ERR("cannot resize \"%s\"", partition);
+               return -1;
+       }
+
        err = ubiupdatevol(libubi, volume, image);
        if (err) {
-               fprintf(stderr, "cannot update \"%s\"", volume);
+               ULOG_ERR("cannot update \"%s\"", volume);
                return -1;
        }
 
        if (overlay) {
                err = ubimkvol(libubi, node, overlay, 1);
                if (err) {
-                       fprintf(stderr, "cannot make \"%s\"", node);
+                       ULOG_ERR("cannot make \"%s\"", overlay);
                        return -1;
                }
        }
@@ -205,12 +263,12 @@ static int main_info(void)
 
        libubi = libubi_open();
        if (!libubi) {
-               fprintf(stderr, "cannot open libubi");
+               ULOG_ERR("cannot open libubi");
                return -1;
        }
 
        if (ubi_get_info(libubi, &info)) {
-               fprintf(stderr, "failed to get info\n");
+               ULOG_ERR("failed to get info\n");
                return -1;
        }
 
@@ -223,7 +281,7 @@ static int main_info(void)
                if (ubi_get_dev_info(libubi, ubi, &dinfo))
                        continue;
                printf("device - %s\n  size: %lldBytes\n  bad blocks: %d\n",
-                       &ubi[5], dinfo.total_bytes, dinfo.bad_count);
+                      &ubi[5], dinfo.total_bytes, dinfo.bad_count);
                for (j = dinfo.lowest_vol_id; j <= dinfo.highest_vol_id; j++) {
                        struct ubi_vol_info vinfo;
 
@@ -241,16 +299,6 @@ static int main_info(void)
        return 0;
 }
 
-static int print_usage(void)
-{
-       printf("ubi info\n");
-       printf("ubi kernel <image.kernel.ubifs>\n");
-       printf("ubi rootfs <image.rootfs.ubifs>\n");
-       printf("ubi overlay <image.rootfs-overlay.ubifs>\n");
-
-       return -1;
-}
-
 int main(int argc, char **argv)
 {
        if (argc > 1 && !strcmp(argv[1], "info"))
@@ -267,6 +315,9 @@ int main(int argc, char **argv)
 
        } else if (!strcmp(argv[1], "overlay")) {
                return main_image("rootfs", argv[2], "rootfs_data");
+
+       } else if (!strcmp(argv[1], "detach")) {
+               return main_detach(argv[2]);
        }
 
        return -1;