aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2007-12-26 15:12:26 +0200
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2007-12-26 16:23:04 +0200
commit9ba41c4dc891e38c92126bfcc4c366d765841da0 (patch)
tree5d095e949421d86dc2e2df83245405bbf7c84945
parent126341588c5e9d9077e31c4a5f550c83b2e3e93d (diff)
ubi-utils: add ubiattach and ubidetach
Add 2 new utilities to attach and detach UBI devices. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
-rw-r--r--include/mtd/ubi-user.h82
-rw-r--r--tests/ubi-tests/Makefile6
-rw-r--r--tests/ubi-tests/rmvol.c308
-rwxr-xr-xtests/ubi-tests/runtests.sh2
-rw-r--r--tests/ubi-tests/volrefcnt.c122
-rw-r--r--ubi-utils/Makefile11
-rw-r--r--ubi-utils/inc/libubi.h54
-rw-r--r--ubi-utils/src/libubi.c123
-rw-r--r--ubi-utils/src/libubi_int.h2
-rw-r--r--ubi-utils/src/ubiattach.c224
-rw-r--r--ubi-utils/src/ubicrc32.c4
-rw-r--r--ubi-utils/src/ubidetach.c200
-rw-r--r--ubi-utils/src/ubimkvol.c8
-rw-r--r--ubi-utils/src/ubinfo.c6
-rw-r--r--ubi-utils/src/ubirmvol.c8
-rw-r--r--ubi-utils/src/ubiupdate.c4
16 files changed, 817 insertions, 347 deletions
diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h
index bb0aca6..4d184a7 100644
--- a/include/mtd/ubi-user.h
+++ b/include/mtd/ubi-user.h
@@ -15,13 +15,28 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * Author: Artem B. Bityutskiy
+ * Author: Artem Bityutskiy (Битюцкий Артём)
*/
#ifndef __UBI_USER_H__
#define __UBI_USER_H__
/*
+ * UBI device creation (the same as MTD device attachment)
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * MTD devices may be attached using %UBI_IOCATT ioctl command of the UBI
+ * control device. The caller has to properly fill and pass
+ * &struct ubi_attach_req object - UBI will attach the MTD device specified in
+ * the request and return the newly created UBI device number as the ioctl
+ * return value.
+ *
+ * UBI device deletion (the same as MTD device detachment)
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * An UBI device maybe deleted with %UBI_IOCDET ioctl command of the UBI
+ * control device.
+ *
* UBI volume creation
* ~~~~~~~~~~~~~~~~~~~
*
@@ -60,11 +75,12 @@
*/
/*
- * When a new volume is created, users may either specify the volume number they
- * want to create or to let UBI automatically assign a volume number using this
- * constant.
+ * When a new UBI volume or UBI device is created, users may either specify the
+ * volume/device number they want to create or to let UBI automatically assign
+ * the number using these constants.
*/
#define UBI_VOL_NUM_AUTO (-1)
+#define UBI_DEV_NUM_AUTO (-1)
/* Maximum volume name length */
#define UBI_MAX_VOLUME_NAME 127
@@ -80,6 +96,15 @@
/* Re-size an UBI volume */
#define UBI_IOCRSVOL _IOW(UBI_IOC_MAGIC, 2, struct ubi_rsvol_req)
+/* IOCTL commands of the UBI control character device */
+
+#define UBI_CTRL_IOC_MAGIC 'o'
+
+/* Attach an MTD device */
+#define UBI_IOCATT _IOW(UBI_CTRL_IOC_MAGIC, 64, struct ubi_attach_req)
+/* Detach an MTD device */
+#define UBI_IOCDET _IOW(UBI_CTRL_IOC_MAGIC, 65, int32_t)
+
/* IOCTL commands of UBI volume character devices */
#define UBI_VOL_IOC_MAGIC 'O'
@@ -89,6 +114,9 @@
/* An eraseblock erasure command, used for debugging, disabled by default */
#define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, int32_t)
+/* Maximum MTD device name length supported by UBI */
+#define MAX_UBI_MTD_NAME_LEN 127
+
/*
* UBI volume type constants.
*
@@ -97,19 +125,55 @@
*/
enum {
UBI_DYNAMIC_VOLUME = 3,
- UBI_STATIC_VOLUME = 4
+ UBI_STATIC_VOLUME = 4,
+};
+
+/**
+ * struct ubi_attach_req - attach MTD device request.
+ * @ubi_num: UBI device number to create
+ * @mtd_num: MTD device number to attach
+ * @vid_hdr_offset: VID header offset (use defaults if %0)
+ * @padding: reserved for future, not used, has to be zeroed
+ *
+ * This data structure is used to specify MTD device UBI has to attach and the
+ * parameters it has to use. The number which should be assigned to the new UBI
+ * device is passed in @ubi_num. UBI may automatically assing the number if
+ * @UBI_DEV_NUM_AUTO is passed. In this case, the device number is returned in
+ * @ubi_num.
+ *
+ * Most applications should pass %0 in @vid_hdr_offset to make UBI use default
+ * offset of the VID header within physical eraseblocks. The default offset is
+ * the next min. I/O unit after the EC header. For example, it will be offset
+ * 512 in case of a 512 bytes page NAND flash with no sub-page support. Or
+ * it will be 512 in case of a 2KiB page NAND flash with 4 512-byte sub-pages.
+ *
+ * But in rare cases, if this optimizes things, the VID header may be placed to
+ * a different offset. For example, the boot-loader might do things faster if the
+ * VID header sits at the end of the first 2KiB NAND page with 4 sub-pages. As
+ * the boot-loader would not normally need to read EC headers (unless it needs
+ * UBI in RW mode), it might be faster to calculate ECC. This is weird example,
+ * but it real-life example. So, in this example, @vid_hdr_offer would be
+ * 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes
+ * aligned, which is OK, as UBI is clever enough to realize this is 4th sub-page
+ * of the first page and add needed padding.
+ */
+struct ubi_attach_req {
+ int32_t ubi_num;
+ int32_t mtd_num;
+ int32_t vid_hdr_offset;
+ uint8_t padding[12];
};
/**
* struct ubi_mkvol_req - volume description data structure used in
- * volume creation requests.
+ * volume creation requests.
* @vol_id: volume number
* @alignment: volume alignment
* @bytes: volume size in bytes
* @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
- * @padding1: reserved for future, not used
+ * @padding1: reserved for future, not used, has to be zeroed
* @name_len: volume name length
- * @padding2: reserved for future, not used
+ * @padding2: reserved for future, not used, has to be zeroed
* @name: volume name
*
* This structure is used by userspace programs when creating new volumes. The
@@ -139,7 +203,7 @@ struct ubi_mkvol_req {
int8_t padding1;
int16_t name_len;
int8_t padding2[4];
- char name[UBI_MAX_VOLUME_NAME+1];
+ char name[UBI_MAX_VOLUME_NAME + 1];
} __attribute__ ((packed));
/**
diff --git a/tests/ubi-tests/Makefile b/tests/ubi-tests/Makefile
index a15d93c..157aa55 100644
--- a/tests/ubi-tests/Makefile
+++ b/tests/ubi-tests/Makefile
@@ -5,7 +5,7 @@ UBIUTILS_PATH=../../ubi-utils/
CC := $(CROSS)gcc
-TESTS=io_update rmvol integ io_paral io_read io_basic \
+TESTS=io_update volrefcnt integ io_paral io_read io_basic \
mkvol_basic mkvol_bad mkvol_paral rsvol
HELPER_NAMES=ubiupdatevol
@@ -15,13 +15,13 @@ HELPERS=$(addprefix helpers/, $(HELPER_NAMES))
# it removes the. If you want to prevent the removal, uncomment the below
#.SECONDARY: $(addsuffix .o, $(TESTS)) $(addsuffix .o, $(HELPERS))
-CFLAGS += -Wall -I$(LIBUBI_HEADER_PATH) -L $(LIBUBI_PATH) -O0 -ggdb
+CFLAGS += -Wall -I$(LIBUBI_HEADER_PATH) -L. -O2
all: ubi-utils libubi $(TESTS) $(HELPERS)
# Compile ubilib with the udevsettle hack
libubi: $(LIBUBI_SRC_PATH)/libubi.c $(LIBUBI_HEADER_PATH)/libubi.h $(LIBUBI_SRC_PATH)/libubi_int.h
- $(CC) $(CFLAGS) -I $(LIBUBI_SRC_PATH) -DUDEV_SETTLE_HACK -c $(LIBUBI_SRC_PATH)/libubi.c -o libubi.o
+ $(CC) $(CFLAGS) -I $(LIBUBI_SRC_PATH) -I../../include -DUDEV_SETTLE_HACK -c $(LIBUBI_SRC_PATH)/libubi.c -o libubi.o
ar cr libubi.a libubi.o
# The below cancels existing implicite rule to make programs from .c files,
diff --git a/tests/ubi-tests/rmvol.c b/tests/ubi-tests/rmvol.c
deleted file mode 100644
index 6c52319..0000000
--- a/tests/ubi-tests/rmvol.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (c) Nokia Corporation, 2007
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Artem B. Bityutskiy
- *
- * Test volume reference counting - create a volume, open a sysfs file
- * belonging to the volume, delete the volume but do not close the file, make
- * sure the file cannot be read, make sure the volume cannot be open, close the
- * file, make sure the volume disappeard, make sure its sysfs subtree
- * disappeared.
- */
-
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include "libubi.h"
-#define TESTNAME "rmvol"
-#include "common.h"
-
-#define SYSFS_FILE "/sys/class/ubi/ubi%d_%d/usable_leb_size"
-
-int main(int argc, char * const argv[])
-{
- int ret, fd;
- char fname[sizeof(SYSFS_FILE) + 20];
- const char *node;
- libubi_t libubi;
- struct ubi_dev_info dev_info;
- struct ubi_mkvol_request req;
- char tmp[100];
-
- if (initial_check(argc, argv))
- return 1;
-
- node = argv[1];
-
- libubi = libubi_open();
- if (libubi == NULL) {
- failed("libubi_open");
- return 1;
- }
-
- if (ubi_get_dev_info(libubi, node, &dev_info)) {
- failed("ubi_get_dev_info");
- goto out_libubi;
- }
-
- /* Create a small dynamic volume */
- req.vol_id = UBI_VOL_NUM_AUTO;
- req.alignment = dev_info.min_io_size;
- req.bytes = dev_info.leb_size;
- req.vol_type = UBI_DYNAMIC_VOLUME;
- req.name = "rmvol";
-
- if (ubi_mkvol(libubi, node, &req)) {
- failed("ubi_mkvol");
- perror("ubi_mkvol");
- goto out_libubi;
- }
-
- /* Open volume-related sysfs file */
- sprintf(fname, SYSFS_FILE, dev_info.dev_num, req.vol_id);
- fd = open(fname, O_RDONLY);
- if (fd == -1) {
- failed("open");
- perror("open");
- goto out_rmvol;
- }
-
- /* Remove the volume, but do not close the file */
- if (ubi_rmvol(libubi, node, req.vol_id)) {
- failed("ubi_rmvol");
- perror("ubi_rmvol");
- goto out_close;
- }
-
- /* Try to read from the file, this should fail */
- ret = read(fd, tmp, 100);
- if (ret != -1) {
- failed("read");
- err_msg("read returned %d, expected -1", ret);
- goto out_close;
- }
-
- /* Close the file and try to open it again, should fail */
- close(fd);
- fd = open(fname, O_RDONLY);
- if (fd != -1) {
- failed("open");
- err_msg("opened %s again, open returned %d, expected -1",
- fname, fd);
- goto out_libubi;
- }
-
- libubi_close(libubi);
- return 0;
-
-out_rmvol:
- ubi_rmvol(libubi, node, req.vol_id);
-out_libubi:
- libubi_close(libubi);
- return 1;
-
-out_close:
- close(fd);
- libubi_close(libubi);
- return 1;
-}
-
-#if 0
-/**
- * mkvol_alignment - create volumes with different alignments.
- *
- * Thus function returns %0 in case of success and %-1 in case of failure.
- */
-static int mkvol_alignment(void)
-{
- struct ubi_mkvol_request req;
- int i, vol_id, ebsz;
- const char *name = TESTNAME ":mkvol_alignment()";
- int alignments[] = ALIGNMENTS(dev_info.leb_size);
-
- for (i = 0; i < sizeof(alignments)/sizeof(int); i++) {
- req.vol_id = UBI_VOL_NUM_AUTO;
-
- /* Alignment should actually be multiple of min. I/O size */
- req.alignment = alignments[i];
- req.alignment -= req.alignment % dev_info.min_io_size;
- if (req.alignment == 0)
- req.alignment = dev_info.min_io_size;
-
- /* Bear in mind alignment reduces EB size */
- ebsz = dev_info.leb_size - dev_info.leb_size % req.alignment;
- req.bytes = dev_info.avail_lebs * ebsz;
-
- req.vol_type = UBI_DYNAMIC_VOLUME;
- req.name = name;
-
- if (ubi_mkvol(libubi, node, &req)) {
- failed("ubi_mkvol");
- err_msg("alignment %d", req.alignment);
- return -1;
- }
-
- vol_id = req.vol_id;
- if (check_volume(vol_id, &req))
- goto remove;
-
- if (ubi_rmvol(libubi, node, vol_id)) {
- failed("ubi_rmvol");
- return -1;
- }
- }
-
- return 0;
-
-remove:
- ubi_rmvol(libubi, node, vol_id);
- return -1;
-}
-
-/**
- * mkvol_basic - simple test that checks basic volume creation capability.
- *
- * Thus function returns %0 in case of success and %-1 in case of failure.
- */
-static int mkvol_basic(void)
-{
- struct ubi_mkvol_request req;
- struct ubi_vol_info vol_info;
- int vol_id, ret;
- const char *name = TESTNAME ":mkvol_basic()";
-
- /* Create dynamic volume of maximum size */
- req.vol_id = UBI_VOL_NUM_AUTO;
- req.alignment = 1;
- req.bytes = dev_info.avail_bytes;
- req.vol_type = UBI_DYNAMIC_VOLUME;
- req.name = name;
-
- if (ubi_mkvol(libubi, node, &req)) {
- failed("ubi_mkvol");
- return -1;
- }
-
- vol_id = req.vol_id;
- if (check_volume(vol_id, &req))
- goto remove;
-
- if (ubi_rmvol(libubi, node, vol_id)) {
- failed("ubi_rmvol");
- return -1;
- }
-
- /* Create static volume of maximum size */
- req.vol_id = UBI_VOL_NUM_AUTO;
- req.alignment = 1;
- req.bytes = dev_info.avail_bytes;
- req.vol_type = UBI_STATIC_VOLUME;
- req.name = name;
-
- if (ubi_mkvol(libubi, node, &req)) {
- failed("ubi_mkvol");
- return -1;
- }
-
- vol_id = req.vol_id;
- if (check_volume(vol_id, &req))
- goto remove;
-
- if (ubi_rmvol(libubi, node, vol_id)) {
- failed("ubi_rmvol");
- return -1;
- }
-
- /* Make sure volume does not exist */
- ret = ubi_get_vol_info1(libubi, dev_info.dev_num, vol_id, &vol_info);
- if (ret == 0) {
- err_msg("removed volume %d exists", vol_id);
- goto remove;
- }
-
- return 0;
-
-remove:
- ubi_rmvol(libubi, node, vol_id);
- return -1;
-}
-
-/**
- * mkvol_multiple - test multiple volumes creation
- *
- * Thus function returns %0 if the test passed and %-1 if not.
- */
-static int mkvol_multiple(void)
-{
- struct ubi_mkvol_request req;
- int i, ret, max = dev_info.max_vol_count;
- const char *name = TESTNAME ":mkvol_multiple()";
-
- /* Create maximum number of volumes */
- for (i = 0; i < max; i++) {
- char nm[strlen(name) + 50];
-
- req.vol_id = UBI_VOL_NUM_AUTO;
- req.alignment = 1;
- req.bytes = 1;
- req.vol_type = UBI_STATIC_VOLUME;
-
- sprintf(&nm[0], "%s:%d", name, i);
- req.name = &nm[0];
-
- if (ubi_mkvol(libubi, node, &req)) {
- if (errno == ENFILE) {
- max = i;
- break;
- }
- failed("ubi_mkvol");
- err_msg("vol_id %d", i);
- goto remove;
- }
-
- if (check_volume(req.vol_id, &req)) {
- err_msg("vol_id %d", i);
- goto remove;
- }
- }
-
- for (i = 0; i < max; i++) {
- struct ubi_vol_info vol_info;
-
- if (ubi_rmvol(libubi, node, i)) {
- failed("ubi_rmvol");
- return -1;
- }
-
- /* Make sure volume does not exist */
- ret = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info);
- if (ret == 0) {
- err_msg("removed volume %d exists", i);
- goto remove;
- }
- }
-
- return 0;
-
-remove:
- for (i = 0; i < dev_info.max_vol_count + 1; i++)
- ubi_rmvol(libubi, node, i);
- return -1;
-}
-#endif
diff --git a/tests/ubi-tests/runtests.sh b/tests/ubi-tests/runtests.sh
index 7072e03..fa10c3e 100755
--- a/tests/ubi-tests/runtests.sh
+++ b/tests/ubi-tests/runtests.sh
@@ -2,7 +2,7 @@
ubidev="$1"
tests="mkvol_basic mkvol_bad mkvol_paral rsvol io_basic io_read io_update
-io_paral rmvol"
+io_paral volrefcnt"
if test -z "$ubidev";
then
diff --git a/tests/ubi-tests/volrefcnt.c b/tests/ubi-tests/volrefcnt.c
new file mode 100644
index 0000000..a56deae
--- /dev/null
+++ b/tests/ubi-tests/volrefcnt.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) Nokia Corporation, 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Artem B. Bityutskiy
+ *
+ * Test volume reference counting - create a volume, open a sysfs file
+ * belonging to the volume, delete the volume but do not close the file, make
+ * sure the file cannot be read, close the file, make sure the volume
+ * disappeard, make sure its sysfs subtree disappeared.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "libubi.h"
+#define TESTNAME "rmvol"
+#include "common.h"
+
+#define SYSFS_FILE "/sys/class/ubi/ubi%d_%d/usable_eb_size"
+
+int main(int argc, char * const argv[])
+{
+ int ret, fd;
+ char fname[sizeof(SYSFS_FILE) + 20];
+ const char *node;
+ libubi_t libubi;
+ struct ubi_dev_info dev_info;
+ struct ubi_mkvol_request req;
+ char tmp[100];
+
+ if (initial_check(argc, argv))
+ return 1;
+
+ node = argv[1];
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ failed("libubi_open");
+ return 1;
+ }
+
+ if (ubi_get_dev_info(libubi, node, &dev_info)) {
+ failed("ubi_get_dev_info");
+ goto out_libubi;
+ }
+
+ /* Create a small dynamic volume */
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.alignment = dev_info.min_io_size;
+ req.bytes = dev_info.leb_size;
+ req.vol_type = UBI_DYNAMIC_VOLUME;
+ req.name = "rmvol";
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ goto out_libubi;
+ }
+
+ /* Open volume-related sysfs file */
+ sprintf(fname, SYSFS_FILE, dev_info.dev_num, req.vol_id);
+ fd = open(fname, O_RDONLY);
+ if (fd == -1) {
+ err_msg("cannot open %s", fname);
+ failed("open");
+ goto out_rmvol;
+ }
+
+ /* Remove the volume, but do not close the file */
+ if (ubi_rmvol(libubi, node, req.vol_id)) {
+ failed("ubi_rmvol");
+ perror("ubi_rmvol");
+ goto out_close;
+ }
+
+ /* Try to read from the file, this should fail */
+ ret = read(fd, tmp, 100);
+ if (ret != -1) {
+ err_msg("read returned %d, expected -1", ret);
+ failed("read");
+ goto out_close;
+ }
+
+ /* Close the file and try to open it again, should fail */
+ close(fd);
+ fd = open(fname, O_RDONLY);
+ if (fd != -1) {
+ err_msg("opened %s again, open returned %d, expected -1",
+ fname, fd);
+ failed("open");
+ goto out_libubi;
+ }
+
+ libubi_close(libubi);
+ return 0;
+
+out_rmvol:
+ ubi_rmvol(libubi, node, req.vol_id);
+out_libubi:
+ libubi_close(libubi);
+ return 1;
+
+out_close:
+ close(fd);
+ libubi_close(libubi);
+ return 1;
+}
diff --git a/ubi-utils/Makefile b/ubi-utils/Makefile
index abd5dc4..9fd862d 100644
--- a/ubi-utils/Makefile
+++ b/ubi-utils/Makefile
@@ -15,7 +15,8 @@ CFLAGS := -I./inc -I./src -I$(KERNELHDR) $(OPTFLAGS) -Werror \
PERLPROGS = mkpfi ubicrc32.pl
TARGETS = ubiupdate ubimkvol ubirmvol pfiflash pddcustomize ubimirror \
- bin2nand nand2bin ubigen mkbootenv unubi pfi2bin ubicrc32 ubinfo
+ bin2nand nand2bin ubigen mkbootenv unubi pfi2bin ubicrc32 ubinfo \
+ ubiattach ubidetach
vpath %.c ./src
@@ -31,11 +32,17 @@ IGNORE=${wildcard .*.c.dep}
-include ${IGNORE}
clean:
- rm -rf *.o $(TARGETS) .*.c.dep
+ rm -rf *.o $(TARGETS) .*.c.dep libubi.a
libubi: libubi.o
ar cr libubi.a libubi.o
+ubidetach: ubidetach.o common.o libubi.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
+ubiattach: ubiattach.o common.o libubi.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
ubinfo: ubinfo.o common.o libubi.o
$(CC) $(LDFLAGS) -o $@ $^
diff --git a/ubi-utils/inc/libubi.h b/ubi-utils/inc/libubi.h
index b83f6c6..0cdb67c 100644
--- a/ubi-utils/inc/libubi.h
+++ b/ubi-utils/inc/libubi.h
@@ -39,6 +39,22 @@ extern "C" {
typedef void * libubi_t;
/**
+ * struct ubi_attach_request - MTD device attachement request.
+ * @dev_num: number to assigne to the newly created UBI device
+ * (%UBI_DEV_NUM_AUTO should be used to automatically assign the
+ * number)
+ * @mtd_num: MTD device number to attach
+ * @vid_hdr_offset: VID header offset (%0 means default offset and this is what
+ * most of the users want)
+ */
+struct ubi_attach_request
+{
+ int dev_num;
+ int mtd_num;
+ int vid_hdr_offset;
+};
+
+/**
* struct ubi_mkvol_request - volume creation request.
* @vol_id: ID to assign to the new volume (%UBI_VOL_NUM_AUTO should be used to
* automatically assign ID)
@@ -167,8 +183,8 @@ void libubi_close(libubi_t desc);
/**
* ubi_get_info - get general UBI information.
- * @info: pointer to the &struct ubi_info object to fill
* @desc: UBI library descriptor
+ * @info: pointer to the &struct ubi_info object to fill
*
* This function fills the passed @info object with general UBI information and
* returns %0 in case of success and %-1 in case of failure.
@@ -176,6 +192,42 @@ void libubi_close(libubi_t desc);
int ubi_get_info(libubi_t desc, struct ubi_info *info);
/**
+ * ubi_attach_mtd - attach MTD device to UBI.
+ * @desc: UBI library descriptor
+ * @node: name of the UBI control character device node
+ * @req: MTD attach request.
+ *
+ * This function creates a new UBI device by attaching an MTD device as
+ * described by @req. Returns %0 in case of success and %-1 in case of failure.
+ * The newly created UBI device number is returned in @req->dev_num.
+ */
+int ubi_attach_mtd(libubi_t desc, const char *node,
+ struct ubi_attach_request *req);
+
+/**
+ * ubi_detach_mtd - detach an MTD device.
+ * @desc: UBI library descriptor
+ * @node: name of the UBI control character device node
+ * @mtd_num: MTD device number to detach
+ *
+ * This function detaches MTD device number @mtd_num from UBI, which means the
+ * corresponding UBI device is removed. Returns zero in case of success and %-1
+ * in case of failure.
+ */
+int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num);
+
+/**
+ * ubi_remove_dev - remove an UBI device.
+ * @desc: UBI library descriptor
+ * @node: name of the UBI control character device node
+ * @ubi_dev: UBI device number to remove
+ *
+ * This function removes UBI device number @ubi_dev and returns zero in case of
+ * success and %-1 in case of failure.
+ */
+int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev);
+
+/**
* ubi_mkvol - create an UBI volume.
* @desc: UBI library descriptor
* @node: name of the UBI character device to create a volume at
diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c
index 32d988e..855aa82 100644
--- a/ubi-utils/src/libubi.c
+++ b/ubi-utils/src/libubi.c
@@ -434,7 +434,7 @@ static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num,
}
if (i > info.highest_dev_num) {
- errno = ENOENT;
+ errno = ENODEV;
return -1;
}
@@ -442,12 +442,13 @@ static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num,
sprintf(file, lib->ubi_vol, i, minor - 1);
fd = open(file, O_RDONLY);
if (fd == -1) {
- errno = ENOENT;
+ errno = ENODEV;
return -1;
}
*dev_num = i;
*vol_id = minor - 1;
+ errno = 0;
return 0;
}
@@ -503,12 +504,40 @@ static int dev_node2num(struct libubi *lib, const char *node, int *dev_num)
errno = EINVAL;
return -1;
}
+ errno = 0;
*dev_num = i;
return 0;
}
}
- errno = ENOENT;
+ errno = ENODEV;
+ return -1;
+}
+
+static int mtd_num2ubi_dev(struct libubi *lib, int mtd_num, int *dev_num)
+{
+ struct ubi_info info;
+ int i, ret, mtd_num1;
+
+ if (ubi_get_info((libubi_t *)lib, &info))
+ return -1;
+
+ for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+ ret = dev_read_int(lib->dev_mtd_num, i, &mtd_num1);
+ if (ret) {
+ if (errno == ENOENT)
+ continue;
+ return -1;
+ }
+
+ if (mtd_num1 == mtd_num) {
+ errno = 0;
+ *dev_num = i;
+ return 0;
+ }
+ }
+
+ errno = ENODEV;
return -1;
}
@@ -596,6 +625,10 @@ libubi_t libubi_open(void)
if (!lib->dev_min_io_size)
goto out_error;
+ lib->dev_mtd_num = mkpath(lib->ubi_dev, DEV_MTD_NUM);
+ if (!lib->dev_mtd_num)
+ goto out_error;
+
lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT);
if (!lib->ubi_vol)
goto out_error;
@@ -661,6 +694,7 @@ void libubi_close(libubi_t desc)
free(lib->vol_dev);
free(lib->vol_type);
free(lib->ubi_vol);
+ free(lib->dev_mtd_num);
free(lib->dev_min_io_size);
free(lib->dev_max_vols);
free(lib->dev_bad_rsvd);
@@ -679,6 +713,74 @@ void libubi_close(libubi_t desc)
free(lib);
}
+int ubi_attach_mtd(libubi_t desc, const char *node,
+ struct ubi_attach_request *req)
+{
+ int fd, ret;
+ struct ubi_attach_req r;
+
+ memset(&r, sizeof(struct ubi_attach_req), '\0');
+
+ 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 -1;
+
+ 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;
+ if (system("udevsettle") == -1)
+ return -1;
+#endif
+
+ return ret;
+}
+
+int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num)
+{
+ int ret, ubi_dev;
+
+ ret = mtd_num2ubi_dev(desc, mtd_num, &ubi_dev);
+ if (ret == -1)
+ return ret;
+
+ return ubi_remove_dev(desc, node, ubi_dev);
+}
+
+int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev)
+{
+ int fd, ret;
+
+ desc = desc;
+
+ fd = open(node, O_RDONLY);
+ if (fd == -1)
+ return -1;
+ ret = ioctl(fd, UBI_IOCDET, &ubi_dev);
+ if (ret == -1)
+ goto out_close;
+
+#ifdef UDEV_SETTLE_HACK
+ if (system("udevsettle") == -1)
+ return -1;
+#endif
+
+out_close:
+ close(fd);
+ return ret;
+}
+
int ubi_node_type(libubi_t desc, const char *node)
{
struct stat st;
@@ -842,16 +944,18 @@ int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req)
return -1;
ret = ioctl(fd, UBI_IOCMKVOL, &r);
- if (ret == 0)
- req->vol_id = r.vol_id;
+ if (ret == -1)
+ goto out_close;
- close(fd);
+ req->vol_id = r.vol_id;
#ifdef UDEV_SETTLE_HACK
if (system("udevsettle") == -1)
return -1;
#endif
+out_close:
+ close(fd);
return ret;
}
@@ -865,13 +969,16 @@ int ubi_rmvol(libubi_t desc, const char *node, int vol_id)
return -1;
ret = ioctl(fd, UBI_IOCRMVOL, &vol_id);
- close(fd);
+ if (ret == -1)
+ goto out_close;
#ifdef UDEV_SETTLE_HACK
if (system("udevsettle") == -1)
return -1;
#endif
+out_close:
+ close(fd);
return ret;
}
@@ -880,7 +987,7 @@ int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes)
int fd, ret;
struct ubi_rsvol_req req;
- desc = desc;
+ desc = desc;
fd = open(node, O_RDONLY);
if (fd == -1)
return -1;
diff --git a/ubi-utils/src/libubi_int.h b/ubi-utils/src/libubi_int.h
index 4c26eb5..6490864 100644
--- a/ubi-utils/src/libubi_int.h
+++ b/ubi-utils/src/libubi_int.h
@@ -58,6 +58,7 @@ extern "C" {
#define DEV_MAX_RSVD "reserved_for_bad"
#define DEV_MAX_VOLS "max_vol_count"
#define DEV_MIN_IO_SIZE "min_io_size"
+#define DEV_MTD_NUM "mtd_num"
#define UBI_VOL_NAME_PATT "ubi%d_%d"
#define VOL_TYPE "type"
@@ -114,6 +115,7 @@ struct libubi
char *dev_bad_rsvd;
char *dev_max_vols;
char *dev_min_io_size;
+ char *dev_mtd_num;
char *ubi_vol;
char *vol_type;
char *vol_dev;
diff --git a/ubi-utils/src/ubiattach.c b/ubi-utils/src/ubiattach.c
new file mode 100644
index 0000000..3476a3d
--- /dev/null
+++ b/ubi-utils/src/ubiattach.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * An utility to attach MTD devices to UBI.
+ *
+ * Author: Artem Bityutskiy
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <libubi.h>
+#include "common.h"
+
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME "ubiattach"
+
+/* The variables below are set by command line arguments */
+struct args {
+ int devn;
+ int mtdn;
+ int vidoffs;
+ const char *node;
+};
+
+static struct args myargs = {
+ .devn = UBI_DEV_NUM_AUTO,
+ .mtdn = -1,
+ .vidoffs = 0,
+ .node = NULL,
+};
+
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+ " - a tool to attach MTD device to UBI.";
+
+static const char *optionsstr =
+"-d, --devn=<UBI device number> the number to assign to the newly created UBI device\n"
+" (the number is assigned automatically if this is not\n"
+" specified\n"
+"-m, --mtdn=<MTD device number> MTD device number to attach\n"
+"-o, --vid-hdr-offset VID header offset (do not specify this unless you\n"
+" really know what you do and the optimal defaults wukk\n"
+" be used)\n"
+"-h, --help print help message\n"
+"-V, --version print program version";
+
+static const char *usage =
+"Usage: " PROGRAM_NAME "<UBI control device node file name> [-m <MTD device number>] [-d <UBI device number>]\n"
+"\t\t[--mtdn=<MTD device number>] [--devn <UBI device number>]\n"
+"Example 1: " PROGRAM_NAME " /dev/ubi_ctrl -m 0 - attach MTD device 0 (mtd0) to UBI\n"
+"Example 2: " PROGRAM_NAME " /dev/ubi_ctrl -m 0 -d 3 - attach MTD device 0 (mtd0) to UBI and\n"
+" and create UBI device number 3 (ubi3)";
+
+static const struct option long_options[] = {
+ { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' },
+ { .name = "mtdn", .has_arg = 1, .flag = NULL, .val = 'm' },
+ { .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'o' },
+ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
+ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+ { NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+ while (1) {
+ int key;
+ char *endp;
+
+ key = getopt_long(argc, argv, "m:d:ohV", long_options, NULL);
+ if (key == -1)
+ break;
+
+ switch (key) {
+ case 'd':
+ myargs.devn = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg || myargs.devn < 0) {
+ errmsg("bad UBI device number: \"%s\"", optarg);
+ return -1;
+ }
+
+ break;
+
+ case 'm':
+ myargs.mtdn = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg || myargs.mtdn < 0) {
+ errmsg("bad MTD device number: \"%s\"", optarg);
+ return -1;
+ }
+
+ break;
+
+ case 'o':
+ myargs.vidoffs = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg || myargs.vidoffs <= 0) {
+ errmsg("bad VID header offset: \"%s\"", optarg);
+ return -1;
+ }
+
+ break;
+
+ case 'h':
+ fprintf(stderr, "%s\n\n", doc);
+ fprintf(stderr, "%s\n\n", usage);
+ fprintf(stderr, "%s\n", optionsstr);
+ exit(0);
+
+ case 'V':
+ fprintf(stderr, "%s\n", PROGRAM_VERSION);
+ exit(0);
+
+ case ':':
+ errmsg("parameter is missing");
+ return -1;
+
+ default:
+ fprintf(stderr, "Use -h for help\n");
+ exit(-1);
+ }
+ }
+
+ if (optind == argc) {
+ errmsg("UBI control device name was not specified (use -h for help)");
+ return -1;
+ } else if (optind != argc - 1) {
+ errmsg("more then one UBI control device specified (use -h for help)");
+ return -1;
+ }
+
+ if (myargs.mtdn == -1) {
+ errmsg("MTD device number was not specified (use -h for help)");
+ return -1;
+ }
+
+ myargs.node = argv[optind];
+ return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+ int err;
+ libubi_t libubi;
+ struct ubi_info ubi_info;
+ struct ubi_dev_info dev_info;
+ struct ubi_attach_request req;
+
+ err = parse_opt(argc, argv);
+ if (err)
+ return -1;
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ errmsg("cannot open libubi");
+ perror("libubi_open");
+ return -1;
+ }
+
+ /*
+ * Make sure the kernel is fresh enough and this feature is supported.
+ */
+ err = ubi_get_info(libubi, &ubi_info);
+ if (err) {
+ errmsg("cannot get UBI information");
+ perror("ubi_get_info");
+ goto out_libubi;
+ }
+
+ if (ubi_info.ctrl_major == -1) {
+ errmsg("MTD attach/detach feature is not supported by your kernel");
+ goto out_libubi;
+ }
+
+ req.dev_num = myargs.devn;
+ req.mtd_num = myargs.mtdn;
+ req.vid_hdr_offset = myargs.vidoffs;
+
+ err = ubi_attach_mtd(libubi, myargs.node, &req);
+ if (err) {
+ errmsg("cannot attach mtd%d", myargs.mtdn);
+ perror("ubi_attach_mtd");
+ goto out_libubi;
+ }
+
+ /* Print some information about the new UBI device */
+ err = ubi_get_dev_info1(libubi, req.dev_num, &dev_info);
+ if (err) {
+ errmsg("cannot get information about newly created UBI device");
+ perror("ubi_get_dev_info1");
+ goto out_libubi;
+ }
+
+ printf("UBI device number %d, total %d LEBs (", dev_info.dev_num, dev_info.total_lebs);
+ ubiutils_print_bytes(dev_info.total_bytes, 0);
+ printf("), available %d LEBs (", dev_info.avail_lebs);
+ ubiutils_print_bytes(dev_info.avail_bytes, 0);
+ printf("), LEB size ");
+ ubiutils_print_bytes(dev_info.leb_size, 1);
+ printf("\n");
+
+ libubi_close(libubi);
+ return 0;
+
+out_libubi:
+ libubi_close(libubi);
+ return -1;
+}
diff --git a/ubi-utils/src/ubicrc32.c b/ubi-utils/src/ubicrc32.c
index 034cb10..cde3104 100644
--- a/ubi-utils/src/ubicrc32.c
+++ b/ubi-utils/src/ubicrc32.c
@@ -39,8 +39,8 @@
#define PROGRAM_VERSION "1.2"
#define PROGRAM_NAME "ubicrc32"
-static const char *doc = "Version " PROGRAM_VERSION "\n"
- PROGRAM_NAME " - a tool to calculate CRC32 with UBI start value (0xFFFFFFFF)";
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+ " - a tool to calculate CRC32 with UBI start value (0xFFFFFFFF)";
static const char *optionsstr =
"-h, --help print help message\n"
diff --git a/ubi-utils/src/ubidetach.c b/ubi-utils/src/ubidetach.c
new file mode 100644
index 0000000..cde21d0
--- /dev/null
+++ b/ubi-utils/src/ubidetach.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * An utility to delete UBI devices (detach MTD devices from UBI).
+ *
+ * Author: Artem Bityutskiy
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <libubi.h>
+#include "common.h"
+
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME "ubidetach"
+
+/* The variables below are set by command line arguments */
+struct args {
+ int devn;
+ int mtdn;
+ const char *node;
+};
+
+static struct args myargs = {
+ .devn = UBI_DEV_NUM_AUTO,
+ .mtdn = -1,
+ .node = NULL,
+};
+
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+" - a tool to remove UBI devices (detach MTD devices from UBI)";
+
+static const char *optionsstr =
+"-d, --devn=<UBI device number> UBI device number to delete\n"
+"-m, --mtdn=<MTD device number> or altrnatively, MTD device number to detach -\n"
+" this will delete corresponding UBI device\n"
+"-h, --help print help message\n"
+"-V, --version print program version";
+
+static const char *usage =
+"Usage: " PROGRAM_NAME "<UBI control device node file name> [-d <UBI device number>] [-m <MTD device number>]\n"
+"\t\t[--devn <UBI device number>] [--mtdn=<MTD device number>]\n"
+"Example 1: " PROGRAM_NAME " /dev/ubi_ctrl -d 2 - delete UBI device 2 (ubi2)\n"
+"Example 2: " PROGRAM_NAME " /dev/ubi_ctrl -m 0 - detach MTD device 0 (mtd0)";
+
+static const struct option long_options[] = {
+ { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' },
+ { .name = "mtdn", .has_arg = 1, .flag = NULL, .val = 'm' },
+ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
+ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+ { NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+ while (1) {
+ int key;
+ char *endp;
+
+ key = getopt_long(argc, argv, "m:d:hV", long_options, NULL);
+ if (key == -1)
+ break;
+
+ switch (key) {
+ case 'd':
+ myargs.devn = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg || myargs.devn < 0) {
+ errmsg("bad UBI device number: \"%s\"", optarg);
+ return -1;
+ }
+
+ break;
+
+ case 'm':
+ myargs.mtdn = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg || myargs.mtdn < 0) {
+ errmsg("bad MTD device number: \"%s\"", optarg);
+ return -1;
+ }
+
+ break;
+
+ case 'h':
+ fprintf(stderr, "%s\n\n", doc);
+ fprintf(stderr, "%s\n\n", usage);
+ fprintf(stderr, "%s\n", optionsstr);
+ exit(0);
+
+ case 'V':
+ fprintf(stderr, "%s\n", PROGRAM_VERSION);
+ exit(0);
+
+ case ':':
+ errmsg("parameter is missing");
+ return -1;
+
+ default:
+ fprintf(stderr, "Use -h for help\n");
+ exit(-1);
+ }
+ }
+
+ if (optind == argc) {
+ errmsg("UBI control device name was not specified (use -h for help)");
+ return -1;
+ } else if (optind != argc - 1) {
+ errmsg("more then one UBI control device specified (use -h for help)");
+ return -1;
+ }
+
+ if (myargs.mtdn == -1 && myargs.devn == -1) {
+ errmsg("neither MTD nor UBI devices were specified (use -h for help)");
+ return -1;
+ }
+
+ if (myargs.mtdn != -1 && myargs.devn != -1) {
+ errmsg("specify either MTD or UBI device (use -h for help)");
+ return -1;
+ }
+
+ myargs.node = argv[optind];
+ return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+ int err;
+ libubi_t libubi;
+ struct ubi_info ubi_info;
+
+ err = parse_opt(argc, argv);
+ if (err)
+ return -1;
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ errmsg("cannot open libubi");
+ perror("libubi_open");
+ return -1;
+ }
+
+ /*
+ * Make sure the kernel is fresh enough and this feature is supported.
+ */
+ err = ubi_get_info(libubi, &ubi_info);
+ if (err) {
+ errmsg("cannot get UBI information");
+ perror("ubi_get_info");
+ goto out_libubi;
+ }
+
+ if (ubi_info.ctrl_major == -1) {
+ errmsg("MTD detach/detach feature is not supported by your kernel");
+ goto out_libubi;
+ }
+
+ if (myargs.devn != -1) {
+ err = ubi_remove_dev(libubi, myargs.node, myargs.devn);
+ if (err) {
+ errmsg("cannot remove ubi%d", myargs.devn);
+ perror("ubi_remove_dev");
+ goto out_libubi;
+ }
+ } else {
+ err = ubi_detach_mtd(libubi, myargs.node, myargs.mtdn);
+ if (err) {
+ errmsg("cannot detach mtd%d", myargs.mtdn);
+ perror("ubi_detach_mtd");
+ goto out_libubi;
+ }
+ }
+
+ libubi_close(libubi);
+ return 0;
+
+out_libubi:
+ libubi_close(libubi);
+ return -1;
+}
+
diff --git a/ubi-utils/src/ubimkvol.c b/ubi-utils/src/ubimkvol.c
index 38c737d..42b61b8 100644
--- a/ubi-utils/src/ubimkvol.c
+++ b/ubi-utils/src/ubimkvol.c
@@ -36,7 +36,7 @@
#define PROGRAM_VERSION "1.6"
#define PROGRAM_NAME "ubimkvol"
-/* The variables below is set by command line arguments */
+/* The variables below are set by command line arguments */
struct args {
int vol_id;
int vol_type;
@@ -61,8 +61,8 @@ static struct args myargs = {
.maxavs = 0,
};
-static const char *doc = "Version " PROGRAM_VERSION "\n"
- PROGRAM_NAME " - a tool to create UBI volumes.";
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+ " - a tool to create UBI volumes.";
static const char *optionsstr =
"-a, --alignment=<alignment> volume alignment (default is 1)\n"
@@ -228,7 +228,7 @@ static int parse_opt(int argc, char * const argv[])
errmsg("UBI device name was not specified (use -h for help)");
return -1;
} else if (optind != argc - 1) {
- errmsg("more then one UBI devices specified (use -h for help)");
+ errmsg("more then one UBI device specified (use -h for help)");
return -1;
}
diff --git a/ubi-utils/src/ubinfo.c b/ubi-utils/src/ubinfo.c
index c907335..35c70a1 100644
--- a/ubi-utils/src/ubinfo.c
+++ b/ubi-utils/src/ubinfo.c
@@ -34,7 +34,7 @@
#define PROGRAM_VERSION "1.0"
#define PROGRAM_NAME "ubinfo"
-/* The variables below is set by command line arguments */
+/* The variables below are set by command line arguments */
struct args {
int devn;
int vol_id;
@@ -49,8 +49,8 @@ static struct args myargs = {
.node = NULL,
};
-static const char *doc = "Version " PROGRAM_VERSION "\n"
- PROGRAM_NAME " - a tool to print UBI information.";
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+ " - a tool to print UBI information.";
static const char *optionsstr =
"-d, --devn=<UBI device number> UBI device number to get information about\n"
diff --git a/ubi-utils/src/ubirmvol.c b/ubi-utils/src/ubirmvol.c
index 5f35525..60bcdc0 100644
--- a/ubi-utils/src/ubirmvol.c
+++ b/ubi-utils/src/ubirmvol.c
@@ -36,7 +36,7 @@
#define PROGRAM_VERSION "1.5"
#define PROGRAM_NAME "ubirmvol"
-/* The variables below is set by command line arguments */
+/* The variables below are set by command line arguments */
struct args {
int vol_id;
const char *node;
@@ -47,8 +47,8 @@ static struct args myargs = {
.node = NULL,
};
-static const char *doc = "Version: " PROGRAM_VERSION "\n"
- PROGRAM_NAME " - a tool to remove UBI volumes.";
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+ " - a tool to remove UBI volumes.";
static const char *optionsstr =
" -n, --vol_id=<volume id> volume ID to remove\n"
@@ -121,7 +121,7 @@ static int parse_opt(int argc, char * const argv[])
errmsg("UBI device name was not specified (use -h for help)");
return -1;
} else if (optind != argc - 1) {
- errmsg("more then one UBI devices specified (use -h for help)");
+ errmsg("more then one UBI device specified (use -h for help)");
return -1;
}
diff --git a/ubi-utils/src/ubiupdate.c b/ubi-utils/src/ubiupdate.c
index 1b9188e..75222d4 100644
--- a/ubi-utils/src/ubiupdate.c
+++ b/ubi-utils/src/ubiupdate.c
@@ -53,8 +53,8 @@ static struct args myargs = {
.img = NULL,
};
-static const char *doc = "Version " PROGRAM_VERSION "\n"
- PROGRAM_NAME " - a tool to write data to UBI volumes.";
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+ " - a tool to write data to UBI volumes.";
static const char *optionsstr =
"-n, --vol_id=<volume id> ID of UBI volume to update\n"