]> www.infradead.org Git - mtd-utils.git/commitdiff
ubi-utils: re-arrange directory layout
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Tue, 17 Mar 2009 08:14:54 +0000 (10:14 +0200)
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Tue, 17 Mar 2009 08:16:38 +0000 (10:16 +0200)
Move new-utils to ubi-utils and old ones to ubi-utils/old-utils.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
105 files changed:
ubi-utils/.gitignore
ubi-utils/LICENSE.libiniparser [moved from ubi-utils/new-utils/LICENSE.libiniparser with 100% similarity]
ubi-utils/Makefile
ubi-utils/include/libiniparser.h [moved from ubi-utils/new-utils/include/libiniparser.h with 100% similarity]
ubi-utils/include/libmtd.h [moved from ubi-utils/new-utils/include/libmtd.h with 100% similarity]
ubi-utils/include/libscan.h [moved from ubi-utils/new-utils/include/libscan.h with 100% similarity]
ubi-utils/include/libubi.h [moved from ubi-utils/new-utils/include/libubi.h with 100% similarity]
ubi-utils/include/libubigen.h [moved from ubi-utils/new-utils/include/libubigen.h with 100% similarity]
ubi-utils/new-utils/.gitignore [deleted file]
ubi-utils/new-utils/Makefile [deleted file]
ubi-utils/new-utils/README [deleted file]
ubi-utils/new-utils/src/crc32.c [deleted file]
ubi-utils/new-utils/src/crc32.h [deleted file]
ubi-utils/new-utils/src/libubi.c [deleted file]
ubi-utils/new-utils/src/libubigen.c [deleted file]
ubi-utils/old-utils/.gitignore [new file with mode: 0644]
ubi-utils/old-utils/Makefile [new file with mode: 0644]
ubi-utils/old-utils/README [moved from ubi-utils/README with 100% similarity]
ubi-utils/old-utils/UBI.TXT [moved from ubi-utils/UBI.TXT with 100% similarity]
ubi-utils/old-utils/doc/unubi.roff [moved from ubi-utils/doc/unubi.roff with 100% similarity]
ubi-utils/old-utils/inc/libubi.h [moved from ubi-utils/inc/libubi.h with 100% similarity]
ubi-utils/old-utils/lib/Makefile.am [moved from ubi-utils/lib/Makefile.am with 100% similarity]
ubi-utils/old-utils/perl/f128_nand_sample.cfg [moved from ubi-utils/perl/f128_nand_sample.cfg with 100% similarity]
ubi-utils/old-utils/perl/f64_nor_sample.cfg [moved from ubi-utils/perl/f64_nor_sample.cfg with 100% similarity]
ubi-utils/old-utils/perl/mkpfi [moved from ubi-utils/perl/mkpfi with 100% similarity]
ubi-utils/old-utils/perl/ubicrc32.pl [moved from ubi-utils/perl/ubicrc32.pl with 100% similarity]
ubi-utils/old-utils/scripts/Makefile [moved from ubi-utils/scripts/Makefile with 100% similarity]
ubi-utils/old-utils/scripts/README [moved from ubi-utils/scripts/README with 100% similarity]
ubi-utils/old-utils/scripts/TODO [moved from ubi-utils/scripts/TODO with 100% similarity]
ubi-utils/old-utils/scripts/bin2nand2bin_test.sh [moved from ubi-utils/scripts/bin2nand2bin_test.sh with 100% similarity]
ubi-utils/old-utils/scripts/inject_biterror.pl [moved from ubi-utils/scripts/inject_biterror.pl with 100% similarity]
ubi-utils/old-utils/scripts/jffs2_test.sh [moved from ubi-utils/scripts/jffs2_test.sh with 100% similarity]
ubi-utils/old-utils/scripts/mkdevs.pl [moved from ubi-utils/scripts/mkdevs.pl with 100% similarity]
ubi-utils/old-utils/scripts/pdd.txt [moved from ubi-utils/scripts/pdd.txt with 100% similarity]
ubi-utils/old-utils/scripts/run_all.sh [moved from ubi-utils/scripts/run_all.sh with 100% similarity]
ubi-utils/old-utils/scripts/test.cfg [moved from ubi-utils/scripts/test.cfg with 100% similarity]
ubi-utils/old-utils/scripts/ubi_jffs2_test.sh [moved from ubi-utils/scripts/ubi_jffs2_test.sh with 100% similarity]
ubi-utils/old-utils/scripts/ubi_test.sh [moved from ubi-utils/scripts/ubi_test.sh with 100% similarity]
ubi-utils/old-utils/scripts/ubi_tools_test.sh [moved from ubi-utils/scripts/ubi_tools_test.sh with 100% similarity]
ubi-utils/old-utils/scripts/unubi_test.sh [moved from ubi-utils/scripts/unubi_test.sh with 100% similarity]
ubi-utils/old-utils/src/bin2nand.c [moved from ubi-utils/src/bin2nand.c with 100% similarity]
ubi-utils/old-utils/src/bootenv.c [moved from ubi-utils/src/bootenv.c with 100% similarity]
ubi-utils/old-utils/src/bootenv.h [moved from ubi-utils/src/bootenv.h with 100% similarity]
ubi-utils/old-utils/src/config.h [moved from ubi-utils/src/config.h with 100% similarity]
ubi-utils/old-utils/src/crc32.c [new file with mode: 0644]
ubi-utils/old-utils/src/crc32.h [new file with mode: 0644]
ubi-utils/old-utils/src/eb_chain.c [moved from ubi-utils/src/eb_chain.c with 100% similarity]
ubi-utils/old-utils/src/error.c [moved from ubi-utils/src/error.c with 100% similarity]
ubi-utils/old-utils/src/error.h [moved from ubi-utils/src/error.h with 100% similarity]
ubi-utils/old-utils/src/example_ubi.h [moved from ubi-utils/src/example_ubi.h with 100% similarity]
ubi-utils/old-utils/src/hashmap.c [moved from ubi-utils/src/hashmap.c with 100% similarity]
ubi-utils/old-utils/src/hashmap.h [moved from ubi-utils/src/hashmap.h with 100% similarity]
ubi-utils/old-utils/src/libpfiflash.c [moved from ubi-utils/src/libpfiflash.c with 100% similarity]
ubi-utils/old-utils/src/libubi.c [new file with mode: 0644]
ubi-utils/old-utils/src/libubi_int.h [moved from ubi-utils/new-utils/src/libubi_int.h with 51% similarity]
ubi-utils/old-utils/src/libubigen.c [new file with mode: 0644]
ubi-utils/old-utils/src/libubimirror.c [moved from ubi-utils/src/libubimirror.c with 100% similarity]
ubi-utils/old-utils/src/list.c [moved from ubi-utils/src/list.c with 100% similarity]
ubi-utils/old-utils/src/list.h [moved from ubi-utils/src/list.h with 100% similarity]
ubi-utils/old-utils/src/mkbootenv.c [moved from ubi-utils/src/mkbootenv.c with 100% similarity]
ubi-utils/old-utils/src/nand2bin.c [moved from ubi-utils/src/nand2bin.c with 100% similarity]
ubi-utils/old-utils/src/nandcorr.c [moved from ubi-utils/src/nandcorr.c with 100% similarity]
ubi-utils/old-utils/src/nandecc.c [moved from ubi-utils/src/nandecc.c with 100% similarity]
ubi-utils/old-utils/src/nandecc.h [moved from ubi-utils/src/nandecc.h with 100% similarity]
ubi-utils/old-utils/src/pddcustomize.c [moved from ubi-utils/src/pddcustomize.c with 100% similarity]
ubi-utils/old-utils/src/peb.c [moved from ubi-utils/src/peb.c with 100% similarity]
ubi-utils/old-utils/src/peb.h [moved from ubi-utils/src/peb.h with 100% similarity]
ubi-utils/old-utils/src/pfi.c [moved from ubi-utils/src/pfi.c with 100% similarity]
ubi-utils/old-utils/src/pfi.h [moved from ubi-utils/src/pfi.h with 100% similarity]
ubi-utils/old-utils/src/pfi2bin.c [moved from ubi-utils/src/pfi2bin.c with 100% similarity]
ubi-utils/old-utils/src/pfiflash.c [moved from ubi-utils/src/pfiflash.c with 100% similarity]
ubi-utils/old-utils/src/pfiflash.h [moved from ubi-utils/src/pfiflash.h with 100% similarity]
ubi-utils/old-utils/src/pfiflash_error.h [moved from ubi-utils/src/pfiflash_error.h with 100% similarity]
ubi-utils/old-utils/src/reader.c [moved from ubi-utils/src/reader.c with 100% similarity]
ubi-utils/old-utils/src/reader.h [moved from ubi-utils/src/reader.h with 100% similarity]
ubi-utils/old-utils/src/ubigen.c [moved from ubi-utils/src/ubigen.c with 100% similarity]
ubi-utils/old-utils/src/ubigen.h [moved from ubi-utils/src/ubigen.h with 100% similarity]
ubi-utils/old-utils/src/ubimirror.c [moved from ubi-utils/src/ubimirror.c with 100% similarity]
ubi-utils/old-utils/src/ubimirror.h [moved from ubi-utils/src/ubimirror.h with 100% similarity]
ubi-utils/old-utils/src/unubi.c [moved from ubi-utils/src/unubi.c with 100% similarity]
ubi-utils/old-utils/src/unubi_analyze.c [moved from ubi-utils/src/unubi_analyze.c with 100% similarity]
ubi-utils/old-utils/src/unubi_analyze.h [moved from ubi-utils/src/unubi_analyze.h with 100% similarity]
ubi-utils/old-utils/testcases.txt [moved from ubi-utils/testcases.txt with 100% similarity]
ubi-utils/src/common.c [moved from ubi-utils/new-utils/src/common.c with 100% similarity]
ubi-utils/src/common.h [moved from ubi-utils/new-utils/src/common.h with 100% similarity]
ubi-utils/src/crc32.c
ubi-utils/src/crc32.h
ubi-utils/src/dictionary.c [moved from ubi-utils/new-utils/src/dictionary.c with 100% similarity]
ubi-utils/src/dictionary.h [moved from ubi-utils/new-utils/src/dictionary.h with 100% similarity]
ubi-utils/src/libiniparser.c [moved from ubi-utils/new-utils/src/libiniparser.c with 100% similarity]
ubi-utils/src/libmtd.c [moved from ubi-utils/new-utils/src/libmtd.c with 100% similarity]
ubi-utils/src/libscan.c [moved from ubi-utils/new-utils/src/libscan.c with 100% similarity]
ubi-utils/src/libubi.c
ubi-utils/src/libubi_int.h
ubi-utils/src/libubigen.c
ubi-utils/src/ubiattach.c [moved from ubi-utils/new-utils/src/ubiattach.c with 100% similarity]
ubi-utils/src/ubicrc32.c [moved from ubi-utils/new-utils/src/ubicrc32.c with 100% similarity]
ubi-utils/src/ubidetach.c [moved from ubi-utils/new-utils/src/ubidetach.c with 100% similarity]
ubi-utils/src/ubiformat.c [moved from ubi-utils/new-utils/src/ubiformat.c with 100% similarity]
ubi-utils/src/ubimkvol.c [moved from ubi-utils/new-utils/src/ubimkvol.c with 100% similarity]
ubi-utils/src/ubinfo.c [moved from ubi-utils/new-utils/src/ubinfo.c with 100% similarity]
ubi-utils/src/ubinize.c [moved from ubi-utils/new-utils/src/ubinize.c with 100% similarity]
ubi-utils/src/ubirename.c [moved from ubi-utils/new-utils/src/ubirename.c with 100% similarity]
ubi-utils/src/ubirmvol.c [moved from ubi-utils/new-utils/src/ubirmvol.c with 100% similarity]
ubi-utils/src/ubiupdatevol.c [moved from ubi-utils/new-utils/src/ubiupdatevol.c with 100% similarity]

index 83e8b71497d796f9d29778c722fdea6aa4b6ccc2..4155cd1bcf26cca17267d9a0b46bff951129f423 100644 (file)
@@ -1,9 +1,10 @@
-/bin2nand
-/mkbootenv
-/nand2bin
-/pddcustomize
-/pfi2bin
-/pfiflash
-/ubigen
-/ubimirror
-/unubi
+/ubiattach
+/ubicrc32
+/ubidetach
+/ubiformat
+/ubimkvol
+/ubinfo
+/ubinize
+/ubirename
+/ubirmvol
+/ubiupdatevol
index 3be813aa90eb011ac6373eb9a801fca60327f165..020fe09561b5dac680faaf80d3621d3f72417d3e 100644 (file)
@@ -4,58 +4,56 @@
 
 KERNELHDR := ../include
 
-CFLAGS ?= -O2 -g -Werror
-CPPFLAGS += -I./inc -I./src -I$(KERNELHDR) \
-       -std=gnu99 -DPACKAGE_VERSION=\"1.0\"
+SUBDIRS = old-utils
 
-PERLPROGS = mkpfi ubicrc32.pl
+#CFLAGS += -Werror
+CPPFLAGS += -Iinclude -Isrc -I$(KERNELHDR)
 
-SUBDIRS = new-utils
+LIBS = libubi libmtd libubigen libiniparser libscan
+TARGETS = ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
+          ubidetach ubinize ubiformat ubirename
 
-TARGETS = pfiflash pddcustomize ubimirror bin2nand nand2bin ubigen \
-       mkbootenv unubi pfi2bin
-
-vpath   %.c ./src
+vpath %.c src
 
 include ../common.mk
 
-$(BUILDDIR)/pddcustomize: $(addprefix $(BUILDDIR)/,\
-       pddcustomize.o error.o libubimirror.o bootenv.o hashmap.o \
-       libubi.o crc32.o)
+# And the below is the rule to get final executable from its .o and common.o
+$(TARGETS): $(addprefix $(BUILDDIR)/,\
+       libubi.a common.o)
+#      $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@
+
+$(BUILDDIR)/ubicrc32: $(addprefix $(BUILDDIR)/,\
+       ubicrc32.o crc32.o)
+#      $(CC) $(CFLAGS) -o $@ $^
 
-$(BUILDDIR)/pfiflash: $(addprefix $(BUILDDIR)/,\
-       pfiflash.o libpfiflash.o list.o reader.o error.o libubimirror.o \
-       bootenv.o hashmap.o pfi.o libubi.o crc32.o)
+$(BUILDDIR)/ubinize: $(addprefix $(BUILDDIR)/,\
+       ubinize.o common.o crc32.o libiniparser.a libubigen.a)
+#      $(CC) $(CFLAGS) $(filter %.o, $^) -L. -liniparser -lubigen -o $@
 
-$(BUILDDIR)/ubimirror: $(addprefix $(BUILDDIR)/,\
-       ubimirror.o error.o libubimirror.o bootenv.o hashmap.o \
-       libubi.o crc32.o)
+$(BUILDDIR)/ubiformat: $(addprefix $(BUILDDIR)/,\
+       ubiformat.o common.o crc32.o libmtd.a libscan.a libubi.a libubigen.a)
+#      $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lmtd -lscan -lubi -lubigen -o $@
 
-$(BUILDDIR)/nand2bin: $(addprefix $(BUILDDIR)/,\
-       nand2bin.o nandecc.o nandcorr.o)
+$(BUILDDIR)/libubi.a: $(BUILDDIR)/libubi.o
 
-$(BUILDDIR)/bin2nand: $(addprefix $(BUILDDIR)/,\
-       bin2nand.o error.o nandecc.o)
+$(BUILDDIR)/libmtd.a: $(BUILDDIR)/libmtd.o
 
-$(BUILDDIR)/ubigen: $(addprefix $(BUILDDIR)/,\
-       ubigen.o libubigen.o crc32.o)
+$(BUILDDIR)/libubigen.a: $(BUILDDIR)/libubigen.o
 
-$(BUILDDIR)/mkbootenv: $(addprefix $(BUILDDIR)/,\
-       mkbootenv.o bootenv.o hashmap.o error.o crc32.o)
+$(BUILDDIR)/libiniparser.a: $(addprefix $(BUILDDIR)/,\
+       libiniparser.o dictionary.o)
 
-$(BUILDDIR)/unubi: $(addprefix $(BUILDDIR)/,\
-       unubi.o crc32.o unubi_analyze.o eb_chain.o)
+$(BUILDDIR)/libscan.a: $(addprefix $(BUILDDIR)/,\
+       libscan.o crc32.o)
 
-$(BUILDDIR)/pfi2bin: $(addprefix $(BUILDDIR)/,\
-       pfi2bin.o peb.o error.o list.o crc32.o libubigen.o bootenv.o \
-       hashmap.o reader.o pfi.o)
+clean::
+       rm -f $(addsuffix .a, $(LIBS))
 
 install::
        mkdir -p ${DESTDIR}/${SBINDIR}
        install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
-       (cd perl && install ${PERLPROGS} ${DESTDIR}/${SBINDIR}/)
 
 uninstall:
-       for file in ${TARGETS} ${PERLPROGS}; do \
+       for file in ${TARGETS}; do \
                $(RM) ${DESTDIR}/${SBINDIR}/$$file; \
        done
diff --git a/ubi-utils/new-utils/.gitignore b/ubi-utils/new-utils/.gitignore
deleted file mode 100644 (file)
index 4155cd1..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/ubiattach
-/ubicrc32
-/ubidetach
-/ubiformat
-/ubimkvol
-/ubinfo
-/ubinize
-/ubirename
-/ubirmvol
-/ubiupdatevol
diff --git a/ubi-utils/new-utils/Makefile b/ubi-utils/new-utils/Makefile
deleted file mode 100644 (file)
index 83751e6..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# Makefile for ubi-utils
-#
-
-KERNELHDR := ../../include
-
-#CFLAGS += -Werror
-CPPFLAGS += -Iinclude -Isrc -I$(KERNELHDR)
-
-LIBS = libubi libmtd libubigen libiniparser libscan
-TARGETS = ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
-          ubidetach ubinize ubiformat ubirename
-
-vpath %.c src
-
-include ../../common.mk
-
-# And the below is the rule to get final executable from its .o and common.o
-$(TARGETS): $(addprefix $(BUILDDIR)/,\
-       libubi.a common.o)
-#      $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@
-
-$(BUILDDIR)/ubicrc32: $(addprefix $(BUILDDIR)/,\
-       ubicrc32.o crc32.o)
-#      $(CC) $(CFLAGS) -o $@ $^
-
-$(BUILDDIR)/ubinize: $(addprefix $(BUILDDIR)/,\
-       ubinize.o common.o crc32.o libiniparser.a libubigen.a)
-#      $(CC) $(CFLAGS) $(filter %.o, $^) -L. -liniparser -lubigen -o $@
-
-$(BUILDDIR)/ubiformat: $(addprefix $(BUILDDIR)/,\
-       ubiformat.o common.o crc32.o libmtd.a libscan.a libubi.a libubigen.a)
-#      $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lmtd -lscan -lubi -lubigen -o $@
-
-$(BUILDDIR)/libubi.a: $(BUILDDIR)/libubi.o
-
-$(BUILDDIR)/libmtd.a: $(BUILDDIR)/libmtd.o
-
-$(BUILDDIR)/libubigen.a: $(BUILDDIR)/libubigen.o
-
-$(BUILDDIR)/libiniparser.a: $(addprefix $(BUILDDIR)/,\
-       libiniparser.o dictionary.o)
-
-$(BUILDDIR)/libscan.a: $(addprefix $(BUILDDIR)/,\
-       libscan.o crc32.o)
-
-clean::
-       rm -f $(addsuffix .a, $(LIBS))
-
-install::
-       mkdir -p ${DESTDIR}/${SBINDIR}
-       install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
-
-uninstall:
-       for file in ${TARGETS}; do \
-               $(RM) ${DESTDIR}/${SBINDIR}/$$file; \
-       done
diff --git a/ubi-utils/new-utils/README b/ubi-utils/new-utils/README
deleted file mode 100644 (file)
index 41c5957..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-This directory contains a new UBI toolchain which is intended to replace
-the old one. All utilities support "-h" option which prints sufficient
-usage information. See the MTD web-site for more information.
-
-Motivation for new tool-chain.
-
-I was doing very active UBI development and had to add new features like
-dynamic UBI devices and auto-resize feature. Because of the mess in the
-the old tools I basically could not figure out how to upgrade them. In
-my humble oppinion, they are unmaintainable. The original authors did not
-show enthusiasm when I mailed them and asked to clean-up the tool-chain
-[1]. Thus, I re-implemented them, but I did borrow things from the old
-tool-chain and preserved copyrights and author names.
-
-I really did try to clean-up the old tool chain, but gave up (see git
-history for confirmation). So,
-
-1. I found the source codes very difficult to navigate and read, especially
-   those related to pdd, pfi, and bootenv. Try to do this yourself - they
-   are a puzzle.
-2. I foud the concept of PFI needlesly complecated - PFI file is nothing
-   else but the initial configuration .ini file + the contents of the
-   UBI volumes packed into one file, but with some changes of the .ini file's
-   format. The PFI file format is not very nice and it is difficult to parse,
-   especially because the PFI headers do not tell you data star and end for
-   each data chunk, and you have to do additional parsing.
-
-   So basically, you have .ini file + images, then you transfer this to pfi,
-   which does not add any other information. For .ini you have libraries
-   which may parse them, for pfi - not. Then you have to parse this pfi
-   which adds unneeded and complex code. This all needs lists, hashmaps,
-   and so on - for no reason.
-3. I found the command line options of the utilities to be inconsistent.
-   This is OK when you script your single task and do not touch it anymore.
-   But when you have to use the utilities while developing and testing,
-   It is difficult to remember their inconsistent options.
-4. I found it wrong to add development options to user utilities like
-   "broken update". End users should not see them.
-5. I did not find any consistent style and convention inside which
-   irritated me.
-6. I found it weird to introduce needless "logging infrastructure" instead
-   of just re-directing stdout and stderr to another file.
-7. I found the tool to be rather IBM-setup oriented. For example, the VID
-   header position was hard-coded. Some utilities were just weird, like
-   mkbootenv, which changed some ethernet addresses mentioned in a
-   configuration file.
-8. Finally, it was very difficult to realize what is pfi and pdd, what for,
-   why I need this transiant pfi file when I just want to create an UBI
-   image. There was zero documentation.
-
-And so on.
-
-Feb 19, 2008, Artem Bityutskiy.
-
-[1]. http://lists.infradead.org/pipermail/linux-mtd/2007-December/020134.html
diff --git a/ubi-utils/new-utils/src/crc32.c b/ubi-utils/new-utils/src/crc32.c
deleted file mode 100644 (file)
index 6b1e50c..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
- *  code or tables extracted from it, as desired without restriction.
- *
- *  First, the polynomial itself and its table of feedback terms.  The
- *  polynomial is
- *  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
- *
- *  Note that we take it "backwards" and put the highest-order term in
- *  the lowest-order bit.  The X^32 term is "implied"; the LSB is the
- *  X^31 term, etc.  The X^0 term (usually shown as "+1") results in
- *  the MSB being 1
- *
- *  Note that the usual hardware shift register implementation, which
- *  is what we're using (we're merely optimizing it by doing eight-bit
- *  chunks at a time) shifts bits into the lowest-order term.  In our
- *  implementation, that means shifting towards the right.  Why do we
- *  do it this way?  Because the calculated CRC must be transmitted in
- *  order from highest-order term to lowest-order term.  UARTs transmit
- *  characters in order from LSB to MSB.  By storing the CRC this way
- *  we hand it to the UART in the order low-byte to high-byte; the UART
- *  sends each low-bit to hight-bit; and the result is transmission bit
- *  by bit from highest- to lowest-order term without requiring any bit
- *  shuffling on our part.  Reception works similarly
- *
- *  The feedback terms table consists of 256, 32-bit entries.  Notes
- *
- *      The table can be generated at runtime if desired; code to do so
- *      is shown later.  It might not be obvious, but the feedback
- *      terms simply represent the results of eight shift/xor opera
- *      tions for all combinations of data and CRC register values
- *
- *      The values must be right-shifted by eight bits by the "updcrc
- *      logic; the shift must be unsigned (bring in zeroes).  On some
- *      hardware you could probably optimize the shift in assembler by
- *      using byte-swap instructions
- *      polynomial $edb88320
- */
-
-#include <stdint.h>
-
-const uint32_t crc32_table[256] = {
-       0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
-       0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
-       0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
-       0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
-       0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
-       0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
-       0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
-       0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
-       0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
-       0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
-       0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
-       0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
-       0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
-       0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
-       0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
-       0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
-       0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
-       0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
-       0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
-       0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
-       0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
-       0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
-       0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
-       0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
-       0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
-       0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
-       0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
-       0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
-       0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
-       0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
-       0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
-       0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
-       0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
-       0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
-       0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
-       0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
-       0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
-       0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
-       0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
-       0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
-       0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
-       0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
-       0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
-       0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
-       0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
-       0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
-       0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
-       0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
-       0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
-       0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
-       0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
-       0x2d02ef8dL
-};
diff --git a/ubi-utils/new-utils/src/crc32.h b/ubi-utils/new-utils/src/crc32.h
deleted file mode 100644 (file)
index ee3145b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef CRC32_H
-#define CRC32_H
-
-#include <stdint.h>
-
-extern const uint32_t crc32_table[256];
-
-/* Return a 32-bit CRC of the contents of the buffer. */
-
-       static inline uint32_t
-crc32(uint32_t val, const void *ss, int len)
-{
-       const unsigned char *s = ss;
-       while (--len >= 0)
-               val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8);
-       return val;
-}
-
-#endif
diff --git a/ubi-utils/new-utils/src/libubi.c b/ubi-utils/new-utils/src/libubi.c
deleted file mode 100644 (file)
index 1aa66d8..0000000
+++ /dev/null
@@ -1,1206 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * 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 Bityutskiy
- *
- * UBI (Unsorted Block Images) library.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include "libubi.h"
-#include "libubi_int.h"
-#include "common.h"
-
-#define PROGRAM_NAME "libubi"
-
-/**
- * mkpath - compose full path from 2 given components.
- * @path: the first component
- * @name: the second component
- *
- * This function returns the resulting path in case of success and %NULL in
- * case of failure.
- */
-static char *mkpath(const char *path, const char *name)
-{
-       char *n;
-       int len1 = strlen(path);
-       int len2 = strlen(name);
-
-       n = malloc(len1 + len2 + 2);
-       if (!n) {
-               sys_errmsg("cannot allocate %d bytes", len1 + len2 + 2);
-               return NULL;
-       }
-
-       memcpy(n, path, len1);
-       if (n[len1 - 1] != '/')
-               n[len1++] = '/';
-
-       memcpy(n + len1, name, len2 + 1);
-       return n;
-}
-
-/**
- * read_positive_ll - read a positive 'long long' value from a file.
- * @file: the file to read from
- * @value: the result is stored here
- *
- * This function reads file @file and interprets its contents as a positive
- * 'long long' integer. If this is not true, it fails with %EINVAL error code.
- * Returns %0 in case of success and %-1 in case of failure.
- */
-static int read_positive_ll(const char *file, long long *value)
-{
-       int fd, rd;
-       char buf[50];
-
-       fd = open(file, O_RDONLY);
-       if (fd == -1)
-               return -1;
-
-       rd = read(fd, buf, 50);
-       if (rd == -1) {
-               sys_errmsg("cannot read \"%s\"", file);
-               goto out_error;
-       }
-       if (rd == 50) {
-               errmsg("contents of \"%s\" is too long", file);
-               errno = EINVAL;
-               goto out_error;
-       }
-
-       if (sscanf(buf, "%lld\n", value) != 1) {
-               /* This must be a UBI bug */
-               errmsg("cannot read integer from \"%s\"\n", file);
-               errno = EINVAL;
-               goto out_error;
-       }
-
-       if (*value < 0) {
-               errmsg("negative value %lld in \"%s\"", *value, file);
-               errno = EINVAL;
-               goto out_error;
-       }
-
-       if (close(fd))
-               return sys_errmsg("close failed on \"%s\"", file);
-
-       return 0;
-
-out_error:
-       close(fd);
-       return -1;
-}
-
-/**
- * read_positive_int - read a positive 'int' value from a file.
- * @file: the file to read from
- * @value: the result is stored here
- *
- * This function is the same as 'read_positive_ll()', but it reads an 'int'
- * value, not 'long long'.
- */
-static int read_positive_int(const char *file, int *value)
-{
-       long long res;
-
-       if (read_positive_ll(file, &res))
-               return -1;
-
-       /* Make sure the value is not too big */
-       if (res > INT_MAX) {
-               errmsg("value %lld read from file \"%s\" is out of range",
-                      res, file);
-               errno = EINVAL;
-               return -1;
-       }
-
-       *value = res;
-       return 0;
-}
-
-/**
- * read_data - read data from a file.
- * @file: the file to read from
- * @buf: the buffer to read to
- * @buf_len: buffer length
- *
- * This function returns number of read bytes in case of success and %-1 in
- * case of failure. Note, if the file contains more then @buf_len bytes of
- * date, this function fails with %EINVAL error code.
- */
-static int read_data(const char *file, void *buf, int buf_len)
-{
-       int fd, rd, tmp, tmp1;
-
-       fd = open(file, O_RDONLY);
-       if (fd == -1)
-               return -1;
-
-       rd = read(fd, buf, buf_len);
-       if (rd == -1) {
-               sys_errmsg("cannot read \"%s\"", file);
-               goto out_error;
-       }
-
-       /* Make sure all data is read */
-       tmp1 = read(fd, &tmp, 1);
-       if (tmp1 == 1) {
-               sys_errmsg("cannot read \"%s\"", file);
-               goto out_error;
-       }
-       if (tmp1) {
-               errmsg("file \"%s\" contains too much data (> %d bytes)",
-                      file, buf_len);
-               errno = EINVAL;
-               goto out_error;
-       }
-
-       if (close(fd)) {
-               sys_errmsg("close failed on \"%s\"", file);
-               return -1;
-       }
-
-       return rd;
-
-out_error:
-       close(fd);
-       return -1;
-}
-
-/**
- * read_major - read major and minor numbers from a file.
- * @file: name of the file to read from
- * @major: major number is returned here
- * @minor: minor number is returned here
- *
- * This function returns % in case of succes, and %-1 in case of failure.
- */
-static int read_major(const char *file, int *major, int *minor)
-{
-       int ret;
-       char buf[50];
-
-       ret = read_data(file, buf, 50);
-       if (ret < 0)
-               return ret;
-
-       ret = sscanf(buf, "%d:%d\n", major, minor);
-       if (ret != 2) {
-               errno = EINVAL;
-               return errmsg("\"%s\" does not have major:minor format", file);
-       }
-
-       if (*major < 0 || *minor < 0) {
-               errno = EINVAL;
-               return errmsg("bad major:minor %d:%d in \"%s\"",
-                             *major, *minor, file);
-       }
-
-       return 0;
-}
-
-/**
- * dev_read_int - read a positive 'int' value from an UBI device sysfs file.
- * @patt: file pattern to read from
- * @dev_num:  UBI device number
- * @value: the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int dev_read_int(const char *patt, int dev_num, int *value)
-{
-       char file[strlen(patt) + 50];
-
-       sprintf(file, patt, dev_num);
-       return read_positive_int(file, value);
-}
-
-/**
- * vol_read_int - read a positive 'int' value from an UBI volume sysfs file.
- * @patt: file pattern to read from
- * @dev_num: UBI device number
- * @vol_id: volume ID
- * @value: the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value)
-{
-       char file[strlen(patt) + 100];
-
-       sprintf(file, patt, dev_num, vol_id);
-       return read_positive_int(file, value);
-}
-
-/**
- * dev_read_ll - read a positive 'long long' value from an UBI device sysfs file.
- * @patt: file pattern to read from
- * @dev_num: UBI device number
- * @value: the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int dev_read_ll(const char *patt, int dev_num, long long *value)
-{
-       char file[strlen(patt) + 50];
-
-       sprintf(file, patt, dev_num);
-       return read_positive_ll(file, value);
-}
-
-/**
- * vol_read_ll - read a positive 'long long' value from an UBI volume sysfs file.
- * @patt: file pattern to read from
- * @dev_num: UBI device number
- * @vol_id: volume ID
- * @value: the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int vol_read_ll(const char *patt, int dev_num, int vol_id,
-                      long long *value)
-{
-       char file[strlen(patt) + 100];
-
-       sprintf(file, patt, dev_num, vol_id);
-       return read_positive_ll(file, value);
-}
-
-/**
- * vol_read_data - read data from an UBI volume's sysfs file.
- * @patt: file pattern to read from
- * @dev_num: UBI device number
- * @vol_id: volume ID
- * @buf: buffer to read to
- * @buf_len: buffer length
- *
- * This function returns number of read bytes in case of success and %-1 in
- * case of failure.
- */
-static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
-                        int buf_len)
-{
-       char file[strlen(patt) + 100];
-
-       sprintf(file, patt, dev_num, vol_id);
-       return read_data(file, buf, buf_len);
-}
-
-/**
- * dev_get_major - get major and minor numbers of an UBI device.
- * @lib: libubi descriptor
- * @dev_num: UBI device number
- * @major: major number is returned here
- * @minor: minor number is returned here
- *
- * This function returns zero in case of succes and %-1 in case of failure.
- */
-static int dev_get_major(struct libubi *lib, int dev_num, int *major, int *minor)
-{
-       char file[strlen(lib->dev_dev) + 50];
-
-       sprintf(file, lib->dev_dev, dev_num);
-       return read_major(file, major, minor);
-}
-
-/**
- * vol_get_major - get major and minor numbers of an UBI volume.
- * @lib: libubi descriptor
- * @dev_num: UBI device number
- * @vol_id: volume ID
- * @major: major number is returned here
- * @minor: minor number is returned here
- *
- * This function returns zero in case of succes and %-1 in case of failure.
- */
-static int vol_get_major(struct libubi *lib, int dev_num, int vol_id,
-                        int *major, int *minor)
-{
-       char file[strlen(lib->vol_dev) + 100];
-
-       sprintf(file, lib->vol_dev, dev_num, vol_id);
-       return read_major(file, major, minor);
-}
-
-/**
- * vol_node2nums - find UBI device number and volume ID by volume device node
- *                 file.
- * @lib: UBI library descriptor
- * @node: UBI character device node name
- * @dev_num: UBI device number is returned here
- * @vol_id: volume ID is returned hers
- *
- * This function returns zero in case of succes and %-1 in case of failure.
- */
-static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num,
-                        int *vol_id)
-{
-       struct stat st;
-       struct ubi_info info;
-       int i, fd, major, minor;
-       char file[strlen(lib->ubi_vol) + 100];
-
-       if (stat(node, &st))
-               return sys_errmsg("cannot get information about \"%s\"",
-                                 node);
-
-       if (!S_ISCHR(st.st_mode)) {
-               errno = EINVAL;
-               return errmsg("\"%s\" is not a character device", node);
-       }
-
-       major = major(st.st_rdev);
-       minor = minor(st.st_rdev);
-
-       if (minor == 0) {
-               errno = EINVAL;
-               return errmsg("\"%s\" is not a volume character device", node);
-       }
-
-       if (ubi_get_info((libubi_t *)lib, &info))
-               return -1;
-
-       for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-               int major1, minor1, ret;
-
-               ret = dev_get_major(lib, i, &major1, &minor1);
-               if (ret) {
-                       if (errno == ENOENT)
-                               continue;
-                       return -1;
-               }
-
-               if (major1 == major)
-                       break;
-       }
-
-       if (i > info.highest_dev_num) {
-               errno = ENODEV;
-               return -1;
-       }
-
-       /* Make sure this UBI volume exists */
-       sprintf(file, lib->ubi_vol, i, minor - 1);
-       fd = open(file, O_RDONLY);
-       if (fd == -1) {
-               errno = ENODEV;
-               return -1;
-       }
-
-       *dev_num = i;
-       *vol_id = minor - 1;
-       errno = 0;
-       return 0;
-}
-
-/**
- * dev_node2num - find UBI device number by its character device node.
- * @lib: UBI library descriptor
- * @node: UBI character device node name
- *
- * This function returns positive UBI device number in case of success and %-1
- * in case of failure.
- */
-static int dev_node2num(struct libubi *lib, const char *node, int *dev_num)
-{
-       struct stat st;
-       struct ubi_info info;
-       int i, major, minor;
-
-       if (stat(node, &st))
-               return sys_errmsg("cannot get information about \"%s\"",
-                                 node);
-
-       if (!S_ISCHR(st.st_mode)) {
-               errno = EINVAL;
-               return errmsg("\"%s\" is not a character device", node);
-       }
-
-       major = major(st.st_rdev);
-       minor = minor(st.st_rdev);
-
-       if (minor != 0) {
-               errno = EINVAL;
-               return errmsg("\"%s\" is not an UBI character device", node);
-       }
-
-       if (ubi_get_info((libubi_t *)lib, &info))
-               return -1;
-
-       for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-               int major1, minor1, ret;
-
-               ret = dev_get_major(lib, i, &major1, &minor1);
-               if (ret) {
-                       if (errno == ENOENT)
-                               continue;
-                       return -1;
-               }
-
-               if (major1 == major) {
-                       if (minor1 != 0) {
-                               errmsg("UBI character device minor number is "
-                                      "%d, but must be 0", minor1);
-                               errno = EINVAL;
-                               return -1;
-                       }
-                       errno = 0;
-                       *dev_num = i;
-                       return 0;
-               }
-       }
-
-       errno = ENODEV;
-       return -1;
-}
-
-int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num)
-{
-       struct ubi_info info;
-       int i, ret, mtd_num1;
-       struct libubi *lib = desc;
-
-       if (ubi_get_info(desc, &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 = 0;
-       return -1;
-}
-
-libubi_t libubi_open(int required)
-{
-       int fd, version;
-       struct libubi *lib;
-
-       lib = calloc(1, sizeof(struct libubi));
-       if (!lib)
-               return NULL;
-
-       /* TODO: this must be discovered instead */
-       lib->sysfs = strdup("/sys");
-       if (!lib->sysfs)
-               goto out_error;
-
-       lib->sysfs_ctrl = mkpath(lib->sysfs, SYSFS_CTRL);
-       if (!lib->sysfs_ctrl)
-               goto out_error;
-
-       lib->ctrl_dev = mkpath(lib->sysfs_ctrl, CTRL_DEV);
-       if (!lib->ctrl_dev)
-               goto out_error;
-
-       lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI);
-       if (!lib->sysfs_ubi)
-               goto out_error;
-
-       /* Make sure UBI is present */
-       fd = open(lib->sysfs_ubi, O_RDONLY);
-       if (fd == -1) {
-               if (required)
-                       errmsg("cannot open \"%s\", UBI does not seem to "
-                              "exist in system", lib->sysfs_ubi);
-               goto out_error;
-       }
-
-       if (close(fd)) {
-               sys_errmsg("close failed on \"%s\"", lib->sysfs_ubi);
-               goto out_error;
-       }
-
-       lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT);
-       if (!lib->ubi_dev)
-               goto out_error;
-
-       lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER);
-       if (!lib->ubi_version)
-               goto out_error;
-
-       lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV);
-       if (!lib->dev_dev)
-               goto out_error;
-
-       lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS);
-       if (!lib->dev_avail_ebs)
-               goto out_error;
-
-       lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS);
-       if (!lib->dev_total_ebs)
-               goto out_error;
-
-       lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT);
-       if (!lib->dev_bad_count)
-               goto out_error;
-
-       lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE);
-       if (!lib->dev_eb_size)
-               goto out_error;
-
-       lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC);
-       if (!lib->dev_max_ec)
-               goto out_error;
-
-       lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD);
-       if (!lib->dev_bad_rsvd)
-               goto out_error;
-
-       lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS);
-       if (!lib->dev_max_vols)
-               goto out_error;
-
-       lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE);
-       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;
-
-       lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE);
-       if (!lib->vol_type)
-               goto out_error;
-
-       lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV);
-       if (!lib->vol_dev)
-               goto out_error;
-
-       lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT);
-       if (!lib->vol_alignment)
-               goto out_error;
-
-       lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES);
-       if (!lib->vol_data_bytes)
-               goto out_error;
-
-       lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS);
-       if (!lib->vol_rsvd_ebs)
-               goto out_error;
-
-       lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE);
-       if (!lib->vol_eb_size)
-               goto out_error;
-
-       lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED);
-       if (!lib->vol_corrupted)
-               goto out_error;
-
-       lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME);
-       if (!lib->vol_name)
-               goto out_error;
-
-       if (read_positive_int(lib->ubi_version, &version))
-               goto out_error;
-       if (version != LIBUBI_UBI_VERSION) {
-               errmsg("this library was made for UBI version %d, but UBI "
-                      "version %d is detected\n", LIBUBI_UBI_VERSION, version);
-               goto out_error;
-       }
-
-       return lib;
-
-out_error:
-       libubi_close((libubi_t)lib);
-       return NULL;
-}
-
-void libubi_close(libubi_t desc)
-{
-       struct libubi *lib = (struct libubi *)desc;
-
-       free(lib->vol_name);
-       free(lib->vol_corrupted);
-       free(lib->vol_eb_size);
-       free(lib->vol_rsvd_ebs);
-       free(lib->vol_data_bytes);
-       free(lib->vol_alignment);
-       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);
-       free(lib->dev_max_ec);
-       free(lib->dev_eb_size);
-       free(lib->dev_bad_count);
-       free(lib->dev_total_ebs);
-       free(lib->dev_avail_ebs);
-       free(lib->dev_dev);
-       free(lib->ubi_version);
-       free(lib->ubi_dev);
-       free(lib->sysfs_ubi);
-       free(lib->ctrl_dev);
-       free(lib->sysfs_ctrl);
-       free(lib->sysfs);
-       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 sys_errmsg("cannot open \"%s\"", node);
-
-       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;
-#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) {
-               errno = ENODEV;
-               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 sys_errmsg("cannot open \"%s\"", node);
-       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;
-       struct ubi_info info;
-       int i, fd, major, minor;
-       struct libubi *lib = (struct libubi *)desc;
-       char file[strlen(lib->ubi_vol) + 100];
-
-       if (stat(node, &st))
-               return sys_errmsg("cannot get information about \"%s\"",
-                                 node);
-
-       if (!S_ISCHR(st.st_mode)) {
-               errmsg("\"%s\" is not a character device", node);
-               errno = EINVAL;
-               return -1;
-       }
-
-       major = major(st.st_rdev);
-       minor = minor(st.st_rdev);
-
-       if (ubi_get_info((libubi_t *)lib, &info))
-               return -1;
-
-       for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-               int major1, minor1, ret;
-
-               ret = dev_get_major(lib, i, &major1, &minor1);
-               if (ret) {
-                       if (errno == ENOENT)
-                               continue;
-                       if (!errno)
-                               goto out_not_ubi;
-                       return -1;
-               }
-
-               if (major1 == major)
-                       break;
-       }
-
-       if (i > info.highest_dev_num)
-               goto out_not_ubi;
-
-       if (minor == 0)
-               return 1;
-
-       /* This is supposdely an UBI volume device node */
-       sprintf(file, lib->ubi_vol, i, minor - 1);
-       fd = open(file, O_RDONLY);
-       if (fd == -1) {
-               sys_errmsg("cannot open \"%s\"", node);
-               return -1;
-       }
-
-       return 2;
-
-out_not_ubi:
-       errmsg("\"%s\" has major:minor %d:%d, but this does not correspond to "
-              "any UBI device or volume", node, major, minor);
-       errno = 0;
-       return -1;
-}
-
-int ubi_get_info(libubi_t desc, struct ubi_info *info)
-{
-       DIR *sysfs_ubi;
-       struct dirent *dirent;
-       struct libubi *lib = (struct libubi *)desc;
-
-       memset(info, '\0', sizeof(struct ubi_info));
-
-       if (read_major(lib->ctrl_dev, &info->ctrl_major, &info->ctrl_minor)) {
-               /*
-                * Older UBI versions did not have control device, so we do not
-                * panic here for compatibility reasons. May be few years later
-                * we could return -1 here, but for now just set major:minor to
-                * -1.
-                */
-               info->ctrl_major = info->ctrl_minor = -1;
-       }
-
-       /*
-        * We have to scan the UBI sysfs directory to identify how many UBI
-        * devices are present.
-        */
-       sysfs_ubi = opendir(lib->sysfs_ubi);
-       if (!sysfs_ubi)
-               return -1;
-
-       info->lowest_dev_num = INT_MAX;
-       while (1) {
-               int dev_num, ret;
-               char tmp_buf[256];
-
-               errno = 0;
-               dirent = readdir(sysfs_ubi);
-               if (!dirent)
-                       break;
-
-               if (strlen(dirent->d_name) > 256) {
-                       errmsg("invalid entry in %s: \"%s\"",
-                              lib->sysfs_ubi, dirent->d_name);
-                       goto out_close;
-               }
-
-               ret = sscanf(dirent->d_name, UBI_DEV_NAME_PATT"%s",
-                            &dev_num, tmp_buf);
-               if (ret == 1) {
-                       info->dev_count += 1;
-                       if (dev_num > info->highest_dev_num)
-                               info->highest_dev_num = dev_num;
-                       if (dev_num < info->lowest_dev_num)
-                               info->lowest_dev_num = dev_num;
-               }
-       }
-
-       if (!dirent && errno) {
-               sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
-               goto out_close;
-       }
-
-       if (closedir(sysfs_ubi))
-               return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
-
-       if (info->lowest_dev_num == INT_MAX)
-               info->lowest_dev_num = 0;
-
-       if (read_positive_int(lib->ubi_version, &info->version))
-               return -1;
-
-       return 0;
-
-out_close:
-       closedir(sysfs_ubi);
-       return -1;
-}
-
-int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req)
-{
-       int fd, ret;
-       struct ubi_mkvol_req r;
-       size_t n;
-
-       memset(&r, sizeof(struct ubi_mkvol_req), '\0');
-
-       desc = desc;
-       r.vol_id = req->vol_id;
-       r.alignment = req->alignment;
-       r.bytes = req->bytes;
-       r.vol_type = req->vol_type;
-
-       n = strlen(req->name);
-       if (n > UBI_MAX_VOLUME_NAME)
-               return -1;
-
-       strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1);
-       r.name_len = n;
-
-       fd = open(node, O_RDONLY);
-       if (fd == -1)
-               return sys_errmsg("cannot open \"%s\"", node);
-
-       ret = ioctl(fd, UBI_IOCMKVOL, &r);
-       if (ret == -1)
-               goto out_close;
-
-       req->vol_id = r.vol_id;
-
-#ifdef UDEV_SETTLE_HACK
-       if (system("udevsettle") == -1)
-               return -1;
-#endif
-
-out_close:
-       close(fd);
-       return ret;
-}
-
-int ubi_rmvol(libubi_t desc, const char *node, int vol_id)
-{
-       int fd, ret;
-
-       desc = desc;
-       fd = open(node, O_RDONLY);
-       if (fd == -1)
-               return sys_errmsg("cannot open \"%s\"", node);
-
-       ret = ioctl(fd, UBI_IOCRMVOL, &vol_id);
-       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_rnvols(libubi_t desc, const char *node, struct ubi_rnvol_req *rnvol)
-{
-       int fd, ret;
-
-       fd = open(node, O_RDONLY);
-       if (fd == -1)
-               return -1;
-       ret = ioctl(fd, UBI_IOCRNVOL, rnvol);
-       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_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes)
-{
-       int fd, ret;
-       struct ubi_rsvol_req req;
-
-       desc = desc;
-       fd = open(node, O_RDONLY);
-       if (fd == -1)
-               return sys_errmsg("cannot open \"%s\"", node);
-
-       req.bytes = bytes;
-       req.vol_id = vol_id;
-
-       ret = ioctl(fd, UBI_IOCRSVOL, &req);
-       close(fd);
-       return ret;
-}
-
-int ubi_update_start(libubi_t desc, int fd, long long bytes)
-{
-       desc = desc;
-       if (ioctl(fd, UBI_IOCVOLUP, &bytes))
-               return -1;
-       return 0;
-}
-
-int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype)
-{
-       struct ubi_leb_change_req req;
-
-       desc = desc;
-       memset(&req, 0, sizeof(struct ubi_leb_change_req));
-       req.lnum = lnum;
-       req.bytes = bytes;
-       req.dtype = dtype;
-
-       if (ioctl(fd, UBI_IOCEBCH, &req))
-               return -1;
-       return 0;
-}
-
-int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
-{
-       DIR *sysfs_ubi;
-       struct dirent *dirent;
-       struct libubi *lib = (struct libubi *)desc;
-
-       memset(info, '\0', sizeof(struct ubi_dev_info));
-       info->dev_num = dev_num;
-
-       sysfs_ubi = opendir(lib->sysfs_ubi);
-       if (!sysfs_ubi)
-               return -1;
-
-       info->lowest_vol_id = INT_MAX;
-
-       while (1) {
-               int vol_id, ret, devno;
-               char tmp_buf[256];
-
-               errno = 0;
-               dirent = readdir(sysfs_ubi);
-               if (!dirent)
-                       break;
-
-               if (strlen(dirent->d_name) > 256) {
-                       errmsg("invalid entry in %s: \"%s\"",
-                              lib->sysfs_ubi, dirent->d_name);
-                       goto out_close;
-               }
-
-               ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT"%s", &devno, &vol_id, tmp_buf);
-               if (ret == 2 && devno == dev_num) {
-                       info->vol_count += 1;
-                       if (vol_id > info->highest_vol_id)
-                               info->highest_vol_id = vol_id;
-                       if (vol_id < info->lowest_vol_id)
-                               info->lowest_vol_id = vol_id;
-               }
-       }
-
-       if (!dirent && errno) {
-               sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
-               goto out_close;
-       }
-
-       if (closedir(sysfs_ubi))
-               return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
-
-       if (info->lowest_vol_id == INT_MAX)
-               info->lowest_vol_id = 0;
-
-       if (dev_get_major(lib, dev_num, &info->major, &info->minor))
-               return -1;
-
-       if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_lebs))
-               return -1;
-       if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_lebs))
-               return -1;
-       if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count))
-               return -1;
-       if (dev_read_int(lib->dev_eb_size, dev_num, &info->leb_size))
-               return -1;
-       if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd))
-               return -1;
-       if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec))
-               return -1;
-       if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count))
-               return -1;
-       if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size))
-               return -1;
-
-       info->avail_bytes = info->avail_lebs * info->leb_size;
-       info->total_bytes = info->total_lebs * info->leb_size;
-
-       return 0;
-
-out_close:
-       closedir(sysfs_ubi);
-       return -1;
-}
-
-int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info)
-{
-       int dev_num;
-       struct libubi *lib = (struct libubi *)desc;
-
-       if (dev_node2num(lib, node, &dev_num))
-               return -1;
-
-       return ubi_get_dev_info1(desc, dev_num, info);
-}
-
-int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
-                     struct ubi_vol_info *info)
-{
-       int ret;
-       struct libubi *lib = (struct libubi *)desc;
-       char buf[50];
-
-       memset(info, '\0', sizeof(struct ubi_vol_info));
-       info->dev_num = dev_num;
-       info->vol_id = vol_id;
-
-       if (dev_get_major(lib, dev_num, &info->dev_major, &info->dev_minor))
-               return -1;
-       if (vol_get_major(lib, dev_num, vol_id, &info->major, &info->minor))
-               return -1;
-
-       ret = vol_read_data(lib->vol_type, dev_num, vol_id, buf, 50);
-       if (ret < 0)
-               return -1;
-
-       if (strncmp(buf, "static\n", ret) == 0)
-               info->type = UBI_STATIC_VOLUME;
-       else if (strncmp(buf, "dynamic\n", ret) == 0)
-               info->type = UBI_DYNAMIC_VOLUME;
-       else {
-               errmsg("bad value at \"%s\"", buf);
-               errno = EINVAL;
-               return -1;
-       }
-
-       ret = vol_read_int(lib->vol_alignment, dev_num, vol_id,
-                          &info->alignment);
-       if (ret)
-               return -1;
-       ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id,
-                         &info->data_bytes);
-       if (ret)
-               return -1;
-       ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_lebs);
-       if (ret)
-               return -1;
-       ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->leb_size);
-       if (ret)
-               return -1;
-       ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id,
-                          &info->corrupted);
-       if (ret)
-               return -1;
-       info->rsvd_bytes = info->leb_size * info->rsvd_lebs;
-
-       ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name,
-                           UBI_VOL_NAME_MAX + 2);
-       if (ret < 0)
-               return -1;
-
-       info->name[ret - 1] = '\0';
-       return 0;
-}
-
-int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info)
-{
-       int vol_id, dev_num;
-       struct libubi *lib = (struct libubi *)desc;
-
-       if (vol_node2nums(lib, node, &dev_num, &vol_id))
-               return -1;
-
-       return ubi_get_vol_info1(desc, dev_num, vol_id, info);
-}
-
-int ubi_get_vol_info1_nm(libubi_t desc, int dev_num, const char *name,
-                        struct ubi_vol_info *info)
-{
-       int i, err;
-       unsigned int nlen = strlen(name);
-       struct ubi_dev_info dev_info;
-
-       if (nlen == 0) {
-               errmsg("bad \"name\" input parameter");
-               errno = EINVAL;
-               return -1;
-       }
-
-       err = ubi_get_dev_info1(desc, dev_num, &dev_info);
-       if (err)
-               return err;
-
-       for (i = dev_info.lowest_vol_id;
-            i <= dev_info.highest_vol_id; i++) {
-               err = ubi_get_vol_info1(desc, dev_num, i, info);
-               if (err == -1) {
-                       if (errno == ENOENT)
-                               continue;
-                       return -1;
-               }
-
-               if (nlen == strlen(info->name) && !strcmp(name, info->name))
-                       return 0;
-       }
-
-       errno = ENOENT;
-       return -1;
-}
diff --git a/ubi-utils/new-utils/src/libubigen.c b/ubi-utils/new-utils/src/libubigen.c
deleted file mode 100644 (file)
index 91bb274..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- * Copyright (C) 2008 Nokia Corporation
- *
- * 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.
- */
-
-/*
- * Generating UBI images.
- *
- * Authors: Oliver Lohmann
- *          Artem Bityutskiy
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <mtd/ubi-media.h>
-#include <mtd_swab.h>
-#include <libubigen.h>
-#include "crc32.h"
-#include "common.h"
-
-#define PROGRAM_NAME "libubigen"
-
-/**
- * ubigen_info_init - initialize libubigen.
- * @ui: libubigen information
- * @peb_size: flash physical eraseblock size
- * @min_io_size: flash minimum input/output unit size
- * @subpage_size: flash sub-page, if present (has to be equivalent to
- *                @min_io_size if does not exist)
- * @vid_hdr_offs: offset of the VID header
- * @ubi_ver: UBI version
- */
-void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size,
-                     int subpage_size, int vid_hdr_offs, int ubi_ver)
-{
-       if (!vid_hdr_offs) {
-               vid_hdr_offs = UBI_EC_HDR_SIZE + subpage_size - 1;
-               vid_hdr_offs /= subpage_size;
-               vid_hdr_offs *= subpage_size;
-       }
-
-       ui->peb_size = peb_size;
-       ui->min_io_size = min_io_size;
-       ui->vid_hdr_offs = vid_hdr_offs;
-       ui->data_offs = vid_hdr_offs + UBI_VID_HDR_SIZE + min_io_size - 1;
-       ui->data_offs /= min_io_size;
-       ui->data_offs *= min_io_size;
-       ui->leb_size = peb_size - ui->data_offs;
-       ui->ubi_ver = ubi_ver;
-
-       ui->max_volumes = ui->leb_size / UBI_VTBL_RECORD_SIZE;
-       if (ui->max_volumes > UBI_MAX_VOLUMES)
-               ui->max_volumes = UBI_MAX_VOLUMES;
-       ui->vtbl_size = ui->max_volumes * UBI_VTBL_RECORD_SIZE;
-}
-
-/**
- * ubigen_create_empty_vtbl - creates empty volume table.
- *
- * This function creates an empty volume table and returns a pointer to it in
- * case of success and %NULL in case of failure. The returned object has to be
- * freed with 'free()' call.
- */
-struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui)
-{
-       struct ubi_vtbl_record *vtbl;
-       int i;
-
-       vtbl = calloc(1, ui->vtbl_size);
-       if (!vtbl) {
-               sys_errmsg("cannot allocate %d bytes of memory", ui->vtbl_size);
-               return NULL;
-       }
-
-       for (i = 0; i < ui->max_volumes; i++) {
-               uint32_t crc = crc32(UBI_CRC32_INIT, &vtbl[i],
-                                    UBI_VTBL_RECORD_SIZE_CRC);
-               vtbl[i].crc = cpu_to_be32(crc);
-       }
-
-       return vtbl;
-}
-
-/**
- * ubigen_add_volume - add a volume to the volume table.
- * @ui: libubigen information
- * @vi: volume information
- * @vtbl: volume table to add to
- *
- * This function adds volume described by input parameters to the volume table
- * @vtbl.
- */
-int ubigen_add_volume(const struct ubigen_info *ui,
-                     const struct ubigen_vol_info *vi,
-                     struct ubi_vtbl_record *vtbl)
-{
-       struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id];
-       uint32_t tmp;
-
-       if (vi->id >= ui->max_volumes)
-               return errmsg("too high volume id %d, max. volumes is %d",
-                             vi->id, ui->max_volumes);
-
-       if (vi->alignment >= ui->leb_size)
-               return errmsg("too large alignment %d, max is %d (LEB size)",
-                             vi->alignment, ui->leb_size);
-
-       memset(vtbl_rec, '\0', sizeof(struct ubi_vtbl_record));
-       tmp = (vi->bytes + ui->leb_size - 1) / ui->leb_size;
-       vtbl_rec->reserved_pebs = cpu_to_be32(tmp);
-       vtbl_rec->alignment = cpu_to_be32(vi->alignment);
-       vtbl_rec->vol_type = vi->type;
-       tmp = ui->leb_size % vi->alignment;
-       vtbl_rec->data_pad = cpu_to_be32(tmp);
-       vtbl_rec->flags = vi->flags;
-
-       memcpy(vtbl_rec->name, vi->name, vi->name_len);
-       vtbl_rec->name[vi->name_len] = '\0';
-       vtbl_rec->name_len = cpu_to_be16(vi->name_len);
-
-       tmp = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
-       vtbl_rec->crc =  cpu_to_be32(tmp);
-       return 0;
-}
-
-/**
- * ubigen_init_ec_hdr - initialize EC header.
- * @ui: libubigen information
- * @hdr: the EC header to initialize
- * @ec: erase counter value
- */
-void ubigen_init_ec_hdr(const struct ubigen_info *ui,
-                       struct ubi_ec_hdr *hdr, long long ec)
-{
-       uint32_t crc;
-
-       memset(hdr, '\0', sizeof(struct ubi_ec_hdr));
-
-       hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
-       hdr->version = ui->ubi_ver;
-       hdr->ec = cpu_to_be64(ec);
-       hdr->vid_hdr_offset = cpu_to_be32(ui->vid_hdr_offs);
-
-       hdr->data_offset = cpu_to_be32(ui->data_offs);
-
-       crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
-       hdr->hdr_crc = cpu_to_be32(crc);
-}
-
-/**
- * init_vid_hdr - initialize VID header.
- * @ui: libubigen information
- * @vi: volume information
- * @hdr: the VID header to initialize
- * @lnum: logical eraseblock number
- * @data: the contents of the LEB (static volumes only)
- * @data_size: amount of data in this LEB (static volumes only)
- *
- * Note, @used_ebs, @data and @data_size are ignored in case of dynamic
- * volumes.
- */
-static void init_vid_hdr(const struct ubigen_info *ui,
-                        const struct ubigen_vol_info *vi,
-                        struct ubi_vid_hdr *hdr, int lnum,
-                        const void *data, int data_size)
-{
-       uint32_t crc;
-
-       memset(hdr, '\0', sizeof(struct ubi_vid_hdr));
-
-       hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
-       hdr->version = ui->ubi_ver;
-       hdr->vol_type = vi->type;
-       hdr->vol_id = cpu_to_be32(vi->id);
-       hdr->lnum = cpu_to_be32(lnum);
-       hdr->data_pad = cpu_to_be32(vi->data_pad);
-       hdr->compat = vi->compat;
-
-       if (vi->type == UBI_VID_STATIC) {
-               hdr->data_size = cpu_to_be32(data_size);
-               hdr->used_ebs = cpu_to_be32(vi->used_ebs);
-               crc = crc32(UBI_CRC32_INIT, data, data_size);
-               hdr->data_crc = cpu_to_be32(crc);
-       }
-
-       crc = crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC);
-       hdr->hdr_crc = cpu_to_be32(crc);
-}
-
-/**
- * ubigen_write_volume - write UBI volume.
- * @ui: libubigen information
- * @vi: volume information
- * @ec: erase coutner value to put to EC headers
- * @bytes: volume size in bytes
- * @in: input file descriptor (has to be properly seeked)
- * @out: output file descriptor
- *
- * This function reads the contents of the volume from the input file @in and
- * writes the UBI volume to the output file @out. Returns zero on success and
- * %-1 on failure.
- */
-int ubigen_write_volume(const struct ubigen_info *ui,
-                       const struct ubigen_vol_info *vi, long long ec,
-                       long long bytes, int in, int out)
-{
-       int len = vi->usable_leb_size, rd, lnum = 0;
-       char inbuf[ui->leb_size], outbuf[ui->peb_size];
-
-       if (vi->id >= ui->max_volumes)
-               return errmsg("too high volume id %d, max. volumes is %d",
-                             vi->id, ui->max_volumes);
-
-       if (vi->alignment >= ui->leb_size)
-               return errmsg("too large alignment %d, max is %d (LEB size)",
-                             vi->alignment, ui->leb_size);
-
-       memset(outbuf, 0xFF, ui->data_offs);
-       ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec);
-
-       while (bytes) {
-               int l;
-               struct ubi_vid_hdr *vid_hdr;
-
-               if (bytes < len)
-                       len = bytes;
-               bytes -= len;
-
-               l = len;
-               do {
-                       rd = read(in, inbuf + len - l, l);
-                       if (rd != l)
-                               return sys_errmsg("cannot read %d bytes from the input file", l);
-
-                       l -= rd;
-               } while (l);
-
-               vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
-               init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len);
-
-               memcpy(outbuf + ui->data_offs, inbuf, len);
-               memset(outbuf + ui->data_offs + len, 0xFF,
-                      ui->peb_size - ui->data_offs - len);
-
-               if (write(out, outbuf, ui->peb_size) != ui->peb_size)
-                       return sys_errmsg("cannot write %d bytes to the output file", ui->peb_size);
-
-               lnum += 1;
-       }
-
-       return 0;
-}
-
-/**
- * ubigen_write_layout_vol - write UBI layout volume
- * @ui: libubigen information
- * @peb1: physical eraseblock number to write the first volume table copy
- * @peb2: physical eraseblock number to write the second volume table copy
- * @ec1: erase counter value for @peb1
- * @ec2: erase counter value for @peb1
- * @vtbl: volume table
- * @fd: output file descriptor seeked to the proper position
- *
- * This function creates the UBI layout volume which contains 2 copies of the
- * volume table. Returns zero in case of success and %-1 in case of failure.
- */
-int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
-                           long long ec1, long long ec2,
-                           struct ubi_vtbl_record *vtbl, int fd)
-{
-       int ret;
-       struct ubigen_vol_info vi;
-       char outbuf[ui->peb_size];
-       struct ubi_vid_hdr *vid_hdr;
-       off_t seek;
-
-       vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS;
-       vi.id = UBI_LAYOUT_VOLUME_ID;
-       vi.alignment = UBI_LAYOUT_VOLUME_ALIGN;
-       vi.data_pad = ui->leb_size % UBI_LAYOUT_VOLUME_ALIGN;
-       vi.usable_leb_size = ui->leb_size - vi.data_pad;
-       vi.data_pad = ui->leb_size - vi.usable_leb_size;
-       vi.type = UBI_LAYOUT_VOLUME_TYPE;
-       vi.name = UBI_LAYOUT_VOLUME_NAME;
-       vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME);
-       vi.compat = UBI_LAYOUT_VOLUME_COMPAT;
-
-       memset(outbuf, 0xFF, ui->data_offs);
-       vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
-       memcpy(outbuf + ui->data_offs, vtbl, ui->vtbl_size);
-       memset(outbuf + ui->data_offs + ui->vtbl_size, 0xFF,
-              ui->peb_size - ui->data_offs - ui->vtbl_size);
-
-       seek = peb1 * ui->peb_size;
-       if (lseek(fd, seek, SEEK_SET) != seek)
-               return sys_errmsg("cannot seek output file");
-       ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec1);
-       init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0);
-       ret = write(fd, outbuf, ui->peb_size);
-       if (ret != ui->peb_size)
-               return sys_errmsg("cannot write %d bytes", ui->peb_size);
-
-       seek = peb2 * ui->peb_size;
-       if (lseek(fd, seek, SEEK_SET) != seek)
-               return sys_errmsg("cannot seek output file");
-       ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec2);
-       init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0);
-       ret = write(fd, outbuf, ui->peb_size);
-       if (ret != ui->peb_size)
-               return sys_errmsg("cannot write %d bytes", ui->peb_size);
-
-       return 0;
-}
diff --git a/ubi-utils/old-utils/.gitignore b/ubi-utils/old-utils/.gitignore
new file mode 100644 (file)
index 0000000..83e8b71
--- /dev/null
@@ -0,0 +1,9 @@
+/bin2nand
+/mkbootenv
+/nand2bin
+/pddcustomize
+/pfi2bin
+/pfiflash
+/ubigen
+/ubimirror
+/unubi
diff --git a/ubi-utils/old-utils/Makefile b/ubi-utils/old-utils/Makefile
new file mode 100644 (file)
index 0000000..5d20592
--- /dev/null
@@ -0,0 +1,59 @@
+#
+# Makefile for ubi-utils
+#
+
+KERNELHDR := ../../include
+
+CFLAGS ?= -O2 -g -Werror
+CPPFLAGS += -I./inc -I./src -I$(KERNELHDR) \
+       -std=gnu99 -DPACKAGE_VERSION=\"1.0\"
+
+PERLPROGS = mkpfi ubicrc32.pl
+
+TARGETS = pfiflash pddcustomize ubimirror bin2nand nand2bin ubigen \
+       mkbootenv unubi pfi2bin
+
+vpath   %.c ./src
+
+include ../../common.mk
+
+$(BUILDDIR)/pddcustomize: $(addprefix $(BUILDDIR)/,\
+       pddcustomize.o error.o libubimirror.o bootenv.o hashmap.o \
+       libubi.o crc32.o)
+
+$(BUILDDIR)/pfiflash: $(addprefix $(BUILDDIR)/,\
+       pfiflash.o libpfiflash.o list.o reader.o error.o libubimirror.o \
+       bootenv.o hashmap.o pfi.o libubi.o crc32.o)
+
+$(BUILDDIR)/ubimirror: $(addprefix $(BUILDDIR)/,\
+       ubimirror.o error.o libubimirror.o bootenv.o hashmap.o \
+       libubi.o crc32.o)
+
+$(BUILDDIR)/nand2bin: $(addprefix $(BUILDDIR)/,\
+       nand2bin.o nandecc.o nandcorr.o)
+
+$(BUILDDIR)/bin2nand: $(addprefix $(BUILDDIR)/,\
+       bin2nand.o error.o nandecc.o)
+
+$(BUILDDIR)/ubigen: $(addprefix $(BUILDDIR)/,\
+       ubigen.o libubigen.o crc32.o)
+
+$(BUILDDIR)/mkbootenv: $(addprefix $(BUILDDIR)/,\
+       mkbootenv.o bootenv.o hashmap.o error.o crc32.o)
+
+$(BUILDDIR)/unubi: $(addprefix $(BUILDDIR)/,\
+       unubi.o crc32.o unubi_analyze.o eb_chain.o)
+
+$(BUILDDIR)/pfi2bin: $(addprefix $(BUILDDIR)/,\
+       pfi2bin.o peb.o error.o list.o crc32.o libubigen.o bootenv.o \
+       hashmap.o reader.o pfi.o)
+
+install::
+       mkdir -p ${DESTDIR}/${SBINDIR}
+       install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
+       (cd perl && install ${PERLPROGS} ${DESTDIR}/${SBINDIR}/)
+
+uninstall:
+       for file in ${TARGETS} ${PERLPROGS}; do \
+               $(RM) ${DESTDIR}/${SBINDIR}/$$file; \
+       done
similarity index 100%
rename from ubi-utils/README
rename to ubi-utils/old-utils/README
diff --git a/ubi-utils/old-utils/src/crc32.c b/ubi-utils/old-utils/src/crc32.c
new file mode 100644 (file)
index 0000000..666e217
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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: Thomas Gleixner
+ */
+
+/*
+ * CRC32 functions
+ *
+ * Can be compiled as seperate object, but is included into the ipl source
+ * so gcc can inline the functions. We optimize for size so the omission of
+ * the function frame is helpful.
+ *
+ */
+
+#include <stdint.h>
+#include <crc32.h>
+
+/* CRC polynomial */
+#define CRC_POLY       0xEDB88320
+
+/**
+ * init_crc32_table - Initialize crc table
+ *
+ * @table:     pointer to the CRC table which must be initialized
+ *
+ * Create CRC32 table for given polynomial. The table is created with
+ * the lowest order term in the highest order bit. So the x^32 term
+ * has to implied in the crc calculation function.
+ */
+void init_crc32_table(uint32_t *table)
+{
+       uint32_t crc;
+       int i, j;
+
+       for (i = 0; i < 256; i++) {
+               crc = i;
+               for (j = 8; j > 0; j--) {
+                       if (crc & 1)
+                               crc = (crc >> 1) ^ CRC_POLY;
+                       else
+                               crc >>= 1;
+               }
+               table[i] = crc;
+       }
+}
+
+/**
+ * clc_crc32 - Calculate CRC32 over a buffer
+ *
+ * @table:     pointer to the CRC table
+ * @crc:       initial crc value
+ * @buf:       pointer to the buffer
+ * @len:       number of bytes to calc
+ *
+ * Returns the updated crc value.
+ *
+ * The algorithm resembles a hardware shift register, but calculates 8
+ * bit at once.
+ */
+uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf,
+                  int len)
+{
+       const unsigned char *p = buf;
+
+       while(--len >= 0)
+               crc = table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+       return crc;
+}
diff --git a/ubi-utils/old-utils/src/crc32.h b/ubi-utils/old-utils/src/crc32.h
new file mode 100644 (file)
index 0000000..31362b0
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef __CRC32_H__
+#define __CRC32_H__
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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: Thomas Gleixner
+ *
+ * CRC32 functions
+ *
+ * Can be compiled as seperate object, but is included into the ipl source
+ * so gcc can inline the functions. We optimize for size so the omission of
+ * the function frame is helpful.
+ *
+ */
+#include <stdint.h>
+
+void init_crc32_table(uint32_t *table);
+uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, int len);
+
+#endif /* __CRC32_H__ */
diff --git a/ubi-utils/old-utils/src/libubi.c b/ubi-utils/old-utils/src/libubi.c
new file mode 100644 (file)
index 0000000..a536b47
--- /dev/null
@@ -0,0 +1,915 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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
+ *
+ * UBI (Unsorted Block Images) library.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <limits.h>
+#include "libubi.h"
+#include "libubi_int.h"
+
+libubi_t libubi_open(void)
+{
+       int fd, version;
+       struct libubi *lib;
+
+       lib = calloc(1, sizeof(struct libubi));
+       if (!lib)
+               return NULL;
+
+       /* TODO: this must be discovered instead */
+       lib->sysfs = strdup("/sys");
+       if (!lib->sysfs)
+               goto error;
+
+       lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI);
+       if (!lib->sysfs_ubi)
+               goto error;
+
+       /* Make sure UBI is present */
+       fd = open(lib->sysfs_ubi, O_RDONLY);
+       if (fd == -1)
+               goto error;
+       close(fd);
+
+       lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT);
+       if (!lib->ubi_dev)
+               goto error;
+
+       lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER);
+       if (!lib->ubi_version)
+               goto error;
+
+       lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV);
+       if (!lib->dev_dev)
+               goto error;
+
+       lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS);
+       if (!lib->dev_avail_ebs)
+               goto error;
+
+       lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS);
+       if (!lib->dev_total_ebs)
+               goto error;
+
+       lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT);
+       if (!lib->dev_bad_count)
+               goto error;
+
+       lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE);
+       if (!lib->dev_eb_size)
+               goto error;
+
+       lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC);
+       if (!lib->dev_max_ec)
+               goto error;
+
+       lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD);
+       if (!lib->dev_bad_rsvd)
+               goto error;
+
+       lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS);
+       if (!lib->dev_max_vols)
+               goto error;
+
+       lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE);
+       if (!lib->dev_min_io_size)
+               goto error;
+
+       lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT);
+       if (!lib->ubi_vol)
+               goto error;
+
+       lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE);
+       if (!lib->vol_type)
+               goto error;
+
+       lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV);
+       if (!lib->vol_dev)
+               goto error;
+
+       lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT);
+       if (!lib->vol_alignment)
+               goto error;
+
+       lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES);
+       if (!lib->vol_data_bytes)
+               goto error;
+
+       lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS);
+       if (!lib->vol_rsvd_ebs)
+               goto error;
+
+       lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE);
+       if (!lib->vol_eb_size)
+               goto error;
+
+       lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED);
+       if (!lib->vol_corrupted)
+               goto error;
+
+       lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME);
+       if (!lib->vol_name)
+               goto error;
+
+       if (read_int(lib->ubi_version, &version))
+               goto error;
+       if (version != LIBUBI_UBI_VERSION) {
+               fprintf(stderr, "LIBUBI: this library was made for UBI version "
+                               "%d, but UBI version %d is detected\n",
+                       LIBUBI_UBI_VERSION, version);
+               goto error;
+       }
+
+       return lib;
+
+error:
+       free(lib->vol_corrupted);
+       free(lib->vol_eb_size);
+       free(lib->vol_rsvd_ebs);
+       free(lib->vol_data_bytes);
+       free(lib->vol_alignment);
+       free(lib->vol_dev);
+       free(lib->vol_type);
+       free(lib->ubi_vol);
+       free(lib->dev_min_io_size);
+       free(lib->dev_max_vols);
+       free(lib->dev_bad_rsvd);
+       free(lib->dev_max_ec);
+       free(lib->dev_eb_size);
+       free(lib->dev_bad_count);
+       free(lib->dev_total_ebs);
+       free(lib->dev_avail_ebs);
+       free(lib->dev_dev);
+       free(lib->ubi_version);
+       free(lib->ubi_dev);
+       free(lib->sysfs_ubi);
+       free(lib->sysfs);
+       free(lib);
+       return NULL;
+}
+
+void libubi_close(libubi_t desc)
+{
+       struct libubi *lib = (struct libubi *)desc;
+
+       free(lib->vol_name);
+       free(lib->vol_corrupted);
+       free(lib->vol_eb_size);
+       free(lib->vol_rsvd_ebs);
+       free(lib->vol_data_bytes);
+       free(lib->vol_alignment);
+       free(lib->vol_dev);
+       free(lib->vol_type);
+       free(lib->ubi_vol);
+       free(lib->dev_min_io_size);
+       free(lib->dev_max_vols);
+       free(lib->dev_bad_rsvd);
+       free(lib->dev_max_ec);
+       free(lib->dev_eb_size);
+       free(lib->dev_bad_count);
+       free(lib->dev_total_ebs);
+       free(lib->dev_avail_ebs);
+       free(lib->dev_dev);
+       free(lib->ubi_version);
+       free(lib->ubi_dev);
+       free(lib->sysfs_ubi);
+       free(lib->sysfs);
+       free(lib);
+}
+
+int ubi_get_info(libubi_t desc, struct ubi_info *info)
+{
+       DIR *sysfs_ubi;
+       struct dirent *dirent;
+       struct libubi *lib = (struct libubi *)desc;
+
+       memset(info, '\0', sizeof(struct ubi_info));
+
+       /*
+        * We have to scan the UBI sysfs directory to identify how many UBI
+        * devices are present.
+        */
+       sysfs_ubi = opendir(lib->sysfs_ubi);
+       if (!sysfs_ubi)
+               return -1;
+
+       info->lowest_dev_num = INT_MAX;
+       while ((dirent = readdir(sysfs_ubi))) {
+               char *name = &dirent->d_name[0];
+               int dev_num, ret;
+
+               ret = sscanf(name, UBI_DEV_NAME_PATT, &dev_num);
+               if (ret == 1) {
+                       info->dev_count += 1;
+                       if (dev_num > info->highest_dev_num)
+                               info->highest_dev_num = dev_num;
+                       if (dev_num < info->lowest_dev_num)
+                               info->lowest_dev_num = dev_num;
+               }
+       }
+
+       if (info->lowest_dev_num == INT_MAX)
+               info->lowest_dev_num = 0;
+
+       if (read_int(lib->ubi_version, &info->version))
+               goto close;
+
+       return closedir(sysfs_ubi);
+
+close:
+       closedir(sysfs_ubi);
+       return -1;
+}
+
+int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req)
+{
+       int fd, ret;
+       struct ubi_mkvol_req r;
+       size_t n;
+
+       desc = desc;
+       r.vol_id = req->vol_id;
+       r.alignment = req->alignment;
+       r.bytes = req->bytes;
+       r.vol_type = req->vol_type;
+
+       n = strlen(req->name);
+       if (n > UBI_MAX_VOLUME_NAME)
+               return -1;
+
+       strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1);
+       r.name_len = n;
+
+       fd = open(node, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       ret = ioctl(fd, UBI_IOCMKVOL, &r);
+       if (!ret)
+               req->vol_id = r.vol_id;
+
+       close(fd);
+       return ret;
+}
+
+int ubi_rmvol(libubi_t desc, const char *node, int vol_id)
+{
+       int fd, ret;
+
+       desc = desc;
+       fd = open(node, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       ret = ioctl(fd, UBI_IOCRMVOL, &vol_id);
+       close(fd);
+       return ret;
+}
+
+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;
+       fd = open(node, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       req.bytes = bytes;
+       req.vol_id = vol_id;
+
+       ret = ioctl(fd, UBI_IOCRSVOL, &req);
+       close(fd);
+       return ret;
+}
+
+int ubi_update_start(libubi_t desc, int fd, long long bytes)
+{
+       desc = desc;
+       if (ioctl(fd, UBI_IOCVOLUP, &bytes))
+               return -1;
+       return 0;
+}
+
+int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info)
+{
+       int dev_num;
+       struct libubi *lib = (struct libubi *)desc;
+
+       dev_num = find_dev_num(lib, node);
+       if (dev_num == -1)
+               return -1;
+
+       return ubi_get_dev_info1(desc, dev_num, info);
+}
+
+int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
+{
+       DIR *sysfs_ubi;
+       struct dirent *dirent;
+       struct libubi *lib = (struct libubi *)desc;
+
+       memset(info, '\0', sizeof(struct ubi_dev_info));
+       info->dev_num = dev_num;
+
+       sysfs_ubi = opendir(lib->sysfs_ubi);
+       if (!sysfs_ubi)
+               return -1;
+
+       info->lowest_vol_num = INT_MAX;
+       while ((dirent = readdir(sysfs_ubi))) {
+               char *name = &dirent->d_name[0];
+               int vol_id, ret, devno;
+
+               ret = sscanf(name, UBI_VOL_NAME_PATT, &devno, &vol_id);
+               if (ret == 2 && devno == dev_num) {
+                       info->vol_count += 1;
+                       if (vol_id > info->highest_vol_num)
+                               info->highest_vol_num = vol_id;
+                       if (vol_id < info->lowest_vol_num)
+                               info->lowest_vol_num = vol_id;
+               }
+       }
+
+       closedir(sysfs_ubi);
+
+       if (info->lowest_vol_num == INT_MAX)
+               info->lowest_vol_num = 0;
+
+       if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_ebs))
+               return -1;
+       if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_ebs))
+               return -1;
+       if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count))
+               return -1;
+       if (dev_read_int(lib->dev_eb_size, dev_num, &info->eb_size))
+               return -1;
+       if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd))
+               return -1;
+       if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec))
+               return -1;
+       if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count))
+               return -1;
+       if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size))
+               return -1;
+
+       info->avail_bytes = info->avail_ebs * info->eb_size;
+       info->total_bytes = info->total_ebs * info->eb_size;
+
+       return 0;
+}
+
+int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info)
+{
+       int vol_id, dev_num;
+       struct libubi *lib = (struct libubi *)desc;
+
+       dev_num = find_dev_num_vol(lib, node);
+       if (dev_num == -1)
+               return -1;
+
+       vol_id = find_vol_num(lib, dev_num, node);
+       if (vol_id == -1)
+               return -1;
+
+       return ubi_get_vol_info1(desc, dev_num, vol_id, info);
+}
+
+int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
+                     struct ubi_vol_info *info)
+{
+       int ret;
+       struct libubi *lib = (struct libubi *)desc;
+       char buf[50];
+
+       memset(info, '\0', sizeof(struct ubi_vol_info));
+       info->dev_num = dev_num;
+       info->vol_id = vol_id;
+
+       ret = vol_read_data(lib->vol_type, dev_num, vol_id, &buf[0], 50);
+       if (ret < 0)
+               return -1;
+
+       if (strncmp(&buf[0], "static\n", ret) == 0)
+               info->type = UBI_STATIC_VOLUME;
+       else if (strncmp(&buf[0], "dynamic\n", ret) == 0)
+               info->type = UBI_DYNAMIC_VOLUME;
+       else {
+               fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+               errno = EINVAL;
+               return -1;
+       }
+
+       ret = vol_read_int(lib->vol_alignment, dev_num, vol_id,
+                          &info->alignment);
+       if (ret)
+               return -1;
+       ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id,
+                         &info->data_bytes);
+       if (ret)
+               return -1;
+       ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_ebs);
+       if (ret)
+               return -1;
+       ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->eb_size);
+       if (ret)
+               return -1;
+       ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id,
+                          &info->corrupted);
+       if (ret)
+               return -1;
+       info->rsvd_bytes = info->eb_size * info->rsvd_ebs;
+
+       ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name,
+                           UBI_VOL_NAME_MAX + 2);
+       if (ret < 0)
+               return -1;
+
+       info->name[ret - 1] = '\0';
+       return 0;
+}
+
+/**
+ * read_int - read an 'int' value from a file.
+ *
+ * @file   the file to read from
+ * @value  the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int read_int(const char *file, int *value)
+{
+       int fd, rd;
+       char buf[50];
+
+       fd = open(file, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       rd = read(fd, &buf[0], 50);
+       if (rd == -1)
+               goto error;
+
+       if (sscanf(&buf[0], "%d\n", value) != 1) {
+               /* This must be a UBI bug */
+               fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+               errno = EINVAL;
+               goto error;
+       }
+
+       close(fd);
+       return 0;
+
+error:
+       close(fd);
+       return -1;
+}
+
+/**
+ * dev_read_int - read an 'int' value from an UBI device's sysfs file.
+ *
+ * @patt     the file pattern to read from
+ * @dev_num  UBI device number
+ * @value    the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int dev_read_int(const char *patt, int dev_num, int *value)
+{
+       int fd, rd;
+       char buf[50];
+       char file[strlen(patt) + 50];
+
+       sprintf(&file[0], patt, dev_num);
+       fd = open(&file[0], O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       rd = read(fd, &buf[0], 50);
+       if (rd == -1)
+               goto error;
+
+       if (sscanf(&buf[0], "%d\n", value) != 1) {
+               /* This must be a UBI bug */
+               fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+               errno = EINVAL;
+               goto error;
+       }
+
+       close(fd);
+       return 0;
+
+error:
+       close(fd);
+       return -1;
+}
+
+/**
+ * dev_read_ll - read a 'long long' value from an UBI device's sysfs file.
+ *
+ * @patt     the file pattern to read from
+ * @dev_num  UBI device number
+ * @value    the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int dev_read_ll(const char *patt, int dev_num, long long *value)
+{
+       int fd, rd;
+       char buf[50];
+       char file[strlen(patt) + 50];
+
+       sprintf(&file[0], patt, dev_num);
+       fd = open(&file[0], O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       rd = read(fd, &buf[0], 50);
+       if (rd == -1)
+               goto error;
+
+       if (sscanf(&buf[0], "%lld\n", value) != 1) {
+               /* This must be a UBI bug */
+               fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+               errno = EINVAL;
+               goto error;
+       }
+
+       close(fd);
+       return 0;
+
+error:
+       close(fd);
+       return -1;
+}
+
+/**
+ * dev_read_data - read data from an UBI device's sysfs file.
+ *
+ * @patt     the file pattern to read from
+ * @dev_num  UBI device number
+ * @buf      buffer to read data to
+ * @buf_len  buffer length
+ *
+ * This function returns number of read bytes in case of success and %-1 in
+ * case of failure.
+ */
+static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len)
+{
+       int fd, rd;
+       char file[strlen(patt) + 50];
+
+       sprintf(&file[0], patt, dev_num);
+       fd = open(&file[0], O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       rd = read(fd, buf, buf_len);
+       if (rd == -1) {
+               close(fd);
+               return -1;
+       }
+
+       close(fd);
+       return rd;
+}
+
+/**
+ * vol_read_int - read an 'int' value from an UBI volume's sysfs file.
+ *
+ * @patt     the file pattern to read from
+ * @dev_num  UBI device number
+ * @vol_id   volume identifier
+ * @value    the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value)
+{
+       int fd, rd;
+       char buf[50];
+       char file[strlen(patt) + 100];
+
+       sprintf(&file[0], patt, dev_num, vol_id);
+       fd = open(&file[0], O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       rd = read(fd, &buf[0], 50);
+       if (rd == -1)
+               goto error;
+
+       if (sscanf(&buf[0], "%d\n", value) != 1) {
+               /* This must be a UBI bug */
+               fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+               errno = EINVAL;
+               goto error;
+       }
+
+       close(fd);
+       return 0;
+
+error:
+       close(fd);
+       return -1;
+}
+
+/**
+ * vol_read_ll - read a 'long long' value from an UBI volume's sysfs file.
+ *
+ * @patt     the file pattern to read from
+ * @dev_num  UBI device number
+ * @vol_id   volume identifier
+ * @value    the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int vol_read_ll(const char *patt, int dev_num, int vol_id,
+                      long long *value)
+{
+       int fd, rd;
+       char buf[50];
+       char file[strlen(patt) + 100];
+
+       sprintf(&file[0], patt, dev_num, vol_id);
+       fd = open(&file[0], O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       rd = read(fd, &buf[0], 50);
+       if (rd == -1)
+               goto error;
+
+       if (sscanf(&buf[0], "%lld\n", value) != 1) {
+               /* This must be a UBI bug */
+               fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+               errno = EINVAL;
+               goto error;
+       }
+
+       close(fd);
+       return 0;
+
+error:
+       close(fd);
+       return -1;
+}
+
+/**
+ * vol_read_data - read data from an UBI volume's sysfs file.
+ *
+ * @patt     the file pattern to read from
+ * @dev_num  UBI device number
+ * @vol_id   volume identifier
+ * @buf      buffer to read to
+ * @buf_len  buffer length
+ *
+ * This function returns number of read bytes in case of success and %-1 in
+ * case of failure.
+ */
+static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
+                        int buf_len)
+{
+       int fd, rd;
+       char file[strlen(patt) + 100];
+
+       sprintf(&file[0], patt, dev_num, vol_id);
+       fd = open(&file[0], O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       rd = read(fd, buf, buf_len);
+       if (rd == -1) {
+               close(fd);
+               return -1;
+       }
+
+       close(fd);
+       return rd;
+}
+
+/**
+ * mkpath - compose full path from 2 given components.
+ *
+ * @path  first component
+ * @name  second component
+ *
+ * This function returns the resulting path in case of success and %NULL in
+ * case of failure.
+ */
+static char *mkpath(const char *path, const char *name)
+{
+       char *n;
+       int len1 = strlen(path);
+       int len2 = strlen(name);
+
+       n = malloc(len1 + len2 + 2);
+       if (!n)
+               return NULL;
+
+       memcpy(n, path, len1);
+       if (n[len1 - 1] != '/')
+               n[len1++] = '/';
+
+       memcpy(n + len1, name, len2 + 1);
+       return n;
+}
+
+/**
+ * find_dev_num - find UBI device number by its character device node.
+ *
+ * @lib   UBI library descriptor
+ * @node  UBI character device node name
+ *
+ * This function returns positive UBI device number in case of success and %-1
+ * in case of failure.
+ */
+static int find_dev_num(struct libubi *lib, const char *node)
+{
+       struct stat st;
+       struct ubi_info info;
+       int i, major, minor;
+
+       if (stat(node, &st))
+               return -1;
+
+       if (!S_ISCHR(st.st_mode)) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       major = major(st.st_rdev);
+       minor = minor(st.st_rdev);
+
+       if (minor != 0) {
+               errno = -EINVAL;
+               return -1;
+       }
+
+       if (ubi_get_info((libubi_t *)lib, &info))
+               return -1;
+
+       for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+               int major1, minor1, ret;
+               char buf[50];
+
+               ret = dev_read_data(lib->dev_dev, i, &buf[0], 50);
+               if (ret < 0)
+                       return -1;
+
+               ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1);
+               if (ret != 2) {
+                       fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+                       errno = EINVAL;
+                       return -1;
+               }
+
+               if (minor1 == minor && major1 == major)
+                       return i;
+       }
+
+       errno = ENOENT;
+       return -1;
+}
+
+/**
+ * find_dev_num_vol - find UBI device number by volume character device node.
+ *
+ * @lib   UBI library descriptor
+ * @node  UBI character device node name
+ *
+ * This function returns positive UBI device number in case of success and %-1
+ * in case of failure.
+ */
+static int find_dev_num_vol(struct libubi *lib, const char *node)
+{
+       struct stat st;
+       struct ubi_info info;
+       int i, major;
+
+       if (stat(node, &st))
+               return -1;
+
+       if (!S_ISCHR(st.st_mode)) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       major = major(st.st_rdev);
+
+       if (minor(st.st_rdev) == 0) {
+               errno = -EINVAL;
+               return -1;
+       }
+
+       if (ubi_get_info((libubi_t *)lib, &info))
+               return -1;
+
+       for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+               int major1, minor1, ret;
+               char buf[50];
+
+               ret = dev_read_data(lib->dev_dev, i, &buf[0], 50);
+               if (ret < 0)
+                       return -1;
+
+               ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1);
+               if (ret != 2) {
+                       fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+                       errno = EINVAL;
+                       return -1;
+               }
+
+               if (major1 == major)
+                       return i;
+       }
+
+       errno = ENOENT;
+       return -1;
+}
+
+/**
+ * find_vol_num - find UBI volume number by its character device node.
+ *
+ * @lib      UBI library descriptor
+ * @dev_num  UBI device number
+ * @node     UBI volume character device node name
+ *
+ * This function returns positive UBI volume number in case of success and %-1
+ * in case of failure.
+ */
+static int find_vol_num(struct libubi *lib, int dev_num, const char *node)
+{
+       struct stat st;
+       struct ubi_dev_info info;
+       int i, major, minor;
+
+       if (stat(node, &st))
+               return -1;
+
+       if (!S_ISCHR(st.st_mode)) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       major = major(st.st_rdev);
+       minor = minor(st.st_rdev);
+
+       if (minor == 0) {
+               errno = -EINVAL;
+               return -1;
+       }
+
+       if (ubi_get_dev_info1((libubi_t *)lib, dev_num, &info))
+               return -1;
+
+       for (i = info.lowest_vol_num; i <= info.highest_vol_num; i++) {
+               int major1, minor1, ret;
+               char buf[50];
+
+               ret = vol_read_data(lib->vol_dev,  dev_num, i, &buf[0], 50);
+               if (ret < 0)
+                       return -1;
+
+               ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1);
+               if (ret != 2) {
+                       fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+                       errno = EINVAL;
+                       return -1;
+               }
+
+               if (minor1 == minor && major1 == major)
+                       return i;
+       }
+
+       errno = ENOENT;
+       return -1;
+}
similarity index 51%
rename from ubi-utils/new-utils/src/libubi_int.h
rename to ubi-utils/old-utils/src/libubi_int.h
index 2e664b8750627937194e052fee463d74bce33f89..e68b79121cb5824ab1fde14b194932db3c9f0ad3 100644 (file)
@@ -15,7 +15,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Author: Artem Bityutskiy
+ * Author: Artem B. Bityutskiy
  *
  * UBI (Unsorted Block Images) library.
  */
 #ifndef __LIBUBI_INT_H__
 #define __LIBUBI_INT_H__
 
-#include <string.h>
-#include <errno.h>
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*
+ * UBI heavily makes use of the sysfs file system to interact with users-pace.
  * The below are pre-define UBI file and directory names.
- *
- * Note, older kernels put 'ubiX_Y' directories straight to '/sys/class/ubi/'.
- * New kernels puts 'ubiX_Y' directories to '/sys/class/ubi/ubiX/', which is
- * saner. And for compatibility reasons it also puts symlinks to 'ubiX_Y'
- * directories to '/sys/class/ubi/'. For now libubi assumes old layout.
  */
 
 #define SYSFS_UBI         "class/ubi"
-#define SYSFS_CTRL        "class/misc/ubi_ctrl/"
-
-#define CTRL_DEV          "dev"
-
-#define UBI_VER           "version"
 #define UBI_DEV_NAME_PATT "ubi%d"
-
+#define UBI_VER           "version"
 #define DEV_DEV           "dev"
+#define UBI_VOL_NAME_PATT "ubi%d_%d"
 #define DEV_AVAIL_EBS     "avail_eraseblocks"
 #define DEV_TOTAL_EBS     "total_eraseblocks"
 #define DEV_BAD_COUNT     "bad_peb_count"
@@ -56,9 +45,6 @@ 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"
 #define VOL_DEV           "dev"
 #define VOL_ALIGNMENT     "alignment"
@@ -70,37 +56,34 @@ extern "C" {
 
 /**
  * libubi - UBI library description data structure.
- * @sysfs: sysfs file system path
- * @sysfs_ctrl: UBI control device directory in sysfs
- * @ctrl_dev: UBI control device major/minor numbers sysfs file
- * @sysfs_ubi: UBI directory in sysfs
- * @ubi_dev: UBI device sysfs directory pattern
- * @ubi_version: UBI version file sysfs path
- * @dev_dev: UBI device major/minor numbers file pattern
- * @dev_avail_ebs: count of available eraseblocks sysfs path pattern
- * @dev_total_ebs: total eraseblocks count sysfs path pattern
- * @dev_bad_count: count of bad eraseblocks sysfs path pattern
- * @dev_eb_size: size of UBI device's eraseblocks sysfs path pattern
- * @dev_max_ec: maximum erase counter sysfs path pattern
- * @dev_bad_rsvd: count of physical eraseblock reserved for bad eraseblocks
- *                handling
- * @dev_max_vols: maximum volumes number count sysfs path pattern
- * @dev_min_io_size: minimum I/O unit size sysfs path pattern
- * @ubi_vol: UBI volume sysfs directory pattern
- * @vol_type: volume type sysfs path pattern
- * @vol_dev: volume major/minor numbers file pattern
- * @vol_alignment: volume alignment sysfs path pattern
- * @vol_data_bytes: volume data size sysfs path pattern
- * @vol_rsvd_ebs: volume reserved size sysfs path pattern
- * @vol_eb_size: volume eraseblock size sysfs path pattern
- * @vol_corrupted: volume corruption flag sysfs path pattern
- * @vol_name: volume name sysfs path pattern
+ *
+ * @sysfs            sysfs file system path
+ * @sysfs_ubi        UBI directory in sysfs
+ * @ubi_dev          UBI device sysfs directory pattern
+ * @ubi_version      UBI version file sysfs path
+ * @dev_dev          UBI device's major/minor numbers file pattern
+ * @dev_avail_ebs    count of available eraseblocks sysfs path pattern
+ * @dev_total_ebs    total eraseblocks count sysfs path pattern
+ * @dev_bad_count    count of bad eraseblocks sysfs path pattern
+ * @dev_eb_size      size of UBI device's eraseblocks sysfs path pattern
+ * @dev_max_ec       maximum erase counter sysfs path pattern
+ * @dev_bad_rsvd     count of physical eraseblock reserved for bad eraseblocks
+ *                   handling
+ * @dev_max_vols     maximum volumes number count sysfs path pattern
+ * @dev_min_io_size  minimum I/O unit size sysfs path pattern
+ * @ubi_vol          UBI volume sysfs directory pattern
+ * @vol_type         volume type sysfs path pattern
+ * @vol_dev          volume's major/minor numbers file pattern
+ * @vol_alignment    volume alignment sysfs path pattern
+ * @vol_data_bytes   volume data size sysfs path pattern
+ * @vol_rsvd_ebs     volume reserved size sysfs path pattern
+ * @vol_eb_size      volume eraseblock size sysfs path pattern
+ * @vol_corrupted    volume corruption flag sysfs path pattern
+ * @vol_name         volume name sysfs path pattern
  */
 struct libubi
 {
        char *sysfs;
-       char *sysfs_ctrl;
-       char *ctrl_dev;
        char *sysfs_ubi;
        char *ubi_dev;
        char *ubi_version;
@@ -113,7 +96,6 @@ 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;
@@ -126,6 +108,20 @@ struct libubi
        char *vol_max_count;
 };
 
+static int read_int(const char *file, int *value);
+static int dev_read_int(const char *patt, int dev_num, int *value);
+static int dev_read_ll(const char *patt, int dev_num, long long *value);
+static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len);
+static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value);
+static int vol_read_ll(const char *patt, int dev_num, int vol_id,
+                      long long *value);
+static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
+                        int buf_len);
+static char *mkpath(const char *path, const char *name);
+static int find_dev_num(struct libubi *lib, const char *node);
+static int find_dev_num_vol(struct libubi *lib, const char *node);
+static int find_vol_num(struct libubi *lib, int dev_num, const char *node);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/ubi-utils/old-utils/src/libubigen.c b/ubi-utils/old-utils/src/libubigen.c
new file mode 100644 (file)
index 0000000..1793009
--- /dev/null
@@ -0,0 +1,487 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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: Oliver Lohmann
+ *
+ * Add UBI headers to binary data.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <mtd/ubi-media.h>
+#include <mtd_swab.h>
+
+#include "config.h"
+#include "ubigen.h"
+#include "crc32.h"
+
+#define UBI_NAME_SIZE          256
+#define DEFAULT_VID_OFFSET     ((DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE))
+#define MIN(a,b)               ((a) < (b) ? (a) : (b))
+
+static uint32_t crc32_table[256];
+
+struct ubi_info {
+       struct ubi_vid_hdr* v;  /* Volume ID header */
+       struct ubi_ec_hdr* ec;  /* Erase count header */
+
+       FILE* fp_in;            /* Input Stream */
+       FILE* fp_out;           /* Output stream */
+
+       size_t eb_size;         /* Physical EB size in bytes */
+       size_t leb_size;        /* Size of a logical EB in a physical EB */
+       size_t leb_total;       /* Total input size in logical EB */
+       size_t alignment;       /* Block alignment */
+       size_t data_pad;        /* Size of padding in each physical EB */
+
+       size_t bytes_total;     /* Total input size in bytes */
+       size_t bytes_read;      /* Nymber of read bytes (total) */
+
+       uint32_t blks_written;  /* Number of written logical EB */
+
+       uint8_t* buf;           /* Allocated buffer */
+       uint8_t* ptr_ec_hdr;    /* Pointer to EC hdr in buf */
+       uint8_t* ptr_vid_hdr;   /* Pointer to VID hdr in buf */
+       uint8_t* ptr_data;      /* Pointer to data region in buf */
+};
+
+
+static uint32_t
+byte_to_blk(uint64_t byte, uint32_t eb_size)
+{
+       return (byte % eb_size) == 0
+               ? (byte / eb_size)
+               : (byte / eb_size) + 1;
+}
+
+static int
+validate_ubi_info(ubi_info_t u)
+{
+       if ((u->v->vol_type != UBI_VID_DYNAMIC) &&
+           (u->v->vol_type != UBI_VID_STATIC)) {
+               return EUBIGEN_INVALID_TYPE;
+       }
+
+       if (be32_to_cpu(u->ec->vid_hdr_offset) < UBI_VID_HDR_SIZE) {
+               return EUBIGEN_INVALID_HDR_OFFSET;
+       }
+
+       return 0;
+}
+
+static int
+skip_blks(ubi_info_t u, uint32_t blks)
+{
+       uint32_t i;
+       size_t read = 0, to_read = 0;
+
+       /* Step to a maximum of leb_total - 1 to keep the
+          restrictions. */
+       for (i = 0; i < MIN(blks, u->leb_total-1); i++) {
+               /* Read in data */
+               to_read = MIN(u->leb_size,
+                             (u->bytes_total - u->bytes_read));
+               read = fread(u->ptr_data, 1, to_read, u->fp_in);
+               if (read != to_read) {
+                       return -EIO;
+               }
+               u->bytes_read += read;
+               u->blks_written++;
+       }
+
+       return 0;
+}
+
+static void
+clear_buf(ubi_info_t u)
+{
+       memset(u->buf, 0xff, u->eb_size);
+}
+
+static void
+write_ec_hdr(ubi_info_t u)
+{
+       memcpy(u->ptr_ec_hdr, u->ec, UBI_EC_HDR_SIZE);
+}
+
+static int
+fill_data_buffer_from_file(ubi_info_t u, size_t* read)
+{
+       size_t to_read = 0;
+
+       if (u-> fp_in == NULL)
+               return -EIO;
+
+       to_read = MIN(u->leb_size, (u->bytes_total - u->bytes_read));
+       *read = fread(u->ptr_data, 1, to_read, u->fp_in);
+       if (*read != to_read) {
+               return -EIO;
+       }
+       return 0;
+}
+
+static void
+add_static_info(ubi_info_t u, size_t data_size, ubigen_action_t action)
+{
+       uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
+                                u->ptr_data, data_size);
+
+       u->v->data_size = cpu_to_be32(data_size);
+       u->v->data_crc = cpu_to_be32(crc);
+
+       if (action & BROKEN_DATA_CRC) {
+               u->v->data_crc =
+                       cpu_to_be32(be32_to_cpu(u->v->data_crc) + 1);
+       }
+       if (action & BROKEN_DATA_SIZE) {
+               u->v->data_size =
+                       cpu_to_be32(be32_to_cpu(u->v->data_size) + 1);
+       }
+}
+
+static void
+write_vid_hdr(ubi_info_t u, ubigen_action_t action)
+{
+       uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
+                                u->v, UBI_VID_HDR_SIZE_CRC);
+       /* Write VID header */
+       u->v->hdr_crc = cpu_to_be32(crc);
+       if (action & BROKEN_HDR_CRC) {
+               u->v->hdr_crc = cpu_to_be32(be32_to_cpu(u->v->hdr_crc) + 1);
+       }
+       memcpy(u->ptr_vid_hdr, u->v, UBI_VID_HDR_SIZE);
+}
+
+static int
+write_to_output_stream(ubi_info_t u)
+{
+       size_t written;
+
+       written = fwrite(u->buf, 1, u->eb_size, u->fp_out);
+       if (written != u->eb_size) {
+               return -EIO;
+       }
+       return 0;
+}
+
+int
+ubigen_write_leb(ubi_info_t u, ubigen_action_t action)
+{
+       int rc = 0;
+       size_t read = 0;
+
+       clear_buf(u);
+       write_ec_hdr(u);
+
+       rc = fill_data_buffer_from_file(u, &read);
+       if (rc != 0)
+               return rc;
+
+       if (u->v->vol_type == UBI_VID_STATIC)  {
+               add_static_info(u, read, action);
+       }
+
+       u->v->lnum = cpu_to_be32(u->blks_written);
+
+       if (action & MARK_AS_UPDATE) {
+               u->v->copy_flag = (u->v->copy_flag)++;
+       }
+
+       write_vid_hdr(u, action);
+       rc = write_to_output_stream(u);
+       if (rc != 0)
+               return rc;
+
+       /* Update current handle */
+       u->bytes_read += read;
+       u->blks_written++;
+       return 0;
+}
+
+int
+ubigen_write_complete(ubi_info_t u)
+{
+       size_t i;
+       int rc = 0;
+
+       for (i = 0; i < u->leb_total; i++) {
+               rc = ubigen_write_leb(u,  NO_ERROR);
+               if (rc != 0)
+                       return rc;
+       }
+
+       return 0;
+}
+
+int
+ubigen_write_broken_update(ubi_info_t u, uint32_t blk)
+{
+       int rc = 0;
+
+       rc = skip_blks(u, blk);
+       if (rc != 0)
+               return rc;
+
+       rc = ubigen_write_leb(u, MARK_AS_UPDATE | BROKEN_DATA_CRC);
+       if (rc != 0)
+               return rc;
+
+
+       return 0;
+}
+
+void
+dump_info(ubi_info_t u ubi_unused)
+{
+#ifdef DEBUG
+       int err = 0;
+       if (!u) {
+               fprintf(stderr, "<empty>");
+               return;
+       }
+       if (!u->ec) {
+               fprintf(stderr, "<ec-empty>");
+               err = 1;
+       }
+       if (!u->v) {
+               fprintf(stderr, "<v-empty>");
+               err = 1;
+       }
+       if (err) return;
+
+       fprintf(stderr, "ubi volume\n");
+       fprintf(stderr, "version      :   %8d\n", u->v->version);
+       fprintf(stderr, "vol_id       :   %8d\n", be32_to_cpu(u->v->vol_id));
+       fprintf(stderr, "vol_type     :   %8s\n",
+               u->v->vol_type == UBI_VID_STATIC ?
+               "static" : "dynamic");
+       fprintf(stderr, "used_ebs     :   %8d\n",
+               be32_to_cpu(u->v->used_ebs));
+       fprintf(stderr, "eb_size      : 0x%08x\n", u->eb_size);
+       fprintf(stderr, "leb_size     : 0x%08x\n", u->leb_size);
+       fprintf(stderr, "data_pad     : 0x%08x\n",
+               be32_to_cpu(u->v->data_pad));
+       fprintf(stderr, "leb_total    :   %8d\n", u->leb_total);
+       fprintf(stderr, "header offs  : 0x%08x\n",
+               be32_to_cpu(u->ec->vid_hdr_offset));
+       fprintf(stderr, "bytes_total  :   %8d\n", u->bytes_total);
+       fprintf(stderr, "  +  in MiB  : %8.2f M\n",
+               ((float)(u->bytes_total)) / 1024 / 1024);
+       fprintf(stderr, "-------------------------------\n\n");
+#else
+       return;
+#endif
+}
+
+int
+ubigen_destroy(ubi_info_t *u)
+{
+       if (u == NULL)
+               return -EINVAL;
+
+       ubi_info_t tmp = *u;
+
+       if (tmp) {
+               if (tmp->v)
+                       free(tmp->v);
+               if (tmp->ec)
+                       free(tmp->ec);
+               if (tmp->buf)
+                       free(tmp->buf);
+               free(tmp);
+       }
+       *u = NULL;
+       return 0;
+}
+
+void
+ubigen_init(void)
+{
+       init_crc32_table(crc32_table);
+}
+
+int
+ubigen_create(ubi_info_t* u, uint32_t vol_id, uint8_t vol_type,
+             uint32_t eb_size, uint64_t ec, uint32_t alignment,
+             uint8_t version, uint32_t vid_hdr_offset, uint8_t compat_flag,
+             size_t data_size, FILE* fp_in, FILE* fp_out)
+{
+       int rc = 0;
+       ubi_info_t res = NULL;
+       uint32_t crc;
+       uint32_t data_offset;
+
+       if (alignment == 0) {
+               rc = EUBIGEN_INVALID_ALIGNMENT;
+               goto ubigen_create_err;
+       }
+       if ((fp_in == NULL) || (fp_out == NULL)) {
+               rc = -EINVAL;
+               goto ubigen_create_err;
+       }
+
+       res = (ubi_info_t) calloc(1, sizeof(struct ubi_info));
+       if (res == NULL) {
+               rc = -ENOMEM;
+               goto ubigen_create_err;
+       }
+
+       res->v = (struct ubi_vid_hdr*) calloc(1, sizeof(struct ubi_vid_hdr));
+       if (res->v == NULL) {
+               rc = -ENOMEM;
+               goto ubigen_create_err;
+       }
+
+       res->ec = (struct ubi_ec_hdr*) calloc(1, sizeof(struct ubi_ec_hdr));
+       if (res->ec == NULL) {
+               rc = -ENOMEM;
+               goto ubigen_create_err;
+       }
+
+       /* data which is needed in the general process */
+       vid_hdr_offset = vid_hdr_offset ? vid_hdr_offset : DEFAULT_VID_OFFSET;
+       data_offset = vid_hdr_offset + UBI_VID_HDR_SIZE;
+       res->bytes_total = data_size;
+       res->eb_size = eb_size ? eb_size : DEFAULT_BLOCKSIZE;
+       res->data_pad = (res->eb_size - data_offset) % alignment;
+       res->leb_size = res->eb_size - data_offset - res->data_pad;
+       res->leb_total = byte_to_blk(data_size, res->leb_size);
+       res->alignment = alignment;
+
+       if ((res->eb_size < (vid_hdr_offset + UBI_VID_HDR_SIZE))) {
+               rc = EUBIGEN_TOO_SMALL_EB;
+               goto ubigen_create_err;
+       }
+       res->fp_in = fp_in;
+       res->fp_out = fp_out;
+
+       /* vid hdr data which doesn't change */
+       res->v->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
+       res->v->version = version ? version : UBI_VERSION;
+       res->v->vol_type = vol_type;
+       res->v->vol_id = cpu_to_be32(vol_id);
+       res->v->compat = compat_flag;
+       res->v->data_pad = cpu_to_be32(res->data_pad);
+
+       /* static only: used_ebs */
+       if (res->v->vol_type == UBI_VID_STATIC) {
+               res->v->used_ebs = cpu_to_be32(byte_to_blk
+                                               (res->bytes_total,
+                                                res->leb_size));
+       }
+
+       /* ec hdr (fixed, doesn't change) */
+       res->ec->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
+       res->ec->version = version ? version : UBI_VERSION;
+       res->ec->ec = cpu_to_be64(ec);
+       res->ec->vid_hdr_offset = cpu_to_be32(vid_hdr_offset);
+
+       res->ec->data_offset = cpu_to_be32(data_offset);
+
+       crc = clc_crc32(crc32_table, UBI_CRC32_INIT, res->ec,
+                       UBI_EC_HDR_SIZE_CRC);
+       res->ec->hdr_crc = cpu_to_be32(crc);
+
+       /* prepare a read buffer */
+       res->buf = (uint8_t*) malloc (res->eb_size * sizeof(uint8_t));
+       if (res->buf == NULL) {
+               rc = -ENOMEM;
+               goto ubigen_create_err;
+       }
+
+       /* point to distinct regions within the buffer */
+       res->ptr_ec_hdr = res->buf;
+       res->ptr_vid_hdr = res->buf + be32_to_cpu(res->ec->vid_hdr_offset);
+       res->ptr_data = res->buf + be32_to_cpu(res->ec->vid_hdr_offset)
+               + UBI_VID_HDR_SIZE;
+
+       rc = validate_ubi_info(res);
+       if (rc != 0) {
+               fprintf(stderr, "Volume validation failed: %d\n", rc);
+               goto ubigen_create_err;
+       }
+
+       dump_info(res);
+       *u = res;
+       return rc;
+
+ ubigen_create_err:
+       if (res) {
+               if (res->v)
+                       free(res->v);
+               if (res->ec)
+                       free(res->ec);
+               if (res->buf)
+                       free(res->buf);
+               free(res);
+       }
+       *u = NULL;
+       return rc;
+}
+
+int
+ubigen_get_leb_size(ubi_info_t u, size_t* size)
+{
+       if (u == NULL)
+               return -EINVAL;
+
+       *size = u->leb_size;
+       return 0;
+}
+
+
+int
+ubigen_get_leb_total(ubi_info_t u, size_t* total)
+{
+       if (u == NULL)
+               return -EINVAL;
+
+       *total = u->leb_total;
+       return 0;
+}
+
+int
+ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes,
+                   const char* vol_name, struct ubi_vtbl_record *lvol_rec)
+{
+       uint32_t crc;
+
+       if ((u == NULL) || (vol_name == NULL))
+               return -EINVAL;
+
+       memset(lvol_rec, 0x0, UBI_VTBL_RECORD_SIZE);
+
+       lvol_rec->reserved_pebs =
+               cpu_to_be32(byte_to_blk(reserved_bytes, u->leb_size));
+       lvol_rec->alignment = cpu_to_be32(u->alignment);
+       lvol_rec->data_pad = u->v->data_pad;
+       lvol_rec->vol_type = u->v->vol_type;
+
+       lvol_rec->name_len =
+               cpu_to_be16((uint16_t)strlen((const char*)vol_name));
+
+       memcpy(lvol_rec->name, vol_name, UBI_VOL_NAME_MAX + 1);
+
+       crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
+                       lvol_rec, UBI_VTBL_RECORD_SIZE_CRC);
+       lvol_rec->crc =  cpu_to_be32(crc);
+
+       return 0;
+}
index 666e2171f83dd8ac3e1da989c2b3bf8246395e9e..6b1e50c42d9b646c4eba4d591bfb4b0941ac3c17 100644 (file)
@@ -1,83 +1,95 @@
 /*
- * Copyright (c) International Business Machines Corp., 2006
+ *  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
+ *  code or tables extracted from it, as desired without restriction.
  *
- * 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.
+ *  First, the polynomial itself and its table of feedback terms.  The
+ *  polynomial is
+ *  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
  *
- * 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.
+ *  Note that we take it "backwards" and put the highest-order term in
+ *  the lowest-order bit.  The X^32 term is "implied"; the LSB is the
+ *  X^31 term, etc.  The X^0 term (usually shown as "+1") results in
+ *  the MSB being 1
  *
- * 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.
+ *  Note that the usual hardware shift register implementation, which
+ *  is what we're using (we're merely optimizing it by doing eight-bit
+ *  chunks at a time) shifts bits into the lowest-order term.  In our
+ *  implementation, that means shifting towards the right.  Why do we
+ *  do it this way?  Because the calculated CRC must be transmitted in
+ *  order from highest-order term to lowest-order term.  UARTs transmit
+ *  characters in order from LSB to MSB.  By storing the CRC this way
+ *  we hand it to the UART in the order low-byte to high-byte; the UART
+ *  sends each low-bit to hight-bit; and the result is transmission bit
+ *  by bit from highest- to lowest-order term without requiring any bit
+ *  shuffling on our part.  Reception works similarly
  *
- * Author: Thomas Gleixner
- */
-
-/*
- * CRC32 functions
+ *  The feedback terms table consists of 256, 32-bit entries.  Notes
  *
- * Can be compiled as seperate object, but is included into the ipl source
- * so gcc can inline the functions. We optimize for size so the omission of
- * the function frame is helpful.
+ *      The table can be generated at runtime if desired; code to do so
+ *      is shown later.  It might not be obvious, but the feedback
+ *      terms simply represent the results of eight shift/xor opera
+ *      tions for all combinations of data and CRC register values
  *
+ *      The values must be right-shifted by eight bits by the "updcrc
+ *      logic; the shift must be unsigned (bring in zeroes).  On some
+ *      hardware you could probably optimize the shift in assembler by
+ *      using byte-swap instructions
+ *      polynomial $edb88320
  */
 
 #include <stdint.h>
-#include <crc32.h>
-
-/* CRC polynomial */
-#define CRC_POLY       0xEDB88320
-
-/**
- * init_crc32_table - Initialize crc table
- *
- * @table:     pointer to the CRC table which must be initialized
- *
- * Create CRC32 table for given polynomial. The table is created with
- * the lowest order term in the highest order bit. So the x^32 term
- * has to implied in the crc calculation function.
- */
-void init_crc32_table(uint32_t *table)
-{
-       uint32_t crc;
-       int i, j;
-
-       for (i = 0; i < 256; i++) {
-               crc = i;
-               for (j = 8; j > 0; j--) {
-                       if (crc & 1)
-                               crc = (crc >> 1) ^ CRC_POLY;
-                       else
-                               crc >>= 1;
-               }
-               table[i] = crc;
-       }
-}
-
-/**
- * clc_crc32 - Calculate CRC32 over a buffer
- *
- * @table:     pointer to the CRC table
- * @crc:       initial crc value
- * @buf:       pointer to the buffer
- * @len:       number of bytes to calc
- *
- * Returns the updated crc value.
- *
- * The algorithm resembles a hardware shift register, but calculates 8
- * bit at once.
- */
-uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf,
-                  int len)
-{
-       const unsigned char *p = buf;
 
-       while(--len >= 0)
-               crc = table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
-       return crc;
-}
+const uint32_t crc32_table[256] = {
+       0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+       0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+       0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+       0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+       0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+       0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+       0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+       0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+       0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+       0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+       0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+       0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+       0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+       0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+       0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+       0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+       0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+       0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+       0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+       0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+       0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+       0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+       0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+       0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+       0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+       0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+       0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+       0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+       0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+       0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+       0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+       0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+       0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+       0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+       0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+       0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+       0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+       0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+       0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+       0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+       0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+       0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+       0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+       0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+       0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+       0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+       0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+       0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+       0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+       0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+       0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+       0x2d02ef8dL
+};
index 31362b0944c15c0104f1c0d5ad1cc8c5e0181394..ee3145bc1597a05344c694d9bc3ba6639086a36f 100644 (file)
@@ -1,36 +1,19 @@
-#ifndef __CRC32_H__
-#define __CRC32_H__
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * 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.
- */
+#ifndef CRC32_H
+#define CRC32_H
 
-/*
- * Author: Thomas Gleixner
- *
- * CRC32 functions
- *
- * Can be compiled as seperate object, but is included into the ipl source
- * so gcc can inline the functions. We optimize for size so the omission of
- * the function frame is helpful.
- *
- */
 #include <stdint.h>
 
-void init_crc32_table(uint32_t *table);
-uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, int len);
+extern const uint32_t crc32_table[256];
 
-#endif /* __CRC32_H__ */
+/* Return a 32-bit CRC of the contents of the buffer. */
+
+       static inline uint32_t
+crc32(uint32_t val, const void *ss, int len)
+{
+       const unsigned char *s = ss;
+       while (--len >= 0)
+               val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8);
+       return val;
+}
+
+#endif
index a536b471ec4c5035c704874d0acbdda1045376f0..1aa66d8bea434ed2a2fd07c2e49fb97edec4a25f 100644 (file)
@@ -15,7 +15,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Author: Artem B. Bityutskiy
+ * Author: Artem Bityutskiy
  *
  * UBI (Unsorted Block Images) library.
  */
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <dirent.h>
-#include <errno.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <limits.h>
 #include "libubi.h"
 #include "libubi_int.h"
+#include "common.h"
 
-libubi_t libubi_open(void)
+#define PROGRAM_NAME "libubi"
+
+/**
+ * mkpath - compose full path from 2 given components.
+ * @path: the first component
+ * @name: the second component
+ *
+ * This function returns the resulting path in case of success and %NULL in
+ * case of failure.
+ */
+static char *mkpath(const char *path, const char *name)
+{
+       char *n;
+       int len1 = strlen(path);
+       int len2 = strlen(name);
+
+       n = malloc(len1 + len2 + 2);
+       if (!n) {
+               sys_errmsg("cannot allocate %d bytes", len1 + len2 + 2);
+               return NULL;
+       }
+
+       memcpy(n, path, len1);
+       if (n[len1 - 1] != '/')
+               n[len1++] = '/';
+
+       memcpy(n + len1, name, len2 + 1);
+       return n;
+}
+
+/**
+ * read_positive_ll - read a positive 'long long' value from a file.
+ * @file: the file to read from
+ * @value: the result is stored here
+ *
+ * This function reads file @file and interprets its contents as a positive
+ * 'long long' integer. If this is not true, it fails with %EINVAL error code.
+ * Returns %0 in case of success and %-1 in case of failure.
+ */
+static int read_positive_ll(const char *file, long long *value)
+{
+       int fd, rd;
+       char buf[50];
+
+       fd = open(file, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       rd = read(fd, buf, 50);
+       if (rd == -1) {
+               sys_errmsg("cannot read \"%s\"", file);
+               goto out_error;
+       }
+       if (rd == 50) {
+               errmsg("contents of \"%s\" is too long", file);
+               errno = EINVAL;
+               goto out_error;
+       }
+
+       if (sscanf(buf, "%lld\n", value) != 1) {
+               /* This must be a UBI bug */
+               errmsg("cannot read integer from \"%s\"\n", file);
+               errno = EINVAL;
+               goto out_error;
+       }
+
+       if (*value < 0) {
+               errmsg("negative value %lld in \"%s\"", *value, file);
+               errno = EINVAL;
+               goto out_error;
+       }
+
+       if (close(fd))
+               return sys_errmsg("close failed on \"%s\"", file);
+
+       return 0;
+
+out_error:
+       close(fd);
+       return -1;
+}
+
+/**
+ * read_positive_int - read a positive 'int' value from a file.
+ * @file: the file to read from
+ * @value: the result is stored here
+ *
+ * This function is the same as 'read_positive_ll()', but it reads an 'int'
+ * value, not 'long long'.
+ */
+static int read_positive_int(const char *file, int *value)
+{
+       long long res;
+
+       if (read_positive_ll(file, &res))
+               return -1;
+
+       /* Make sure the value is not too big */
+       if (res > INT_MAX) {
+               errmsg("value %lld read from file \"%s\" is out of range",
+                      res, file);
+               errno = EINVAL;
+               return -1;
+       }
+
+       *value = res;
+       return 0;
+}
+
+/**
+ * read_data - read data from a file.
+ * @file: the file to read from
+ * @buf: the buffer to read to
+ * @buf_len: buffer length
+ *
+ * This function returns number of read bytes in case of success and %-1 in
+ * case of failure. Note, if the file contains more then @buf_len bytes of
+ * date, this function fails with %EINVAL error code.
+ */
+static int read_data(const char *file, void *buf, int buf_len)
+{
+       int fd, rd, tmp, tmp1;
+
+       fd = open(file, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       rd = read(fd, buf, buf_len);
+       if (rd == -1) {
+               sys_errmsg("cannot read \"%s\"", file);
+               goto out_error;
+       }
+
+       /* Make sure all data is read */
+       tmp1 = read(fd, &tmp, 1);
+       if (tmp1 == 1) {
+               sys_errmsg("cannot read \"%s\"", file);
+               goto out_error;
+       }
+       if (tmp1) {
+               errmsg("file \"%s\" contains too much data (> %d bytes)",
+                      file, buf_len);
+               errno = EINVAL;
+               goto out_error;
+       }
+
+       if (close(fd)) {
+               sys_errmsg("close failed on \"%s\"", file);
+               return -1;
+       }
+
+       return rd;
+
+out_error:
+       close(fd);
+       return -1;
+}
+
+/**
+ * read_major - read major and minor numbers from a file.
+ * @file: name of the file to read from
+ * @major: major number is returned here
+ * @minor: minor number is returned here
+ *
+ * This function returns % in case of succes, and %-1 in case of failure.
+ */
+static int read_major(const char *file, int *major, int *minor)
+{
+       int ret;
+       char buf[50];
+
+       ret = read_data(file, buf, 50);
+       if (ret < 0)
+               return ret;
+
+       ret = sscanf(buf, "%d:%d\n", major, minor);
+       if (ret != 2) {
+               errno = EINVAL;
+               return errmsg("\"%s\" does not have major:minor format", file);
+       }
+
+       if (*major < 0 || *minor < 0) {
+               errno = EINVAL;
+               return errmsg("bad major:minor %d:%d in \"%s\"",
+                             *major, *minor, file);
+       }
+
+       return 0;
+}
+
+/**
+ * dev_read_int - read a positive 'int' value from an UBI device sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num:  UBI device number
+ * @value: the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int dev_read_int(const char *patt, int dev_num, int *value)
+{
+       char file[strlen(patt) + 50];
+
+       sprintf(file, patt, dev_num);
+       return read_positive_int(file, value);
+}
+
+/**
+ * vol_read_int - read a positive 'int' value from an UBI volume sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num: UBI device number
+ * @vol_id: volume ID
+ * @value: the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value)
+{
+       char file[strlen(patt) + 100];
+
+       sprintf(file, patt, dev_num, vol_id);
+       return read_positive_int(file, value);
+}
+
+/**
+ * dev_read_ll - read a positive 'long long' value from an UBI device sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num: UBI device number
+ * @value: the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int dev_read_ll(const char *patt, int dev_num, long long *value)
+{
+       char file[strlen(patt) + 50];
+
+       sprintf(file, patt, dev_num);
+       return read_positive_ll(file, value);
+}
+
+/**
+ * vol_read_ll - read a positive 'long long' value from an UBI volume sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num: UBI device number
+ * @vol_id: volume ID
+ * @value: the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int vol_read_ll(const char *patt, int dev_num, int vol_id,
+                      long long *value)
+{
+       char file[strlen(patt) + 100];
+
+       sprintf(file, patt, dev_num, vol_id);
+       return read_positive_ll(file, value);
+}
+
+/**
+ * vol_read_data - read data from an UBI volume's sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num: UBI device number
+ * @vol_id: volume ID
+ * @buf: buffer to read to
+ * @buf_len: buffer length
+ *
+ * This function returns number of read bytes in case of success and %-1 in
+ * case of failure.
+ */
+static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
+                        int buf_len)
+{
+       char file[strlen(patt) + 100];
+
+       sprintf(file, patt, dev_num, vol_id);
+       return read_data(file, buf, buf_len);
+}
+
+/**
+ * dev_get_major - get major and minor numbers of an UBI device.
+ * @lib: libubi descriptor
+ * @dev_num: UBI device number
+ * @major: major number is returned here
+ * @minor: minor number is returned here
+ *
+ * This function returns zero in case of succes and %-1 in case of failure.
+ */
+static int dev_get_major(struct libubi *lib, int dev_num, int *major, int *minor)
+{
+       char file[strlen(lib->dev_dev) + 50];
+
+       sprintf(file, lib->dev_dev, dev_num);
+       return read_major(file, major, minor);
+}
+
+/**
+ * vol_get_major - get major and minor numbers of an UBI volume.
+ * @lib: libubi descriptor
+ * @dev_num: UBI device number
+ * @vol_id: volume ID
+ * @major: major number is returned here
+ * @minor: minor number is returned here
+ *
+ * This function returns zero in case of succes and %-1 in case of failure.
+ */
+static int vol_get_major(struct libubi *lib, int dev_num, int vol_id,
+                        int *major, int *minor)
+{
+       char file[strlen(lib->vol_dev) + 100];
+
+       sprintf(file, lib->vol_dev, dev_num, vol_id);
+       return read_major(file, major, minor);
+}
+
+/**
+ * vol_node2nums - find UBI device number and volume ID by volume device node
+ *                 file.
+ * @lib: UBI library descriptor
+ * @node: UBI character device node name
+ * @dev_num: UBI device number is returned here
+ * @vol_id: volume ID is returned hers
+ *
+ * This function returns zero in case of succes and %-1 in case of failure.
+ */
+static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num,
+                        int *vol_id)
+{
+       struct stat st;
+       struct ubi_info info;
+       int i, fd, major, minor;
+       char file[strlen(lib->ubi_vol) + 100];
+
+       if (stat(node, &st))
+               return sys_errmsg("cannot get information about \"%s\"",
+                                 node);
+
+       if (!S_ISCHR(st.st_mode)) {
+               errno = EINVAL;
+               return errmsg("\"%s\" is not a character device", node);
+       }
+
+       major = major(st.st_rdev);
+       minor = minor(st.st_rdev);
+
+       if (minor == 0) {
+               errno = EINVAL;
+               return errmsg("\"%s\" is not a volume character device", node);
+       }
+
+       if (ubi_get_info((libubi_t *)lib, &info))
+               return -1;
+
+       for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+               int major1, minor1, ret;
+
+               ret = dev_get_major(lib, i, &major1, &minor1);
+               if (ret) {
+                       if (errno == ENOENT)
+                               continue;
+                       return -1;
+               }
+
+               if (major1 == major)
+                       break;
+       }
+
+       if (i > info.highest_dev_num) {
+               errno = ENODEV;
+               return -1;
+       }
+
+       /* Make sure this UBI volume exists */
+       sprintf(file, lib->ubi_vol, i, minor - 1);
+       fd = open(file, O_RDONLY);
+       if (fd == -1) {
+               errno = ENODEV;
+               return -1;
+       }
+
+       *dev_num = i;
+       *vol_id = minor - 1;
+       errno = 0;
+       return 0;
+}
+
+/**
+ * dev_node2num - find UBI device number by its character device node.
+ * @lib: UBI library descriptor
+ * @node: UBI character device node name
+ *
+ * This function returns positive UBI device number in case of success and %-1
+ * in case of failure.
+ */
+static int dev_node2num(struct libubi *lib, const char *node, int *dev_num)
+{
+       struct stat st;
+       struct ubi_info info;
+       int i, major, minor;
+
+       if (stat(node, &st))
+               return sys_errmsg("cannot get information about \"%s\"",
+                                 node);
+
+       if (!S_ISCHR(st.st_mode)) {
+               errno = EINVAL;
+               return errmsg("\"%s\" is not a character device", node);
+       }
+
+       major = major(st.st_rdev);
+       minor = minor(st.st_rdev);
+
+       if (minor != 0) {
+               errno = EINVAL;
+               return errmsg("\"%s\" is not an UBI character device", node);
+       }
+
+       if (ubi_get_info((libubi_t *)lib, &info))
+               return -1;
+
+       for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+               int major1, minor1, ret;
+
+               ret = dev_get_major(lib, i, &major1, &minor1);
+               if (ret) {
+                       if (errno == ENOENT)
+                               continue;
+                       return -1;
+               }
+
+               if (major1 == major) {
+                       if (minor1 != 0) {
+                               errmsg("UBI character device minor number is "
+                                      "%d, but must be 0", minor1);
+                               errno = EINVAL;
+                               return -1;
+                       }
+                       errno = 0;
+                       *dev_num = i;
+                       return 0;
+               }
+       }
+
+       errno = ENODEV;
+       return -1;
+}
+
+int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num)
+{
+       struct ubi_info info;
+       int i, ret, mtd_num1;
+       struct libubi *lib = desc;
+
+       if (ubi_get_info(desc, &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 = 0;
+       return -1;
+}
+
+libubi_t libubi_open(int required)
 {
        int fd, version;
        struct libubi *lib;
@@ -46,132 +519,130 @@ libubi_t libubi_open(void)
        /* TODO: this must be discovered instead */
        lib->sysfs = strdup("/sys");
        if (!lib->sysfs)
-               goto error;
+               goto out_error;
+
+       lib->sysfs_ctrl = mkpath(lib->sysfs, SYSFS_CTRL);
+       if (!lib->sysfs_ctrl)
+               goto out_error;
+
+       lib->ctrl_dev = mkpath(lib->sysfs_ctrl, CTRL_DEV);
+       if (!lib->ctrl_dev)
+               goto out_error;
 
        lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI);
        if (!lib->sysfs_ubi)
-               goto error;
+               goto out_error;
 
        /* Make sure UBI is present */
        fd = open(lib->sysfs_ubi, O_RDONLY);
-       if (fd == -1)
-               goto error;
-       close(fd);
+       if (fd == -1) {
+               if (required)
+                       errmsg("cannot open \"%s\", UBI does not seem to "
+                              "exist in system", lib->sysfs_ubi);
+               goto out_error;
+       }
+
+       if (close(fd)) {
+               sys_errmsg("close failed on \"%s\"", lib->sysfs_ubi);
+               goto out_error;
+       }
 
        lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT);
        if (!lib->ubi_dev)
-               goto error;
+               goto out_error;
 
        lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER);
        if (!lib->ubi_version)
-               goto error;
+               goto out_error;
 
        lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV);
        if (!lib->dev_dev)
-               goto error;
+               goto out_error;
 
        lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS);
        if (!lib->dev_avail_ebs)
-               goto error;
+               goto out_error;
 
        lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS);
        if (!lib->dev_total_ebs)
-               goto error;
+               goto out_error;
 
        lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT);
        if (!lib->dev_bad_count)
-               goto error;
+               goto out_error;
 
        lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE);
        if (!lib->dev_eb_size)
-               goto error;
+               goto out_error;
 
        lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC);
        if (!lib->dev_max_ec)
-               goto error;
+               goto out_error;
 
        lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD);
        if (!lib->dev_bad_rsvd)
-               goto error;
+               goto out_error;
 
        lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS);
        if (!lib->dev_max_vols)
-               goto error;
+               goto out_error;
 
        lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE);
        if (!lib->dev_min_io_size)
-               goto error;
+               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 error;
+               goto out_error;
 
        lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE);
        if (!lib->vol_type)
-               goto error;
+               goto out_error;
 
        lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV);
        if (!lib->vol_dev)
-               goto error;
+               goto out_error;
 
        lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT);
        if (!lib->vol_alignment)
-               goto error;
+               goto out_error;
 
        lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES);
        if (!lib->vol_data_bytes)
-               goto error;
+               goto out_error;
 
        lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS);
        if (!lib->vol_rsvd_ebs)
-               goto error;
+               goto out_error;
 
        lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE);
        if (!lib->vol_eb_size)
-               goto error;
+               goto out_error;
 
        lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED);
        if (!lib->vol_corrupted)
-               goto error;
+               goto out_error;
 
        lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME);
        if (!lib->vol_name)
-               goto error;
+               goto out_error;
 
-       if (read_int(lib->ubi_version, &version))
-               goto error;
+       if (read_positive_int(lib->ubi_version, &version))
+               goto out_error;
        if (version != LIBUBI_UBI_VERSION) {
-               fprintf(stderr, "LIBUBI: this library was made for UBI version "
-                               "%d, but UBI version %d is detected\n",
-                       LIBUBI_UBI_VERSION, version);
-               goto error;
+               errmsg("this library was made for UBI version %d, but UBI "
+                      "version %d is detected\n", LIBUBI_UBI_VERSION, version);
+               goto out_error;
        }
 
        return lib;
 
-error:
-       free(lib->vol_corrupted);
-       free(lib->vol_eb_size);
-       free(lib->vol_rsvd_ebs);
-       free(lib->vol_data_bytes);
-       free(lib->vol_alignment);
-       free(lib->vol_dev);
-       free(lib->vol_type);
-       free(lib->ubi_vol);
-       free(lib->dev_min_io_size);
-       free(lib->dev_max_vols);
-       free(lib->dev_bad_rsvd);
-       free(lib->dev_max_ec);
-       free(lib->dev_eb_size);
-       free(lib->dev_bad_count);
-       free(lib->dev_total_ebs);
-       free(lib->dev_avail_ebs);
-       free(lib->dev_dev);
-       free(lib->ubi_version);
-       free(lib->ubi_dev);
-       free(lib->sysfs_ubi);
-       free(lib->sysfs);
-       free(lib);
+out_error:
+       libubi_close((libubi_t)lib);
        return NULL;
 }
 
@@ -188,6 +659,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);
@@ -200,714 +672,533 @@ void libubi_close(libubi_t desc)
        free(lib->ubi_version);
        free(lib->ubi_dev);
        free(lib->sysfs_ubi);
-       free(lib->sysfs);
-       free(lib);
-}
-
-int ubi_get_info(libubi_t desc, struct ubi_info *info)
-{
-       DIR *sysfs_ubi;
-       struct dirent *dirent;
-       struct libubi *lib = (struct libubi *)desc;
-
-       memset(info, '\0', sizeof(struct ubi_info));
-
-       /*
-        * We have to scan the UBI sysfs directory to identify how many UBI
-        * devices are present.
-        */
-       sysfs_ubi = opendir(lib->sysfs_ubi);
-       if (!sysfs_ubi)
-               return -1;
-
-       info->lowest_dev_num = INT_MAX;
-       while ((dirent = readdir(sysfs_ubi))) {
-               char *name = &dirent->d_name[0];
-               int dev_num, ret;
-
-               ret = sscanf(name, UBI_DEV_NAME_PATT, &dev_num);
-               if (ret == 1) {
-                       info->dev_count += 1;
-                       if (dev_num > info->highest_dev_num)
-                               info->highest_dev_num = dev_num;
-                       if (dev_num < info->lowest_dev_num)
-                               info->lowest_dev_num = dev_num;
-               }
-       }
-
-       if (info->lowest_dev_num == INT_MAX)
-               info->lowest_dev_num = 0;
-
-       if (read_int(lib->ubi_version, &info->version))
-               goto close;
-
-       return closedir(sysfs_ubi);
-
-close:
-       closedir(sysfs_ubi);
-       return -1;
-}
-
-int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req)
-{
-       int fd, ret;
-       struct ubi_mkvol_req r;
-       size_t n;
-
-       desc = desc;
-       r.vol_id = req->vol_id;
-       r.alignment = req->alignment;
-       r.bytes = req->bytes;
-       r.vol_type = req->vol_type;
-
-       n = strlen(req->name);
-       if (n > UBI_MAX_VOLUME_NAME)
-               return -1;
-
-       strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1);
-       r.name_len = n;
-
-       fd = open(node, O_RDONLY);
-       if (fd == -1)
-               return -1;
-
-       ret = ioctl(fd, UBI_IOCMKVOL, &r);
-       if (!ret)
-               req->vol_id = r.vol_id;
-
-       close(fd);
-       return ret;
+       free(lib->ctrl_dev);
+       free(lib->sysfs_ctrl);
+       free(lib->sysfs);
+       free(lib);
 }
 
-int ubi_rmvol(libubi_t desc, const char *node, int vol_id)
+int ubi_attach_mtd(libubi_t desc, const char *node,
+                  struct ubi_attach_request *req)
 {
        int fd, ret;
+       struct ubi_attach_req r;
 
-       desc = desc;
-       fd = open(node, O_RDONLY);
-       if (fd == -1)
-               return -1;
-
-       ret = ioctl(fd, UBI_IOCRMVOL, &vol_id);
-       close(fd);
-       return ret;
-}
-
-int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes)
-{
-       int fd, ret;
-       struct ubi_rsvol_req req;
+       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;
-
-       req.bytes = bytes;
-       req.vol_id = vol_id;
+               return sys_errmsg("cannot open \"%s\"", node);
 
-       ret = ioctl(fd, UBI_IOCRSVOL, &req);
+       ret = ioctl(fd, UBI_IOCATT, &r);
        close(fd);
-       return ret;
-}
-
-int ubi_update_start(libubi_t desc, int fd, long long bytes)
-{
-       desc = desc;
-       if (ioctl(fd, UBI_IOCVOLUP, &bytes))
+       if (ret == -1)
                return -1;
-       return 0;
-}
 
-int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info)
-{
-       int dev_num;
-       struct libubi *lib = (struct libubi *)desc;
+       req->dev_num = r.ubi_num;
 
-       dev_num = find_dev_num(lib, node);
-       if (dev_num == -1)
+#ifdef UDEV_SETTLE_HACK
+       if (system("udevsettle") == -1)
                return -1;
+#endif
 
-       return ubi_get_dev_info1(desc, dev_num, info);
+       return ret;
 }
 
-int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
+int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num)
 {
-       DIR *sysfs_ubi;
-       struct dirent *dirent;
-       struct libubi *lib = (struct libubi *)desc;
-
-       memset(info, '\0', sizeof(struct ubi_dev_info));
-       info->dev_num = dev_num;
-
-       sysfs_ubi = opendir(lib->sysfs_ubi);
-       if (!sysfs_ubi)
-               return -1;
-
-       info->lowest_vol_num = INT_MAX;
-       while ((dirent = readdir(sysfs_ubi))) {
-               char *name = &dirent->d_name[0];
-               int vol_id, ret, devno;
+       int ret, ubi_dev;
 
-               ret = sscanf(name, UBI_VOL_NAME_PATT, &devno, &vol_id);
-               if (ret == 2 && devno == dev_num) {
-                       info->vol_count += 1;
-                       if (vol_id > info->highest_vol_num)
-                               info->highest_vol_num = vol_id;
-                       if (vol_id < info->lowest_vol_num)
-                               info->lowest_vol_num = vol_id;
-               }
+       ret = mtd_num2ubi_dev(desc, mtd_num, &ubi_dev);
+       if (ret == -1) {
+               errno = ENODEV;
+               return ret;
        }
 
-       closedir(sysfs_ubi);
-
-       if (info->lowest_vol_num == INT_MAX)
-               info->lowest_vol_num = 0;
-
-       if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_ebs))
-               return -1;
-       if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_ebs))
-               return -1;
-       if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count))
-               return -1;
-       if (dev_read_int(lib->dev_eb_size, dev_num, &info->eb_size))
-               return -1;
-       if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd))
-               return -1;
-       if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec))
-               return -1;
-       if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count))
-               return -1;
-       if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size))
-               return -1;
-
-       info->avail_bytes = info->avail_ebs * info->eb_size;
-       info->total_bytes = info->total_ebs * info->eb_size;
-
-       return 0;
+       return ubi_remove_dev(desc, node, ubi_dev);
 }
 
-int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info)
+int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev)
 {
-       int vol_id, dev_num;
-       struct libubi *lib = (struct libubi *)desc;
+       int fd, ret;
 
-       dev_num = find_dev_num_vol(lib, node);
-       if (dev_num == -1)
-               return -1;
+       desc = desc;
+
+       fd = open(node, O_RDONLY);
+       if (fd == -1)
+               return sys_errmsg("cannot open \"%s\"", node);
+       ret = ioctl(fd, UBI_IOCDET, &ubi_dev);
+       if (ret == -1)
+               goto out_close;
 
-       vol_id = find_vol_num(lib, dev_num, node);
-       if (vol_id == -1)
+#ifdef UDEV_SETTLE_HACK
+       if (system("udevsettle") == -1)
                return -1;
+#endif
 
-       return ubi_get_vol_info1(desc, dev_num, vol_id, info);
+out_close:
+       close(fd);
+       return ret;
 }
 
-int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
-                     struct ubi_vol_info *info)
+int ubi_node_type(libubi_t desc, const char *node)
 {
-       int ret;
+       struct stat st;
+       struct ubi_info info;
+       int i, fd, major, minor;
        struct libubi *lib = (struct libubi *)desc;
-       char buf[50];
-
-       memset(info, '\0', sizeof(struct ubi_vol_info));
-       info->dev_num = dev_num;
-       info->vol_id = vol_id;
+       char file[strlen(lib->ubi_vol) + 100];
 
-       ret = vol_read_data(lib->vol_type, dev_num, vol_id, &buf[0], 50);
-       if (ret < 0)
-               return -1;
+       if (stat(node, &st))
+               return sys_errmsg("cannot get information about \"%s\"",
+                                 node);
 
-       if (strncmp(&buf[0], "static\n", ret) == 0)
-               info->type = UBI_STATIC_VOLUME;
-       else if (strncmp(&buf[0], "dynamic\n", ret) == 0)
-               info->type = UBI_DYNAMIC_VOLUME;
-       else {
-               fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+       if (!S_ISCHR(st.st_mode)) {
+               errmsg("\"%s\" is not a character device", node);
                errno = EINVAL;
                return -1;
        }
 
-       ret = vol_read_int(lib->vol_alignment, dev_num, vol_id,
-                          &info->alignment);
-       if (ret)
-               return -1;
-       ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id,
-                         &info->data_bytes);
-       if (ret)
-               return -1;
-       ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_ebs);
-       if (ret)
-               return -1;
-       ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->eb_size);
-       if (ret)
-               return -1;
-       ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id,
-                          &info->corrupted);
-       if (ret)
-               return -1;
-       info->rsvd_bytes = info->eb_size * info->rsvd_ebs;
+       major = major(st.st_rdev);
+       minor = minor(st.st_rdev);
 
-       ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name,
-                           UBI_VOL_NAME_MAX + 2);
-       if (ret < 0)
+       if (ubi_get_info((libubi_t *)lib, &info))
                return -1;
 
-       info->name[ret - 1] = '\0';
-       return 0;
-}
+       for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+               int major1, minor1, ret;
 
-/**
- * read_int - read an 'int' value from a file.
- *
- * @file   the file to read from
- * @value  the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int read_int(const char *file, int *value)
-{
-       int fd, rd;
-       char buf[50];
+               ret = dev_get_major(lib, i, &major1, &minor1);
+               if (ret) {
+                       if (errno == ENOENT)
+                               continue;
+                       if (!errno)
+                               goto out_not_ubi;
+                       return -1;
+               }
 
-       fd = open(file, O_RDONLY);
-       if (fd == -1)
-               return -1;
+               if (major1 == major)
+                       break;
+       }
 
-       rd = read(fd, &buf[0], 50);
-       if (rd == -1)
-               goto error;
+       if (i > info.highest_dev_num)
+               goto out_not_ubi;
 
-       if (sscanf(&buf[0], "%d\n", value) != 1) {
-               /* This must be a UBI bug */
-               fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-               errno = EINVAL;
-               goto error;
+       if (minor == 0)
+               return 1;
+
+       /* This is supposdely an UBI volume device node */
+       sprintf(file, lib->ubi_vol, i, minor - 1);
+       fd = open(file, O_RDONLY);
+       if (fd == -1) {
+               sys_errmsg("cannot open \"%s\"", node);
+               return -1;
        }
 
-       close(fd);
-       return 0;
+       return 2;
 
-error:
-       close(fd);
+out_not_ubi:
+       errmsg("\"%s\" has major:minor %d:%d, but this does not correspond to "
+              "any UBI device or volume", node, major, minor);
+       errno = 0;
        return -1;
 }
 
-/**
- * dev_read_int - read an 'int' value from an UBI device's sysfs file.
- *
- * @patt     the file pattern to read from
- * @dev_num  UBI device number
- * @value    the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int dev_read_int(const char *patt, int dev_num, int *value)
+int ubi_get_info(libubi_t desc, struct ubi_info *info)
 {
-       int fd, rd;
-       char buf[50];
-       char file[strlen(patt) + 50];
-
-       sprintf(&file[0], patt, dev_num);
-       fd = open(&file[0], O_RDONLY);
-       if (fd == -1)
-               return -1;
+       DIR *sysfs_ubi;
+       struct dirent *dirent;
+       struct libubi *lib = (struct libubi *)desc;
 
-       rd = read(fd, &buf[0], 50);
-       if (rd == -1)
-               goto error;
+       memset(info, '\0', sizeof(struct ubi_info));
 
-       if (sscanf(&buf[0], "%d\n", value) != 1) {
-               /* This must be a UBI bug */
-               fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-               errno = EINVAL;
-               goto error;
+       if (read_major(lib->ctrl_dev, &info->ctrl_major, &info->ctrl_minor)) {
+               /*
+                * Older UBI versions did not have control device, so we do not
+                * panic here for compatibility reasons. May be few years later
+                * we could return -1 here, but for now just set major:minor to
+                * -1.
+                */
+               info->ctrl_major = info->ctrl_minor = -1;
        }
 
-       close(fd);
-       return 0;
+       /*
+        * We have to scan the UBI sysfs directory to identify how many UBI
+        * devices are present.
+        */
+       sysfs_ubi = opendir(lib->sysfs_ubi);
+       if (!sysfs_ubi)
+               return -1;
 
-error:
-       close(fd);
-       return -1;
-}
+       info->lowest_dev_num = INT_MAX;
+       while (1) {
+               int dev_num, ret;
+               char tmp_buf[256];
 
-/**
- * dev_read_ll - read a 'long long' value from an UBI device's sysfs file.
- *
- * @patt     the file pattern to read from
- * @dev_num  UBI device number
- * @value    the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int dev_read_ll(const char *patt, int dev_num, long long *value)
-{
-       int fd, rd;
-       char buf[50];
-       char file[strlen(patt) + 50];
+               errno = 0;
+               dirent = readdir(sysfs_ubi);
+               if (!dirent)
+                       break;
 
-       sprintf(&file[0], patt, dev_num);
-       fd = open(&file[0], O_RDONLY);
-       if (fd == -1)
-               return -1;
+               if (strlen(dirent->d_name) > 256) {
+                       errmsg("invalid entry in %s: \"%s\"",
+                              lib->sysfs_ubi, dirent->d_name);
+                       goto out_close;
+               }
 
-       rd = read(fd, &buf[0], 50);
-       if (rd == -1)
-               goto error;
+               ret = sscanf(dirent->d_name, UBI_DEV_NAME_PATT"%s",
+                            &dev_num, tmp_buf);
+               if (ret == 1) {
+                       info->dev_count += 1;
+                       if (dev_num > info->highest_dev_num)
+                               info->highest_dev_num = dev_num;
+                       if (dev_num < info->lowest_dev_num)
+                               info->lowest_dev_num = dev_num;
+               }
+       }
 
-       if (sscanf(&buf[0], "%lld\n", value) != 1) {
-               /* This must be a UBI bug */
-               fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-               errno = EINVAL;
-               goto error;
+       if (!dirent && errno) {
+               sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
+               goto out_close;
        }
 
-       close(fd);
+       if (closedir(sysfs_ubi))
+               return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
+
+       if (info->lowest_dev_num == INT_MAX)
+               info->lowest_dev_num = 0;
+
+       if (read_positive_int(lib->ubi_version, &info->version))
+               return -1;
+
        return 0;
 
-error:
-       close(fd);
+out_close:
+       closedir(sysfs_ubi);
        return -1;
 }
 
-/**
- * dev_read_data - read data from an UBI device's sysfs file.
- *
- * @patt     the file pattern to read from
- * @dev_num  UBI device number
- * @buf      buffer to read data to
- * @buf_len  buffer length
- *
- * This function returns number of read bytes in case of success and %-1 in
- * case of failure.
- */
-static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len)
+int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req)
 {
-       int fd, rd;
-       char file[strlen(patt) + 50];
+       int fd, ret;
+       struct ubi_mkvol_req r;
+       size_t n;
 
-       sprintf(&file[0], patt, dev_num);
-       fd = open(&file[0], O_RDONLY);
-       if (fd == -1)
-               return -1;
+       memset(&r, sizeof(struct ubi_mkvol_req), '\0');
 
-       rd = read(fd, buf, buf_len);
-       if (rd == -1) {
-               close(fd);
-               return -1;
-       }
+       desc = desc;
+       r.vol_id = req->vol_id;
+       r.alignment = req->alignment;
+       r.bytes = req->bytes;
+       r.vol_type = req->vol_type;
 
-       close(fd);
-       return rd;
-}
+       n = strlen(req->name);
+       if (n > UBI_MAX_VOLUME_NAME)
+               return -1;
 
-/**
- * vol_read_int - read an 'int' value from an UBI volume's sysfs file.
- *
- * @patt     the file pattern to read from
- * @dev_num  UBI device number
- * @vol_id   volume identifier
- * @value    the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value)
-{
-       int fd, rd;
-       char buf[50];
-       char file[strlen(patt) + 100];
+       strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1);
+       r.name_len = n;
 
-       sprintf(&file[0], patt, dev_num, vol_id);
-       fd = open(&file[0], O_RDONLY);
+       fd = open(node, O_RDONLY);
        if (fd == -1)
-               return -1;
+               return sys_errmsg("cannot open \"%s\"", node);
 
-       rd = read(fd, &buf[0], 50);
-       if (rd == -1)
-               goto error;
+       ret = ioctl(fd, UBI_IOCMKVOL, &r);
+       if (ret == -1)
+               goto out_close;
 
-       if (sscanf(&buf[0], "%d\n", value) != 1) {
-               /* This must be a UBI bug */
-               fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-               errno = EINVAL;
-               goto error;
-       }
+       req->vol_id = r.vol_id;
 
-       close(fd);
-       return 0;
+#ifdef UDEV_SETTLE_HACK
+       if (system("udevsettle") == -1)
+               return -1;
+#endif
 
-error:
+out_close:
        close(fd);
-       return -1;
+       return ret;
 }
 
-/**
- * vol_read_ll - read a 'long long' value from an UBI volume's sysfs file.
- *
- * @patt     the file pattern to read from
- * @dev_num  UBI device number
- * @vol_id   volume identifier
- * @value    the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int vol_read_ll(const char *patt, int dev_num, int vol_id,
-                      long long *value)
+int ubi_rmvol(libubi_t desc, const char *node, int vol_id)
 {
-       int fd, rd;
-       char buf[50];
-       char file[strlen(patt) + 100];
+       int fd, ret;
 
-       sprintf(&file[0], patt, dev_num, vol_id);
-       fd = open(&file[0], O_RDONLY);
+       desc = desc;
+       fd = open(node, O_RDONLY);
        if (fd == -1)
-               return -1;
+               return sys_errmsg("cannot open \"%s\"", node);
 
-       rd = read(fd, &buf[0], 50);
-       if (rd == -1)
-               goto error;
-
-       if (sscanf(&buf[0], "%lld\n", value) != 1) {
-               /* This must be a UBI bug */
-               fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-               errno = EINVAL;
-               goto error;
-       }
+       ret = ioctl(fd, UBI_IOCRMVOL, &vol_id);
+       if (ret == -1)
+               goto out_close;
 
-       close(fd);
-       return 0;
+#ifdef UDEV_SETTLE_HACK
+       if (system("udevsettle") == -1)
+               return -1;
+#endif
 
-error:
+out_close:
        close(fd);
-       return -1;
+       return ret;
 }
 
-/**
- * vol_read_data - read data from an UBI volume's sysfs file.
- *
- * @patt     the file pattern to read from
- * @dev_num  UBI device number
- * @vol_id   volume identifier
- * @buf      buffer to read to
- * @buf_len  buffer length
- *
- * This function returns number of read bytes in case of success and %-1 in
- * case of failure.
- */
-static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
-                        int buf_len)
+int ubi_rnvols(libubi_t desc, const char *node, struct ubi_rnvol_req *rnvol)
 {
-       int fd, rd;
-       char file[strlen(patt) + 100];
+       int fd, ret;
 
-       sprintf(&file[0], patt, dev_num, vol_id);
-       fd = open(&file[0], O_RDONLY);
+       fd = open(node, O_RDONLY);
        if (fd == -1)
                return -1;
+       ret = ioctl(fd, UBI_IOCRNVOL, rnvol);
+       if (ret == -1)
+               goto out_close;
 
-       rd = read(fd, buf, buf_len);
-       if (rd == -1) {
-               close(fd);
+#ifdef UDEV_SETTLE_HACK
+       if (system("udevsettle") == -1)
                return -1;
-       }
+#endif
 
+out_close:
        close(fd);
-       return rd;
+       return ret;
 }
 
-/**
- * mkpath - compose full path from 2 given components.
- *
- * @path  first component
- * @name  second component
- *
- * This function returns the resulting path in case of success and %NULL in
- * case of failure.
- */
-static char *mkpath(const char *path, const char *name)
+int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes)
 {
-       char *n;
-       int len1 = strlen(path);
-       int len2 = strlen(name);
+       int fd, ret;
+       struct ubi_rsvol_req req;
 
-       n = malloc(len1 + len2 + 2);
-       if (!n)
-               return NULL;
+       desc = desc;
+       fd = open(node, O_RDONLY);
+       if (fd == -1)
+               return sys_errmsg("cannot open \"%s\"", node);
 
-       memcpy(n, path, len1);
-       if (n[len1 - 1] != '/')
-               n[len1++] = '/';
+       req.bytes = bytes;
+       req.vol_id = vol_id;
 
-       memcpy(n + len1, name, len2 + 1);
-       return n;
+       ret = ioctl(fd, UBI_IOCRSVOL, &req);
+       close(fd);
+       return ret;
 }
 
-/**
- * find_dev_num - find UBI device number by its character device node.
- *
- * @lib   UBI library descriptor
- * @node  UBI character device node name
- *
- * This function returns positive UBI device number in case of success and %-1
- * in case of failure.
- */
-static int find_dev_num(struct libubi *lib, const char *node)
+int ubi_update_start(libubi_t desc, int fd, long long bytes)
 {
-       struct stat st;
-       struct ubi_info info;
-       int i, major, minor;
-
-       if (stat(node, &st))
+       desc = desc;
+       if (ioctl(fd, UBI_IOCVOLUP, &bytes))
                return -1;
+       return 0;
+}
 
-       if (!S_ISCHR(st.st_mode)) {
-               errno = EINVAL;
-               return -1;
-       }
+int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype)
+{
+       struct ubi_leb_change_req req;
 
-       major = major(st.st_rdev);
-       minor = minor(st.st_rdev);
+       desc = desc;
+       memset(&req, 0, sizeof(struct ubi_leb_change_req));
+       req.lnum = lnum;
+       req.bytes = bytes;
+       req.dtype = dtype;
 
-       if (minor != 0) {
-               errno = -EINVAL;
+       if (ioctl(fd, UBI_IOCEBCH, &req))
                return -1;
-       }
+       return 0;
+}
 
-       if (ubi_get_info((libubi_t *)lib, &info))
+int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
+{
+       DIR *sysfs_ubi;
+       struct dirent *dirent;
+       struct libubi *lib = (struct libubi *)desc;
+
+       memset(info, '\0', sizeof(struct ubi_dev_info));
+       info->dev_num = dev_num;
+
+       sysfs_ubi = opendir(lib->sysfs_ubi);
+       if (!sysfs_ubi)
                return -1;
 
-       for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-               int major1, minor1, ret;
-               char buf[50];
+       info->lowest_vol_id = INT_MAX;
 
-               ret = dev_read_data(lib->dev_dev, i, &buf[0], 50);
-               if (ret < 0)
-                       return -1;
+       while (1) {
+               int vol_id, ret, devno;
+               char tmp_buf[256];
 
-               ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1);
-               if (ret != 2) {
-                       fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-                       errno = EINVAL;
-                       return -1;
+               errno = 0;
+               dirent = readdir(sysfs_ubi);
+               if (!dirent)
+                       break;
+
+               if (strlen(dirent->d_name) > 256) {
+                       errmsg("invalid entry in %s: \"%s\"",
+                              lib->sysfs_ubi, dirent->d_name);
+                       goto out_close;
                }
 
-               if (minor1 == minor && major1 == major)
-                       return i;
+               ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT"%s", &devno, &vol_id, tmp_buf);
+               if (ret == 2 && devno == dev_num) {
+                       info->vol_count += 1;
+                       if (vol_id > info->highest_vol_id)
+                               info->highest_vol_id = vol_id;
+                       if (vol_id < info->lowest_vol_id)
+                               info->lowest_vol_id = vol_id;
+               }
        }
 
-       errno = ENOENT;
-       return -1;
-}
+       if (!dirent && errno) {
+               sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
+               goto out_close;
+       }
 
-/**
- * find_dev_num_vol - find UBI device number by volume character device node.
- *
- * @lib   UBI library descriptor
- * @node  UBI character device node name
- *
- * This function returns positive UBI device number in case of success and %-1
- * in case of failure.
- */
-static int find_dev_num_vol(struct libubi *lib, const char *node)
-{
-       struct stat st;
-       struct ubi_info info;
-       int i, major;
+       if (closedir(sysfs_ubi))
+               return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
 
-       if (stat(node, &st))
-               return -1;
+       if (info->lowest_vol_id == INT_MAX)
+               info->lowest_vol_id = 0;
 
-       if (!S_ISCHR(st.st_mode)) {
-               errno = EINVAL;
+       if (dev_get_major(lib, dev_num, &info->major, &info->minor))
                return -1;
-       }
-
-       major = major(st.st_rdev);
 
-       if (minor(st.st_rdev) == 0) {
-               errno = -EINVAL;
+       if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_lebs))
                return -1;
-       }
-
-       if (ubi_get_info((libubi_t *)lib, &info))
+       if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_lebs))
+               return -1;
+       if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count))
+               return -1;
+       if (dev_read_int(lib->dev_eb_size, dev_num, &info->leb_size))
+               return -1;
+       if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd))
+               return -1;
+       if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec))
+               return -1;
+       if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count))
+               return -1;
+       if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size))
                return -1;
 
-       for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-               int major1, minor1, ret;
-               char buf[50];
+       info->avail_bytes = info->avail_lebs * info->leb_size;
+       info->total_bytes = info->total_lebs * info->leb_size;
 
-               ret = dev_read_data(lib->dev_dev, i, &buf[0], 50);
-               if (ret < 0)
-                       return -1;
+       return 0;
 
-               ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1);
-               if (ret != 2) {
-                       fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-                       errno = EINVAL;
-                       return -1;
-               }
+out_close:
+       closedir(sysfs_ubi);
+       return -1;
+}
 
-               if (major1 == major)
-                       return i;
-       }
+int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info)
+{
+       int dev_num;
+       struct libubi *lib = (struct libubi *)desc;
 
-       errno = ENOENT;
-       return -1;
+       if (dev_node2num(lib, node, &dev_num))
+               return -1;
+
+       return ubi_get_dev_info1(desc, dev_num, info);
 }
 
-/**
- * find_vol_num - find UBI volume number by its character device node.
- *
- * @lib      UBI library descriptor
- * @dev_num  UBI device number
- * @node     UBI volume character device node name
- *
- * This function returns positive UBI volume number in case of success and %-1
- * in case of failure.
- */
-static int find_vol_num(struct libubi *lib, int dev_num, const char *node)
+int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
+                     struct ubi_vol_info *info)
 {
-       struct stat st;
-       struct ubi_dev_info info;
-       int i, major, minor;
+       int ret;
+       struct libubi *lib = (struct libubi *)desc;
+       char buf[50];
 
-       if (stat(node, &st))
+       memset(info, '\0', sizeof(struct ubi_vol_info));
+       info->dev_num = dev_num;
+       info->vol_id = vol_id;
+
+       if (dev_get_major(lib, dev_num, &info->dev_major, &info->dev_minor))
+               return -1;
+       if (vol_get_major(lib, dev_num, vol_id, &info->major, &info->minor))
                return -1;
 
-       if (!S_ISCHR(st.st_mode)) {
+       ret = vol_read_data(lib->vol_type, dev_num, vol_id, buf, 50);
+       if (ret < 0)
+               return -1;
+
+       if (strncmp(buf, "static\n", ret) == 0)
+               info->type = UBI_STATIC_VOLUME;
+       else if (strncmp(buf, "dynamic\n", ret) == 0)
+               info->type = UBI_DYNAMIC_VOLUME;
+       else {
+               errmsg("bad value at \"%s\"", buf);
                errno = EINVAL;
                return -1;
        }
 
-       major = major(st.st_rdev);
-       minor = minor(st.st_rdev);
+       ret = vol_read_int(lib->vol_alignment, dev_num, vol_id,
+                          &info->alignment);
+       if (ret)
+               return -1;
+       ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id,
+                         &info->data_bytes);
+       if (ret)
+               return -1;
+       ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_lebs);
+       if (ret)
+               return -1;
+       ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->leb_size);
+       if (ret)
+               return -1;
+       ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id,
+                          &info->corrupted);
+       if (ret)
+               return -1;
+       info->rsvd_bytes = info->leb_size * info->rsvd_lebs;
 
-       if (minor == 0) {
-               errno = -EINVAL;
+       ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name,
+                           UBI_VOL_NAME_MAX + 2);
+       if (ret < 0)
                return -1;
-       }
 
-       if (ubi_get_dev_info1((libubi_t *)lib, dev_num, &info))
+       info->name[ret - 1] = '\0';
+       return 0;
+}
+
+int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info)
+{
+       int vol_id, dev_num;
+       struct libubi *lib = (struct libubi *)desc;
+
+       if (vol_node2nums(lib, node, &dev_num, &vol_id))
                return -1;
 
-       for (i = info.lowest_vol_num; i <= info.highest_vol_num; i++) {
-               int major1, minor1, ret;
-               char buf[50];
+       return ubi_get_vol_info1(desc, dev_num, vol_id, info);
+}
 
-               ret = vol_read_data(lib->vol_dev,  dev_num, i, &buf[0], 50);
-               if (ret < 0)
-                       return -1;
+int ubi_get_vol_info1_nm(libubi_t desc, int dev_num, const char *name,
+                        struct ubi_vol_info *info)
+{
+       int i, err;
+       unsigned int nlen = strlen(name);
+       struct ubi_dev_info dev_info;
+
+       if (nlen == 0) {
+               errmsg("bad \"name\" input parameter");
+               errno = EINVAL;
+               return -1;
+       }
+
+       err = ubi_get_dev_info1(desc, dev_num, &dev_info);
+       if (err)
+               return err;
 
-               ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1);
-               if (ret != 2) {
-                       fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-                       errno = EINVAL;
+       for (i = dev_info.lowest_vol_id;
+            i <= dev_info.highest_vol_id; i++) {
+               err = ubi_get_vol_info1(desc, dev_num, i, info);
+               if (err == -1) {
+                       if (errno == ENOENT)
+                               continue;
                        return -1;
                }
 
-               if (minor1 == minor && major1 == major)
-                       return i;
+               if (nlen == strlen(info->name) && !strcmp(name, info->name))
+                       return 0;
        }
 
        errno = ENOENT;
index e68b79121cb5824ab1fde14b194932db3c9f0ad3..2e664b8750627937194e052fee463d74bce33f89 100644 (file)
@@ -15,7 +15,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Author: Artem B. Bityutskiy
+ * Author: Artem Bityutskiy
  *
  * UBI (Unsorted Block Images) library.
  */
 #ifndef __LIBUBI_INT_H__
 #define __LIBUBI_INT_H__
 
+#include <string.h>
+#include <errno.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*
- * UBI heavily makes use of the sysfs file system to interact with users-pace.
  * The below are pre-define UBI file and directory names.
+ *
+ * Note, older kernels put 'ubiX_Y' directories straight to '/sys/class/ubi/'.
+ * New kernels puts 'ubiX_Y' directories to '/sys/class/ubi/ubiX/', which is
+ * saner. And for compatibility reasons it also puts symlinks to 'ubiX_Y'
+ * directories to '/sys/class/ubi/'. For now libubi assumes old layout.
  */
 
 #define SYSFS_UBI         "class/ubi"
-#define UBI_DEV_NAME_PATT "ubi%d"
+#define SYSFS_CTRL        "class/misc/ubi_ctrl/"
+
+#define CTRL_DEV          "dev"
+
 #define UBI_VER           "version"
+#define UBI_DEV_NAME_PATT "ubi%d"
+
 #define DEV_DEV           "dev"
-#define UBI_VOL_NAME_PATT "ubi%d_%d"
 #define DEV_AVAIL_EBS     "avail_eraseblocks"
 #define DEV_TOTAL_EBS     "total_eraseblocks"
 #define DEV_BAD_COUNT     "bad_peb_count"
@@ -45,6 +56,9 @@ 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"
 #define VOL_DEV           "dev"
 #define VOL_ALIGNMENT     "alignment"
@@ -56,34 +70,37 @@ extern "C" {
 
 /**
  * libubi - UBI library description data structure.
- *
- * @sysfs            sysfs file system path
- * @sysfs_ubi        UBI directory in sysfs
- * @ubi_dev          UBI device sysfs directory pattern
- * @ubi_version      UBI version file sysfs path
- * @dev_dev          UBI device's major/minor numbers file pattern
- * @dev_avail_ebs    count of available eraseblocks sysfs path pattern
- * @dev_total_ebs    total eraseblocks count sysfs path pattern
- * @dev_bad_count    count of bad eraseblocks sysfs path pattern
- * @dev_eb_size      size of UBI device's eraseblocks sysfs path pattern
- * @dev_max_ec       maximum erase counter sysfs path pattern
- * @dev_bad_rsvd     count of physical eraseblock reserved for bad eraseblocks
- *                   handling
- * @dev_max_vols     maximum volumes number count sysfs path pattern
- * @dev_min_io_size  minimum I/O unit size sysfs path pattern
- * @ubi_vol          UBI volume sysfs directory pattern
- * @vol_type         volume type sysfs path pattern
- * @vol_dev          volume's major/minor numbers file pattern
- * @vol_alignment    volume alignment sysfs path pattern
- * @vol_data_bytes   volume data size sysfs path pattern
- * @vol_rsvd_ebs     volume reserved size sysfs path pattern
- * @vol_eb_size      volume eraseblock size sysfs path pattern
- * @vol_corrupted    volume corruption flag sysfs path pattern
- * @vol_name         volume name sysfs path pattern
+ * @sysfs: sysfs file system path
+ * @sysfs_ctrl: UBI control device directory in sysfs
+ * @ctrl_dev: UBI control device major/minor numbers sysfs file
+ * @sysfs_ubi: UBI directory in sysfs
+ * @ubi_dev: UBI device sysfs directory pattern
+ * @ubi_version: UBI version file sysfs path
+ * @dev_dev: UBI device major/minor numbers file pattern
+ * @dev_avail_ebs: count of available eraseblocks sysfs path pattern
+ * @dev_total_ebs: total eraseblocks count sysfs path pattern
+ * @dev_bad_count: count of bad eraseblocks sysfs path pattern
+ * @dev_eb_size: size of UBI device's eraseblocks sysfs path pattern
+ * @dev_max_ec: maximum erase counter sysfs path pattern
+ * @dev_bad_rsvd: count of physical eraseblock reserved for bad eraseblocks
+ *                handling
+ * @dev_max_vols: maximum volumes number count sysfs path pattern
+ * @dev_min_io_size: minimum I/O unit size sysfs path pattern
+ * @ubi_vol: UBI volume sysfs directory pattern
+ * @vol_type: volume type sysfs path pattern
+ * @vol_dev: volume major/minor numbers file pattern
+ * @vol_alignment: volume alignment sysfs path pattern
+ * @vol_data_bytes: volume data size sysfs path pattern
+ * @vol_rsvd_ebs: volume reserved size sysfs path pattern
+ * @vol_eb_size: volume eraseblock size sysfs path pattern
+ * @vol_corrupted: volume corruption flag sysfs path pattern
+ * @vol_name: volume name sysfs path pattern
  */
 struct libubi
 {
        char *sysfs;
+       char *sysfs_ctrl;
+       char *ctrl_dev;
        char *sysfs_ubi;
        char *ubi_dev;
        char *ubi_version;
@@ -96,6 +113,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;
@@ -108,20 +126,6 @@ struct libubi
        char *vol_max_count;
 };
 
-static int read_int(const char *file, int *value);
-static int dev_read_int(const char *patt, int dev_num, int *value);
-static int dev_read_ll(const char *patt, int dev_num, long long *value);
-static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len);
-static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value);
-static int vol_read_ll(const char *patt, int dev_num, int vol_id,
-                      long long *value);
-static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
-                        int buf_len);
-static char *mkpath(const char *path, const char *name);
-static int find_dev_num(struct libubi *lib, const char *node);
-static int find_dev_num_vol(struct libubi *lib, const char *node);
-static int find_vol_num(struct libubi *lib, int dev_num, const char *node);
-
 #ifdef __cplusplus
 }
 #endif
index 1793009c2b335726de2551658800a73906ac0f69..91bb274c68819d7c2ff58404c0386ef629292790 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) International Business Machines Corp., 2006
+ * Copyright (C) 2008 Nokia Corporation
  *
  * 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
  * 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.
+ */
+
+/*
+ * Generating UBI images.
  *
- * Author: Oliver Lohmann
- *
- * Add UBI headers to binary data.
+ * Authors: Oliver Lohmann
+ *          Artem Bityutskiy
  */
 
 #include <stdlib.h>
 #include <stdint.h>
-#include <stdio.h>
-#include <errno.h>
+#include <unistd.h>
 #include <string.h>
+
 #include <mtd/ubi-media.h>
 #include <mtd_swab.h>
-
-#include "config.h"
-#include "ubigen.h"
+#include <libubigen.h>
 #include "crc32.h"
-
-#define UBI_NAME_SIZE          256
-#define DEFAULT_VID_OFFSET     ((DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE))
-#define MIN(a,b)               ((a) < (b) ? (a) : (b))
-
-static uint32_t crc32_table[256];
-
-struct ubi_info {
-       struct ubi_vid_hdr* v;  /* Volume ID header */
-       struct ubi_ec_hdr* ec;  /* Erase count header */
-
-       FILE* fp_in;            /* Input Stream */
-       FILE* fp_out;           /* Output stream */
-
-       size_t eb_size;         /* Physical EB size in bytes */
-       size_t leb_size;        /* Size of a logical EB in a physical EB */
-       size_t leb_total;       /* Total input size in logical EB */
-       size_t alignment;       /* Block alignment */
-       size_t data_pad;        /* Size of padding in each physical EB */
-
-       size_t bytes_total;     /* Total input size in bytes */
-       size_t bytes_read;      /* Nymber of read bytes (total) */
-
-       uint32_t blks_written;  /* Number of written logical EB */
-
-       uint8_t* buf;           /* Allocated buffer */
-       uint8_t* ptr_ec_hdr;    /* Pointer to EC hdr in buf */
-       uint8_t* ptr_vid_hdr;   /* Pointer to VID hdr in buf */
-       uint8_t* ptr_data;      /* Pointer to data region in buf */
-};
-
-
-static uint32_t
-byte_to_blk(uint64_t byte, uint32_t eb_size)
-{
-       return (byte % eb_size) == 0
-               ? (byte / eb_size)
-               : (byte / eb_size) + 1;
-}
-
-static int
-validate_ubi_info(ubi_info_t u)
-{
-       if ((u->v->vol_type != UBI_VID_DYNAMIC) &&
-           (u->v->vol_type != UBI_VID_STATIC)) {
-               return EUBIGEN_INVALID_TYPE;
-       }
-
-       if (be32_to_cpu(u->ec->vid_hdr_offset) < UBI_VID_HDR_SIZE) {
-               return EUBIGEN_INVALID_HDR_OFFSET;
-       }
-
-       return 0;
-}
-
-static int
-skip_blks(ubi_info_t u, uint32_t blks)
-{
-       uint32_t i;
-       size_t read = 0, to_read = 0;
-
-       /* Step to a maximum of leb_total - 1 to keep the
-          restrictions. */
-       for (i = 0; i < MIN(blks, u->leb_total-1); i++) {
-               /* Read in data */
-               to_read = MIN(u->leb_size,
-                             (u->bytes_total - u->bytes_read));
-               read = fread(u->ptr_data, 1, to_read, u->fp_in);
-               if (read != to_read) {
-                       return -EIO;
-               }
-               u->bytes_read += read;
-               u->blks_written++;
-       }
-
-       return 0;
-}
-
-static void
-clear_buf(ubi_info_t u)
-{
-       memset(u->buf, 0xff, u->eb_size);
-}
-
-static void
-write_ec_hdr(ubi_info_t u)
-{
-       memcpy(u->ptr_ec_hdr, u->ec, UBI_EC_HDR_SIZE);
-}
-
-static int
-fill_data_buffer_from_file(ubi_info_t u, size_t* read)
-{
-       size_t to_read = 0;
-
-       if (u-> fp_in == NULL)
-               return -EIO;
-
-       to_read = MIN(u->leb_size, (u->bytes_total - u->bytes_read));
-       *read = fread(u->ptr_data, 1, to_read, u->fp_in);
-       if (*read != to_read) {
-               return -EIO;
-       }
-       return 0;
-}
-
-static void
-add_static_info(ubi_info_t u, size_t data_size, ubigen_action_t action)
-{
-       uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
-                                u->ptr_data, data_size);
-
-       u->v->data_size = cpu_to_be32(data_size);
-       u->v->data_crc = cpu_to_be32(crc);
-
-       if (action & BROKEN_DATA_CRC) {
-               u->v->data_crc =
-                       cpu_to_be32(be32_to_cpu(u->v->data_crc) + 1);
-       }
-       if (action & BROKEN_DATA_SIZE) {
-               u->v->data_size =
-                       cpu_to_be32(be32_to_cpu(u->v->data_size) + 1);
-       }
-}
-
-static void
-write_vid_hdr(ubi_info_t u, ubigen_action_t action)
+#include "common.h"
+
+#define PROGRAM_NAME "libubigen"
+
+/**
+ * ubigen_info_init - initialize libubigen.
+ * @ui: libubigen information
+ * @peb_size: flash physical eraseblock size
+ * @min_io_size: flash minimum input/output unit size
+ * @subpage_size: flash sub-page, if present (has to be equivalent to
+ *                @min_io_size if does not exist)
+ * @vid_hdr_offs: offset of the VID header
+ * @ubi_ver: UBI version
+ */
+void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size,
+                     int subpage_size, int vid_hdr_offs, int ubi_ver)
 {
-       uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
-                                u->v, UBI_VID_HDR_SIZE_CRC);
-       /* Write VID header */
-       u->v->hdr_crc = cpu_to_be32(crc);
-       if (action & BROKEN_HDR_CRC) {
-               u->v->hdr_crc = cpu_to_be32(be32_to_cpu(u->v->hdr_crc) + 1);
+       if (!vid_hdr_offs) {
+               vid_hdr_offs = UBI_EC_HDR_SIZE + subpage_size - 1;
+               vid_hdr_offs /= subpage_size;
+               vid_hdr_offs *= subpage_size;
        }
-       memcpy(u->ptr_vid_hdr, u->v, UBI_VID_HDR_SIZE);
-}
 
-static int
-write_to_output_stream(ubi_info_t u)
-{
-       size_t written;
-
-       written = fwrite(u->buf, 1, u->eb_size, u->fp_out);
-       if (written != u->eb_size) {
-               return -EIO;
-       }
-       return 0;
+       ui->peb_size = peb_size;
+       ui->min_io_size = min_io_size;
+       ui->vid_hdr_offs = vid_hdr_offs;
+       ui->data_offs = vid_hdr_offs + UBI_VID_HDR_SIZE + min_io_size - 1;
+       ui->data_offs /= min_io_size;
+       ui->data_offs *= min_io_size;
+       ui->leb_size = peb_size - ui->data_offs;
+       ui->ubi_ver = ubi_ver;
+
+       ui->max_volumes = ui->leb_size / UBI_VTBL_RECORD_SIZE;
+       if (ui->max_volumes > UBI_MAX_VOLUMES)
+               ui->max_volumes = UBI_MAX_VOLUMES;
+       ui->vtbl_size = ui->max_volumes * UBI_VTBL_RECORD_SIZE;
 }
 
-int
-ubigen_write_leb(ubi_info_t u, ubigen_action_t action)
+/**
+ * ubigen_create_empty_vtbl - creates empty volume table.
+ *
+ * This function creates an empty volume table and returns a pointer to it in
+ * case of success and %NULL in case of failure. The returned object has to be
+ * freed with 'free()' call.
+ */
+struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui)
 {
-       int rc = 0;
-       size_t read = 0;
-
-       clear_buf(u);
-       write_ec_hdr(u);
+       struct ubi_vtbl_record *vtbl;
+       int i;
 
-       rc = fill_data_buffer_from_file(u, &read);
-       if (rc != 0)
-               return rc;
-
-       if (u->v->vol_type == UBI_VID_STATIC)  {
-               add_static_info(u, read, action);
+       vtbl = calloc(1, ui->vtbl_size);
+       if (!vtbl) {
+               sys_errmsg("cannot allocate %d bytes of memory", ui->vtbl_size);
+               return NULL;
        }
 
-       u->v->lnum = cpu_to_be32(u->blks_written);
-
-       if (action & MARK_AS_UPDATE) {
-               u->v->copy_flag = (u->v->copy_flag)++;
+       for (i = 0; i < ui->max_volumes; i++) {
+               uint32_t crc = crc32(UBI_CRC32_INIT, &vtbl[i],
+                                    UBI_VTBL_RECORD_SIZE_CRC);
+               vtbl[i].crc = cpu_to_be32(crc);
        }
 
-       write_vid_hdr(u, action);
-       rc = write_to_output_stream(u);
-       if (rc != 0)
-               return rc;
-
-       /* Update current handle */
-       u->bytes_read += read;
-       u->blks_written++;
-       return 0;
+       return vtbl;
 }
 
-int
-ubigen_write_complete(ubi_info_t u)
+/**
+ * ubigen_add_volume - add a volume to the volume table.
+ * @ui: libubigen information
+ * @vi: volume information
+ * @vtbl: volume table to add to
+ *
+ * This function adds volume described by input parameters to the volume table
+ * @vtbl.
+ */
+int ubigen_add_volume(const struct ubigen_info *ui,
+                     const struct ubigen_vol_info *vi,
+                     struct ubi_vtbl_record *vtbl)
 {
-       size_t i;
-       int rc = 0;
-
-       for (i = 0; i < u->leb_total; i++) {
-               rc = ubigen_write_leb(u,  NO_ERROR);
-               if (rc != 0)
-                       return rc;
-       }
-
+       struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id];
+       uint32_t tmp;
+
+       if (vi->id >= ui->max_volumes)
+               return errmsg("too high volume id %d, max. volumes is %d",
+                             vi->id, ui->max_volumes);
+
+       if (vi->alignment >= ui->leb_size)
+               return errmsg("too large alignment %d, max is %d (LEB size)",
+                             vi->alignment, ui->leb_size);
+
+       memset(vtbl_rec, '\0', sizeof(struct ubi_vtbl_record));
+       tmp = (vi->bytes + ui->leb_size - 1) / ui->leb_size;
+       vtbl_rec->reserved_pebs = cpu_to_be32(tmp);
+       vtbl_rec->alignment = cpu_to_be32(vi->alignment);
+       vtbl_rec->vol_type = vi->type;
+       tmp = ui->leb_size % vi->alignment;
+       vtbl_rec->data_pad = cpu_to_be32(tmp);
+       vtbl_rec->flags = vi->flags;
+
+       memcpy(vtbl_rec->name, vi->name, vi->name_len);
+       vtbl_rec->name[vi->name_len] = '\0';
+       vtbl_rec->name_len = cpu_to_be16(vi->name_len);
+
+       tmp = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
+       vtbl_rec->crc =  cpu_to_be32(tmp);
        return 0;
 }
 
-int
-ubigen_write_broken_update(ubi_info_t u, uint32_t blk)
+/**
+ * ubigen_init_ec_hdr - initialize EC header.
+ * @ui: libubigen information
+ * @hdr: the EC header to initialize
+ * @ec: erase counter value
+ */
+void ubigen_init_ec_hdr(const struct ubigen_info *ui,
+                       struct ubi_ec_hdr *hdr, long long ec)
 {
-       int rc = 0;
+       uint32_t crc;
 
-       rc = skip_blks(u, blk);
-       if (rc != 0)
-               return rc;
+       memset(hdr, '\0', sizeof(struct ubi_ec_hdr));
 
-       rc = ubigen_write_leb(u, MARK_AS_UPDATE | BROKEN_DATA_CRC);
-       if (rc != 0)
-               return rc;
+       hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
+       hdr->version = ui->ubi_ver;
+       hdr->ec = cpu_to_be64(ec);
+       hdr->vid_hdr_offset = cpu_to_be32(ui->vid_hdr_offs);
 
+       hdr->data_offset = cpu_to_be32(ui->data_offs);
 
-       return 0;
+       crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
+       hdr->hdr_crc = cpu_to_be32(crc);
 }
 
-void
-dump_info(ubi_info_t u ubi_unused)
+/**
+ * init_vid_hdr - initialize VID header.
+ * @ui: libubigen information
+ * @vi: volume information
+ * @hdr: the VID header to initialize
+ * @lnum: logical eraseblock number
+ * @data: the contents of the LEB (static volumes only)
+ * @data_size: amount of data in this LEB (static volumes only)
+ *
+ * Note, @used_ebs, @data and @data_size are ignored in case of dynamic
+ * volumes.
+ */
+static void init_vid_hdr(const struct ubigen_info *ui,
+                        const struct ubigen_vol_info *vi,
+                        struct ubi_vid_hdr *hdr, int lnum,
+                        const void *data, int data_size)
 {
-#ifdef DEBUG
-       int err = 0;
-       if (!u) {
-               fprintf(stderr, "<empty>");
-               return;
-       }
-       if (!u->ec) {
-               fprintf(stderr, "<ec-empty>");
-               err = 1;
-       }
-       if (!u->v) {
-               fprintf(stderr, "<v-empty>");
-               err = 1;
-       }
-       if (err) return;
-
-       fprintf(stderr, "ubi volume\n");
-       fprintf(stderr, "version      :   %8d\n", u->v->version);
-       fprintf(stderr, "vol_id       :   %8d\n", be32_to_cpu(u->v->vol_id));
-       fprintf(stderr, "vol_type     :   %8s\n",
-               u->v->vol_type == UBI_VID_STATIC ?
-               "static" : "dynamic");
-       fprintf(stderr, "used_ebs     :   %8d\n",
-               be32_to_cpu(u->v->used_ebs));
-       fprintf(stderr, "eb_size      : 0x%08x\n", u->eb_size);
-       fprintf(stderr, "leb_size     : 0x%08x\n", u->leb_size);
-       fprintf(stderr, "data_pad     : 0x%08x\n",
-               be32_to_cpu(u->v->data_pad));
-       fprintf(stderr, "leb_total    :   %8d\n", u->leb_total);
-       fprintf(stderr, "header offs  : 0x%08x\n",
-               be32_to_cpu(u->ec->vid_hdr_offset));
-       fprintf(stderr, "bytes_total  :   %8d\n", u->bytes_total);
-       fprintf(stderr, "  +  in MiB  : %8.2f M\n",
-               ((float)(u->bytes_total)) / 1024 / 1024);
-       fprintf(stderr, "-------------------------------\n\n");
-#else
-       return;
-#endif
-}
+       uint32_t crc;
 
-int
-ubigen_destroy(ubi_info_t *u)
-{
-       if (u == NULL)
-               return -EINVAL;
-
-       ubi_info_t tmp = *u;
-
-       if (tmp) {
-               if (tmp->v)
-                       free(tmp->v);
-               if (tmp->ec)
-                       free(tmp->ec);
-               if (tmp->buf)
-                       free(tmp->buf);
-               free(tmp);
+       memset(hdr, '\0', sizeof(struct ubi_vid_hdr));
+
+       hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
+       hdr->version = ui->ubi_ver;
+       hdr->vol_type = vi->type;
+       hdr->vol_id = cpu_to_be32(vi->id);
+       hdr->lnum = cpu_to_be32(lnum);
+       hdr->data_pad = cpu_to_be32(vi->data_pad);
+       hdr->compat = vi->compat;
+
+       if (vi->type == UBI_VID_STATIC) {
+               hdr->data_size = cpu_to_be32(data_size);
+               hdr->used_ebs = cpu_to_be32(vi->used_ebs);
+               crc = crc32(UBI_CRC32_INIT, data, data_size);
+               hdr->data_crc = cpu_to_be32(crc);
        }
-       *u = NULL;
-       return 0;
-}
 
-void
-ubigen_init(void)
-{
-       init_crc32_table(crc32_table);
+       crc = crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC);
+       hdr->hdr_crc = cpu_to_be32(crc);
 }
 
-int
-ubigen_create(ubi_info_t* u, uint32_t vol_id, uint8_t vol_type,
-             uint32_t eb_size, uint64_t ec, uint32_t alignment,
-             uint8_t version, uint32_t vid_hdr_offset, uint8_t compat_flag,
-             size_t data_size, FILE* fp_in, FILE* fp_out)
+/**
+ * ubigen_write_volume - write UBI volume.
+ * @ui: libubigen information
+ * @vi: volume information
+ * @ec: erase coutner value to put to EC headers
+ * @bytes: volume size in bytes
+ * @in: input file descriptor (has to be properly seeked)
+ * @out: output file descriptor
+ *
+ * This function reads the contents of the volume from the input file @in and
+ * writes the UBI volume to the output file @out. Returns zero on success and
+ * %-1 on failure.
+ */
+int ubigen_write_volume(const struct ubigen_info *ui,
+                       const struct ubigen_vol_info *vi, long long ec,
+                       long long bytes, int in, int out)
 {
-       int rc = 0;
-       ubi_info_t res = NULL;
-       uint32_t crc;
-       uint32_t data_offset;
+       int len = vi->usable_leb_size, rd, lnum = 0;
+       char inbuf[ui->leb_size], outbuf[ui->peb_size];
 
-       if (alignment == 0) {
-               rc = EUBIGEN_INVALID_ALIGNMENT;
-               goto ubigen_create_err;
-       }
-       if ((fp_in == NULL) || (fp_out == NULL)) {
-               rc = -EINVAL;
-               goto ubigen_create_err;
-       }
+       if (vi->id >= ui->max_volumes)
+               return errmsg("too high volume id %d, max. volumes is %d",
+                             vi->id, ui->max_volumes);
 
-       res = (ubi_info_t) calloc(1, sizeof(struct ubi_info));
-       if (res == NULL) {
-               rc = -ENOMEM;
-               goto ubigen_create_err;
-       }
+       if (vi->alignment >= ui->leb_size)
+               return errmsg("too large alignment %d, max is %d (LEB size)",
+                             vi->alignment, ui->leb_size);
 
-       res->v = (struct ubi_vid_hdr*) calloc(1, sizeof(struct ubi_vid_hdr));
-       if (res->v == NULL) {
-               rc = -ENOMEM;
-               goto ubigen_create_err;
-       }
+       memset(outbuf, 0xFF, ui->data_offs);
+       ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec);
 
-       res->ec = (struct ubi_ec_hdr*) calloc(1, sizeof(struct ubi_ec_hdr));
-       if (res->ec == NULL) {
-               rc = -ENOMEM;
-               goto ubigen_create_err;
-       }
+       while (bytes) {
+               int l;
+               struct ubi_vid_hdr *vid_hdr;
 
-       /* data which is needed in the general process */
-       vid_hdr_offset = vid_hdr_offset ? vid_hdr_offset : DEFAULT_VID_OFFSET;
-       data_offset = vid_hdr_offset + UBI_VID_HDR_SIZE;
-       res->bytes_total = data_size;
-       res->eb_size = eb_size ? eb_size : DEFAULT_BLOCKSIZE;
-       res->data_pad = (res->eb_size - data_offset) % alignment;
-       res->leb_size = res->eb_size - data_offset - res->data_pad;
-       res->leb_total = byte_to_blk(data_size, res->leb_size);
-       res->alignment = alignment;
-
-       if ((res->eb_size < (vid_hdr_offset + UBI_VID_HDR_SIZE))) {
-               rc = EUBIGEN_TOO_SMALL_EB;
-               goto ubigen_create_err;
-       }
-       res->fp_in = fp_in;
-       res->fp_out = fp_out;
-
-       /* vid hdr data which doesn't change */
-       res->v->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
-       res->v->version = version ? version : UBI_VERSION;
-       res->v->vol_type = vol_type;
-       res->v->vol_id = cpu_to_be32(vol_id);
-       res->v->compat = compat_flag;
-       res->v->data_pad = cpu_to_be32(res->data_pad);
-
-       /* static only: used_ebs */
-       if (res->v->vol_type == UBI_VID_STATIC) {
-               res->v->used_ebs = cpu_to_be32(byte_to_blk
-                                               (res->bytes_total,
-                                                res->leb_size));
-       }
+               if (bytes < len)
+                       len = bytes;
+               bytes -= len;
 
-       /* ec hdr (fixed, doesn't change) */
-       res->ec->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
-       res->ec->version = version ? version : UBI_VERSION;
-       res->ec->ec = cpu_to_be64(ec);
-       res->ec->vid_hdr_offset = cpu_to_be32(vid_hdr_offset);
+               l = len;
+               do {
+                       rd = read(in, inbuf + len - l, l);
+                       if (rd != l)
+                               return sys_errmsg("cannot read %d bytes from the input file", l);
 
-       res->ec->data_offset = cpu_to_be32(data_offset);
+                       l -= rd;
+               } while (l);
 
-       crc = clc_crc32(crc32_table, UBI_CRC32_INIT, res->ec,
-                       UBI_EC_HDR_SIZE_CRC);
-       res->ec->hdr_crc = cpu_to_be32(crc);
+               vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
+               init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len);
 
-       /* prepare a read buffer */
-       res->buf = (uint8_t*) malloc (res->eb_size * sizeof(uint8_t));
-       if (res->buf == NULL) {
-               rc = -ENOMEM;
-               goto ubigen_create_err;
-       }
-
-       /* point to distinct regions within the buffer */
-       res->ptr_ec_hdr = res->buf;
-       res->ptr_vid_hdr = res->buf + be32_to_cpu(res->ec->vid_hdr_offset);
-       res->ptr_data = res->buf + be32_to_cpu(res->ec->vid_hdr_offset)
-               + UBI_VID_HDR_SIZE;
+               memcpy(outbuf + ui->data_offs, inbuf, len);
+               memset(outbuf + ui->data_offs + len, 0xFF,
+                      ui->peb_size - ui->data_offs - len);
 
-       rc = validate_ubi_info(res);
-       if (rc != 0) {
-               fprintf(stderr, "Volume validation failed: %d\n", rc);
-               goto ubigen_create_err;
-       }
+               if (write(out, outbuf, ui->peb_size) != ui->peb_size)
+                       return sys_errmsg("cannot write %d bytes to the output file", ui->peb_size);
 
-       dump_info(res);
-       *u = res;
-       return rc;
-
- ubigen_create_err:
-       if (res) {
-               if (res->v)
-                       free(res->v);
-               if (res->ec)
-                       free(res->ec);
-               if (res->buf)
-                       free(res->buf);
-               free(res);
+               lnum += 1;
        }
-       *u = NULL;
-       return rc;
-}
 
-int
-ubigen_get_leb_size(ubi_info_t u, size_t* size)
-{
-       if (u == NULL)
-               return -EINVAL;
-
-       *size = u->leb_size;
        return 0;
 }
 
-
-int
-ubigen_get_leb_total(ubi_info_t u, size_t* total)
-{
-       if (u == NULL)
-               return -EINVAL;
-
-       *total = u->leb_total;
-       return 0;
-}
-
-int
-ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes,
-                   const char* vol_name, struct ubi_vtbl_record *lvol_rec)
+/**
+ * ubigen_write_layout_vol - write UBI layout volume
+ * @ui: libubigen information
+ * @peb1: physical eraseblock number to write the first volume table copy
+ * @peb2: physical eraseblock number to write the second volume table copy
+ * @ec1: erase counter value for @peb1
+ * @ec2: erase counter value for @peb1
+ * @vtbl: volume table
+ * @fd: output file descriptor seeked to the proper position
+ *
+ * This function creates the UBI layout volume which contains 2 copies of the
+ * volume table. Returns zero in case of success and %-1 in case of failure.
+ */
+int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
+                           long long ec1, long long ec2,
+                           struct ubi_vtbl_record *vtbl, int fd)
 {
-       uint32_t crc;
-
-       if ((u == NULL) || (vol_name == NULL))
-               return -EINVAL;
-
-       memset(lvol_rec, 0x0, UBI_VTBL_RECORD_SIZE);
-
-       lvol_rec->reserved_pebs =
-               cpu_to_be32(byte_to_blk(reserved_bytes, u->leb_size));
-       lvol_rec->alignment = cpu_to_be32(u->alignment);
-       lvol_rec->data_pad = u->v->data_pad;
-       lvol_rec->vol_type = u->v->vol_type;
-
-       lvol_rec->name_len =
-               cpu_to_be16((uint16_t)strlen((const char*)vol_name));
-
-       memcpy(lvol_rec->name, vol_name, UBI_VOL_NAME_MAX + 1);
-
-       crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
-                       lvol_rec, UBI_VTBL_RECORD_SIZE_CRC);
-       lvol_rec->crc =  cpu_to_be32(crc);
+       int ret;
+       struct ubigen_vol_info vi;
+       char outbuf[ui->peb_size];
+       struct ubi_vid_hdr *vid_hdr;
+       off_t seek;
+
+       vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS;
+       vi.id = UBI_LAYOUT_VOLUME_ID;
+       vi.alignment = UBI_LAYOUT_VOLUME_ALIGN;
+       vi.data_pad = ui->leb_size % UBI_LAYOUT_VOLUME_ALIGN;
+       vi.usable_leb_size = ui->leb_size - vi.data_pad;
+       vi.data_pad = ui->leb_size - vi.usable_leb_size;
+       vi.type = UBI_LAYOUT_VOLUME_TYPE;
+       vi.name = UBI_LAYOUT_VOLUME_NAME;
+       vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME);
+       vi.compat = UBI_LAYOUT_VOLUME_COMPAT;
+
+       memset(outbuf, 0xFF, ui->data_offs);
+       vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
+       memcpy(outbuf + ui->data_offs, vtbl, ui->vtbl_size);
+       memset(outbuf + ui->data_offs + ui->vtbl_size, 0xFF,
+              ui->peb_size - ui->data_offs - ui->vtbl_size);
+
+       seek = peb1 * ui->peb_size;
+       if (lseek(fd, seek, SEEK_SET) != seek)
+               return sys_errmsg("cannot seek output file");
+       ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec1);
+       init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0);
+       ret = write(fd, outbuf, ui->peb_size);
+       if (ret != ui->peb_size)
+               return sys_errmsg("cannot write %d bytes", ui->peb_size);
+
+       seek = peb2 * ui->peb_size;
+       if (lseek(fd, seek, SEEK_SET) != seek)
+               return sys_errmsg("cannot seek output file");
+       ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec2);
+       init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0);
+       ret = write(fd, outbuf, ui->peb_size);
+       if (ret != ui->peb_size)
+               return sys_errmsg("cannot write %d bytes", ui->peb_size);
 
        return 0;
 }