aboutsummaryrefslogtreecommitdiff
path: root/ubi-utils
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2008-02-19 14:54:17 +0200
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2008-02-19 16:41:16 +0200
commit86dd9696d3a1acb036d65909d93d73455b8aed3a (patch)
tree9e8bb6797b3bebd0bf83ae1fab2151a6dfeafe6a /ubi-utils
parentef644090223e5983ca2492850354c1390e3368d1 (diff)
Revert ubi-tools changes
Restore ubi tools to their "original" state, which means to the state they were before I stareted cleaning them up. Instead, create a "new-utils" subdirectory and move my work there. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'ubi-utils')
-rw-r--r--ubi-utils/Makefile95
-rw-r--r--ubi-utils/README236
-rw-r--r--ubi-utils/UBI.TXT (renamed from ubi-utils/old-tools/README)51
-rw-r--r--ubi-utils/doc/unubi.roff123
-rw-r--r--ubi-utils/inc/libubi.h268
-rw-r--r--ubi-utils/lib/Makefile.am58
-rw-r--r--ubi-utils/new-utils/LICENSE.libiniparser (renamed from ubi-utils/LICENSE.libiniparser)0
-rw-r--r--ubi-utils/new-utils/Makefile63
-rw-r--r--ubi-utils/new-utils/README56
-rw-r--r--ubi-utils/new-utils/include/libiniparser.h (renamed from ubi-utils/include/libiniparser.h)0
-rw-r--r--ubi-utils/new-utils/include/libubi.h (renamed from ubi-utils/include/libubi.h)0
-rw-r--r--ubi-utils/new-utils/include/libubigen.h (renamed from ubi-utils/include/libubigen.h)0
-rw-r--r--ubi-utils/new-utils/src/common.c (renamed from ubi-utils/src/common.c)0
-rw-r--r--ubi-utils/new-utils/src/common.h (renamed from ubi-utils/src/common.h)0
-rw-r--r--ubi-utils/new-utils/src/crc32.c95
-rw-r--r--ubi-utils/new-utils/src/crc32.h19
-rw-r--r--ubi-utils/new-utils/src/dictionary.c (renamed from ubi-utils/src/dictionary.c)0
-rw-r--r--ubi-utils/new-utils/src/dictionary.h (renamed from ubi-utils/src/dictionary.h)0
-rw-r--r--ubi-utils/new-utils/src/libiniparser.c (renamed from ubi-utils/src/libiniparser.c)0
-rw-r--r--ubi-utils/new-utils/src/libubi.c (renamed from ubi-utils/old-tools/src/libubi.c)140
-rw-r--r--ubi-utils/new-utils/src/libubi_int.h (renamed from ubi-utils/old-tools/src/libubi_int.h)16
-rw-r--r--ubi-utils/new-utils/src/libubigen.c321
-rw-r--r--ubi-utils/new-utils/src/ubi-attach.c (renamed from ubi-utils/src/ubiattach.c)2
-rw-r--r--ubi-utils/new-utils/src/ubi-crc32.c125
-rw-r--r--ubi-utils/new-utils/src/ubi-detach.c (renamed from ubi-utils/src/ubidetach.c)2
-rw-r--r--ubi-utils/new-utils/src/ubi-info.c (renamed from ubi-utils/src/ubinfo.c)2
-rw-r--r--ubi-utils/new-utils/src/ubi-mkvol.c288
-rw-r--r--ubi-utils/new-utils/src/ubi-nize.c (renamed from ubi-utils/src/ubinize.c)4
-rw-r--r--ubi-utils/new-utils/src/ubi-rmvol.c170
-rw-r--r--ubi-utils/new-utils/src/ubi-update.c (renamed from ubi-utils/src/ubiupdate.c)4
-rw-r--r--ubi-utils/old-tools/Makefile99
-rw-r--r--ubi-utils/old-tools/inc/libubi.h340
-rw-r--r--ubi-utils/old-tools/src/common.c89
-rw-r--r--ubi-utils/old-tools/src/common.h43
-rw-r--r--ubi-utils/old-tools/src/crc32.c83
-rw-r--r--ubi-utils/old-tools/src/crc32.h36
-rw-r--r--ubi-utils/old-tools/src/ecclayouts.h66
-rw-r--r--ubi-utils/old-tools/src/libubigen.c486
-rw-r--r--ubi-utils/old-tools/src/ubiupdate.c318
-rw-r--r--ubi-utils/perl/f128_nand_sample.cfg (renamed from ubi-utils/old-tools/scripts/f128_nand_sample.cfg)6
-rw-r--r--ubi-utils/perl/f64_nor_sample.cfg (renamed from ubi-utils/old-tools/scripts/f64_nor_sample.cfg)6
-rwxr-xr-x[-rw-r--r--]ubi-utils/perl/mkpfi (renamed from ubi-utils/old-tools/scripts/mkpfi)0
-rwxr-xr-x[-rw-r--r--]ubi-utils/perl/ubicrc32.pl (renamed from ubi-utils/old-tools/scripts/ubicrc32.pl)2
-rw-r--r--ubi-utils/scripts/Makefile (renamed from ubi-utils/old-tools/scripts/Makefile)20
-rw-r--r--ubi-utils/scripts/README (renamed from ubi-utils/old-tools/scripts/README)3
-rw-r--r--ubi-utils/scripts/TODO5
-rw-r--r--ubi-utils/scripts/bin2nand2bin_test.sh (renamed from ubi-utils/old-tools/scripts/bin2nand2bin_test.sh)46
-rw-r--r--ubi-utils/scripts/inject_biterror.pl (renamed from ubi-utils/old-tools/scripts/inject_biterror.pl)0
-rwxr-xr-xubi-utils/scripts/jffs2_test.sh (renamed from ubi-utils/old-tools/scripts/jffs2_test.sh)0
-rwxr-xr-xubi-utils/scripts/mkdevs.pl (renamed from ubi-utils/old-tools/scripts/mkdevs.pl)0
-rw-r--r--ubi-utils/scripts/pdd.txt (renamed from ubi-utils/old-tools/scripts/pdd.txt)0
-rwxr-xr-xubi-utils/scripts/run_all.sh (renamed from ubi-utils/old-tools/scripts/run_all.sh)0
-rw-r--r--ubi-utils/scripts/test.cfg (renamed from ubi-utils/old-tools/scripts/test.cfg)0
-rwxr-xr-xubi-utils/scripts/ubi_jffs2_test.sh411
-rwxr-xr-xubi-utils/scripts/ubi_test.sh (renamed from ubi-utils/old-tools/scripts/ubi_test.sh)0
-rwxr-xr-xubi-utils/scripts/ubi_tools_test.sh (renamed from ubi-utils/old-tools/scripts/ubi_tools_test.sh)0
-rw-r--r--ubi-utils/scripts/unubi_test.sh (renamed from ubi-utils/old-tools/scripts/unubi_test.sh)0
-rw-r--r--ubi-utils/src/bin2nand.c (renamed from ubi-utils/old-tools/src/bin2nand.c)156
-rw-r--r--ubi-utils/src/bootenv.c (renamed from ubi-utils/old-tools/src/bootenv.c)0
-rw-r--r--ubi-utils/src/bootenv.h (renamed from ubi-utils/old-tools/src/bootenv.h)0
-rw-r--r--ubi-utils/src/config.h (renamed from ubi-utils/old-tools/src/config.h)0
-rw-r--r--ubi-utils/src/crc32.c156
-rw-r--r--ubi-utils/src/crc32.h47
-rw-r--r--ubi-utils/src/eb_chain.c (renamed from ubi-utils/old-tools/src/eb_chain.c)0
-rw-r--r--ubi-utils/src/error.c (renamed from ubi-utils/old-tools/src/error.c)0
-rw-r--r--ubi-utils/src/error.h (renamed from ubi-utils/old-tools/src/error.h)0
-rw-r--r--ubi-utils/src/example_ubi.h (renamed from ubi-utils/old-tools/src/example_ubi.h)0
-rw-r--r--ubi-utils/src/hashmap.c (renamed from ubi-utils/old-tools/src/hashmap.c)0
-rw-r--r--ubi-utils/src/hashmap.h (renamed from ubi-utils/old-tools/src/hashmap.h)0
-rw-r--r--ubi-utils/src/libpfiflash.c (renamed from ubi-utils/old-tools/src/libpfiflash.c)0
-rw-r--r--ubi-utils/src/libubi.c1318
-rw-r--r--ubi-utils/src/libubi_int.h100
-rw-r--r--ubi-utils/src/libubigen.c660
-rw-r--r--ubi-utils/src/libubimirror.c (renamed from ubi-utils/old-tools/src/libubimirror.c)0
-rw-r--r--ubi-utils/src/list.c (renamed from ubi-utils/old-tools/src/list.c)0
-rw-r--r--ubi-utils/src/list.h (renamed from ubi-utils/old-tools/src/list.h)0
-rw-r--r--ubi-utils/src/mkbootenv.c (renamed from ubi-utils/old-tools/src/mkbootenv.c)0
-rw-r--r--ubi-utils/src/nand2bin.c (renamed from ubi-utils/old-tools/src/nand2bin.c)212
-rw-r--r--ubi-utils/src/nandcorr.c (renamed from ubi-utils/old-tools/src/nandcorr.c)0
-rw-r--r--ubi-utils/src/nandecc.c (renamed from ubi-utils/old-tools/src/nandecc.c)0
-rw-r--r--ubi-utils/src/nandecc.h (renamed from ubi-utils/old-tools/src/nandecc.h)0
-rw-r--r--ubi-utils/src/pddcustomize.c (renamed from ubi-utils/old-tools/src/pddcustomize.c)0
-rw-r--r--ubi-utils/src/peb.c (renamed from ubi-utils/old-tools/src/peb.c)4
-rw-r--r--ubi-utils/src/peb.h (renamed from ubi-utils/old-tools/src/peb.h)0
-rw-r--r--ubi-utils/src/pfi.c (renamed from ubi-utils/old-tools/src/pfi.c)0
-rw-r--r--ubi-utils/src/pfi.h (renamed from ubi-utils/old-tools/src/pfi.h)0
-rw-r--r--ubi-utils/src/pfi2bin.c (renamed from ubi-utils/old-tools/src/pfi2bin.c)1
-rw-r--r--ubi-utils/src/pfiflash.c (renamed from ubi-utils/old-tools/src/pfiflash.c)0
-rw-r--r--ubi-utils/src/pfiflash.h (renamed from ubi-utils/old-tools/src/pfiflash.h)0
-rw-r--r--ubi-utils/src/pfiflash_error.h (renamed from ubi-utils/old-tools/src/pfiflash_error.h)0
-rw-r--r--ubi-utils/src/reader.c (renamed from ubi-utils/old-tools/src/reader.c)0
-rw-r--r--ubi-utils/src/reader.h (renamed from ubi-utils/old-tools/src/reader.h)0
-rw-r--r--ubi-utils/src/ubicrc32.c166
-rw-r--r--ubi-utils/src/ubigen.c (renamed from ubi-utils/old-tools/src/ubigen.c)0
-rw-r--r--ubi-utils/src/ubigen.h (renamed from ubi-utils/old-tools/src/ubigen.h)1
-rw-r--r--ubi-utils/src/ubimirror.c (renamed from ubi-utils/old-tools/src/ubimirror.c)0
-rw-r--r--ubi-utils/src/ubimirror.h (renamed from ubi-utils/old-tools/src/ubimirror.h)0
-rw-r--r--ubi-utils/src/ubimkvol.c424
-rw-r--r--ubi-utils/src/ubirmvol.c223
-rw-r--r--ubi-utils/src/ubiupdatevol.c336
-rw-r--r--ubi-utils/src/unubi.c (renamed from ubi-utils/old-tools/src/unubi.c)0
-rw-r--r--ubi-utils/src/unubi_analyze.c (renamed from ubi-utils/old-tools/src/unubi_analyze.c)0
-rw-r--r--ubi-utils/src/unubi_analyze.h (renamed from ubi-utils/old-tools/src/unubi_analyze.h)0
-rw-r--r--ubi-utils/testcases.txt9
-rw-r--r--ubi-utils/tests/Makefile40
-rw-r--r--ubi-utils/tests/README.udev19
-rw-r--r--ubi-utils/tests/common.c336
-rw-r--r--ubi-utils/tests/common.h103
-rw-r--r--ubi-utils/tests/integ.c783
-rw-r--r--ubi-utils/tests/io_basic.c182
-rw-r--r--ubi-utils/tests/io_paral.c251
-rw-r--r--ubi-utils/tests/io_read.c398
-rw-r--r--ubi-utils/tests/io_update.c370
-rw-r--r--ubi-utils/tests/mkvol_bad.c304
-rw-r--r--ubi-utils/tests/mkvol_basic.c253
-rw-r--r--ubi-utils/tests/mkvol_paral.c112
-rw-r--r--ubi-utils/tests/rsvol.c310
-rwxr-xr-xubi-utils/tests/runtests.pl30
-rwxr-xr-xubi-utils/tests/runtests.sh41
119 files changed, 8028 insertions, 3514 deletions
diff --git a/ubi-utils/Makefile b/ubi-utils/Makefile
index 8d4412d..7c573e0 100644
--- a/ubi-utils/Makefile
+++ b/ubi-utils/Makefile
@@ -2,7 +2,7 @@
# Makefile for ubi-utils
#
-OPTFLAGS := -O2 -Wall
+OPTFLAGS := -O2 -g -Wall
KERNELHDR := ../include
DESTDIR := /usr/local
SBINDIR=/usr/sbin
@@ -10,53 +10,82 @@ MANDIR=/usr/man
INCLUDEDIR=/usr/include
CC := $(CROSS)gcc
-CFLAGS := -Iinclude -Isrc -I$(KERNELHDR) $(OPTFLAGS) -Werror -Wall
+CFLAGS := -I./inc -I./src -I$(KERNELHDR) $(OPTFLAGS) -Werror \
+ -Wwrite-strings -W -std=gnu99 -DPACKAGE_VERSION=\"1.0\"
-LIBS = libubi libubigen libiniparser
-UTILS = ubiupdate ubimkvol ubirmvol ubicrc32 ubinfo ubiattach ubidetach ubinize
+PERLPROGS = mkpfi ubicrc32.pl
+TARGETS = ubiupdatevol ubimkvol ubirmvol pfiflash pddcustomize ubimirror \
+ bin2nand nand2bin ubigen mkbootenv unubi pfi2bin ubicrc32
-vpath %.c src
+vpath %.c ./src
-all: $(UTILS)
+%: %.o
+ $(CC) $(LDFLAGS) -g -o $@ $^
-# The below cancels existing implicite rule to make programs from .c files,
-# in order to force make using our rule defined below
-%: %.c
-
-# The below is the rule to get an .o file from a .c file
%.o: %.c
- $(CC) $(CFLAGS) $< -c -o $@
+ $(CC) $(CFLAGS) -g -c -o $@ $< -g -Wp,-MD,.$(shell basename $<).dep
-# And the below is the rule to get final executable from its .o and common.o
-%: libubi %.o common.o
- $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@
+all: $(TARGETS)
+ make -C new-utils
-ubicrc32: ubicrc32.o crc32.o
- $(CC) $(CFLAGS) -o $@ $^
+IGNORE=${wildcard .*.c.dep}
+-include ${IGNORE}
-ubinize: ubinize.o common.o crc32.o libiniparser libubigen
- $(CC) $(CFLAGS) $(filter %.o, $^) -L. -liniparser -lubigen -o $@
+clean:
+ rm -rf *.o $(TARGETS) .*.c.dep
+ make -C new-utils clean
-libubi: libubi.o
- $(AR) crv $@.a $^
- ranlib $@.a
+ubiupdatevol: ubiupdatevol.o error.o libubi.o
+ $(CC) $(LDFLAGS) -o $@ $^
-libubigen: libubigen.o
- $(AR) crv $@.a $^
- ranlib $@.a
+ubimkvol: ubimkvol.o error.o libubi.o
+ $(CC) $(LDFLAGS) -o $@ $^
-libiniparser: libiniparser.o dictionary.o
- $(AR) crv $@.a $^
- ranlib $@.a
+ubirmvol: ubirmvol.o error.o libubi.o
+ $(CC) $(LDFLAGS) -o $@ $^
-clean:
- rm -rf *.o $(addsuffix .a, $(LIBS)) $(UTILS) .*.c.dep
+pddcustomize: pddcustomize.o error.o libubimirror.o bootenv.o hashmap.o \
+ libubi.o crc32.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
+pfiflash: pfiflash.o libpfiflash.o list.o reader.o error.o libubimirror.o \
+ bootenv.o hashmap.o pfi.o libubi.o crc32.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
+ubimirror: ubimirror.o error.o libubimirror.o bootenv.o hashmap.o \
+ libubi.o crc32.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
+nand2bin: nand2bin.o nandecc.o nandcorr.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
+bin2nand: bin2nand.o error.o nandecc.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
+ubigen: ubigen.o libubigen.o crc32.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
+mkbootenv: mkbootenv.o bootenv.o hashmap.o error.o crc32.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
+unubi: unubi.o crc32.o unubi_analyze.o eb_chain.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
+pfi2bin: pfi2bin.o peb.o error.o list.o crc32.o libubigen.o bootenv.o \
+ hashmap.o reader.o pfi.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
+ubicrc32: ubicrc32.o crc32.o
+ $(CC) $(LDFLAGS) -o $@ $^
-install: ${UTILS}
+install: ${TARGETS}
mkdir -p ${DESTDIR}/${SBINDIR}
- install -m0755 ${UTILS} ${DESTDIR}/${SBINDIR}/
+ install -m0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
+ (cd perl && install ${PERLPROGS} ${DESTDIR}/${SBINDIR}/)
+ make -C new-utils install
uninstall:
- for file in ${UTILS}; do \
+ for file in ${TARGETS} ${PERLPROGS}; do \
$(RM) ${DESTDIR}/${SBINDIR}/$$file; \
done
+ make -C new-utils uninstall
diff --git a/ubi-utils/README b/ubi-utils/README
new file mode 100644
index 0000000..d976a76
--- /dev/null
+++ b/ubi-utils/README
@@ -0,0 +1,236 @@
+README
+======
+
+The programs and libraries in this directory provide a tool-chain to
+generate binary data for embedded systems which can be flashed either
+by a hardware flash programmer, e.g. JTAG debugger, or on the target
+system directly using pfiflash, or ubimkvol, ubirmvol, ubiwritevol.
+
+The latter is the case when there is already Linux running which has
+build in UBI support.
+
+Authors: Oliver Lohmann
+ Frank Haverkamp
+ Andreas Arnez
+
+mkpfi - tool for flash content generation in PFI
+ format
+pfi2bin - conversion tool to transfer a PFI file into a
+ binary image
+pfiflash - tool to update the embedded systems flash using
+ pfi files created by mkpfi
+libbootenv - library for boot-parameter processing
+libpfi - library for partial flash image (PFI) creation
+ and handling
+ubigen - tool to create binary UBI images e.g. for a
+ jtag flashing tool
+nandimg - tool to add OOB data to binary images intended
+ for NAND flash systems
+ubilib - UBI library
+
+!!! NOTICE !!!
+If you execute ./configure in the top_level directory the helper Makefile
+gets overwritten. Thats actually no problem, but be aware of that.
+
+1. Build Process
+
+1.1 Build, install and forget
+ o Build all and everything
+ $make all (takes a while, builds ppc and x86 binaries/libs)
+ o Installation:
+ $make install
+ o Uninstallation:
+ $make uninstall
+
+ o x86 only would be:
+ $make x86 && make install_x86
+
+1.2 Usage for a developer
+
+ 1.2.1 The build process in detail
+
+ o If you've checked out the sources from the CVS repository you'll find a
+ directory setup like this:
+
+ flashutils/
+ -rw-r--r-- 1 olli olli 1.3K Mar 14 11:53 Makefile
+ -rw-r--r-- 1 olli olli 1.9K Mar 14 10:50 Makefile.am
+ -rwxr-xr-x 1 olli olli 265 Mar 9 00:47 bootstrap
+ -rw-r--r-- 1 olli olli 1.1K Mar 9 16:55 configure.ac
+ drwxr-xr-x 2 olli olli 4.0K Mar 9 00:28 doc
+ drwxr-xr-x 2 olli olli 4.0K Mar 14 11:56 inc
+ drwxr-xr-x 2 olli olli 4.0K Mar 14 11:56 lib
+ drwxr-xr-x 17 olli olli 4.0K Mar 13 16:50 src
+
+ o To generate the initial build templates you have to call the bootstrap
+ script:
+ $ ./bootstrap
+ o Create a directory for the target platform
+ $ mkdir build_x86
+ o Descend into the directory and call the top-level configure script
+ with the desired options.
+ $ cd build_x86
+ $ ../configure --prefix=/usr/local [...]
+ o Now you'll find a directory structure like this:
+
+ flashutils/build_x86/
+ -rw-r--r-- 1 olli olli 47K Mar 14 13:33 Makefile
+ -rw-r--r-- 1 olli olli 33K Mar 14 13:33 config.log
+ -rwxr-xr-x 1 olli olli 38K Mar 14 13:33 config.status
+ drwxr-xr-x 2 olli olli 4.0K Mar 14 13:33 inc
+ drwxr-xr-x 3 olli olli 4.0K Mar 14 13:33 lib
+ -rwxr-xr-x 1 olli olli 202K Mar 14 13:33 libtool
+
+ o The config.guess script can be used to update the Makefiles in the
+ target directory after a change of the top-level template files
+ (i.e. the Makefile.in files).
+ $ ./config.guess
+ o To compile everything for this platform just invoke make in
+ flashutils/build_x86:
+ $ make
+ or from toplevel:
+ $ make -C ./build_x86
+ o The build process creates a new directory "bin":
+ flashutils/build_x86/
+ [...]
+ drwxr-xr-x 3 olli olli 4.0K Mar 14 13:41 bin
+ [...]
+
+ This directory contains all binary files which will be installed
+ by make install, e.g.:
+
+ flashutils/build_x86/bin/
+ -rwxr-xr-x 1 olli olli 7.2K Mar 14 13:41 bin2nand
+ -rwxr-xr-x 1 olli olli 15K Mar 14 13:41 mkbootenv
+ -rwxr-xr-x 1 olli olli 16K Mar 14 13:41 pddcustomize
+ -rwxr-xr-x 1 olli olli 36K Mar 14 13:41 pfi2bin
+ -rwxr-xr-x 1 olli olli 6.8K Mar 14 13:41 pfiflash
+ -rwxr-xr-x 1 olli olli 5.0K Mar 14 13:41 ubicrc32
+ -rwxr-xr-x 1 olli olli 13K Mar 14 13:41 ubigen
+ -rwxr-xr-x 1 olli olli 6.3K Mar 14 13:41 ubimirror
+
+
+ 1.2.2 Modifying and Adding Sources
+
+ o There is a dedicated directory which contains all source code
+ of the flashutils package, e.g.:
+
+ flashutils/src/
+ drwxr-xr-x 2 olli olli 4.0K Mar 13 11:42 libbootenv
+ drwxr-xr-x 2 olli olli 4.0K Mar 13 11:42 liberror
+ drwxr-xr-x 2 olli olli 4.0K Mar 13 16:48 mkpfi
+ drwxr-xr-x 2 olli olli 4.0K Mar 13 16:12 pddcustomize
+
+
+
+ The prefix "lib" is used to mark directories as part of a convenience
+ library. Binaries have no special prefix.
+
+ o How to add sources?
+
+ Just create a new directory at flashutils/src/, e.g.:
+
+ For a binary:
+ $ mkdir rider
+ $ cd rider
+ $ vi rider.c
+ /* do sth with that file... */
+
+ For a convenience library (as well as for "normal libs")
+ $ mkdir libworld
+ $ cd libworld
+ $ vi world.c
+ /* do sth with that file... */
+
+ o How to register sources in the build process (for binaries)?
+
+ You have to register your sources at the top-level automake Makefile:
+
+ In directory flashutils/
+ $ vi Makefile.am
+
+ Binaries have to be registered at "bin_PROGRAMS", e.g.:
+ bin_PROGRAMS = bin/pddcustomize \
+ bin/rider
+
+ Add the rule how the binary is assembled, e.g.:
+ bin_pddcustomize_SOURCES = \
+ $(top_srcdir)/src/pddcustomize/pddcustomize.c
+ bin_pddcustomize_LDADD = \
+ $(top_builddir)/lib/libbootenv.la \
+ $(top_builddir)/lib/liberror.la
+
+ bin_rider_SOURCES = \
+ $(top_srcdir)/src/rider/rider.c
+
+ This example reflects a simple build process for "rider". "rider"
+ is built without any other dependencies or convenience libraries.
+ The example for pddcustomize is a bit more complicated.
+ "_LDADD" adds some convenience libraris into the link process of
+ "pddcustomize". Imagine, that your "rider" has common code
+ with "dragon_bin" which is held in a library called "libworld".
+ The build rules would like like the following:
+
+ bin_rider_SOURCES = \
+ $(top_srcdir)/src/rider/rider.c
+ bin_rider_LDADD = \
+ $(top_builddir)/lib/libworld.la
+
+ bin_dragon_SOURCES = \
+ $(top_srcdir)/src/dragon_bin/dragon_bin.c
+ bin_dragon_LDADD = \
+ $(top_builddir)/lib/libworld.la
+
+ Don't forget to add "dragon" to "bin_PROGRAMS"!
+ Don't forget to set the build rule for the "libworld" itself!
+ This is documented in the next section.
+
+
+ o How to register sources in the build process (for libraries)?
+
+ Until now we didn't care about the build process of "libworld".
+ Libraries are handled special in this build process because
+ they are handled as "modules", i.e. they are able to be built
+ without building the binaries in the same step. Additionally,
+ it is possible to assemble complex libraries out of simple ones.
+ That especially makes sense if you want to export (install) a
+ library on a system which uses some common code and makes
+ some adoptions for usability and presents a comfortable interface to
+ the user (see libpfiflash in the sources for an example).
+
+ o Registering "libworld" as convenience library.
+
+ Instead of editing the "Makefile.am" in "flashtools/", we have to
+ edit now the "Makefile.am" in "flashtools/lib/":
+
+ noinst_LTLIBRARIES = libworld.la
+
+ libworld_la_SOURCES = $(top_srcdir)/src/libworld/world.c
+
+ o Registering "libworld" as library which gets installed.
+
+ lib_LTLIBRARIES = libworld.la
+ libworld_la_SOURCES = $(top_srcdir)/src/libworld/world.c
+ libworld_la_LDFLAGS = -no-undefined -version-info 0:0:0
+
+ o Header files
+
+ All header files are stored at "flashutils/inc", regardless
+ if convenience library or not.
+
+ If you want to export headers you have to specify this in the Makefile.am
+ located at "flashutils/inc", e.g. (this should not be done
+ for convenience libraries):
+
+ nobase_include_HEADERS = world.h
+
+
+
+Appendix
+
+A.1. FAQ
+
+ Q How to call configure to setup a cross-platform build?
+ A $ ./configure --build=i686-pc-linux-gnu --host=ppc-linux \
+ --prefix=/opt/.../ppcnf/crossroot/ \
+ --exec-prefix=/opt/..../ppcnf/crossroot/usr
diff --git a/ubi-utils/old-tools/README b/ubi-utils/UBI.TXT
index 39ed0e9..9a1c3c7 100644
--- a/ubi-utils/old-tools/README
+++ b/ubi-utils/UBI.TXT
@@ -1,50 +1,3 @@
-This directory contains old UBI tools which I cannot maintain
-because they are too messy and vague for me and the original authors
-do not seem to have much time for them. Some of the utilities are
-just not of general interest because they are oriented to specific
-tasks of the guys from IBM.
-
-But the "unubi" utility must be very useful but it fails when I
-try to feed an image to it, so it should be looked at and fixed,
-then moved to the main "main" place.
-
-Artem Bityutskiy
-
-README
-======
-
-The programs and libraries in this directory provide a tool-chain to
-generate binary data for embedded systems which can be flashed either
-by a hardware flash programmer, e.g. JTAG debugger, or on the target
-system directly using pfiflash, or ubimkvol, ubirmvol, ubiupdatevol.
-
-The latter is the case when there is already Linux running which has
-build in UBI support.
-
-Authors: Oliver Lohmann
- Frank Haverkamp
- Andreas Arnez
- Artem Bityutskiy
-
-mkpfi - tool for flash content generation in PFI
- format
-pfi2bin - conversion tool to transfer a PFI file into a
- binary image
-pfiflash - tool to update the embedded systems flash using
- pfi files created by mkpfi
-libbootenv - library for boot-parameter processing
-libpfi - library for partial flash image (PFI) creation
- and handling
-ubigen - tool to create binary UBI images e.g. for a
- jtag flashing tool
-nandimg - tool to add OOB data to binary images intended
- for NAND flash systems
-ubilib - UBI library
-
-
-The following text is from original UBI announcement
-====================================================
-
UBI - Unsorted Block Images
UBI (Latin: "where?") manages multiple logical volumes on a single
@@ -57,7 +10,7 @@ In a sense, UBI may be compared to the Logical Volume Manager
numbers, UBI maps logical eraseblocks to physical eraseblocks.
More information may be found in the UBI design documentation:
-ubidesign.pdf. Which can be found here:
+ubidesign.pdf. Which can be found here:
http://www.linux-mtd.infradead.org/doc/ubi.html
Partitioning/Re-partitioning
@@ -131,7 +84,7 @@ UBI volumes vs. static partitions
Where can it be found?
Documentation, kernel code and applications can be found in the MTD
- gits.
+ gits.
What are the applications for?
diff --git a/ubi-utils/doc/unubi.roff b/ubi-utils/doc/unubi.roff
new file mode 100644
index 0000000..6cebc46
--- /dev/null
+++ b/ubi-utils/doc/unubi.roff
@@ -0,0 +1,123 @@
+.TH UNUBI 1 "NOVEMBER 2006" FSP "FSP Flashutils"
+.SH NAME
+unubi \- extract volumes/eraseblocks from a raw\-UBI image
+.SH SYNOPSIS
+\fBunubi [\-aevEV] [\-d \fIout\-dir\fB] [\-r \fIvolume\-id\fB]
+[\-b \fIblock\-size\fB] \fIimage\-file
+.SH DESCRIPTION
+.PP
+\fBunubi\fR reads an image file containing blocks of UBI headers and data
+(such as produced from \fBnand2bin\fR) and rebuilds the volumes within.
+The default operation (when no flags are given) is to rebuild all valid
+volumes found in the image. \fBunubi\fR can also read straight from the
+onboard MTD device (ex. /dev/mtdblock/NAND).
+.SH OPTIONS
+.IP "\-a, \-\-analyze"
+When flagged, analysis files are generated within the output directory. These
+may include tables and or graphs detailing statistics gathered from the
+eraseblock data. Files are prefixed `analysis_'.
+
+See \fBANALYSIS\fR.
+.IP "\-b, \-\-blocksize \fIblock\-size\fR"
+Specify in bytes the \fIimage\-file\fR eraseblock size. Sizes may be
+postfixed with `KiB' or `MiB' to indicate mebibytes or kibibytes
+respectively. Default is 128KiB.
+.IP "\-d, \-\-dir \fIoutput\-dir\fR"
+Specify the output directory. If no directory is specified, the default
+is `unubi_\fIimage\-file\fR' within the curent working directory. If the
+attempt to create the output directory fails,
+.B unubi
+will try to create it in /tmp before aborting.
+.IP "\-e, \-\-eb\-split"
+When flagged, images are created for each eraseblock in \fIimage\-file\fR
+regardless of its validity. Each image is the complete eraseblock, including
+headers and any space to the end of the eraseblock after where the data may
+end.
+
+Invalid images are named `ebEEEE', where EEEE is the physical index of the
+eraseblock in the image. Valid images are named `ebEEEE_VVV_NNN_RRR' where
+VVV is the known volume ID, NNN is the logical number and RRR is the version
+of the eraseblock data. Note that the version number is in hexadecimal.
+
+Invalid images may also contain this postfix, if the data in the header
+could be valid (ie. the header contains a resonable volume ID, but the
+header and/or data CRCs are not valid). If this is the case, images are named
+`ebEEEE_VVV_NNN_RRR.reason', so as to distinguish known values from
+non\-definite ones.
+
+See \fBREASON SUFFIXES\fR.
+.IP "\-r, \-\-rebuild \fIvolume\-id\fR"
+Specify a volume to rebuild. Can be used successively to specify
+several volumes to be rebuilt.
+
+Images are named `volumeVVV' where VVV is the volume ID. For each missing
+eraseblock, an error message will be printed.
+.IP "\-v, \-\-vol\-split"
+When flagged, images are created for each valid eraseblock in
+\fIimage\-file\fR. Since a vaild eraseblock will have a defined data start and
+data length, only this range will make up the image.
+
+Images are named `volVVV_NNN_RRR_EEEE', where, for the data in the eraseblock,
+VVV is the volume ID, NNN is the logical number, RRR is the version and EEEE
+is the phyisical index of the eraseblock in the image.
+.IP "\-V, \-\-vol\-split!"
+Same as above, only all images are the complete eraseblock (including headers,
+and raw data, even past the point where the data is supposed to end).
+Overrides \-v when both \-v and \-V are flagged.
+.SH ANALYSIS
+The following files will be generated during the analysis:
+.IP "analysis_ec_hdr.data"
+A space delimited table with these two columns for each eraseblock: the
+eraseblock's index or physical position in the image, and the eraseblock's
+erase count. The third column contains the erase count data sorted.
+.IP "analysis_vid_hdr.data"
+A space delimited table with these four colums for each eraseblock: the
+volume ID, the volume logical number, the leb version, and the data size.
+In addition there are a normalized column representing the volume ID and
+volume logical number, a normalized column representing the leb version, and
+a normalized column representing the data_size. These normalized columns are
+used to better draw the the gnuplot image.
+.IP "analysis_ec_hdr.plot"
+A gnuplot script for quickly viewing a sample output from the respective .data
+file.
+.IP "analysis_vid_hdr.plot"
+A gnuplot script for quickly viewing a sample output from the respective .data
+file.
+.SH REASONS SUFFIXES
+When \-\-eb\-split produces possibly invalid, though usable, eraseblocks, the
+known reason suffixes are:
+.IP ".ec_magic"
+The erase counter header did not contain a valid magic field.
+.IP ".ec_hdr_crc"
+The erase counter header did not contain a vaild header CRC field.
+.IP ".vid_magic"
+The volume ID header did not contain a valid magic field.
+.IP ".vid_hdr_crc"
+The volume ID header did not contain a valid header CRC field.
+.IP ".data_crc"
+The volume ID header did not contain a valid data CRC field.
+.SH EXAMPLES
+To extract and rebuild all valid volumes from demo.img (note the output
+directory will be /home/user/unubi_demo.img):
+.sp 1
+.RS
+.B /home/user# unubi demo.img
+.sp 1
+.RE
+To analyze demo.img as well as extract and rebuild volume 7:
+.sp 1
+.RS
+.B /home/user# unubi \-a \-r 7 demo.img
+.sp 1
+.RE
+To split demo.img into raw images for each eraseblock into the folder
+/var/eraseblocks:
+.sp 1
+.RS
+.B /home/user# unubi \-e \-d /var/eraseblocks demo.img
+.SH AUTHORS
+Frank Haverkamp <haver@vnet.ibm.com>
+.sp 0
+Drake Dowsett <dowsett@de.ibm.com>
+.SH CONTACT
+Andreas Arnez <arnez@de.ibm.com>
diff --git a/ubi-utils/inc/libubi.h b/ubi-utils/inc/libubi.h
new file mode 100644
index 0000000..d39c1b9
--- /dev/null
+++ b/ubi-utils/inc/libubi.h
@@ -0,0 +1,268 @@
+/*
+ * 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.
+ */
+
+#ifndef __LIBUBI_H__
+#define __LIBUBI_H__
+
+#include <stdint.h>
+#include <mtd/ubi-user.h>
+#include <ctype.h>
+#include <mtd/ubi-header.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* UBI version libubi is made for */
+#define LIBUBI_UBI_VERSION 1
+
+/* UBI library descriptor */
+typedef void * libubi_t;
+
+/**
+ * struct ubi_mkvol_request - volume creation request.
+ * */
+struct ubi_mkvol_request
+{
+ int vol_id;
+ int alignment;
+ long long bytes;
+ int vol_type;
+ const char *name;
+};
+
+/**
+ * struct ubi_info - general UBI information.
+ *
+ * @dev_count count of UBI devices in system
+ * @lowest_dev_num lowest UBI device number
+ * @highest_dev_num highest UBI device number
+ * @version UBI version
+ */
+struct ubi_info
+{
+ int dev_count;
+ int lowest_dev_num;
+ int highest_dev_num;
+ int version;
+};
+
+/**
+ * struct ubi_dev_info - UBI device information.
+ *
+ * @vol_count count of volumes on this UBI device
+ * @lowest_vol_num lowest volume number
+ * @highest_vol_num highest volume number
+ * @total_ebs total number of eraseblocks on this UBI device
+ * @avail_ebs how many eraseblocks are not used and available for new
+ * volumes
+ * @total_bytes @total_ebs * @eb_size
+ * @avail_bytes @avail_ebs * @eb_size
+ * @bad_count count of bad eraseblocks
+ * @eb_size size of UBI eraseblock
+ * @max_ec current highest erase counter value
+ * @bad_rsvd how many physical eraseblocks of the underlying flash
+ * device are reserved for bad eraseblocks handling
+ * @max_vol_count maximum count of volumes on this UBI device
+ * @min_io_size minimum input/output size of the UBI device
+ */
+struct ubi_dev_info
+{
+ int dev_num;
+ int vol_count;
+ int lowest_vol_num;
+ int highest_vol_num;
+ int total_ebs;
+ int avail_ebs;
+ long long total_bytes;
+ long long avail_bytes;
+ int bad_count;
+ int eb_size;
+ long long max_ec;
+ int bad_rsvd;
+ int max_vol_count;
+ int min_io_size;
+};
+
+/**
+ * struct ubi_vol_info - UBI volume information.
+ *
+ * @dev_num UBI device number the volume resides on
+ * @vol_id ID of this volume
+ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+ * @alignment alignemnt of this volume
+ * @data_bytes how many data bytes are stored on this volume (equivalent to
+ * @rsvd_bytes for dynamic volumes)
+ * @rsvd_bytes how many bytes are reserved for this volume
+ * @rsvd_ebs how many eraseblocks are reserved for this volume
+ * @eb_size logical eraseblock size of this volume (may be less then
+ * device's logical eraseblock size due to alignment)
+ * @corrupted the volume is corrupted if this flag is not zero
+ * @name volume name (null-terminated)
+ */
+struct ubi_vol_info
+{
+ int dev_num;
+ int vol_id;
+ int type;
+ int alignment;
+ long long data_bytes;
+ long long rsvd_bytes;
+ int rsvd_ebs;
+ int eb_size;
+ int corrupted;
+ char name[UBI_VOL_NAME_MAX + 1];
+};
+
+/**
+ * libubi_open - open UBI library.
+ *
+ * This function initializes and opens the UBI library and returns UBI library
+ * descriptor in case of success and %NULL in case of failure.
+ */
+libubi_t libubi_open(void);
+
+/**
+ * libubi_close - close UBI library
+ *
+ * @desc UBI library descriptor
+ */
+void libubi_close(libubi_t desc);
+
+/**
+ * ubi_get_info - get general UBI information.
+ *
+ * @info pointer to the &struct ubi_info object to fill
+ * @desc UBI library descriptor
+ *
+ * This function fills the passed @info object with general UBI information and
+ * returns %0 in case of success and %-1 in case of failure.
+ */
+int ubi_get_info(libubi_t desc, struct ubi_info *info);
+
+/**
+ * ubi_mkvol - create an UBI volume.
+ *
+ * @desc UBI library descriptor
+ * @node name of the UBI character device to create a volume at
+ * @req UBI volume creation request (defined at <mtd/ubi-user.h>)
+ *
+ * This function creates a UBI volume as described at @req and returns %0 in
+ * case of success and %-1 in case of failure. The assigned volume ID is
+ * returned in @req->vol_id.
+ */
+int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req);
+
+/**
+ * ubi_rmvol - remove a UBI volume.
+ *
+ * @desc UBI library descriptor
+ * @node name of the UBI character device to remove a volume from
+ * @vol_id ID of the volume to remove
+ *
+ * This function removes volume @vol_id from UBI device @node and returns %0 in
+ * case of success and %-1 in case of failure.
+ */
+int ubi_rmvol(libubi_t desc, const char *node, int vol_id);
+
+/**
+ * ubi_rsvol - re-size UBI volume.
+ *
+ * @desc UBI library descriptor
+ * @node name of the UBI character device owning the volume which should be
+ * re-sized
+ * @vol_id volume ID to re-size
+ * @bytes new volume size in bytes
+ *
+ * This function returns %0 in case of success and %-1 in case of error.
+ */
+int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes);
+
+/**
+ * ubi_get_dev_info - get UBI device information.
+ *
+ * @desc UBI library descriptor
+ * @node name of the UBI character device to fetch information about
+ * @info pointer to the &struct ubi_dev_info object to fill
+ *
+ * This function fills the passed @info object with UBI device information and
+ * returns %0 in case of success and %-1 in case of failure.
+ */
+int ubi_get_dev_info(libubi_t desc, const char *node,
+ struct ubi_dev_info *info);
+
+/**
+ * ubi_get_dev_info1 - get UBI device information.
+ *
+ * @desc UBI library descriptor
+ * @dev_num UBI device number to fetch information about
+ * @info pointer to the &struct ubi_dev_info object to fill
+ *
+ * This function is identical to 'ubi_get_dev_info()' except that it accepts UBI
+ * device number, not UBI character device.
+ */
+int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info);
+
+/**
+ * ubi_get_vol_info - get UBI volume information.
+ *
+ * @desc UBI library descriptor
+ * @node name of the UBI volume character device to fetch information about
+ * @info pointer to the &struct ubi_vol_info object to fill
+ *
+ * This function fills the passed @info object with UBI volume information and
+ * returns %0 in case of success and %-1 in case of failure.
+ */
+int ubi_get_vol_info(libubi_t desc, const char *node,
+ struct ubi_vol_info *info);
+
+/**
+ * ubi_get_vol_info1 - get UBI volume information.
+ *
+ * @desc UBI library descriptor
+ * @dev_num UBI device number
+ * @vol_id ID of the UBI volume to fetch information about
+ * @info pointer to the &struct ubi_vol_info object to fill
+ *
+ * This function is identical to 'ubi_get_vol_info()' except that it accepts UBI
+ * volume number, not UBI volume character device.
+ */
+int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
+ struct ubi_vol_info *info);
+
+/**
+ * ubi_update_start - start UBI volume update.
+ *
+ * @desc UBI library descriptor
+ * @fd volume character devie file descriptor
+ * @bytes how many bytes will be written to the volume
+ *
+ * This function initiates UBI volume update and returns %0 in case of success
+ * and %-1 in case of error.
+ */
+int ubi_update_start(libubi_t desc, int fd, long long bytes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__LIBUBI_H__ */
diff --git a/ubi-utils/lib/Makefile.am b/ubi-utils/lib/Makefile.am
new file mode 100644
index 0000000..1b0dc01
--- /dev/null
+++ b/ubi-utils/lib/Makefile.am
@@ -0,0 +1,58 @@
+AUTOMAKE_OPTIONS = foreign
+INCLUDES=-I$(top_srcdir)/inc -I$(top_srcdir)/../../kernel/include
+
+# -----------------------------------------------------------------------------
+# all export libs which shall be generated
+lib_LTLIBRARIES = libubi.la \
+ libpfiflash.la
+
+# -----------------------------------------------------------------------------
+# all convinence libs which shall be generated
+noinst_LTLIBRARIES = libcrc32.la \
+ libubigen.la \
+ liberror.la \
+ liblist.la \
+ libbootenv.la \
+ libpfi.la \
+ libpeb.la \
+ libreader.la \
+ libubimirror.la
+
+# -----------------------------------------------------------------------------
+# exported libs
+libpfiflash_la_SOURCES = $(top_srcdir)/src/libpfiflash/pfiflash.c
+libpfiflash_la_LDFLAGS = -no-undefined -version-info 1:0:0
+libpfiflash_la_LIBADD = libreader.la \
+ libubimirror.la \
+ libubi.la
+
+libubi_la_SOURCES = $(top_srcdir)/src/libubi/libubi.c \
+ $(top_srcdir)/src/libubi/libubi_sysfs.c
+libubi_la_LDFLAGS = -no-undefined -version-info 1:0:0
+
+# -----------------------------------------------------------------------------
+# complex convinence libs, beware for double includes.
+libreader_la_SOURCES = $(top_srcdir)/src/libreader/reader.c
+libreader_la_LIBADD = libpfi.la \
+ liblist.la \
+ libpeb.la \
+ libbootenv.la
+
+libubigen_la_SOURCES = $(top_srcdir)/src/libubigen/ubigen.c
+libubigen_la_LIBADD = libcrc32.la
+
+libbootenv_la_SOURCES = $(top_srcdir)/src/libbootenv/bootenv.c \
+ $(top_srcdir)/src/libbootenv/hashmap.c
+libbootenv_la_LIBADD = libcrc32.la
+
+libubimirror_la_SOURCES = $(top_srcdir)/src/libubimirror/ubimirror.c
+libubimirror_la_LIBADD = libubi.la
+
+
+# -----------------------------------------------------------------------------
+# simple convinence libs
+libcrc32_la_SOURCES = $(top_srcdir)/src/libcrc32/crc32.c
+liberror_la_SOURCES = $(top_srcdir)/src/liberror/error.c
+liblist_la_SOURCES = $(top_srcdir)/src/liblist/list.c
+libpeb_la_SOURCES = $(top_srcdir)/src/libpeb/peb.c
+libpfi_la_SOURCES = $(top_srcdir)/src/libpfi/pfi.c
diff --git a/ubi-utils/LICENSE.libiniparser b/ubi-utils/new-utils/LICENSE.libiniparser
index dbfa45d..dbfa45d 100644
--- a/ubi-utils/LICENSE.libiniparser
+++ b/ubi-utils/new-utils/LICENSE.libiniparser
diff --git a/ubi-utils/new-utils/Makefile b/ubi-utils/new-utils/Makefile
new file mode 100644
index 0000000..fe60ffe
--- /dev/null
+++ b/ubi-utils/new-utils/Makefile
@@ -0,0 +1,63 @@
+#
+# Makefile for ubi-utils
+#
+
+OPTFLAGS := -O2 -Wall
+KERNELHDR := ../../include
+DESTDIR := /usr/local
+SBINDIR=/usr/sbin
+MANDIR=/usr/man
+INCLUDEDIR=/usr/include
+
+CC := $(CROSS)gcc
+CFLAGS := -Iinclude -Isrc -I$(KERNELHDR) $(OPTFLAGS) -Werror -Wall
+
+LIBS = libubi libubigen libiniparser
+UTILS = ubi-update ubi-mkvol ubi-rmvol ubi-crc32 ubi-info ubi-attach \
+ ubi-detach ubi-nize
+
+vpath %.c src
+
+all: $(UTILS)
+
+# The below cancels existing implicite rule to make programs from .c files,
+# in order to force make using our rule defined below
+%: %.c
+
+# The below is the rule to get an .o file from a .c file
+%.o: %.c
+ $(CC) $(CFLAGS) $< -c -o $@
+
+# And the below is the rule to get final executable from its .o and common.o
+%: libubi %.o common.o
+ $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@
+
+ubi-crc32: ubi-crc32.o crc32.o
+ $(CC) $(CFLAGS) -o $@ $^
+
+ubi-nize: ubi-nize.o common.o crc32.o libiniparser libubigen
+ $(CC) $(CFLAGS) $(filter %.o, $^) -L. -liniparser -lubigen -o $@
+
+libubi: libubi.o
+ $(AR) crv $@.a $^
+ ranlib $@.a
+
+libubigen: libubigen.o
+ $(AR) crv $@.a $^
+ ranlib $@.a
+
+libiniparser: libiniparser.o dictionary.o
+ $(AR) crv $@.a $^
+ ranlib $@.a
+
+clean:
+ rm -rf *.o $(addsuffix .a, $(LIBS)) $(UTILS) .*.c.dep
+
+install: ${UTILS}
+ mkdir -p ${DESTDIR}/${SBINDIR}
+ install -m0755 ${UTILS} ${DESTDIR}/${SBINDIR}/
+
+uninstall:
+ for file in ${UTILS}; do \
+ $(RM) ${DESTDIR}/${SBINDIR}/$$file; \
+ done
diff --git a/ubi-utils/new-utils/README b/ubi-utils/new-utils/README
new file mode 100644
index 0000000..7113b69
--- /dev/null
+++ b/ubi-utils/new-utils/README
@@ -0,0 +1,56 @@
+This directory contains a new UBI toolchain which is intended to replace
+the old one. All the utilities start with "ubi-" to distinguish them from
+the old utilities. All 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/include/libiniparser.h b/ubi-utils/new-utils/include/libiniparser.h
index be3c667..be3c667 100644
--- a/ubi-utils/include/libiniparser.h
+++ b/ubi-utils/new-utils/include/libiniparser.h
diff --git a/ubi-utils/include/libubi.h b/ubi-utils/new-utils/include/libubi.h
index 7e0bfcd..7e0bfcd 100644
--- a/ubi-utils/include/libubi.h
+++ b/ubi-utils/new-utils/include/libubi.h
diff --git a/ubi-utils/include/libubigen.h b/ubi-utils/new-utils/include/libubigen.h
index 058cf8a..058cf8a 100644
--- a/ubi-utils/include/libubigen.h
+++ b/ubi-utils/new-utils/include/libubigen.h
diff --git a/ubi-utils/src/common.c b/ubi-utils/new-utils/src/common.c
index fec640d..fec640d 100644
--- a/ubi-utils/src/common.c
+++ b/ubi-utils/new-utils/src/common.c
diff --git a/ubi-utils/src/common.h b/ubi-utils/new-utils/src/common.h
index a3fc51f..a3fc51f 100644
--- a/ubi-utils/src/common.h
+++ b/ubi-utils/new-utils/src/common.h
diff --git a/ubi-utils/new-utils/src/crc32.c b/ubi-utils/new-utils/src/crc32.c
new file mode 100644
index 0000000..6b1e50c
--- /dev/null
+++ b/ubi-utils/new-utils/src/crc32.c
@@ -0,0 +1,95 @@
+/*
+ * 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
new file mode 100644
index 0000000..ee3145b
--- /dev/null
+++ b/ubi-utils/new-utils/src/crc32.h
@@ -0,0 +1,19 @@
+#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/src/dictionary.c b/ubi-utils/new-utils/src/dictionary.c
index b7c9ebf..b7c9ebf 100644
--- a/ubi-utils/src/dictionary.c
+++ b/ubi-utils/new-utils/src/dictionary.c
diff --git a/ubi-utils/src/dictionary.h b/ubi-utils/new-utils/src/dictionary.h
index c7d1790..c7d1790 100644
--- a/ubi-utils/src/dictionary.h
+++ b/ubi-utils/new-utils/src/dictionary.h
diff --git a/ubi-utils/src/libiniparser.c b/ubi-utils/new-utils/src/libiniparser.c
index 3bea51e..3bea51e 100644
--- a/ubi-utils/src/libiniparser.c
+++ b/ubi-utils/new-utils/src/libiniparser.c
diff --git a/ubi-utils/old-tools/src/libubi.c b/ubi-utils/new-utils/src/libubi.c
index be06f70..b53f18c 100644
--- a/ubi-utils/old-tools/src/libubi.c
+++ b/ubi-utils/new-utils/src/libubi.c
@@ -27,7 +27,6 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
-#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <limits.h>
@@ -50,8 +49,7 @@ static char *mkpath(const char *path, const char *name)
n = malloc(len1 + len2 + 2);
if (!n) {
- errmsg("cannot allocate %d bytes", len1 + len2 + 2);
- perror("malloc");
+ sys_errmsg("cannot allocate %d bytes", len1 + len2 + 2);
return NULL;
}
@@ -83,8 +81,7 @@ static int read_positive_ll(const char *file, long long *value)
rd = read(fd, buf, 50);
if (rd == -1) {
- errmsg("cannot read \"%s\"", file);
- perror("read");
+ sys_errmsg("cannot read \"%s\"", file);
goto out_error;
}
if (rd == 50) {
@@ -106,11 +103,8 @@ static int read_positive_ll(const char *file, long long *value)
goto out_error;
}
- if (close(fd)) {
- errmsg("close failed on \"%s\"", file);
- perror("close");
- return -1;
- }
+ if (close(fd))
+ return sys_errmsg("close failed on \"%s\"", file);
return 0;
@@ -166,16 +160,14 @@ static int read_data(const char *file, void *buf, int buf_len)
rd = read(fd, buf, buf_len);
if (rd == -1) {
- errmsg("cannot read \"%s\"", file);
- perror("read");
+ sys_errmsg("cannot read \"%s\"", file);
goto out_error;
}
/* Make sure all data is read */
tmp1 = read(fd, &tmp, 1);
if (tmp1 == 1) {
- errmsg("cannot read \"%s\"", file);
- perror("read");
+ sys_errmsg("cannot read \"%s\"", file);
goto out_error;
}
if (tmp1) {
@@ -186,8 +178,7 @@ static int read_data(const char *file, void *buf, int buf_len)
}
if (close(fd)) {
- errmsg("close failed on \"%s\"", file);
- perror("close");
+ sys_errmsg("close failed on \"%s\"", file);
return -1;
}
@@ -217,16 +208,14 @@ static int read_major(const char *file, int *major, int *minor)
ret = sscanf(buf, "%d:%d\n", major, minor);
if (ret != 2) {
- errmsg("\"%s\" does not have major:minor format", file);
errno = EINVAL;
- return -1;
+ return errmsg("\"%s\" does not have major:minor format", file);
}
if (*major < 0 || *minor < 0) {
- errmsg("bad major:minor %d:%d in \"%s\"",
- *major, *minor, file);
errno = EINVAL;
- return -1;
+ return errmsg("bad major:minor %d:%d in \"%s\"",
+ *major, *minor, file);
}
return 0;
@@ -320,31 +309,6 @@ static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
}
/**
- * dent_is_dir - check if a file is a directory.
- * @dir: the base directory path of the file
- * @name: file name
- *
- * This function returns %1 if file @name in directory @dir is a directoru, and
- * %0 if not.
- */
-static int dent_is_dir(const char *dir, const char *name)
-{
- int ret;
- struct stat st;
- char full_path[strlen(dir) + strlen(name) + 2];
-
- sprintf(full_path, "%s/%s", dir, name);
- ret = lstat(full_path, &st);
- if (ret) {
- errmsg("lstat failed on \"%s\"", full_path);
- perror("lstat");
- return -1;
- }
-
- return !!S_ISDIR(st.st_mode);
-}
-
-/**
* dev_get_major - get major and minor numbers of an UBI device.
* @lib: libubi descriptor
* @dev_num: UBI device number
@@ -402,18 +366,16 @@ static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num,
return -1;
if (!S_ISCHR(st.st_mode)) {
- errmsg("\"%s\" is not a character device", node);
errno = EINVAL;
- return -1;
+ return errmsg("\"%s\" is not a character device", node);
}
major = major(st.st_rdev);
minor = minor(st.st_rdev);
if (minor == 0) {
- errmsg("\"%s\" is not a volume character device", node);
errno = EINVAL;
- return -1;
+ return errmsg("\"%s\" is not a volume character device", node);
}
if (ubi_get_info((libubi_t *)lib, &info))
@@ -470,18 +432,16 @@ static int dev_node2num(struct libubi *lib, const char *node, int *dev_num)
return -1;
if (!S_ISCHR(stat.st_mode)) {
- errmsg("\"%s\" is not a character device", node);
errno = EINVAL;
- return -1;
+ return errmsg("\"%s\" is not a character device", node);
}
major = major(stat.st_rdev);
minor = minor(stat.st_rdev);
if (minor != 0) {
- errmsg("\"%s\" is not an UBI character device", node);
errno = EINVAL;
- return -1;
+ return errmsg("\"%s\" is not an UBI character device", node);
}
if (ubi_get_info((libubi_t *)lib, &info))
@@ -576,8 +536,7 @@ libubi_t libubi_open(void)
}
if (close(fd)) {
- errmsg("close failed on \"%s\"", lib->sysfs_ubi);
- perror("close");
+ sys_errmsg("close failed on \"%s\"", lib->sysfs_ubi);
goto out_error;
}
@@ -865,29 +824,27 @@ int ubi_get_info(libubi_t desc, struct ubi_info *info)
* devices are present.
*/
sysfs_ubi = opendir(lib->sysfs_ubi);
- if (!sysfs_ubi) {
- errmsg("cannot open %s", lib->sysfs_ubi);
- perror("opendir");
- return -1;
- }
+ if (!sysfs_ubi)
+ return sys_errmsg("cannot open %s", lib->sysfs_ubi);
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;
- /*
- * Make sure this direntry is a directory and not a symlink -
- * Linux puts symlinks to UBI volumes on this UBI device to the
- * same sysfs directory.
- */
- if (!dent_is_dir(lib->sysfs_ubi, dirent->d_name))
- continue;
- ret = sscanf(dirent->d_name, UBI_DEV_NAME_PATT, &dev_num);
+ 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)
@@ -898,16 +855,12 @@ int ubi_get_info(libubi_t desc, struct ubi_info *info)
}
if (!dirent && errno) {
- errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
- perror("readdir");
+ sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
goto out_close;
}
- if (closedir(sysfs_ubi)) {
- errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
- perror("closedir");
- return -1;
- }
+ 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;
@@ -1012,6 +965,21 @@ int ubi_update_start(libubi_t desc, int fd, long long bytes)
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;
@@ -1029,12 +997,20 @@ int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
while (1) {
int vol_id, ret, devno;
+ char tmp_buf[256];
errno = 0;
dirent = readdir(sysfs_ubi);
if (!dirent)
break;
- ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT, &devno, &vol_id);
+
+ 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_num)
@@ -1045,16 +1021,12 @@ int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
}
if (!dirent && errno) {
- errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
- perror("readdir");
+ sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
goto out_close;
}
- if (closedir(sysfs_ubi)) {
- errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
- perror("closedir");
- return -1;
- }
+ if (closedir(sysfs_ubi))
+ return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
if (info->lowest_vol_num == INT_MAX)
info->lowest_vol_num = 0;
diff --git a/ubi-utils/old-tools/src/libubi_int.h b/ubi-utils/new-utils/src/libubi_int.h
index 6490864..dab3e62 100644
--- a/ubi-utils/old-tools/src/libubi_int.h
+++ b/ubi-utils/new-utils/src/libubi_int.h
@@ -23,14 +23,26 @@
#ifndef __LIBUBI_INT_H__
#define __LIBUBI_INT_H__
+#include <string.h>
+#include <errno.h>
+
#ifdef __cplusplus
extern "C" {
#endif
/* Error messages */
-#define errmsg(fmt, ...) do { \
+#define errmsg(fmt, ...) ({ \
fprintf(stderr, "libubi error: " fmt "\n", ##__VA_ARGS__); \
-} while(0)
+ -1; \
+})
+
+/* System error messages */
+#define sys_errmsg(fmt, ...) ({ \
+ int _err = errno; \
+ fprintf(stderr, "libubi error: " fmt "\n", ##__VA_ARGS__); \
+ fprintf(stderr, "error %d (%s)\n", _err, strerror(_err)); \
+ -1; \
+})
/*
* The below are pre-define UBI file and directory names.
diff --git a/ubi-utils/new-utils/src/libubigen.c b/ubi-utils/new-utils/src/libubigen.c
new file mode 100644
index 0000000..8d71fde
--- /dev/null
+++ b/ubi-utils/new-utils/src/libubigen.c
@@ -0,0 +1,321 @@
+/*
+ * 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 <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <mtd/ubi-header.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
+ * @ec: initial erase counter
+ */
+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,
+ long long ec)
+{
+ if (!vid_hdr_offs)
+ 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->ec = ec;
+
+ ui->vtbl_size = ui->leb_size;
+ if (ui->vtbl_size > UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE)
+ ui->vtbl_size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE;
+ ui->max_volumes = ui->vtbl_size / 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) {
+ errmsg("cannot allocate %d bytes of memory", ui->vtbl_size);
+ return NULL;
+ }
+
+ for (i = 0; i < UBI_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;
+}
+
+/**
+ * init_ec_hdr - initialize EC header.
+ * @ui: libubigen information
+ * @hdr: the EC header to initialize
+ */
+static void init_ec_hdr(const struct ubigen_info *ui,
+ struct ubi_ec_hdr *hdr)
+{
+ 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(ui->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
+ * @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 bytes, FILE *in, FILE *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);
+ init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf);
+
+ while (bytes) {
+ int l;
+ struct ubi_vid_hdr *vid_hdr;
+
+ if (bytes < len)
+ len = bytes;
+ bytes -= len;
+
+ l = len;
+ do {
+ rd = fread(inbuf + len - l, 1, l, in);
+ if (rd == 0) {
+ if (ferror(in))
+ return errmsg("cannot read %d bytes from the input file", l);
+ else
+ return errmsg("not enough data in the input file");
+ }
+
+ 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 (fwrite(outbuf, 1, ui->peb_size, out) != ui->peb_size)
+ return errmsg("cannot write %d bytes from the output file", l);
+
+ lnum += 1;
+ }
+
+ return 0;
+}
+
+/**
+ * ubigen_write_layout_vol - write UBI layout volume
+ * @ui: libubigen information
+ * @vtbl: volume table
+ * @out: output file stream
+ *
+ * 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,
+ struct ubi_vtbl_record *vtbl, FILE *out)
+{
+ int size = ui->leb_size;
+ struct ubigen_vol_info vi;
+ char outbuf[ui->peb_size];
+ struct ubi_vid_hdr *vid_hdr;
+
+ if (size > UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE)
+ size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE;
+
+ 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]);
+ init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf);
+ memcpy(outbuf + ui->data_offs, vtbl, size);
+ memset(outbuf + ui->data_offs + size, 0xFF,
+ ui->peb_size - ui->data_offs - size);
+
+ init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0);
+ size = fwrite(outbuf, 1, ui->peb_size, out);
+ if (size == ui->peb_size) {
+ init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0);
+ size = fwrite(outbuf, 1, ui->peb_size, out);
+ if (size != ui->peb_size)
+ return sys_errmsg("cannot write %d bytes", ui->peb_size);
+ }
+
+ return 0;
+}
diff --git a/ubi-utils/src/ubiattach.c b/ubi-utils/new-utils/src/ubi-attach.c
index b3d768a..7b231a6 100644
--- a/ubi-utils/src/ubiattach.c
+++ b/ubi-utils/new-utils/src/ubi-attach.c
@@ -31,7 +31,7 @@
#include "common.h"
#define PROGRAM_VERSION "1.0"
-#define PROGRAM_NAME "ubiattach"
+#define PROGRAM_NAME "ubi-attach"
/* The variables below are set by command line arguments */
struct args {
diff --git a/ubi-utils/new-utils/src/ubi-crc32.c b/ubi-utils/new-utils/src/ubi-crc32.c
new file mode 100644
index 0000000..d3d3136
--- /dev/null
+++ b/ubi-utils/new-utils/src/ubi-crc32.c
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+/*
+ * Calculate CRC32 with UBI start value (0xFFFFFFFF) for a given binary image.
+ *
+ * Author: Oliver Lohmann
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <argp.h>
+#include <unistd.h>
+#include <mtd/ubi-header.h>
+
+#include "crc32.h"
+#include "common.h"
+
+#define BUFSIZE 4096
+
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME "ubi-crc32"
+
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+ " - a tool to calculate CRC32 with UBI start value (0xFFFFFFFF)";
+
+static const char *optionsstr =
+"-h, --help print help message\n"
+"-V, --version print program version";
+
+static const char *usage =
+"Usage: " PROGRAM_NAME " <file to calculate CRC32 for> [-h] [--help]";
+
+static const struct option long_options[] = {
+ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
+ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+ { NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+ while (1) {
+ int key;
+
+ key = getopt_long(argc, argv, "hV", long_options, NULL);
+ if (key == -1)
+ break;
+
+ switch (key) {
+ case 'h':
+ fprintf(stderr, "%s\n\n", doc);
+ fprintf(stderr, "%s\n\n", usage);
+ fprintf(stderr, "%s\n", optionsstr);
+ exit(EXIT_SUCCESS);
+
+ case 'V':
+ fprintf(stderr, "%s\n", PROGRAM_VERSION);
+ exit(EXIT_SUCCESS);
+
+ case ':':
+ return errmsg("parameter is missing");
+
+ default:
+ fprintf(stderr, "Use -h for help\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+ int err = 0;
+ uint32_t crc = UBI_CRC32_INIT;
+ char buf[BUFSIZE];
+ FILE *fp;
+
+ if (argc > 1) {
+ fp = fopen(argv[1], "r");
+ if (!fp)
+ return sys_errmsg("cannot open \"%s\"", argv[1]);
+ } else
+ fp = stdin;
+
+ err = parse_opt(argc, argv);
+ if (err)
+ return err;
+
+ while (!feof(fp)) {
+ size_t read;
+
+ read = fread(buf, 1, BUFSIZE, fp);
+ if (ferror(fp)) {
+ sys_errmsg("cannot read input file");
+ err = -1;
+ goto out_close;
+ }
+ crc = crc32(crc, buf, read);
+ }
+
+ printf("0x%08x\n", crc);
+
+out_close:
+ if (fp != stdin)
+ fclose(fp);
+ return err;
+}
diff --git a/ubi-utils/src/ubidetach.c b/ubi-utils/new-utils/src/ubi-detach.c
index cd48368..0ee7954 100644
--- a/ubi-utils/src/ubidetach.c
+++ b/ubi-utils/new-utils/src/ubi-detach.c
@@ -31,7 +31,7 @@
#include "common.h"
#define PROGRAM_VERSION "1.0"
-#define PROGRAM_NAME "ubidetach"
+#define PROGRAM_NAME "ubi-detach"
/* The variables below are set by command line arguments */
struct args {
diff --git a/ubi-utils/src/ubinfo.c b/ubi-utils/new-utils/src/ubi-info.c
index 185caae..d469a1a 100644
--- a/ubi-utils/src/ubinfo.c
+++ b/ubi-utils/new-utils/src/ubi-info.c
@@ -31,7 +31,7 @@
#include "common.h"
#define PROGRAM_VERSION "1.0"
-#define PROGRAM_NAME "ubinfo"
+#define PROGRAM_NAME "ubi-nfo"
/* The variables below are set by command line arguments */
struct args {
diff --git a/ubi-utils/new-utils/src/ubi-mkvol.c b/ubi-utils/new-utils/src/ubi-mkvol.c
new file mode 100644
index 0000000..49d1905
--- /dev/null
+++ b/ubi-utils/new-utils/src/ubi-mkvol.c
@@ -0,0 +1,288 @@
+/*
+ * 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.
+ */
+
+/*
+ * An utility to create UBI volumes.
+ *
+ * Authors: Artem Bityutskiy <dedekind@infradead.org>
+ * Frank Haverkamp <haver@vnet.ibm.com>
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libubi.h>
+#include "common.h"
+
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME "ubi-mkvol"
+
+/* The variables below are set by command line arguments */
+struct args {
+ int vol_id;
+ int vol_type;
+ long long bytes;
+ int lebs;
+ int alignment;
+ const char *name;
+ int nlen;
+ const char *node;
+ int maxavs;
+};
+
+static struct args args = {
+ .vol_type = UBI_DYNAMIC_VOLUME,
+ .bytes = -1,
+ .lebs = -1,
+ .alignment = 1,
+ .vol_id = UBI_VOL_NUM_AUTO,
+ .name = NULL,
+ .nlen = 0,
+ .node = NULL,
+ .maxavs = 0,
+};
+
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+ " - a tool to create UBI volumes.";
+
+static const char *optionsstr =
+"-a, --alignment=<alignment> volume alignment (default is 1)\n"
+"-n, --vol_id=<volume ID> UBI volume ID, if not specified, the volume ID\n"
+" will be assigned automatically\n"
+"-N, --name=<name> volume name\n"
+"-s, --size=<bytes> volume size volume size in bytes, kilobytes (KiB)\n"
+" or megabytes (MiB)\n"
+"-S, --lebs=<LEBs count> alternative way to give volume size in logical\n"
+" eraseblocks\n"
+"-m, --maxavsize set volume size to maximum available size\n"
+"-t, --type=<static|dynamic> volume type (dynamic, static), default is dynamic\n"
+"-h, --help print help message\n"
+"-V, --version print program version";
+
+static const char *usage =
+"Usage: " PROGRAM_NAME " <UBI device node file name> [-h] [-a <alignment>] [-n <volume ID>] [-N <name>]\n"
+"\t\t\t[-s <bytes>] [-S <LEBs>] [-t <static|dynamic>] [-V] [-m]\n"
+"\t\t\t[--alignment=<alignment>][--vol_id=<volume ID>] [--name=<name>]\n"
+"\t\t\t[--size=<bytes>] [--lebs=<LEBs>] [--type=<static|dynamic>] [--help]\n"
+"\t\t\t[--version] [--maxavsize]\n\n"
+"Example: " PROGRAM_NAME "/dev/ubi0 -s 20MiB -N config_data - create a 20 Megabytes volume\n"
+" named \"config_data\" on UBI device /dev/ubi0.";
+
+static const struct option long_options[] = {
+ { .name = "alignment", .has_arg = 1, .flag = NULL, .val = 'a' },
+ { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' },
+ { .name = "name", .has_arg = 1, .flag = NULL, .val = 'N' },
+ { .name = "size", .has_arg = 1, .flag = NULL, .val = 's' },
+ { .name = "lebs", .has_arg = 1, .flag = NULL, .val = 'S' },
+ { .name = "type", .has_arg = 1, .flag = NULL, .val = 't' },
+ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
+ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+ { .name = "maxavsize", .has_arg = 0, .flag = NULL, .val = 'm' },
+ { NULL, 0, NULL, 0},
+};
+
+static int param_sanity_check(void)
+{
+ int len;
+
+ if (args.bytes == -1 && !args.maxavs && args.lebs == -1)
+ return errmsg("volume size was not specified (use -h for help)");
+
+ if ((args.bytes != -1 && (args.maxavs || args.lebs != -1)) ||
+ (args.lebs != -1 && (args.maxavs || args.bytes != -1)) ||
+ (args.maxavs && (args.bytes != -1 || args.lebs != -1)))
+ return errmsg("size specified with more then one option");
+
+ if (args.name == NULL)
+ return errmsg("volume name was not specified (use -h for help)");
+
+ len = strlen(args.name);
+ if (len > UBI_MAX_VOLUME_NAME)
+ return errmsg("too long name (%d symbols), max is %d", len, UBI_MAX_VOLUME_NAME);
+
+ return 0;
+}
+
+static int parse_opt(int argc, char * const argv[])
+{
+ while (1) {
+ int key;
+ char *endp;
+
+ key = getopt_long(argc, argv, "a:n:N:s:S:t:hVm", long_options, NULL);
+ if (key == -1)
+ break;
+
+ switch (key) {
+ case 't':
+ if (!strcmp(optarg, "dynamic"))
+ args.vol_type = UBI_DYNAMIC_VOLUME;
+ else if (!strcmp(optarg, "static"))
+ args.vol_type = UBI_STATIC_VOLUME;
+ else
+ return errmsg("bad volume type: \"%s\"", optarg);
+ break;
+
+ case 's':
+ args.bytes = ubiutils_get_bytes(optarg);
+ if (args.bytes <= 0)
+ return errmsg("bad volume size: \"%s\"", optarg);
+ break;
+
+ case 'S':
+ args.lebs = strtoull(optarg, &endp, 0);
+ if (endp == optarg || args.lebs <= 0 || *endp != '\0')
+ return errmsg("bad LEB count: \"%s\"", optarg);
+ break;
+
+ case 'a':
+ args.alignment = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg || args.alignment <= 0)
+ return errmsg("bad volume alignment: \"%s\"", optarg);
+ break;
+
+ case 'n':
+ args.vol_id = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg || args.vol_id < 0)
+ return errmsg("bad volume ID: " "\"%s\"", optarg);
+ break;
+
+ case 'N':
+ args.name = optarg;
+ args.nlen = strlen(args.name);
+ break;
+
+ case 'h':
+ fprintf(stderr, "%s\n\n", doc);
+ fprintf(stderr, "%s\n\n", usage);
+ fprintf(stderr, "%s\n", optionsstr);
+ exit(EXIT_SUCCESS);
+
+ case 'V':
+ fprintf(stderr, "%s\n", PROGRAM_VERSION);
+ exit(EXIT_SUCCESS);
+
+ case 'm':
+ args.maxavs = 1;
+ break;
+
+ case ':':
+ return errmsg("parameter is missing");
+
+ default:
+ fprintf(stderr, "Use -h for help\n");
+ return -1;
+ }
+ }
+
+ if (optind == argc)
+ return errmsg("UBI device name was not specified (use -h for help)");
+ else if (optind != argc - 1)
+ return errmsg("more then one UBI device specified (use -h for help)");
+
+ args.node = argv[optind];
+
+ if (param_sanity_check())
+ return -1;
+
+ return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+ int err;
+ libubi_t libubi;
+ struct ubi_dev_info dev_info;
+ struct ubi_vol_info vol_info;
+ struct ubi_mkvol_request req;
+
+ err = parse_opt(argc, argv);
+ if (err)
+ return err;
+
+ libubi = libubi_open();
+ if (!libubi)
+ return sys_errmsg("cannot open libubi");
+
+ err = ubi_node_type(libubi, args.node);
+ if (err == 2) {
+ errmsg("\"%s\" is an UBI volume node, not an UBI device node",
+ args.node);
+ goto out_libubi;
+ } else if (err < 0) {
+ errmsg("\"%s\" is not an UBI device node", args.node);
+ goto out_libubi;
+ }
+
+ err = ubi_get_dev_info(libubi, args.node, &dev_info);
+ if (err) {
+ sys_errmsg("cannot get information about UBI device \"%s\"",
+ args.node);
+ goto out_libubi;
+ }
+
+ if (args.maxavs) {
+ args.bytes = dev_info.avail_bytes;
+ printf("Set volume size to %lld\n", req.bytes);
+ }
+
+ if (args.lebs != -1) {
+ args.bytes = dev_info.leb_size;
+ args.bytes -= dev_info.leb_size % args.alignment;
+ args.bytes *= args.lebs;
+ }
+
+ req.vol_id = args.vol_id;
+ req.alignment = args.alignment;
+ req.bytes = args.bytes;
+ req.vol_type = args.vol_type;
+ req.name = args.name;
+
+ err = ubi_mkvol(libubi, args.node, &req);
+ if (err < 0) {
+ sys_errmsg("cannot UBI create volume");
+ goto out_libubi;
+ }
+
+ args.vol_id = req.vol_id;
+
+ /* Print information about the created device */
+ err = ubi_get_vol_info1(libubi, dev_info.dev_num, args.vol_id, &vol_info);
+ if (err) {
+ sys_errmsg("cannot get information about newly created UBI volume");
+ goto out_libubi;
+ }
+
+ printf("Volume ID %d, size %d LEBs (", vol_info.vol_id, vol_info.rsvd_lebs);
+ ubiutils_print_bytes(vol_info.rsvd_bytes, 0);
+ printf("), LEB size ");
+ ubiutils_print_bytes(vol_info.leb_size, 1);
+ printf(", %s, name \"%s\", alignment %d\n",
+ req.vol_type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static",
+ vol_info.name, vol_info.alignment);
+
+ libubi_close(libubi);
+ return 0;
+
+out_libubi:
+ libubi_close(libubi);
+ return -1;
+}
diff --git a/ubi-utils/src/ubinize.c b/ubi-utils/new-utils/src/ubi-nize.c
index 47dc571..8041df4 100644
--- a/ubi-utils/src/ubinize.c
+++ b/ubi-utils/new-utils/src/ubi-nize.c
@@ -36,8 +36,8 @@
#include <libiniparser.h>
#include "common.h"
-#define PROGRAM_VERSION "1.5"
-#define PROGRAM_NAME "ubinize"
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME "ubi-nize"
static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
" - a tool to generate UBI images. An UBI image may contain one or more UBI "
diff --git a/ubi-utils/new-utils/src/ubi-rmvol.c b/ubi-utils/new-utils/src/ubi-rmvol.c
new file mode 100644
index 0000000..72bf069
--- /dev/null
+++ b/ubi-utils/new-utils/src/ubi-rmvol.c
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+/*
+ * An utility to remove UBI volumes.
+ *
+ * Authors: Artem Bityutskiy <dedekind@infradead.org>
+ * Frank Haverkamp <haver@vnet.ibm.com>
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libubi.h>
+#include "common.h"
+
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME "ubi-rmvol"
+
+/* The variables below are set by command line arguments */
+struct args {
+ int vol_id;
+ const char *node;
+};
+
+static struct args args = {
+ .vol_id = -1,
+ .node = NULL,
+};
+
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+ " - a tool to remove UBI volumes.";
+
+static const char *optionsstr =
+" -n, --vol_id=<volume id> volume ID to remove\n"
+" -h, --help print help message\n"
+" -V, --version print program version";
+
+static const char *usage =
+"Usage: " PROGRAM_NAME " <UBI device node file name> [-n <volume id>] [--vol_id=<volume id>] [-h] [--help]\n\n"
+"Example: " PROGRAM_NAME "/dev/ubi0 -n 1 - remove UBI volume 1 from UBI device corresponding\n"
+" to the node file /dev/ubi0.";
+
+static const struct option long_options[] = {
+ { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' },
+ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
+ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+ { NULL, 0, NULL, 0},
+};
+
+static int param_sanity_check(void)
+{
+ if (args.vol_id == -1) {
+ errmsg("volume ID is was not specified");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int parse_opt(int argc, char * const argv[])
+{
+ while (1) {
+ int key;
+ char *endp;
+
+ key = getopt_long(argc, argv, "n:hV", long_options, NULL);
+ if (key == -1)
+ break;
+
+ switch (key) {
+
+ case 'n':
+ args.vol_id = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg || args.vol_id < 0) {
+ errmsg("bad volume ID: " "\"%s\"", optarg);
+ return -1;
+ }
+ break;
+
+ case 'h':
+ fprintf(stderr, "%s\n\n", doc);
+ fprintf(stderr, "%s\n\n", usage);
+ fprintf(stderr, "%s\n", optionsstr);
+ exit(EXIT_SUCCESS);
+
+ case 'V':
+ fprintf(stderr, "%s\n", PROGRAM_VERSION);
+ exit(EXIT_SUCCESS);
+
+ case ':':
+ errmsg("parameter is missing");
+ return -1;
+
+ default:
+ fprintf(stderr, "Use -h for help\n");
+ return -1;
+ }
+ }
+
+ if (optind == argc) {
+ errmsg("UBI device name was not specified (use -h for help)");
+ return -1;
+ } else if (optind != argc - 1) {
+ errmsg("more then one UBI device specified (use -h for help)");
+ return -1;
+ }
+
+ args.node = argv[optind];
+
+ if (param_sanity_check())
+ return -1;
+
+ return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+ int err;
+ libubi_t libubi;
+
+ err = parse_opt(argc, argv);
+ if (err)
+ return -1;
+
+ libubi = libubi_open();
+ if (libubi == NULL)
+ return sys_errmsg("cannot open libubi");
+
+ err = ubi_node_type(libubi, args.node);
+ if (err == 2) {
+ errmsg("\"%s\" is an UBI volume node, not an UBI device node",
+ args.node);
+ goto out_libubi;
+ } else if (err < 0) {
+ errmsg("\"%s\" is not an UBI device node", args.node);
+ goto out_libubi;
+ }
+
+ err = ubi_rmvol(libubi, args.node, args.vol_id);
+ if (err) {
+ sys_errmsg("cannot UBI remove volume");
+ goto out_libubi;
+ }
+
+ libubi_close(libubi);
+ return 0;
+
+out_libubi:
+ libubi_close(libubi);
+ return -1;
+}
diff --git a/ubi-utils/src/ubiupdate.c b/ubi-utils/new-utils/src/ubi-update.c
index c17b3c5..bf548a9 100644
--- a/ubi-utils/src/ubiupdate.c
+++ b/ubi-utils/new-utils/src/ubi-update.c
@@ -37,8 +37,8 @@
#include <libubi.h>
#include "common.h"
-#define PROGRAM_VERSION "1.3"
-#define PROGRAM_NAME "ubiupdate"
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME "ubi-update"
struct args {
int truncate;
diff --git a/ubi-utils/old-tools/Makefile b/ubi-utils/old-tools/Makefile
deleted file mode 100644
index d4c908b..0000000
--- a/ubi-utils/old-tools/Makefile
+++ /dev/null
@@ -1,99 +0,0 @@
-#
-# Makefile for ubi-utils
-#
-
-OPTFLAGS := -O2 -Wall
-KERNELHDR := ../../include
-DESTDIR := /usr/local
-SBINDIR=/usr/sbin
-MANDIR=/usr/man
-INCLUDEDIR=/usr/include
-
-CC := $(CROSS)gcc
-CFLAGS := -I./inc -I./src -I$(KERNELHDR) $(OPTFLAGS) -Werror \
- -Wwrite-strings -W -std=gnu99 -DPACKAGE_VERSION=\"1.0\"
-
-PERLPROGS = mkpfi ubicrc32.pl
-TARGETS = pfiflash pddcustomize ubimirror \
- bin2nand nand2bin ubigen mkbootenv unubi pfi2bin
-
-vpath %.c ./src
-
-%: %.o
- $(CC) $(LDFLAGS) -g -o $@ $^
-
-%.o: %.c
- $(CC) $(CFLAGS) -g -c -o $@ $< -g -Wp,-MD,.$(shell basename $<).dep
-
-all: $(TARGETS) libubi.a
-
-IGNORE=${wildcard .*.c.dep}
--include ${IGNORE}
-
-clean:
- rm -rf *.o $(TARGETS) .*.c.dep libubi.a
-
-libubi.a: libubi.o
- ar cr $@ $^
-
-ubidetach: ubidetach.o common.o libubi.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-ubiattach: ubiattach.o common.o libubi.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-ubinfo: ubinfo.o common.o libubi.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-ubiupdate: ubiupdate.o common.o libubi.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-ubimkvol: ubimkvol.o common.o libubi.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-ubirmvol: ubirmvol.o common.o libubi.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-pddcustomize: pddcustomize.o error.o libubimirror.o bootenv.o hashmap.o \
- libubi.o crc32.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-pfiflash: pfiflash.o libpfiflash.o list.o reader.o error.o libubimirror.o \
- bootenv.o hashmap.o pfi.o libubi.o crc32.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-ubimirror: ubimirror.o error.o libubimirror.o bootenv.o hashmap.o \
- libubi.o crc32.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-nand2bin: nand2bin.o nandecc.o nandcorr.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-bin2nand: bin2nand.o error.o nandecc.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-ubigen: ubigen.o libubigen.o crc32.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-mkbootenv: mkbootenv.o bootenv.o hashmap.o error.o crc32.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-unubi: unubi.o crc32.o unubi_analyze.o eb_chain.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-pfi2bin: pfi2bin.o peb.o error.o list.o crc32.o libubigen.o bootenv.o \
- hashmap.o reader.o pfi.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-ubicrc32: ubicrc32.o crc32.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-install: ${TARGETS}
- mkdir -p ${DESTDIR}/${SBINDIR}
- install -m0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
- (cd perl && install ${PERLPROGS} ${DESTDIR}/${SBINDIR}/)
-
-uninstall:
- for file in ${TARGETS} ${PERLPROGS}; do \
- $(RM) ${DESTDIR}/${SBINDIR}/$$file; \
- done
diff --git a/ubi-utils/old-tools/inc/libubi.h b/ubi-utils/old-tools/inc/libubi.h
deleted file mode 100644
index 0cdb67c..0000000
--- a/ubi-utils/old-tools/inc/libubi.h
+++ /dev/null
@@ -1,340 +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 B. Bityutskiy
- *
- * UBI (Unsorted Block Images) library.
- */
-
-#ifndef __LIBUBI_H__
-#define __LIBUBI_H__
-
-#include <stdint.h>
-#include <mtd/ubi-user.h>
-#include <ctype.h>
-#include <mtd/ubi-header.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* UBI version libubi is made for */
-#define LIBUBI_UBI_VERSION 1
-
-/* UBI library descriptor */
-typedef void * libubi_t;
-
-/**
- * struct ubi_attach_request - MTD device attachement request.
- * @dev_num: number to assigne to the newly created UBI device
- * (%UBI_DEV_NUM_AUTO should be used to automatically assign the
- * number)
- * @mtd_num: MTD device number to attach
- * @vid_hdr_offset: VID header offset (%0 means default offset and this is what
- * most of the users want)
- */
-struct ubi_attach_request
-{
- int dev_num;
- int mtd_num;
- int vid_hdr_offset;
-};
-
-/**
- * struct ubi_mkvol_request - volume creation request.
- * @vol_id: ID to assign to the new volume (%UBI_VOL_NUM_AUTO should be used to
- * automatically assign ID)
- * @alignment: volume alignment
- * @bytes: volume size in bytes
- * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
- * @name: volume name
- */
-struct ubi_mkvol_request
-{
- int vol_id;
- int alignment;
- long long bytes;
- int vol_type;
- const char *name;
-};
-
-/**
- * struct ubi_info - general UBI information.
- * @dev_count: count of UBI devices in system
- * @lowest_dev_num: lowest UBI device number
- * @highest_dev_num: highest UBI device number
- * @version: UBI version
- * @ctrl_major: major number of the UBI control device
- * @ctrl_minor: minor number of the UBI control device
- */
-struct ubi_info
-{
- int dev_count;
- int lowest_dev_num;
- int highest_dev_num;
- int version;
- int ctrl_major;
- int ctrl_minor;
-};
-
-/**
- * struct ubi_dev_info - UBI device information.
- * @vol_count: count of volumes on this UBI device
- * @lowest_vol_num: lowest volume number
- * @highest_vol_num: highest volume number
- * @major: major number of corresponding character device
- * @minor: minor number of corresponding character device
- * @total_lebs: total number of logical eraseblocks on this UBI device
- * @avail_lebs: how many logical eraseblocks are not used and available for new
- * volumes
- * @total_bytes: @total_lebs * @leb_size
- * @avail_bytes: @avail_lebs * @leb_size
- * @bad_count: count of bad physical eraseblocks
- * @leb_size: logical eraseblock size
- * @max_ec: current highest erase counter value
- * @bad_rsvd: how many physical eraseblocks of the underlying flash device are
- * reserved for bad eraseblocks handling
- * @max_vol_count: maximum possible number of volumes on this UBI device
- * @min_io_size: minimum input/output unit size of the UBI device
- */
-struct ubi_dev_info
-{
- int dev_num;
- int vol_count;
- int lowest_vol_num;
- int highest_vol_num;
- int major;
- int minor;
- int total_lebs;
- int avail_lebs;
- long long total_bytes;
- long long avail_bytes;
- int bad_count;
- int leb_size;
- long long max_ec;
- int bad_rsvd;
- int max_vol_count;
- int min_io_size;
-};
-
-/**
- * struct ubi_vol_info - UBI volume information.
- * @dev_num: UBI device number the volume resides on
- * @vol_id: ID of this volume
- * @major: major number of corresponding volume character device
- * @minor: minor number of corresponding volume character device
- * @dev_major: major number of corresponding UBI device character device
- * @dev_minor: minor number of corresponding UBI device character device
- * @type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
- * @alignment: alignemnt of this volume
- * @data_bytes: how many data bytes are stored on this volume (equivalent to
- * @rsvd_bytes for dynamic volumes)
- * @rsvd_bytes: how many bytes are reserved for this volume
- * @rsvd_lebs: how many logical eraseblocks are reserved for this volume
- * @leb_size: logical eraseblock size of this volume (may be less then
- * device's logical eraseblock size due to alignment)
- * @corrupted: non-zero if the volume is corrupted
- * @name: volume name (null-terminated)
- */
-struct ubi_vol_info
-{
- int dev_num;
- int vol_id;
- int major;
- int minor;
- int dev_major;
- int dev_minor;
- int type;
- int alignment;
- long long data_bytes;
- long long rsvd_bytes;
- int rsvd_lebs;
- int leb_size;
- int corrupted;
- char name[UBI_VOL_NAME_MAX + 1];
-};
-
-/**
- * libubi_open - open UBI library.
- * This function initializes and opens the UBI library and returns UBI library
- * descriptor in case of success and %NULL in case of failure.
- */
-libubi_t libubi_open(void);
-
-/**
- * libubi_close - close UBI library.
- * @desc UBI library descriptor
- */
-void libubi_close(libubi_t desc);
-
-/**
- * ubi_get_info - get general UBI information.
- * @desc: UBI library descriptor
- * @info: pointer to the &struct ubi_info object to fill
- *
- * This function fills the passed @info object with general UBI information and
- * returns %0 in case of success and %-1 in case of failure.
- */
-int ubi_get_info(libubi_t desc, struct ubi_info *info);
-
-/**
- * ubi_attach_mtd - attach MTD device to UBI.
- * @desc: UBI library descriptor
- * @node: name of the UBI control character device node
- * @req: MTD attach request.
- *
- * This function creates a new UBI device by attaching an MTD device as
- * described by @req. Returns %0 in case of success and %-1 in case of failure.
- * The newly created UBI device number is returned in @req->dev_num.
- */
-int ubi_attach_mtd(libubi_t desc, const char *node,
- struct ubi_attach_request *req);
-
-/**
- * ubi_detach_mtd - detach an MTD device.
- * @desc: UBI library descriptor
- * @node: name of the UBI control character device node
- * @mtd_num: MTD device number to detach
- *
- * This function detaches MTD device number @mtd_num from UBI, which means the
- * corresponding UBI device is removed. Returns zero in case of success and %-1
- * in case of failure.
- */
-int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num);
-
-/**
- * ubi_remove_dev - remove an UBI device.
- * @desc: UBI library descriptor
- * @node: name of the UBI control character device node
- * @ubi_dev: UBI device number to remove
- *
- * This function removes UBI device number @ubi_dev and returns zero in case of
- * success and %-1 in case of failure.
- */
-int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev);
-
-/**
- * ubi_mkvol - create an UBI volume.
- * @desc: UBI library descriptor
- * @node: name of the UBI character device to create a volume at
- * @req: UBI volume creation request
- *
- * This function creates a UBI volume as described at @req and returns %0 in
- * case of success and %-1 in case of failure. The assigned volume ID is
- * returned in @req->vol_id.
- */
-int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req);
-
-/**
- * ubi_rmvol - remove a UBI volume.
- * @desc: UBI library descriptor
- * @node: name of the UBI character device to remove a volume from
- * @vol_id: ID of the volume to remove
- *
- * This function removes volume @vol_id from UBI device @node and returns %0 in
- * case of success and %-1 in case of failure.
- */
-int ubi_rmvol(libubi_t desc, const char *node, int vol_id);
-
-/**
- * ubi_rsvol - re-size UBI volume.
- * @desc: UBI library descriptor
- * @node: name of the UBI character device owning the volume which should be
- * re-sized
- * @vol_id: volume ID to re-size
- * @bytes: new volume size in bytes
- *
- * This function returns %0 in case of success and %-1 in case of error.
- */
-int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes);
-
-/**
- * ubi_node_type - test UBI node type.
- * @desc: UBI library descriptor
- * @node: the node to test
- *
- * This function tests whether @node is a UBI device or volume node and returns
- * %1 if this is an UBI device node, %2 if this is a volume node, and %-1 if
- * this is not an UBI node or if an error occurred (the latter is indicated by
- * a non-zero errno).
- */
-int ubi_node_type(libubi_t desc, const char *node);
-
-/**
- * ubi_get_dev_info - get UBI device information.
- * @desc: UBI library descriptor
- * @node: name of the UBI character device to fetch information about
- * @info: pointer to the &struct ubi_dev_info object to fill
- *
- * This function fills the passed @info object with UBI device information and
- * returns %0 in case of success and %-1 in case of failure.
- */
-int ubi_get_dev_info(libubi_t desc, const char *node,
- struct ubi_dev_info *info);
-
-/**
- * ubi_get_dev_info1 - get UBI device information.
- * @desc: UBI library descriptor
- * @dev_num: UBI device number to fetch information about
- * @info: pointer to the &struct ubi_dev_info object to fill
- *
- * This function is identical to 'ubi_get_dev_info()' except that it accepts UBI
- * device number, not UBI character device.
- */
-int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info);
-
-/**
- * ubi_get_vol_info - get UBI volume information.
- * @desc: UBI library descriptor
- * @node: name of the UBI volume character device to fetch information about
- * @info: pointer to the &struct ubi_vol_info object to fill
- *
- * This function fills the passed @info object with UBI volume information and
- * returns %0 in case of success and %-1 in case of failure.
- */
-int ubi_get_vol_info(libubi_t desc, const char *node,
- struct ubi_vol_info *info);
-
-/**
- * ubi_get_vol_info1 - get UBI volume information.
- * @desc: UBI library descriptor
- * @dev_num: UBI device number
- * @vol_id: ID of the UBI volume to fetch information about
- * @info: pointer to the &struct ubi_vol_info object to fill
- *
- * This function is identical to 'ubi_get_vol_info()' except that it accepts UBI
- * volume number, not UBI volume character device.
- */
-int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
- struct ubi_vol_info *info);
-
-/**
- * ubi_update_start - start UBI volume update.
- * @desc: UBI library descriptor
- * @fd: volume character devie file descriptor
- * @bytes: how many bytes will be written to the volume
- *
- * This function initiates UBI volume update and returns %0 in case of success
- * and %-1 in case of error.
- */
-int ubi_update_start(libubi_t desc, int fd, long long bytes);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !__LIBUBI_H__ */
diff --git a/ubi-utils/old-tools/src/common.c b/ubi-utils/old-tools/src/common.c
deleted file mode 100644
index 7ed1ade..0000000
--- a/ubi-utils/old-tools/src/common.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) Artem Bityutskiy, 2007
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * This file contains various common stuff used by UBI utilities.
- *
- * Author: Artem Bityutskiy
- */
-
-#include <stdio.h>
-#include <string.h>
-
-/**
- * ubiutils_bytes_multiplier - convert size specifier to an integer
- * multiplier.
- *
- * @str: the size specifier string
- *
- * This function parses the @str size specifier, which may be one of
- * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive
- * size multiplier in case of success and %-1 in case of failure.
- */
-int ubiutils_get_multiplier(const char *str)
-{
- if (!str)
- return 1;
-
- /* Remove spaces before the specifier */
- while (*str == ' ' || *str == '\t')
- str += 1;
-
- if (!strcmp(str, "KiB"))
- return 1024;
- if (!strcmp(str, "MiB"))
- return 1024 * 1024;
- if (!strcmp(str, "GiB"))
- return 1024 * 1024 * 1024;
-
- return -1;
-}
-
-/**
- * ubiutils_print_bytes - print bytes.
- * @bytes: variable to print
- * @bracket: whether brackets have to be put or not
- *
- * This is a helper function which prints amount of bytes in a human-readable
- * form, i.e., it prints the exact amount of bytes following by the approximate
- * amount of Kilobytes, Megabytes, or Gigabytes, depending on how big @bytes
- * is.
- */
-void ubiutils_print_bytes(long long bytes, int bracket)
-{
- const char *p;
-
- if (bracket)
- p = " (";
- else
- p = ", ";
-
- printf("%lld bytes", bytes);
-
- if (bytes > 1024 * 1024 * 1024)
- printf("%s%.1f GiB", p, (double)bytes / (1024 * 1024 * 1024));
- else if (bytes > 1024 * 1024)
- printf("%s%.1f MiB", p, (double)bytes / (1024 * 1024));
- else if (bytes > 1024)
- printf("%s%.1f KiB", p, (double)bytes / 1024);
- else
- return;
-
- if (bracket)
- printf(")");
-}
diff --git a/ubi-utils/old-tools/src/common.h b/ubi-utils/old-tools/src/common.h
deleted file mode 100644
index 06ae623..0000000
--- a/ubi-utils/old-tools/src/common.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) Artem Bityutskiy, 2007
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __UBI_UTILS_COMMON_H__
-#define __UBI_UTILS_COMMON_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Error messages */
-#define errmsg(fmt, ...) do { \
- fprintf(stderr, PROGRAM_NAME " error: " fmt "\n", ##__VA_ARGS__); \
-} while(0)
-
-/* Warnings */
-#define warnmsg(fmt, ...) do { \
- fprintf(stderr, PROGRAM_NAME " warning: " fmt "\n", ##__VA_ARGS__); \
-} while(0)
-
-int ubiutils_get_multiplier(const char *str);
-void ubiutils_print_bytes(long long bytes, int bracket);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !__UBI_UTILS_COMMON_H__ */
diff --git a/ubi-utils/old-tools/src/crc32.c b/ubi-utils/old-tools/src/crc32.c
deleted file mode 100644
index 666e217..0000000
--- a/ubi-utils/old-tools/src/crc32.c
+++ /dev/null
@@ -1,83 +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: 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-tools/src/crc32.h b/ubi-utils/old-tools/src/crc32.h
deleted file mode 100644
index 31362b0..0000000
--- a/ubi-utils/old-tools/src/crc32.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#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-tools/src/ecclayouts.h b/ubi-utils/old-tools/src/ecclayouts.h
deleted file mode 100644
index a1c7823..0000000
--- a/ubi-utils/old-tools/src/ecclayouts.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef __ECCLAYOUTS_H__
-#define __ECCLAYOUTS_H__
-/*
- * Copyright (c) International Business Machines Corp., 2007
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <stdint.h>
-#include <mtd/mtd-abi.h>
-
-/* Define default oob placement schemes for large and small page devices */
-static struct nand_ecclayout mtd_nand_oob_16 = {
- .eccbytes = 6,
- .eccpos = { 0, 1, 2, 3, 6, 7 },
- .oobfree = {{ .offset = 8, .length = 8 }}
-};
-
-static struct nand_ecclayout mtd_nand_oob_64 = {
- .eccbytes = 24,
- .eccpos = { 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63 },
- .oobfree = {{ .offset = 2, .length = 38 }}
-};
-
-/* Define IBM oob placement schemes */
-static struct nand_ecclayout ibm_nand_oob_16 = {
- .eccbytes = 6,
- .eccpos = { 9, 10, 11, 13, 14, 15 },
- .oobfree = {{ .offset = 8, .length = 8 }}
-};
-
-static struct nand_ecclayout ibm_nand_oob_64 = {
- .eccbytes = 24,
- .eccpos = { 33, 34, 35, 37, 38, 39, 41, 42,
- 43, 45, 46, 47, 49, 50, 51, 53,
- 54, 55, 57, 58, 59, 61, 62, 63 },
- .oobfree = {{ .offset = 2, .length = 30 }}
-};
-
-struct oob_placement {
- const char *name;
- struct nand_ecclayout *nand_oob[2];
-};
-
-static struct oob_placement oob_placement[] = {
- { .name = "IBM",
- .nand_oob = { &ibm_nand_oob_16, &ibm_nand_oob_64 }},
- { .name = "MTD",
- .nand_oob = { &mtd_nand_oob_16, &mtd_nand_oob_64 }},
-};
-
-#endif
diff --git a/ubi-utils/old-tools/src/libubigen.c b/ubi-utils/old-tools/src/libubigen.c
deleted file mode 100644
index d2cd087..0000000
--- a/ubi-utils/old-tools/src/libubigen.c
+++ /dev/null
@@ -1,486 +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: 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-header.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 peb_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 peb_size)
-{
- return (byte % peb_size) == 0
- ? (byte / peb_size)
- : (byte / peb_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->peb_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->peb_size, u->fp_out);
- if (written != u->peb_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, "peb_size : 0x%08x\n", u->peb_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 peb_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->peb_size = peb_size ? peb_size : DEFAULT_BLOCKSIZE;
- res->data_pad = (res->peb_size - data_offset) % alignment;
- res->leb_size = res->peb_size - data_offset - res->data_pad;
- res->leb_total = byte_to_blk(data_size, res->leb_size);
- res->alignment = alignment;
-
- if ((res->peb_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->peb_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;
-}
diff --git a/ubi-utils/old-tools/src/ubiupdate.c b/ubi-utils/old-tools/src/ubiupdate.c
deleted file mode 100644
index 75222d4..0000000
--- a/ubi-utils/old-tools/src/ubiupdate.c
+++ /dev/null
@@ -1,318 +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.
- */
-
-/*
- * An utility to update UBI volumes.
- *
- * Authors: Frank Haverkamp
- * Joshua W. Boyer
- * Artem Bityutskiy
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#include <libubi.h>
-#include "common.h"
-
-#define PROGRAM_VERSION "1.3"
-#define PROGRAM_NAME "ubiupdate"
-
-struct args {
- int truncate;
- const char *node;
- const char *img;
-};
-
-static struct args myargs = {
- .truncate = 0,
- .node = NULL,
- .img = NULL,
-};
-
-static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
- " - a tool to write data to UBI volumes.";
-
-static const char *optionsstr =
-"-n, --vol_id=<volume id> ID of UBI volume to update\n"
-"-t, --truncate truncate volume (wipe it out)\n"
-"-h, --help print help message\n"
-"-V, --version print program version";
-
-static const char *usage =
-"Usage: " PROGRAM_NAME " <UBI volume node file name> [-t] [-h] [-V] [--truncate] [--help]\n"
-"\t\t[--version] <image file>\n\n"
-"Example 1: " PROGRAM_NAME " /dev/ubi0_1 fs.img - write file \"fs.img\" to UBI volume /dev/ubi0_1\n"
-"Example 2: " PROGRAM_NAME " /dev/ubi0_1 -t - wipe out UBI volume /dev/ubi0_1";
-
-struct option long_options[] = {
- { .name = "truncate", .has_arg = 0, .flag = NULL, .val = 't' },
- { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
- { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
- { NULL, 0, NULL, 0}
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
- while (1) {
- int key;
-
- key = getopt_long(argc, argv, "n:thV", long_options, NULL);
- if (key == -1)
- break;
-
- switch (key) {
- case 't':
- myargs.truncate = 1;
- break;
-
- case 'h':
- fprintf(stderr, "%s\n\n", doc);
- fprintf(stderr, "%s\n\n", usage);
- fprintf(stderr, "%s\n", optionsstr);
- exit(0);
-
- case 'V':
- fprintf(stderr, "%s\n", PROGRAM_VERSION);
- exit(0);
-
- case ':':
- errmsg("parameter is missing");
- return -1;
-
- default:
- fprintf(stderr, "Use -h for help\n");
- exit(-1);
- }
- }
-
- if (optind == argc) {
- errmsg("UBI device name was not specified (use -h for help)");
- return -1;
- } else if (optind != argc - 2) {
- errmsg("specify UBI device name and image file name as first 2 "
- "parameters (use -h for help)");
- return -1;
- }
-
- myargs.node = argv[optind];
- myargs.img = argv[optind + 1];
-
- return 0;
-}
-
-static int truncate_volume(libubi_t libubi)
-{
- int err, fd;
-
- fd = open(myargs.node, O_RDWR);
- if (fd == -1) {
- errmsg("cannot open \"%s\"", myargs.node);
- perror("open");
- return -1;
- }
-
- err = ubi_update_start(libubi, fd, 0);
- if (err) {
- errmsg("cannot truncate volume \"%s\"", myargs.node);
- perror("ubi_update_start");
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
-
-static int ubi_write(int fd, const void *buf, int len)
-{
- int ret;
-
- while (len) {
- ret = write(fd, buf, len);
- if (ret < 0) {
- if (errno == EINTR) {
- warnmsg("do not interrupt me!");
- continue;
- }
- errmsg("cannot write %d bytes to volume \"%s\"",
- len, myargs.node);
- perror("write");
- return -1;
- }
-
- if (ret == 0) {
- errmsg("cannot write %d bytes to volume \"%s\"",
- len, myargs.node);
- return -1;
- }
-
- len -= ret;
- buf += ret;
- }
-
- return 0;
-}
-
-static int update_volume(libubi_t libubi, struct ubi_vol_info *vol_info)
-{
- int err, fd, ifd;
- long long bytes;
- struct stat st;
- char *buf;
-
- buf = malloc(vol_info->leb_size);
- if (!buf) {
- errmsg("cannot allocate %d bytes of memory", vol_info->leb_size);
- return -1;
- }
-
- err = stat(myargs.img, &st);
- if (err < 0) {
- errmsg("stat failed on \"%s\"", myargs.node);
- goto out_free;
- }
-
- bytes = st.st_size;
- if (bytes > vol_info->rsvd_bytes) {
- errmsg("\"%s\" (size %lld) will not fit volume \"%s\" (size %lld)",
- myargs.img, bytes, myargs.node, vol_info->rsvd_bytes);
- goto out_free;
- }
-
- fd = open(myargs.node, O_RDWR);
- if (fd == -1) {
- errmsg("cannot open UBI volume \"%s\"", myargs.node);
- perror("open");
- goto out_free;
- }
-
- ifd = open(myargs.img, O_RDONLY);
- if (ifd == -1) {
- errmsg("cannot open \"%s\"", myargs.img);
- perror("open");
- goto out_close1;
- }
-
- err = ubi_update_start(libubi, fd, bytes);
- if (err) {
- errmsg("cannot start volume \"%s\" update", myargs.node);
- perror("ubi_update_start");
- goto out_close;
- }
-
- while (bytes) {
- int tocopy = vol_info->leb_size;
-
- if (tocopy > bytes)
- tocopy = bytes;
-
- err = read(ifd, buf, tocopy);
- if (err != tocopy) {
- if (errno == EINTR) {
- warnmsg("do not interrupt me!");
- continue;
- } else {
- errmsg("cannot read %d bytes from \"%s\"",
- tocopy, myargs.img);
- perror("read");
- goto out_close;
- }
- }
-
- err = ubi_write(fd, buf, tocopy);
- if (err)
- goto out_close;
- bytes -= tocopy;
- }
-
- close(ifd);
- close(fd);
- free(buf);
- return 0;
-
-out_close:
- close(ifd);
-out_close1:
- close(fd);
-out_free:
- free(buf);
- return -1;
-}
-
-int main(int argc, char * const argv[])
-{
- int err;
- libubi_t libubi;
- struct ubi_vol_info vol_info;
-
- err = parse_opt(argc, argv);
- if (err)
- return -1;
-
- if (!myargs.img && !myargs.truncate) {
- errmsg("incorrect arguments, use -h for help");
- return -1;
- }
-
- libubi = libubi_open();
- if (libubi == NULL) {
- perror("Cannot open libubi");
- goto out_libubi;
- }
-
- err = ubi_node_type(libubi, myargs.node);
- if (err == 1) {
- errmsg("\"%s\" is an UBI device node, not an UBI volume node",
- myargs.node);
- goto out_libubi;
- } else if (err < 0) {
- errmsg("\"%s\" is not an UBI volume node", myargs.node);
- goto out_libubi;
- }
-
- err = ubi_get_vol_info(libubi, myargs.node, &vol_info);
- if (err) {
- errmsg("cannot get information about UBI volume \"%s\"",
- myargs.node);
- perror("ubi_get_dev_info");
- goto out_libubi;
- }
-
- if (myargs.truncate)
- err = truncate_volume(libubi);
- else
- err = update_volume(libubi, &vol_info);
- if (err)
- goto out_libubi;
-
- libubi_close(libubi);
- return 0;
-
-out_libubi:
- libubi_close(libubi);
- return -1;
-}
diff --git a/ubi-utils/old-tools/scripts/f128_nand_sample.cfg b/ubi-utils/perl/f128_nand_sample.cfg
index bb62600..e468d9d 100644
--- a/ubi-utils/old-tools/scripts/f128_nand_sample.cfg
+++ b/ubi-utils/perl/f128_nand_sample.cfg
@@ -3,10 +3,10 @@ complete=ipl,spl,bootenv,kernel,rootfs
bootcode=spl,bootenv
# Build sections
-[ipl]
+[ipl]
image=ipl.bin
raw_starts=0x00000000
-raw_total_size=128kiB
+raw_total_size=128kiB
[spl]
image=u-boot.bin
@@ -33,6 +33,6 @@ ubi_names=kernel_0,kernel_1
image=rootfs.bin
ubi_ids=8,9
ubi_alignment=2kiB
-ubi_size=16MiB
+ubi_size=16MiB
ubi_type=dynamic
ubi_names=rootfs_0,rootfs_1
diff --git a/ubi-utils/old-tools/scripts/f64_nor_sample.cfg b/ubi-utils/perl/f64_nor_sample.cfg
index 889d4c2..fd44e27 100644
--- a/ubi-utils/old-tools/scripts/f64_nor_sample.cfg
+++ b/ubi-utils/perl/f64_nor_sample.cfg
@@ -4,10 +4,10 @@ bootcode=spl,bootenv
rootfs=rootfs
# Build sections
-[ipl]
+[ipl]
image=ipl.bin
raw_starts=0x02FE0000, 0x03FE0000
-raw_total_size=128kiB
+raw_total_size=128kiB
[spl]
image=u-boot.bin
@@ -34,6 +34,6 @@ ubi_names=kernel_0,kernel_1
image=rootfs.bin
ubi_ids=8,9
ubi_alignment=2kiB
-ubi_size=16128kiB
+ubi_size=16128kiB
ubi_type=dynamic
ubi_names=rootfs_0,rootfs_1
diff --git a/ubi-utils/old-tools/scripts/mkpfi b/ubi-utils/perl/mkpfi
index 2cce587..2cce587 100644..100755
--- a/ubi-utils/old-tools/scripts/mkpfi
+++ b/ubi-utils/perl/mkpfi
diff --git a/ubi-utils/old-tools/scripts/ubicrc32.pl b/ubi-utils/perl/ubicrc32.pl
index 92711cb..add5f9d 100644..100755
--- a/ubi-utils/old-tools/scripts/ubicrc32.pl
+++ b/ubi-utils/perl/ubicrc32.pl
@@ -62,7 +62,7 @@ sub crc32_on_file
my $file;
open $file, "<", $path
or die "Error opening '$path'.\n";
-
+
&crc32_on_file($file)
or die "Error reading from '$path'.\n";
close $file;
diff --git a/ubi-utils/old-tools/scripts/Makefile b/ubi-utils/scripts/Makefile
index b8e3c96..ebd9bc6 100644
--- a/ubi-utils/old-tools/scripts/Makefile
+++ b/ubi-utils/scripts/Makefile
@@ -39,23 +39,7 @@ compl_img ?= $(compl).img
compl_nand2048_mif=$(compl).$(flashtype)$(pagesize).mif
compl_nand2048_img=$(compl).$(flashtype)$(pagesize).img
-all: help
-
-help:
- @echo "Testcases for the UBI/NAND manufacturing tool-chain"
- @echo "---------------------------------------------------------------"
- @echo " make mif_test - Generate a mif (manufacturing "
- @echo " image file)."
- @echo " make bin2nand2bin_test - Create binary with ECC information"
- @echo " in the OOB area. Test ECC generation"
- @echo " and correction."
-
-mif_test: $(compl_pfi) $(compl_nand2048_mif)
-
-bin2nand2bin_test:
- chmod a+x ./bin2nand2bin_test.sh
- chmod a+x ./inject_biterror.pl
- ./bin2nand2bin_test.sh
+all: $(compl_pfi) $(compl_nand2048_mif)
$(compl_pfi): $(vmlinux_bin) $(rootfs_bin) $(spl_bin)
$(mkpfi) -c $(mkpfi_cfg)
@@ -85,7 +69,7 @@ $(vmlinux_bin) $(rootfs_bin) $(spl_bin):
$(dd) if=/dev/urandom of=$@ bs=1M count=1
clean:
- $(RM) *.pfi *~ testblock* oob.bin
+ $(RM) *.pfi *~
distclean: clean
$(RM) *.bin *.mif *.oob *.img
diff --git a/ubi-utils/old-tools/scripts/README b/ubi-utils/scripts/README
index 01c7453..899b4a1 100644
--- a/ubi-utils/old-tools/scripts/README
+++ b/ubi-utils/scripts/README
@@ -9,6 +9,3 @@ We should try not forget to run these tests before we release
a new version of UBI.
Frank
-
-Please guys, clean up this and move the tests to mtd-utils/tests/
-Artem.
diff --git a/ubi-utils/scripts/TODO b/ubi-utils/scripts/TODO
new file mode 100644
index 0000000..f093e77
--- /dev/null
+++ b/ubi-utils/scripts/TODO
@@ -0,0 +1,5 @@
+TODO
+====
+
+ * Range checking is broken, reserving 2M and offering 3M binary data
+ ... works!? No!
diff --git a/ubi-utils/old-tools/scripts/bin2nand2bin_test.sh b/ubi-utils/scripts/bin2nand2bin_test.sh
index 51f048c..a17c91b 100644
--- a/ubi-utils/old-tools/scripts/bin2nand2bin_test.sh
+++ b/ubi-utils/scripts/bin2nand2bin_test.sh
@@ -1,8 +1,5 @@
#!/bin/sh
#
-# Version: 1.1
-# Author: Frank Haverkamp <haver@vnet.ibm.com>
-#
# Testcase for nand2bin and bin2nand. Generate testdata and inject
# biterrors. Convert data back and compare with original data.
#
@@ -10,45 +7,15 @@
# bin -> bin2nand -> mif -> nand2bin -> img
#
-inject_biterror=./inject_biterror.pl
+inject_biterror=./scripts/inject_biterror.pl
+
pagesize=2048
oobsize=64
# Create test data
dd if=/dev/urandom of=testblock.bin bs=131072 count=1
-for layout in IBM MTD ; do
- echo "*** Simple test with $layout layout ..."
-
- echo -n "Convert bin to mif ... "
- bin2nand -l$layout --pagesize=${pagesize} -o testblock.mif testblock.bin
- if [ $? -ne "0" ]; then
- echo "failed!"
- exit 1
- else
- echo "ok"
- fi
-
- echo -n "Convert mif to bin ... "
- nand2bin -l$layout --pagesize=${pagesize} -o testblock.img testblock.mif
- if [ $? -ne "0" ]; then
- echo "failed!"
- exit 1
- else
- echo "ok"
- fi
-
- echo -n "Comparing data ... "
- diff testblock.bin testblock.img
- if [ $? -ne "0" ]; then
- echo "failed!"
- exit 1
- else
- echo "ok"
- fi
-done
-
-echo "*** Test conversion without bitflips ..."
+echo "Test conversion without bitflips ..."
echo -n "Convert bin to mif ... "
bin2nand --pagesize=${pagesize} -o testblock.mif testblock.bin
@@ -77,7 +44,7 @@ else
echo "ok"
fi
-echo "*** Test conversion with uncorrectable ECC erors ..."
+echo "Test conversion with uncorrectable ECC erors ..."
echo -n "Inject biterror at offset $ioffs ... "
${inject_biterror} --offset=0 --bitmask=0x81 \
--input=testblock.mif \
@@ -109,7 +76,7 @@ else
exit 1
fi
-echo "*** Test bitflips in data ... "
+echo "Test bitflips in data ... "
for offs in `seq 0 255` ; do
cp testblock.mif testblock_bitflip.mif
@@ -175,7 +142,7 @@ for offs in `seq 0 255` ; do
fi
done
-echo "*** Test bitflips in OOB data ... "
+echo "Test bitflips in OOB data ... "
for offs in `seq 0 $oobsize` ; do
let ioffs=$pagesize+$offs
@@ -214,3 +181,4 @@ for offs in `seq 0 $oobsize` ; do
echo "ok"
fi
done
+
diff --git a/ubi-utils/old-tools/scripts/inject_biterror.pl b/ubi-utils/scripts/inject_biterror.pl
index b4a862a..b4a862a 100644
--- a/ubi-utils/old-tools/scripts/inject_biterror.pl
+++ b/ubi-utils/scripts/inject_biterror.pl
diff --git a/ubi-utils/old-tools/scripts/jffs2_test.sh b/ubi-utils/scripts/jffs2_test.sh
index 0cc9f0c..0cc9f0c 100755
--- a/ubi-utils/old-tools/scripts/jffs2_test.sh
+++ b/ubi-utils/scripts/jffs2_test.sh
diff --git a/ubi-utils/old-tools/scripts/mkdevs.pl b/ubi-utils/scripts/mkdevs.pl
index f0fd464..f0fd464 100755
--- a/ubi-utils/old-tools/scripts/mkdevs.pl
+++ b/ubi-utils/scripts/mkdevs.pl
diff --git a/ubi-utils/old-tools/scripts/pdd.txt b/ubi-utils/scripts/pdd.txt
index a3ad915..a3ad915 100644
--- a/ubi-utils/old-tools/scripts/pdd.txt
+++ b/ubi-utils/scripts/pdd.txt
diff --git a/ubi-utils/old-tools/scripts/run_all.sh b/ubi-utils/scripts/run_all.sh
index 040bcbd..040bcbd 100755
--- a/ubi-utils/old-tools/scripts/run_all.sh
+++ b/ubi-utils/scripts/run_all.sh
diff --git a/ubi-utils/old-tools/scripts/test.cfg b/ubi-utils/scripts/test.cfg
index 0b5ec48..0b5ec48 100644
--- a/ubi-utils/old-tools/scripts/test.cfg
+++ b/ubi-utils/scripts/test.cfg
diff --git a/ubi-utils/scripts/ubi_jffs2_test.sh b/ubi-utils/scripts/ubi_jffs2_test.sh
new file mode 100755
index 0000000..883903d
--- /dev/null
+++ b/ubi-utils/scripts/ubi_jffs2_test.sh
@@ -0,0 +1,411 @@
+#!/bin/sh
+#
+# UBI Volume creation/deletion/write/read and JFFS2 on top of UBI
+# testcases.
+#
+# Written in shell language to reduce dependencies to more sophisticated
+# interpreters, which may not be available on some stupid platforms.
+#
+# Author: Frank Haverkamp <haver@vnet.ibm.com>
+#
+# 1.0 Initial version
+# 1.1 Added fixup for delayed device node creation by udev
+# This points to a problem in the tools, mabe in the desing
+# Tue Oct 31 14:14:54 CET 2006
+#
+
+VERSION="1.1"
+
+export PATH=$PATH:/bin:~/bin:/usr/local/bin:/home/dedekind/work/prj/ubi/tools/flashutils/bin/
+
+ITERATIONS=250
+ALIGNMENT=2048
+
+UBIMKVOL="ubimkvol -a $ALIGNMENT"
+UBIRMVOL=ubirmvol
+UBIUPDATEVOL=ubiupdatevol
+
+SIZE_512K=524288
+SIZE_1M=1310720
+
+MINVOL=10
+MAXVOL=12
+
+TLOG=/dev/null
+
+#
+# To have a standardized output I define the following function to be
+# used when a test was ok or when it failed.
+#
+failed ()
+{
+ echo "FAILED"
+}
+
+passed ()
+{
+ echo "PASSED"
+}
+
+#
+# Print sucess message. Consider to exit with zero as return code.
+#
+exit_success ()
+{
+ echo "SUCCESS"
+ exit 0
+}
+
+#
+# Print failure message. Consider to exit with non zero return code.
+#
+exit_failure ()
+{
+ echo "FAILED"
+ exit 1
+}
+
+###############################################################################
+#
+# START
+#
+###############################################################################
+
+fix_sysfs_issue ()
+{
+ echo "*** Fixing the sysfs issue with the /dev nodes ... "
+
+ minor=0
+ major=`grep ubi0 /proc/devices | sed -e 's/\(.*\) ubi0/\1/'`
+
+ rm -rf /dev/ubi0
+ mknod /dev/ubi0 c $major 0
+
+ for minor in `seq $MINVOL $MAXVOL`; do
+ echo " -> mknod /dev/ubi0_$minor c $major $(($minor + 1))"
+ rm -rf /dev/ubi0_$minor
+ mknod /dev/ubi0_$minor c $major $(($minor + 1))
+ done
+ passed
+}
+
+#
+# FIXME Udev needs some time until the device nodes are created.
+# This will cause trouble if after ubimkvol an update attempt
+# is started immediately, since the device node is not yet
+# available. We should either fix the tools with inotify or
+# other ideas or figure out a different way to solve the problem
+# e.g. to use ubi0 and make the volume device nodes obsolete...
+#
+udev_wait ()
+{
+ echo -n "FIXME Waiting for udev to create/delete device node "
+ grep 2\.6\.5 /proc/version > /dev/null
+ if [ $? -eq "0" ]; then
+ for i in `seq 0 5`; do
+ sleep 1; echo -n ".";
+ done
+ echo " ok"
+ fi
+}
+
+# delete_volume - Delete a volume. If it does not exist, do not try
+# to delete it.
+# @id: volume id
+#
+delete_volume ()
+{
+ volume=$1
+
+ ### FIXME broken sysfs!!!!
+ if [ -e /sys/class/ubi/$volume -o \
+ -e /sys/class/ubi/ubi0/$volume -o \
+ -e /sys/class/ubi/ubi0_$volume ]; then
+
+ echo "*** Truncate volume if it exists ... "
+ echo " $UBIUPDATEVOL -d0 -n$volume -t"
+ $UBIUPDATEVOL -d0 -n$volume -t
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ echo -n "*** Delete volume if it exists ... "
+ $UBIRMVOL -d0 -n$volume
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+ # udev_wait
+ fi
+}
+
+# writevol_test - Tests volume creation and writing data to it.
+#
+# @volume: Volume number
+# @size: Size of random data to write
+# @type: Volume type static or dynamic
+#
+writevol_test ()
+{
+ volume=$1
+ size=$2
+ type=$3
+
+ echo "*** Write volume test with size $size"
+
+### Make sure that volume exist, delete existing volume, create new
+
+ delete_volume $volume
+
+ echo "*** Try to create volume"
+ echo " $UBIMKVOL -d0 -n$volume -t$type -NNEW$volume -s $size ... "
+ $UBIMKVOL -d0 -n$volume -t$type -N"NEW$volume" -s $size
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+ udev_wait
+
+### Try to create same volume again
+ echo -n "*** Try to create some volume again, this must fail ... "
+ $UBIMKVOL -d0 -n$volume -t$type -N"NEW$volume" -s $size
+ if [ $? -eq "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+### Now create test data, write it, read it, compare it
+ echo -n "*** Create test data ... "
+ dd if=/dev/urandom of=testdata.bin bs=$size count=1
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ echo "*** Now writing data to volume ... "
+ echo " $UBIUPDATEVOL -d0 -n$volume testdata.bin"
+ ls -l testdata.bin
+ $UBIUPDATEVOL -d0 -n$volume testdata.bin
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ echo "*** Download data with dd bs=1 ... "
+ dd if=/dev/ubi0_$volume of=readdata.bin bs=$size count=1
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ echo -n "*** Comparing data ... "
+ cmp readdata.bin testdata.bin
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ echo -n "*** Now truncate volume ... "
+ $UBIUPDATEVOL -d0 -n$volume -t
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+}
+
+jffs2_torture ()
+{
+ cat /dev/null > TLOG
+
+ echo "*** Torture test ... "
+
+ for i in `seq $iterations`; do
+ dd if=/dev/urandom of=test.bin bs=$i count=1 2>> $TLOG
+ if [ $? -ne "0" ] ; then
+ echo "Testing $i byte (dd if=/dev/urandom of=foo bs=$i count=1) ... "
+ exit_failure
+ fi
+ #passed
+
+ dd if=test.bin of=new.bin bs=$i count=1 2>> $TLOG
+ if [ $? -ne "0" ] ; then
+ echo "dd if=test.bin of=new.bin bs=$i count=1 2>> $TLOG"
+ exit_failure
+ fi
+ #passed
+
+ #echo "Comparing files ... "
+ cmp test.bin new.bin
+ dd if=test.bin of=new.bin bs=$i count=1 2>> $TLOG
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ #passed
+ #echo -n "."
+ done
+
+ echo -n "step0:ok "
+
+ for i in `seq $iterations`; do
+ dd if=/dev/urandom of=foo bs=$i count=1 2>> $TLOG
+ if [ $? -ne "0" ] ; then
+ echo "Testing $i byte (dd if=/dev/urandom of=foo bs=$i count=1) ... "
+ exit_failure
+ fi
+ #passed
+ done
+
+ echo -n "step1:ok "
+
+ for i in `seq $iterations`; do
+ dd if=/dev/zero of=foo bs=1 count=$i 2>> $TLOG
+ if [ $? -ne "0" ] ; then
+ echo "Testing $i byte (dd if=/dev/zero of=foo bs=1 count=$i) ... "
+ exit_failure
+ fi
+ #passed
+ done
+
+ echo -n "step2:ok "
+
+ for i in `seq $iterations`; do
+ dd if=/dev/zero of=foo bs=$i count=16 2>> $TLOG
+ if [ $? -ne "0" ] ; then
+ echo "Testing $i byte (dd if=/dev/zero of=foo bs=$i count=1024) ... "
+ exit_failure
+ fi
+ #passed
+ done
+
+ echo -n "step3:ok "
+
+ passed
+}
+
+# writevol_test - Tests volume creation and writing data to it.
+#
+# @volume: Volume number
+# @size: Size of random data to write
+# @type: Volume type static or dynamic
+#
+jffs2_test ()
+{
+ name=$1
+ iterations=$2
+ directory=`pwd`
+
+ ### Setup
+ ulimit -c unlimited
+
+ echo -n "*** Create directory /mnt/$name ... "
+ mkdir -p /mnt/$name
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ echo -n "*** mount -t jffs2 mtd:$name /mnt/$name ... "
+ mount -t jffs2 mtd:$name /mnt/$name
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ echo -n "*** change directory ... "
+ cd /mnt/$name
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ ls
+ echo "*** list directory ... "
+ ls -la
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ ### Torture
+ echo -n "*** touch I_WAS_HERE ... "
+ touch I_WAS_HERE
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ jffs2_torture
+
+ echo "*** list directory ... "
+ ls -la
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ ### Cleanup
+ echo -n "*** go back ... "
+ cd $directory
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ ### Still mounted, ubiupdatevol must fail!
+
+ echo -n "*** $UBIUPDATEVOL -d0 -n$volume -t must fail! ..."
+ $UBIUPDATEVOL -d0 -n$volume -t
+ if [ $? -eq "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ echo -n "*** umount /mnt/$name ... "
+ umount /mnt/$name
+ if [ $? -ne "0" ] ; then
+ exit_failure
+ fi
+ passed
+
+ return
+}
+
+echo "***********************************************************************"
+echo "* UBI JFFS2 Testing starts now ... *"
+echo "* Good luck! *"
+echo "***********************************************************************"
+echo "VERSION: $VERSION"
+
+# Set to zero if not running on example hardware
+grep ubi /proc/devices > /dev/null
+if [ $? -ne "0" ]; then
+ echo "No UBI found in /proc/devices! I am broken!"
+ exit_failure
+fi
+
+# Set to zero if not running on example hardware
+grep 1142 /proc/cpuinfo > /dev/null
+if [ $? -eq "0" ]; then
+ echo "Running on example hardware"
+ mount -o remount,rw / /
+ sleep 1
+ fix_sysfs_issue
+else
+ echo "Running on Artems hardware"
+fi
+
+for volume in `seq $MINVOL $MAXVOL`; do
+ echo -n "************ VOLUME $volume NEW$volume "
+ echo "******************************************"
+ writevol_test $volume $SIZE_1M dynamic
+ jffs2_test NEW$volume $ITERATIONS
+ delete_volume $volume
+done
+
+echo "***********************************************************************"
+echo "* Congratulations, no errors found! *"
+echo "* Have fun with your cool UBI system! *"
+echo "***********************************************************************"
+
+exit_success
diff --git a/ubi-utils/old-tools/scripts/ubi_test.sh b/ubi-utils/scripts/ubi_test.sh
index 73e4b19..73e4b19 100755
--- a/ubi-utils/old-tools/scripts/ubi_test.sh
+++ b/ubi-utils/scripts/ubi_test.sh
diff --git a/ubi-utils/old-tools/scripts/ubi_tools_test.sh b/ubi-utils/scripts/ubi_tools_test.sh
index 7f121f1..7f121f1 100755
--- a/ubi-utils/old-tools/scripts/ubi_tools_test.sh
+++ b/ubi-utils/scripts/ubi_tools_test.sh
diff --git a/ubi-utils/old-tools/scripts/unubi_test.sh b/ubi-utils/scripts/unubi_test.sh
index 40dc2e2..40dc2e2 100644
--- a/ubi-utils/old-tools/scripts/unubi_test.sh
+++ b/ubi-utils/scripts/unubi_test.sh
diff --git a/ubi-utils/old-tools/src/bin2nand.c b/ubi-utils/src/bin2nand.c
index 83f50cc..c7c7ccc 100644
--- a/ubi-utils/old-tools/src/bin2nand.c
+++ b/ubi-utils/src/bin2nand.c
@@ -28,8 +28,7 @@
* 1.3 Padds data/oob to a given size. (oloh)
* 1.4 Removed argp because we want to use uClibc.
* 1.5 Minor cleanup
- * 1.6 Written variable not initialized (-j did not work) (haver)
- * 1.7 Made NAND ECC layout configurable (haver)
+ * 1.6 written variable not initialized (-j did not work) (haver)
*/
#include <unistd.h>
@@ -47,11 +46,8 @@
#include "error.h"
#include "config.h"
#include "nandecc.h"
-#include "ecclayouts.h"
-#define PROGRAM_VERSION "1.7"
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#define PROGRAM_VERSION "1.6"
#define CHECK_ENDP(option, endp) do { \
if (*endp) { \
@@ -78,9 +74,8 @@ static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
static const char *optionsstr =
" -c, --copyright Print copyright informatoin.\n"
" -j, --padding=<num> Padding in Byte/Mi/ki. Default = no padding\n"
-" -l, --ecc-placement=<MTD,IBM> OOB placement scheme (default is IBM).\n"
" -p, --pagesize=<num> Pagesize in Byte/Mi/ki. Default = 2048\n"
-" -o, --output=<fname> Output filename. Interleaved Data/OOB if\n"
+" -o, --output=<fname> Output filename. Interleaved Data/OOB if\n"
" output-oob not specified.\n"
" -q, --output-oob=<fname> Write OOB data in separate file.\n"
" -?, --help Give this help list\n"
@@ -99,33 +94,30 @@ struct option long_options[] = {
{ .name = "pagesize", .has_arg = 1, .flag = NULL, .val = 'p' },
{ .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' },
{ .name = "output-oob", .has_arg = 1, .flag = NULL, .val = 'q' },
- { .name = "ecc-layout", .has_arg = 1, .flag = NULL, .val = 'l' },
{ .name = "help", .has_arg = 0, .flag = NULL, .val = '?' },
{ .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 },
{ .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
{ NULL, 0, NULL, 0}
};
-#define __unused __attribute__((unused))
-static const char copyright [] __unused = "Copyright IBM Corp. 2007";
+static const char copyright [] __attribute__((unused)) =
+ "Copyright IBM Corp. 2006";
-struct args {
+typedef struct myargs {
action_t action;
size_t pagesize;
- size_t oobsize;
size_t padding;
FILE* fp_in;
- const char *file_out_data; /* Either: Data and OOB interleaved
- or plain data */
- const char *file_out_oob; /* OOB Data only. */
- struct nand_ecclayout *nand_oob;
+ char *file_out_data; /* Either: Data and OOB interleaved
+ or plain data */
+ char *file_out_oob; /* OOB Data only. */
/* special stuff needed to get additional arguments */
char *arg1;
char **options; /* [STRING...] */
-};
+} myargs;
static int ustrtoull(const char *cp, char **endp, unsigned int base)
@@ -148,53 +140,49 @@ static int ustrtoull(const char *cp, char **endp, unsigned int base)
}
static int
-parse_opt(int argc, char **argv, struct args *args)
+parse_opt(int argc, char **argv, myargs *args)
{
- const char *ecc_layout = NULL;
- unsigned int i, oob_idx = 0;
char* endp;
while (1) {
int key;
- key = getopt_long(argc, argv, "cj:l:p:o:q:?V", long_options, NULL);
+ key = getopt_long(argc, argv, "cj:p:o:q:?V", long_options, NULL);
if (key == -1)
break;
switch (key) {
- case 'p': /* pagesize */
- args->pagesize = (size_t)
- ustrtoull(optarg, &endp, 0);
- CHECK_ENDP("p", endp);
- break;
- case 'j': /* padding */
- args->padding = (size_t)
- ustrtoull(optarg, &endp, 0);
- CHECK_ENDP("j", endp);
- break;
- case 'o': /* output */
- args->file_out_data = optarg;
- break;
- case 'q': /* output oob */
- args->file_out_oob = optarg;
- break;
- case 'l': /* --ecc-layout=<...> */
- ecc_layout = optarg;
- break;
- case '?': /* help */
- printf("%s%s", doc, optionsstr);
- exit(0);
- break;
- case 'V':
- printf("%s\n", PROGRAM_VERSION);
- exit(0);
- break;
- case 'c':
- printf("%s\n", copyright);
- exit(0);
- default:
- printf("%s", usage);
- exit(-1);
+ case 'p': /* pagesize */
+ args->pagesize = (size_t)
+ ustrtoull(optarg, &endp, 0);
+ CHECK_ENDP("p", endp);
+ break;
+ case 'j': /* padding */
+ args->padding = (size_t)
+ ustrtoull(optarg, &endp, 0);
+ CHECK_ENDP("j", endp);
+ break;
+ case 'o': /* output */
+ args->file_out_data = optarg;
+ break;
+ case 'q': /* output oob */
+ args->file_out_oob = optarg;
+ break;
+ case '?': /* help */
+ printf("%s", doc);
+ printf("%s", optionsstr);
+ exit(0);
+ break;
+ case 'V':
+ printf("%s\n", PROGRAM_VERSION);
+ exit(0);
+ break;
+ case 'c':
+ printf("%s\n", copyright);
+ exit(0);
+ default:
+ printf("%s", usage);
+ exit(-1);
}
}
@@ -206,55 +194,46 @@ parse_opt(int argc, char **argv, struct args *args)
}
}
- switch (args->pagesize) {
- case 512: args->oobsize = 16; oob_idx = 0; break;
- case 2048: args->oobsize = 64; oob_idx = 1; break;
- default:
- err_msg("Unsupported page size: %d\n", args->pagesize);
- return -EINVAL;
- }
-
- /* Figure out correct oob layout if it differs from default */
- if (ecc_layout) {
- for (i = 0; i < ARRAY_SIZE(oob_placement); i++)
- if (strcmp(ecc_layout, oob_placement[i].name) == 0)
- args->nand_oob =
- oob_placement[i].nand_oob[oob_idx];
- }
return 0;
}
static int
-process_page(struct args *args, uint8_t *buf, FILE *fp_data, FILE *fp_oob,
- size_t *written)
+process_page(uint8_t* buf, size_t pagesize,
+ FILE *fp_data, FILE* fp_oob, size_t* written)
{
- int eccpoi;
+ int eccpoi, oobsize;
size_t i;
uint8_t oobbuf[64];
- uint8_t ecc_code[3] = { 0, }; /* temp */
- /* Calculate ECC for each subpage of 256 bytes */
memset(oobbuf, 0xff, sizeof(oobbuf));
- for (eccpoi = 0, i = 0; i < args->pagesize; i += 256, eccpoi += 3) {
- int j;
- nand_calculate_ecc(&buf[i], ecc_code);
- for (j = 0; j < 3; j++)
- oobbuf[args->nand_oob->eccpos[eccpoi + j]] = ecc_code[j];
+
+ switch(pagesize) {
+ case 2048: oobsize = 64; eccpoi = 64 / 2; break;
+ case 512: oobsize = 16; eccpoi = 16 / 2; break;
+ default:
+ err_msg("Unsupported page size: %d\n", pagesize);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < pagesize; i += 256, eccpoi += 3) {
+ oobbuf[eccpoi++] = 0x0;
+ /* Calculate ECC */
+ nand_calculate_ecc(&buf[i], &oobbuf[eccpoi]);
}
/* write data */
- *written += fwrite(buf, 1, args->pagesize, fp_data);
+ *written += fwrite(buf, 1, pagesize, fp_data);
/* either separate oob or interleave with data */
if (fp_oob) {
- i = fwrite(oobbuf, 1, args->oobsize, fp_oob);
+ i = fwrite(oobbuf, 1, oobsize, fp_oob);
if (ferror(fp_oob)) {
err_msg("IO error\n");
return -EIO;
}
}
else {
- i = fwrite(oobbuf, 1, args->oobsize, fp_data);
+ i = fwrite(oobbuf, 1, oobsize, fp_data);
if (ferror(fp_data)) {
err_msg("IO error\n");
return -EIO;
@@ -269,14 +248,13 @@ int main (int argc, char** argv)
int rc = -1;
int res = 0;
size_t written = 0, read;
- struct args args = {
+ myargs args = {
.action = ACT_NORMAL,
.pagesize = PAGESIZE,
.padding = PADDING,
.fp_in = NULL,
.file_out_data = NULL,
.file_out_oob = NULL,
- .nand_oob = &ibm_nand_oob_64,
};
FILE* fp_out_data = stdout;
@@ -328,16 +306,16 @@ int main (int argc, char** argv)
goto err;
}
- res = process_page(&args, buf, fp_out_data, fp_out_oob,
- &written);
+ res = process_page(buf, args.pagesize, fp_out_data,
+ fp_out_oob, &written);
if (res != 0)
goto err;
}
while (written < args.padding) {
memset(buf, 0xff, args.pagesize);
- res = process_page(&args, buf, fp_out_data, fp_out_oob,
- &written);
+ res = process_page(buf, args.pagesize, fp_out_data,
+ fp_out_oob, &written);
if (res != 0)
goto err;
}
diff --git a/ubi-utils/old-tools/src/bootenv.c b/ubi-utils/src/bootenv.c
index a6dd4de..a6dd4de 100644
--- a/ubi-utils/old-tools/src/bootenv.c
+++ b/ubi-utils/src/bootenv.c
diff --git a/ubi-utils/old-tools/src/bootenv.h b/ubi-utils/src/bootenv.h
index 8fecdbf..8fecdbf 100644
--- a/ubi-utils/old-tools/src/bootenv.h
+++ b/ubi-utils/src/bootenv.h
diff --git a/ubi-utils/old-tools/src/config.h b/ubi-utils/src/config.h
index 55e60f3..55e60f3 100644
--- a/ubi-utils/old-tools/src/config.h
+++ b/ubi-utils/src/config.h
diff --git a/ubi-utils/src/crc32.c b/ubi-utils/src/crc32.c
index 6b1e50c..666e217 100644
--- a/ubi-utils/src/crc32.c
+++ b/ubi-utils/src/crc32.c
@@ -1,95 +1,83 @@
/*
- * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
- * code or tables extracted from it, as desired without restriction.
+ * Copyright (c) International Business Machines Corp., 2006
*
- * 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 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.
*
- * 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
+ * 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 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
+ * 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.
*
- * The feedback terms table consists of 256, 32-bit entries. Notes
+ * Author: Thomas Gleixner
+ */
+
+/*
+ * CRC32 functions
*
- * 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
+ * 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 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;
-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
-};
+ while(--len >= 0)
+ crc = table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ return crc;
+}
diff --git a/ubi-utils/src/crc32.h b/ubi-utils/src/crc32.h
index ee3145b..31362b0 100644
--- a/ubi-utils/src/crc32.h
+++ b/ubi-utils/src/crc32.h
@@ -1,19 +1,36 @@
-#ifndef CRC32_H
-#define CRC32_H
+#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>
-extern const uint32_t crc32_table[256];
+void init_crc32_table(uint32_t *table);
+uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, int len);
-/* 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
+#endif /* __CRC32_H__ */
diff --git a/ubi-utils/old-tools/src/eb_chain.c b/ubi-utils/src/eb_chain.c
index 4647cf4..4647cf4 100644
--- a/ubi-utils/old-tools/src/eb_chain.c
+++ b/ubi-utils/src/eb_chain.c
diff --git a/ubi-utils/old-tools/src/error.c b/ubi-utils/src/error.c
index 4aaedad..4aaedad 100644
--- a/ubi-utils/old-tools/src/error.c
+++ b/ubi-utils/src/error.c
diff --git a/ubi-utils/old-tools/src/error.h b/ubi-utils/src/error.h
index 05d8078..05d8078 100644
--- a/ubi-utils/old-tools/src/error.h
+++ b/ubi-utils/src/error.h
diff --git a/ubi-utils/old-tools/src/example_ubi.h b/ubi-utils/src/example_ubi.h
index 23c7b54..23c7b54 100644
--- a/ubi-utils/old-tools/src/example_ubi.h
+++ b/ubi-utils/src/example_ubi.h
diff --git a/ubi-utils/old-tools/src/hashmap.c b/ubi-utils/src/hashmap.c
index 3511d56..3511d56 100644
--- a/ubi-utils/old-tools/src/hashmap.c
+++ b/ubi-utils/src/hashmap.c
diff --git a/ubi-utils/old-tools/src/hashmap.h b/ubi-utils/src/hashmap.h
index 1b13e95..1b13e95 100644
--- a/ubi-utils/old-tools/src/hashmap.h
+++ b/ubi-utils/src/hashmap.h
diff --git a/ubi-utils/old-tools/src/libpfiflash.c b/ubi-utils/src/libpfiflash.c
index 7e3d3b3..7e3d3b3 100644
--- a/ubi-utils/old-tools/src/libpfiflash.c
+++ b/ubi-utils/src/libpfiflash.c
diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c
index b53f18c..a028fc6 100644
--- a/ubi-utils/src/libubi.c
+++ b/ubi-utils/src/libubi.c
@@ -27,480 +27,13 @@
#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"
-/**
- * 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 (lstat(node, &st))
- return -1;
-
- 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 stat;
- struct ubi_info info;
- int i, major, minor;
-
- if (lstat(node, &stat))
- return -1;
-
- if (!S_ISCHR(stat.st_mode)) {
- errno = EINVAL;
- return errmsg("\"%s\" is not a character device", node);
- }
-
- major = major(stat.st_rdev);
- minor = minor(stat.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;
-}
-
-static int mtd_num2ubi_dev(struct libubi *lib, int mtd_num, int *dev_num)
-{
- struct ubi_info info;
- int i, ret, mtd_num1;
-
- if (ubi_get_info((libubi_t *)lib, &info))
- return -1;
-
- for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
- ret = dev_read_int(lib->dev_mtd_num, i, &mtd_num1);
- if (ret) {
- if (errno == ENOENT)
- continue;
- return -1;
- }
-
- if (mtd_num1 == mtd_num) {
- errno = 0;
- *dev_num = i;
- return 0;
- }
- }
-
- errno = ENODEV;
- return -1;
-}
-
libubi_t libubi_open(void)
{
int fd, version;
@@ -513,130 +46,132 @@ libubi_t libubi_open(void)
/* 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;
+ goto error;
lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI);
if (!lib->sysfs_ubi)
- goto out_error;
+ goto error;
/* Make sure UBI is present */
fd = open(lib->sysfs_ubi, O_RDONLY);
- if (fd == -1) {
- 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;
- }
+ if (fd == -1)
+ goto error;
+ close(fd);
lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT);
if (!lib->ubi_dev)
- goto out_error;
+ goto error;
lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER);
if (!lib->ubi_version)
- goto out_error;
+ goto error;
lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV);
if (!lib->dev_dev)
- goto out_error;
+ goto error;
lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS);
if (!lib->dev_avail_ebs)
- goto out_error;
+ goto error;
lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS);
if (!lib->dev_total_ebs)
- goto out_error;
+ goto error;
lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT);
if (!lib->dev_bad_count)
- goto out_error;
+ goto error;
lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE);
if (!lib->dev_eb_size)
- goto out_error;
+ goto error;
lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC);
if (!lib->dev_max_ec)
- goto out_error;
+ goto error;
lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD);
if (!lib->dev_bad_rsvd)
- goto out_error;
+ goto error;
lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS);
if (!lib->dev_max_vols)
- goto out_error;
+ goto 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;
+ goto error;
lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT);
if (!lib->ubi_vol)
- goto out_error;
+ goto error;
lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE);
if (!lib->vol_type)
- goto out_error;
+ goto error;
lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV);
if (!lib->vol_dev)
- goto out_error;
+ goto error;
lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT);
if (!lib->vol_alignment)
- goto out_error;
+ goto error;
lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES);
if (!lib->vol_data_bytes)
- goto out_error;
+ goto error;
lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS);
if (!lib->vol_rsvd_ebs)
- goto out_error;
+ goto error;
lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE);
if (!lib->vol_eb_size)
- goto out_error;
+ goto error;
lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED);
if (!lib->vol_corrupted)
- goto out_error;
+ goto error;
lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME);
if (!lib->vol_name)
- goto out_error;
+ goto error;
- if (read_positive_int(lib->ubi_version, &version))
- goto out_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 out_error;
+ goto error;
}
return lib;
-out_error:
- libubi_close((libubi_t)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;
}
@@ -653,7 +188,6 @@ 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);
@@ -666,141 +200,10 @@ void libubi_close(libubi_t desc)
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 -1;
-
- ret = ioctl(fd, UBI_IOCATT, &r);
- close(fd);
- if (ret == -1)
- return -1;
-
- req->dev_num = r.ubi_num;
-
-#ifdef UDEV_SETTLE_HACK
- if (system("udevsettle") == -1)
- return -1;
- if (system("udevsettle") == -1)
- return -1;
-#endif
-
- return ret;
-}
-
-int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num)
-{
- int ret, ubi_dev;
-
- ret = mtd_num2ubi_dev(desc, mtd_num, &ubi_dev);
- if (ret == -1)
- return ret;
-
- return ubi_remove_dev(desc, node, ubi_dev);
-}
-
-int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev)
-{
- int fd, ret;
-
- desc = desc;
-
- fd = open(node, O_RDONLY);
- if (fd == -1)
- return -1;
- ret = ioctl(fd, UBI_IOCDET, &ubi_dev);
- if (ret == -1)
- goto out_close;
-
-#ifdef UDEV_SETTLE_HACK
- if (system("udevsettle") == -1)
- return -1;
-#endif
-
-out_close:
- close(fd);
- return ret;
-}
-
-int ubi_node_type(libubi_t desc, const char *node)
-{
- struct stat st;
- struct ubi_info info;
- int i, fd, major, minor;
- struct libubi *lib = (struct libubi *)desc;
- char file[strlen(lib->ubi_vol) + 100];
-
- if (lstat(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 (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) {
- /*
- * The character device node does not correspond to any
- * existing UBI device or volume, but we do not want to return
- * any error number in this case, to indicate the fact that it
- * could be a UBI device/volume, but it doesn't.
- */
- errno = 0;
- return -1;
- }
-
- 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) {
- errno = 0;
- return -1;
- }
-
- return 2;
-}
-
int ubi_get_info(libubi_t desc, struct ubi_info *info)
{
DIR *sysfs_ubi;
@@ -809,42 +212,20 @@ int ubi_get_info(libubi_t desc, struct ubi_info *info)
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 sys_errmsg("cannot open %s", lib->sysfs_ubi);
+ return -1;
info->lowest_dev_num = INT_MAX;
- while (1) {
+ while ((dirent = readdir(sysfs_ubi))) {
+ char *name = &dirent->d_name[0];
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);
+ ret = sscanf(name, UBI_DEV_NAME_PATT, &dev_num);
if (ret == 1) {
info->dev_count += 1;
if (dev_num > info->highest_dev_num)
@@ -854,23 +235,15 @@ int ubi_get_info(libubi_t desc, struct ubi_info *info)
}
}
- 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;
+ if (read_int(lib->ubi_version, &info->version))
+ goto close;
- return 0;
+ return closedir(sysfs_ubi);
-out_close:
+close:
closedir(sysfs_ubi);
return -1;
}
@@ -881,8 +254,6 @@ int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req)
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;
@@ -901,17 +272,9 @@ int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req)
return -1;
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
+ if (!ret)
+ req->vol_id = r.vol_id;
-out_close:
close(fd);
return ret;
}
@@ -926,15 +289,6 @@ int ubi_rmvol(libubi_t desc, const char *node, int vol_id)
return -1;
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;
}
@@ -965,19 +319,16 @@ int ubi_update_start(libubi_t desc, int fd, long long bytes)
return 0;
}
-int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype)
+int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info)
{
- 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;
+ int dev_num;
+ struct libubi *lib = (struct libubi *)desc;
- if (ioctl(fd, UBI_IOCEBCH, &req))
+ dev_num = find_dev_num(lib, node);
+ if (dev_num == -1)
return -1;
- return 0;
+
+ 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)
@@ -994,23 +345,11 @@ int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
return -1;
info->lowest_vol_num = INT_MAX;
-
- while (1) {
+ while ((dirent = readdir(sysfs_ubi))) {
+ char *name = &dirent->d_name[0];
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);
+ 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)
@@ -1020,27 +359,18 @@ int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
}
}
- 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);
+ closedir(sysfs_ubi);
if (info->lowest_vol_num == INT_MAX)
info->lowest_vol_num = 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))
+ 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_lebs))
+ 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->leb_size))
+ 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;
@@ -1051,25 +381,26 @@ int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
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;
+ info->avail_bytes = info->avail_ebs * info->eb_size;
+ info->total_bytes = info->total_ebs * info->eb_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 ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info)
{
- int dev_num;
+ int vol_id, dev_num;
struct libubi *lib = (struct libubi *)desc;
- if (dev_node2num(lib, node, &dev_num))
+ dev_num = find_dev_num_vol(lib, node);
+ if (dev_num == -1)
return -1;
- return ubi_get_dev_info1(desc, dev_num, info);
+ 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,
@@ -1083,21 +414,16 @@ int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
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);
+ ret = vol_read_data(lib->vol_type, dev_num, vol_id, &buf[0], 50);
if (ret < 0)
return -1;
- if (strncmp(buf, "static\n", ret) == 0)
+ if (strncmp(&buf[0], "static\n", ret) == 0)
info->type = UBI_STATIC_VOLUME;
- else if (strncmp(buf, "dynamic\n", ret) == 0)
+ else if (strncmp(&buf[0], "dynamic\n", ret) == 0)
info->type = UBI_DYNAMIC_VOLUME;
else {
- errmsg("bad value at \"%s\"", buf);
+ fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
errno = EINVAL;
return -1;
}
@@ -1110,17 +436,17 @@ int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
&info->data_bytes);
if (ret)
return -1;
- ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_lebs);
+ 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->leb_size);
+ 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->leb_size * info->rsvd_lebs;
+ 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);
@@ -1131,13 +457,459 @@ int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
return 0;
}
-int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info)
+/**
+ * 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 vol_id, dev_num;
- struct libubi *lib = (struct libubi *)desc;
+ int fd, rd;
+ char buf[50];
- if (vol_node2nums(lib, node, &dev_num, &vol_id))
+ fd = open(file, O_RDONLY);
+ if (fd == -1)
return -1;
- return ubi_get_vol_info1(desc, dev_num, vol_id, info);
+ 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 stat;
+ struct ubi_info info;
+ int i, major, minor;
+
+ if (lstat(node, &stat))
+ return -1;
+
+ if (!S_ISCHR(stat.st_mode)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ major = major(stat.st_rdev);
+ minor = minor(stat.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 stat;
+ struct ubi_info info;
+ int i, major;
+
+ if (lstat(node, &stat))
+ return -1;
+
+ if (!S_ISCHR(stat.st_mode)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ major = major(stat.st_rdev);
+
+ if (minor(stat.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 stat;
+ struct ubi_dev_info info;
+ int i, major, minor;
+
+ if (lstat(node, &stat))
+ return -1;
+
+ if (!S_ISCHR(stat.st_mode)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ major = major(stat.st_rdev);
+ minor = minor(stat.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;
}
diff --git a/ubi-utils/src/libubi_int.h b/ubi-utils/src/libubi_int.h
index dab3e62..e68b791 100644
--- a/ubi-utils/src/libubi_int.h
+++ b/ubi-utils/src/libubi_int.h
@@ -23,45 +23,20 @@
#ifndef __LIBUBI_INT_H__
#define __LIBUBI_INT_H__
-#include <string.h>
-#include <errno.h>
-
#ifdef __cplusplus
extern "C" {
#endif
-/* Error messages */
-#define errmsg(fmt, ...) ({ \
- fprintf(stderr, "libubi error: " fmt "\n", ##__VA_ARGS__); \
- -1; \
-})
-
-/* System error messages */
-#define sys_errmsg(fmt, ...) ({ \
- int _err = errno; \
- fprintf(stderr, "libubi error: " fmt "\n", ##__VA_ARGS__); \
- fprintf(stderr, "error %d (%s)\n", _err, strerror(_err)); \
- -1; \
-})
-
/*
+ * 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"
@@ -70,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"
@@ -84,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;
@@ -127,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;
@@ -140,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/src/libubigen.c b/ubi-utils/src/libubigen.c
index 8d71fde..1fce3f9 100644
--- a/ubi-utils/src/libubigen.c
+++ b/ubi-utils/src/libubigen.c
@@ -1,6 +1,5 @@
/*
* 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
@@ -15,307 +14,474 @@
* 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
+ * Author: Oliver Lohmann
+ *
+ * Add UBI headers to binary data.
*/
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
-#include <unistd.h>
+#include <errno.h>
#include <string.h>
-
#include <mtd/ubi-header.h>
-#include <libubigen.h>
+#include <mtd_swab.h>
+
+#include "config.h"
+#include "ubigen.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
- * @ec: initial erase counter
- */
-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,
- long long ec)
+
+#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)
{
- if (!vid_hdr_offs)
- 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->ec = ec;
-
- ui->vtbl_size = ui->leb_size;
- if (ui->vtbl_size > UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE)
- ui->vtbl_size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE;
- ui->max_volumes = ui->vtbl_size / UBI_VTBL_RECORD_SIZE;
+ return (byte % eb_size) == 0
+ ? (byte / eb_size)
+ : (byte / eb_size) + 1;
}
-/**
- * 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)
+static int
+validate_ubi_info(ubi_info_t u)
{
- struct ubi_vtbl_record *vtbl;
- int i;
-
- vtbl = calloc(1, ui->vtbl_size);
- if (!vtbl) {
- errmsg("cannot allocate %d bytes of memory", ui->vtbl_size);
- return NULL;
+ if ((u->v->vol_type != UBI_VID_DYNAMIC) &&
+ (u->v->vol_type != UBI_VID_STATIC)) {
+ return EUBIGEN_INVALID_TYPE;
}
- for (i = 0; i < UBI_MAX_VOLUMES; i++) {
- uint32_t crc = crc32(UBI_CRC32_INIT, &vtbl[i],
- UBI_VTBL_RECORD_SIZE_CRC);
- vtbl[i].crc = cpu_to_be32(crc);
+ if (be32_to_cpu(u->ec->vid_hdr_offset) < UBI_VID_HDR_SIZE) {
+ return EUBIGEN_INVALID_HDR_OFFSET;
}
- return vtbl;
+ return 0;
}
-/**
- * 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)
+static int
+skip_blks(ubi_info_t u, uint32_t blks)
{
- 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);
+ 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;
}
-/**
- * init_ec_hdr - initialize EC header.
- * @ui: libubigen information
- * @hdr: the EC header to initialize
- */
-static void init_ec_hdr(const struct ubigen_info *ui,
- struct ubi_ec_hdr *hdr)
+static void
+clear_buf(ubi_info_t u)
{
- uint32_t crc;
+ memset(u->buf, 0xff, u->eb_size);
+}
- memset(hdr, '\0', sizeof(struct ubi_ec_hdr));
+static void
+write_ec_hdr(ubi_info_t u)
+{
+ memcpy(u->ptr_ec_hdr, u->ec, UBI_EC_HDR_SIZE);
+}
- hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
- hdr->version = ui->ubi_ver;
- hdr->ec = cpu_to_be64(ui->ec);
- hdr->vid_hdr_offset = cpu_to_be32(ui->vid_hdr_offs);
+static int
+fill_data_buffer_from_file(ubi_info_t u, size_t* read)
+{
+ size_t to_read = 0;
- hdr->data_offset = cpu_to_be32(ui->data_offs);
+ if (u-> fp_in == NULL)
+ return -EIO;
- crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
- hdr->hdr_crc = cpu_to_be32(crc);
+ 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;
}
-/**
- * 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)
+static void
+add_static_info(ubi_info_t u, size_t data_size, ubigen_action_t action)
{
- uint32_t crc;
+ uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
+ u->ptr_data, data_size);
- 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->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);
}
+}
- crc = crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC);
- hdr->hdr_crc = cpu_to_be32(crc);
+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);
}
-/**
- * ubigen_write_volume - write UBI volume.
- * @ui: libubigen information
- * @vi: volume information
- * @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 bytes, FILE *in, FILE *out)
+static int
+write_to_output_stream(ubi_info_t u)
{
- int len = vi->usable_leb_size, rd, lnum = 0;
- char inbuf[ui->leb_size], outbuf[ui->peb_size];
+ size_t written;
- if (vi->id >= ui->max_volumes)
- return errmsg("too high volume id %d, max. volumes is %d",
- vi->id, ui->max_volumes);
+ written = fwrite(u->buf, 1, u->eb_size, u->fp_out);
+ if (written != u->eb_size) {
+ return -EIO;
+ }
+ return 0;
+}
- if (vi->alignment >= ui->leb_size)
- return errmsg("too large alignment %d, max is %d (LEB size)",
- vi->alignment, ui->leb_size);
+int
+ubigen_write_leb(ubi_info_t u, ubigen_action_t action)
+{
+ int rc = 0;
+ size_t read = 0;
- memset(outbuf, 0xFF, ui->data_offs);
- init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf);
+ clear_buf(u);
+ write_ec_hdr(u);
- while (bytes) {
- int l;
- struct ubi_vid_hdr *vid_hdr;
+ rc = fill_data_buffer_from_file(u, &read);
+ if (rc != 0)
+ return rc;
- if (bytes < len)
- len = bytes;
- bytes -= len;
+ if (u->v->vol_type == UBI_VID_STATIC) {
+ add_static_info(u, read, action);
+ }
- l = len;
- do {
- rd = fread(inbuf + len - l, 1, l, in);
- if (rd == 0) {
- if (ferror(in))
- return errmsg("cannot read %d bytes from the input file", l);
- else
- return errmsg("not enough data in the input file");
- }
+ u->v->lnum = cpu_to_be32(u->blks_written);
- l -= rd;
- } while (l);
+ if (action & MARK_AS_UPDATE) {
+ u->v->copy_flag = (u->v->copy_flag)++;
+ }
- vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
- init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len);
+ write_vid_hdr(u, action);
+ rc = write_to_output_stream(u);
+ if (rc != 0)
+ return rc;
- memcpy(outbuf + ui->data_offs, inbuf, len);
- memset(outbuf + ui->data_offs + len, 0xFF,
- ui->peb_size - ui->data_offs - len);
+ /* Update current handle */
+ u->bytes_read += read;
+ u->blks_written++;
+ return 0;
+}
- if (fwrite(outbuf, 1, ui->peb_size, out) != ui->peb_size)
- return errmsg("cannot write %d bytes from the output file", l);
+int
+ubigen_write_complete(ubi_info_t u)
+{
+ size_t i;
+ int rc = 0;
- lnum += 1;
+ for (i = 0; i < u->leb_total; i++) {
+ rc = ubigen_write_leb(u, NO_ERROR);
+ if (rc != 0)
+ return rc;
}
return 0;
}
-/**
- * ubigen_write_layout_vol - write UBI layout volume
- * @ui: libubigen information
- * @vtbl: volume table
- * @out: output file stream
- *
- * 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,
- struct ubi_vtbl_record *vtbl, FILE *out)
+int
+ubigen_write_broken_update(ubi_info_t u, uint32_t blk)
{
- int size = ui->leb_size;
- struct ubigen_vol_info vi;
- char outbuf[ui->peb_size];
- struct ubi_vid_hdr *vid_hdr;
-
- if (size > UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE)
- size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE;
-
- 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]);
- init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf);
- memcpy(outbuf + ui->data_offs, vtbl, size);
- memset(outbuf + ui->data_offs + size, 0xFF,
- ui->peb_size - ui->data_offs - size);
-
- init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0);
- size = fwrite(outbuf, 1, ui->peb_size, out);
- if (size == ui->peb_size) {
- init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0);
- size = fwrite(outbuf, 1, ui->peb_size, out);
- if (size != ui->peb_size)
- return sys_errmsg("cannot write %d bytes", ui->peb_size);
+ 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;
}
diff --git a/ubi-utils/old-tools/src/libubimirror.c b/ubi-utils/src/libubimirror.c
index d06770e..d06770e 100644
--- a/ubi-utils/old-tools/src/libubimirror.c
+++ b/ubi-utils/src/libubimirror.c
diff --git a/ubi-utils/old-tools/src/list.c b/ubi-utils/src/list.c
index 6eb716b..6eb716b 100644
--- a/ubi-utils/old-tools/src/list.c
+++ b/ubi-utils/src/list.c
diff --git a/ubi-utils/old-tools/src/list.h b/ubi-utils/src/list.h
index e8452a2..e8452a2 100644
--- a/ubi-utils/old-tools/src/list.h
+++ b/ubi-utils/src/list.h
diff --git a/ubi-utils/old-tools/src/mkbootenv.c b/ubi-utils/src/mkbootenv.c
index 952f651..952f651 100644
--- a/ubi-utils/old-tools/src/mkbootenv.c
+++ b/ubi-utils/src/mkbootenv.c
diff --git a/ubi-utils/old-tools/src/nand2bin.c b/ubi-utils/src/nand2bin.c
index 8c95b27..be62e30 100644
--- a/ubi-utils/old-tools/src/nand2bin.c
+++ b/ubi-utils/src/nand2bin.c
@@ -25,9 +25,6 @@
* 1.5 Added verbose output and option to set blocksize.
* Added split block mode for more convenient analysis.
* 1.6 Fixed ECC error detection and correction.
- * 1.7 Made NAND ECC layout configurable, the holes which were previously
- * filled with 0x00 are untouched now and will be 0xff just like MTD
- * behaves when writing the oob (haver)
*/
#include <config.h>
@@ -46,11 +43,9 @@
#include "config.h"
#include "nandecc.h"
-#include "ecclayouts.h"
-#define PROGRAM_VERSION "1.7"
+#define PROGRAM_VERSION "1.6"
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define MAXPATH 1024
#define MIN(x,y) ((x)<(y)?(x):(y))
@@ -58,13 +53,10 @@ struct args {
const char *oob_file;
const char *output_file;
size_t pagesize;
- size_t oobsize;
- int bad_marker_offs_in_oob;
size_t blocksize;
int split_blocks;
size_t in_len; /* size of input file */
int correct_ecc;
- struct nand_ecclayout *nand_oob;
/* special stuff needed to get additional arguments */
char *arg1;
@@ -76,7 +68,6 @@ static struct args myargs = {
.oob_file = "oob.bin",
.pagesize = 2048,
.blocksize = 128 * 1024,
- .nand_oob = &ibm_nand_oob_64,
.in_len = 0,
.split_blocks = 0,
.correct_ecc = 0,
@@ -88,7 +79,6 @@ static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
"nand2bin - split data and OOB.\n";
static const char *optionsstr =
-" -l, --ecc-placement=<MTD,IBM> OOB placement scheme (default is IBM).\n"
" -o, --output=<output> Data output file\n"
" -O, --oob=<oob> OOB output file\n"
" -p, --pagesize=<pagesize> NAND pagesize\n"
@@ -107,7 +97,6 @@ static const char *usage =
static int verbose = 0;
static struct option long_options[] = {
- { .name = "ecc-layout", .has_arg = 1, .flag = NULL, .val = 'l' },
{ .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' },
{ .name = "oob", .has_arg = 1, .flag = NULL, .val = 'O' },
{ .name = "pagesize", .has_arg = 1, .flag = NULL, .val = 'p' },
@@ -155,52 +144,56 @@ static uint32_t str_to_num(char *str)
*/
static int parse_opt(int argc, char **argv, struct args *args)
{
- unsigned int i, oob_idx = 0;
- const char *ecc_layout = NULL;
-
while (1) {
int key;
- key = getopt_long(argc, argv, "b:el:o:O:p:sv?", long_options, NULL);
+ key = getopt_long(argc, argv, "b:eo:O:p:sv?", long_options, NULL);
if (key == -1)
break;
switch (key) {
+ case 'p': /* --pagesize<pagesize> */
+ args->pagesize = str_to_num(optarg);
+ break;
+
case 'b': /* --blocksize<blocksize> */
args->blocksize = str_to_num(optarg);
break;
+
+ case 'v': /* --verbose */
+ verbose++;
+ break;
+
+ case 's': /* --split-blocks */
+ args->split_blocks = 1;
+ break;
+
case 'e': /* --correct-ecc */
args->correct_ecc = 1;
break;
- case 'l': /* --ecc-layout=<...> */
- ecc_layout = optarg;
- break;
+
case 'o': /* --output=<output.bin> */
args->output_file = optarg;
break;
+
case 'O': /* --oob=<oob.bin> */
args->oob_file = optarg;
break;
- case 'p': /* --pagesize<pagesize> */
- args->pagesize = str_to_num(optarg);
- break;
- case 's': /* --split-blocks */
- args->split_blocks = 1;
- break;
- case 'v': /* --verbose */
- verbose++;
- break;
- case 'V':
- printf("%s\n", PROGRAM_VERSION);
- exit(0);
- break;
+
case '?': /* help */
printf("Usage: nand2bin [OPTION...] input.mif\n");
- printf("%s%s", doc, optionsstr);
+ printf("%s", doc);
+ printf("%s", optionsstr);
printf("\nReport bugs to %s\n",
PACKAGE_BUGREPORT);
exit(0);
break;
+
+ case 'V':
+ printf("%s\n", PROGRAM_VERSION);
+ exit(0);
+ break;
+
default:
printf("%s", usage);
exit(-1);
@@ -210,44 +203,17 @@ static int parse_opt(int argc, char **argv, struct args *args)
if (optind < argc)
args->arg1 = argv[optind++];
- switch (args->pagesize) {
- case 512:
- args->oobsize = 16;
- args->bad_marker_offs_in_oob = 5;
- oob_idx = 0;
- break;
- case 2048:
- args->oobsize = 64;
- args->bad_marker_offs_in_oob = 0;
- oob_idx = 1;
- break;
- default:
- fprintf(stderr, "Unsupported page size: %d\n", args->pagesize);
- return -EINVAL;
- }
-
- /* Figure out correct oob layout if it differs from default */
- if (ecc_layout) {
- for (i = 0; i < ARRAY_SIZE(oob_placement); i++)
- if (strcmp(ecc_layout, oob_placement[i].name) == 0)
- args->nand_oob =
- oob_placement[i].nand_oob[oob_idx];
- }
return 0;
}
-/*
- * We must only compare the relevant bytes in the OOB area. All other
- * bytes can be ignored. The information we need to do this is in
- * nand_oob.
- */
-static int oob_cmp(struct nand_ecclayout *nand_oob, uint8_t *oob,
- uint8_t *calc_oob)
+static int calc_oobsize(size_t pagesize)
{
- unsigned int i;
- for (i = 0; i < nand_oob->eccbytes; i++)
- if (oob[nand_oob->eccpos[i]] != calc_oob[nand_oob->eccpos[i]])
- return 1;
+ switch (pagesize) {
+ case 512: return 16;
+ case 2048: return 64;
+ default:
+ exit(EXIT_FAILURE);
+ }
return 0;
}
@@ -262,38 +228,65 @@ static inline void hexdump(FILE *fp, const uint8_t *buf, ssize_t size)
}
}
-static int process_page(struct args *args, uint8_t *buf, uint8_t *oobbuf)
+static int process_page(uint8_t* buf, uint8_t *oobbuf, size_t pagesize)
{
- size_t i, j;
- int eccpoi;
- uint8_t ecc_code[3] = { 0, }; /* temp */
-
- /* Calculate ECC */
- memset(oobbuf, 0xff, args->oobsize);
- for (eccpoi = 0, i = 0; i < args->pagesize; i += 256, eccpoi += 3) {
- nand_calculate_ecc(&buf[i], ecc_code);
- for (j = 0; j < 3; j++)
- oobbuf[args->nand_oob->eccpos[eccpoi + j]] = ecc_code[j];
+ int eccpoi, oobsize;
+ size_t i;
+
+ switch (pagesize) {
+ case 2048: oobsize = 64; eccpoi = 64 / 2; break;
+ case 512: oobsize = 16; eccpoi = 16 / 2; break;
+ default:
+ fprintf(stderr, "Unsupported page size: %zd\n", pagesize);
+ return -EINVAL;
+ }
+ memset(oobbuf, 0xff, oobsize);
+
+ for (i = 0; i < pagesize; i += 256, eccpoi += 3) {
+ oobbuf[eccpoi++] = 0x0;
+ /* Calculate ECC */
+ nand_calculate_ecc(&buf[i], &oobbuf[eccpoi]);
}
return 0;
}
+static int bad_marker_offs_in_oob(int pagesize)
+{
+ switch (pagesize) {
+ case 2048: return 0;
+ case 512: return 5;
+ }
+ return -EINVAL;
+}
+
static int decompose_image(struct args *args, FILE *in_fp,
FILE *bin_fp, FILE *oob_fp)
{
- unsigned int i, eccpoi;
int read, rc, page = 0;
+ size_t oobsize = calc_oobsize(args->pagesize);
uint8_t *buf = malloc(args->pagesize);
- uint8_t *oob = malloc(args->oobsize);
- uint8_t *calc_oob = malloc(args->oobsize);
+ uint8_t *oob = malloc(oobsize);
+ uint8_t *calc_oob = malloc(oobsize);
uint8_t *calc_buf = malloc(args->pagesize);
uint8_t *page_buf;
int pages_per_block = args->blocksize / args->pagesize;
- int badpos = args->bad_marker_offs_in_oob;
- uint8_t ecc_code[3] = { 0, }; /* temp */
- uint8_t calc_ecc_code[3] = { 0, }; /* temp */
+ int eccpoi = 0, eccpoi_start;
+ unsigned int i;
+ int badpos = bad_marker_offs_in_oob(args->pagesize);
+
+ switch (args->pagesize) {
+ case 2048: eccpoi_start = 64 / 2; break;
+ case 512: eccpoi_start = 16 / 2; break;
+ default: exit(EXIT_FAILURE);
+ }
- if (!buf || !oob || !calc_oob || !calc_buf)
+ if (!buf)
+ exit(EXIT_FAILURE);
+ if (!oob)
+ exit(EXIT_FAILURE);
+ if (!calc_oob)
+ exit(EXIT_FAILURE);
+ if (!calc_buf)
exit(EXIT_FAILURE);
while (!feof(in_fp)) {
@@ -306,7 +299,7 @@ static int decompose_image(struct args *args, FILE *in_fp,
if (read != (ssize_t)args->pagesize)
break;
- read = fread(oob, 1, args->oobsize, in_fp);
+ read = fread(oob, 1, oobsize, in_fp);
if (ferror(in_fp)) {
fprintf(stderr, "I/O Error.");
exit(EXIT_FAILURE);
@@ -323,31 +316,37 @@ static int decompose_image(struct args *args, FILE *in_fp,
if (args->correct_ecc)
page_buf = calc_buf;
- process_page(args, buf, calc_oob);
+ process_page(buf, calc_oob, args->pagesize);
memcpy(calc_buf, buf, args->pagesize);
- if (verbose && oob_cmp(args->nand_oob, oob, calc_oob) != 0) {
+ /*
+ * Our oob format uses only the last 3 bytes out of 4.
+ * The first byte is 0x00 when the ECC is generated by
+ * our toolset and 0xff when generated by Linux. This
+ * is to be fixed when we want nand2bin work for other
+ * ECC layouts too.
+ */
+ for (i = 0, eccpoi = eccpoi_start; i < args->pagesize;
+ i += 256, eccpoi += 4)
+ oob[eccpoi] = calc_oob[eccpoi] = 0xff;
+
+ if (verbose && memcmp(oob, calc_oob, oobsize) != 0) {
printf("\nECC compare mismatch found at block %d page %d!\n",
page / pages_per_block, page % pages_per_block);
printf("Read out OOB Data:\n");
- hexdump(stdout, oob, args->oobsize);
+ hexdump(stdout, oob, oobsize);
printf("Calculated OOB Data:\n");
- hexdump(stdout, calc_oob, args->oobsize);
+ hexdump(stdout, calc_oob, oobsize);
}
/* Do correction on subpage base */
- for (i = 0, eccpoi = 0; i < args->pagesize; i += 256, eccpoi += 3) {
- int j;
-
- for (j = 0; j < 3; j++) {
- ecc_code[j] = oob[args->nand_oob->eccpos[eccpoi + j]];
- calc_ecc_code[j] =
- calc_oob[args->nand_oob->eccpos[eccpoi + j]];
- }
- rc = nand_correct_data(calc_buf + i, ecc_code,
- calc_ecc_code);
+ for (i = 0, eccpoi = eccpoi_start; i < args->pagesize;
+ i += 256, eccpoi += 4) {
+ rc = nand_correct_data(calc_buf + i, &oob[eccpoi + 1],
+ &calc_oob[eccpoi + 1]);
+
if (rc == -1)
fprintf(stdout, "Uncorrectable ECC error at "
"block %d page %d/%d\n",
@@ -366,7 +365,7 @@ static int decompose_image(struct args *args, FILE *in_fp,
fprintf(stderr, "I/O Error.");
exit(EXIT_FAILURE);
}
- rc = fwrite(oob, 1, args->oobsize, oob_fp);
+ rc = fwrite(oob, 1, oobsize, oob_fp);
if (ferror(bin_fp)) {
fprintf(stderr, "I/O Error.");
exit(EXIT_FAILURE);
@@ -384,11 +383,12 @@ static int decompose_image(struct args *args, FILE *in_fp,
static int split_blocks(struct args *args, FILE *in_fp)
{
uint8_t *buf;
+ size_t oobsize = calc_oobsize(args->pagesize);
int pages_per_block = args->blocksize / args->pagesize;
- int block_len = pages_per_block * (args->pagesize + args->oobsize);
+ int block_len = pages_per_block * (args->pagesize + oobsize);
int blocks = args->in_len / block_len;
char bname[256] = { 0, };
- int badpos = args->bad_marker_offs_in_oob;
+ int badpos = bad_marker_offs_in_oob(args->pagesize);
int bad_blocks = 0, i, bad_block = 0;
ssize_t rc;
FILE *b;
@@ -409,16 +409,16 @@ static int split_blocks(struct args *args, FILE *in_fp)
/* do block analysis */
bad_block = 0;
if ((buf[args->pagesize + badpos] != 0xff) ||
- (buf[2 * args->pagesize + args->oobsize + badpos] != 0xff)) {
+ (buf[2 * args->pagesize + oobsize + badpos] != 0xff)) {
bad_blocks++;
bad_block = 1;
}
if ((verbose && bad_block) || (verbose > 1)) {
printf("-- (block %d oob of page 0 and 1)\n", i);
- hexdump(stdout, buf + args->pagesize, args->oobsize);
+ hexdump(stdout, buf + args->pagesize, oobsize);
printf("--\n");
hexdump(stdout, buf + 2 * args->pagesize +
- args->oobsize, args->oobsize);
+ oobsize, oobsize);
}
/* write complete block out */
diff --git a/ubi-utils/old-tools/src/nandcorr.c b/ubi-utils/src/nandcorr.c
index caa07e2..caa07e2 100644
--- a/ubi-utils/old-tools/src/nandcorr.c
+++ b/ubi-utils/src/nandcorr.c
diff --git a/ubi-utils/old-tools/src/nandecc.c b/ubi-utils/src/nandecc.c
index 71660ef..71660ef 100644
--- a/ubi-utils/old-tools/src/nandecc.c
+++ b/ubi-utils/src/nandecc.c
diff --git a/ubi-utils/old-tools/src/nandecc.h b/ubi-utils/src/nandecc.h
index bcf1982..bcf1982 100644
--- a/ubi-utils/old-tools/src/nandecc.h
+++ b/ubi-utils/src/nandecc.h
diff --git a/ubi-utils/old-tools/src/pddcustomize.c b/ubi-utils/src/pddcustomize.c
index 515efd6..515efd6 100644
--- a/ubi-utils/old-tools/src/pddcustomize.c
+++ b/ubi-utils/src/pddcustomize.c
diff --git a/ubi-utils/old-tools/src/peb.c b/ubi-utils/src/peb.c
index 160a463..08b770f 100644
--- a/ubi-utils/old-tools/src/peb.c
+++ b/ubi-utils/src/peb.c
@@ -36,7 +36,7 @@ peb_cmp(peb_t eb_1, peb_t eb_2)
}
int
-peb_new(uint32_t eb_num, uint32_t peb_size, peb_t *peb)
+peb_new(uint32_t eb_num, uint32_t eb_size, peb_t *peb)
{
int rc = 0;
@@ -47,7 +47,7 @@ peb_new(uint32_t eb_num, uint32_t peb_size, peb_t *peb)
}
res->num = eb_num;
- res->size = peb_size;
+ res->size = eb_size;
res->data = (uint8_t*) malloc(res->size * sizeof(uint8_t));
if (!res->data) {
rc = -ENOMEM;
diff --git a/ubi-utils/old-tools/src/peb.h b/ubi-utils/src/peb.h
index 246bce8..246bce8 100644
--- a/ubi-utils/old-tools/src/peb.h
+++ b/ubi-utils/src/peb.h
diff --git a/ubi-utils/old-tools/src/pfi.c b/ubi-utils/src/pfi.c
index fa835e2..fa835e2 100644
--- a/ubi-utils/old-tools/src/pfi.c
+++ b/ubi-utils/src/pfi.c
diff --git a/ubi-utils/old-tools/src/pfi.h b/ubi-utils/src/pfi.h
index 8c5cc07..8c5cc07 100644
--- a/ubi-utils/old-tools/src/pfi.h
+++ b/ubi-utils/src/pfi.h
diff --git a/ubi-utils/old-tools/src/pfi2bin.c b/ubi-utils/src/pfi2bin.c
index 3300df2..a8c76a3 100644
--- a/ubi-utils/old-tools/src/pfi2bin.c
+++ b/ubi-utils/src/pfi2bin.c
@@ -37,6 +37,7 @@
#include <ubigen.h>
#include <mtd/ubi-header.h>
+#include <mtd_swab.h>
#include "config.h"
#include "list.h"
diff --git a/ubi-utils/old-tools/src/pfiflash.c b/ubi-utils/src/pfiflash.c
index 754fe33..754fe33 100644
--- a/ubi-utils/old-tools/src/pfiflash.c
+++ b/ubi-utils/src/pfiflash.c
diff --git a/ubi-utils/old-tools/src/pfiflash.h b/ubi-utils/src/pfiflash.h
index 039705d..039705d 100644
--- a/ubi-utils/old-tools/src/pfiflash.h
+++ b/ubi-utils/src/pfiflash.h
diff --git a/ubi-utils/old-tools/src/pfiflash_error.h b/ubi-utils/src/pfiflash_error.h
index 0f27f4a..0f27f4a 100644
--- a/ubi-utils/old-tools/src/pfiflash_error.h
+++ b/ubi-utils/src/pfiflash_error.h
diff --git a/ubi-utils/old-tools/src/reader.c b/ubi-utils/src/reader.c
index 0ea8c6d..0ea8c6d 100644
--- a/ubi-utils/old-tools/src/reader.c
+++ b/ubi-utils/src/reader.c
diff --git a/ubi-utils/old-tools/src/reader.h b/ubi-utils/src/reader.h
index 715e464..715e464 100644
--- a/ubi-utils/old-tools/src/reader.h
+++ b/ubi-utils/src/reader.h
diff --git a/ubi-utils/src/ubicrc32.c b/ubi-utils/src/ubicrc32.c
index 5c7a8ba..7e3f045 100644
--- a/ubi-utils/src/ubicrc32.c
+++ b/ubi-utils/src/ubicrc32.c
@@ -14,12 +14,10 @@
* 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.
- */
-
-/*
- * Calculate CRC32 with UBI start value (0xFFFFFFFF) for a given binary image.
*
* Author: Oliver Lohmann
+ *
+ * Calculate CRC32 with UBI start value for a given binary image.
*/
#include <stdio.h>
@@ -28,98 +26,116 @@
#include <getopt.h>
#include <argp.h>
#include <unistd.h>
+#include <errno.h>
#include <mtd/ubi-header.h>
+#include "config.h"
#include "crc32.h"
-#include "common.h"
#define BUFSIZE 4096
-#define PROGRAM_VERSION "1.2"
-#define PROGRAM_NAME "ubicrc32"
+const char *argp_program_version = PACKAGE_VERSION;
+const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+static char doc[] = "\nVersion: " PACKAGE_VERSION "\n"
+ "ubicrc32 - calculates the UBI CRC32 value and prints it to stdout.\n";
-static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
- " - a tool to calculate CRC32 with UBI start value (0xFFFFFFFF)";
+static const char copyright [] __attribute__((unused)) =
+ "FIXME: insert license type"; /* FIXME */
-static const char *optionsstr =
-"-h, --help print help message\n"
-"-V, --version print program version";
-static const char *usage =
-"Usage: " PROGRAM_NAME " <file to calculate CRC32 for> [-h] [--help]";
+static struct argp_option options[] = {
+ { name: "copyright", key: 'c', arg: NULL, flags: 0,
+ doc: "Print copyright information.",
+ group: 1 },
-static const struct option long_options[] = {
- { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
- { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
- { NULL, 0, NULL, 0},
+ { name: NULL, key: 0, arg: NULL, flags: 0, doc: NULL, group: 0 },
};
-static int parse_opt(int argc, char * const argv[])
+typedef struct myargs {
+ FILE* fp_in;
+
+ char *arg1;
+ char **options; /* [STRING...] */
+} myargs;
+
+static error_t
+parse_opt(int key, char *arg, struct argp_state *state)
{
- while (1) {
- int key;
-
- key = getopt_long(argc, argv, "hV", long_options, NULL);
- if (key == -1)
- break;
-
- switch (key) {
- case 'h':
- fprintf(stderr, "%s\n\n", doc);
- fprintf(stderr, "%s\n\n", usage);
- fprintf(stderr, "%s\n", optionsstr);
- exit(EXIT_SUCCESS);
-
- case 'V':
- fprintf(stderr, "%s\n", PROGRAM_VERSION);
- exit(EXIT_SUCCESS);
-
- case ':':
- return errmsg("parameter is missing");
-
- default:
- fprintf(stderr, "Use -h for help\n");
- return -1;
+ int err = 0;
+
+ myargs *args = state->input;
+
+ switch (key) {
+ case 'c':
+ fprintf(stderr, "%s\n", copyright);
+ exit(0);
+ break;
+ case ARGP_KEY_ARG:
+ args->fp_in = fopen(arg, "rb");
+ if ((args->fp_in) == NULL) {
+ fprintf(stderr,
+ "Cannot open file %s for input\n", arg);
+ exit(1);
+ }
+ args->arg1 = arg;
+ args->options = &state->argv[state->next];
+ state->next = state->argc;
+ break;
+ case ARGP_KEY_END:
+ if (err) {
+ fprintf(stderr, "\n");
+ argp_usage(state);
+ exit(1);
}
+ break;
+ default:
+ return(ARGP_ERR_UNKNOWN);
}
return 0;
}
-int main(int argc, char * const argv[])
-{
- int err = 0;
- uint32_t crc = UBI_CRC32_INIT;
- char buf[BUFSIZE];
- FILE *fp;
-
- if (argc > 1) {
- fp = fopen(argv[1], "r");
- if (!fp)
- return sys_errmsg("cannot open \"%s\"", argv[1]);
- } else
- fp = stdin;
-
- err = parse_opt(argc, argv);
- if (err)
- return err;
-
- while (!feof(fp)) {
- size_t read;
-
- read = fread(buf, 1, BUFSIZE, fp);
- if (ferror(fp)) {
- sys_errmsg("cannot read input file");
- err = -1;
- goto out_close;
+static struct argp argp = {
+ options: options,
+ parser: parse_opt,
+ args_doc: "[file]",
+ doc: doc,
+ children: NULL,
+ help_filter: NULL,
+ argp_domain: NULL,
+};
+
+int
+main(int argc, char **argv) {
+ int rc = 0;
+ uint32_t crc32_table[256];
+ uint8_t buf[BUFSIZE];
+ size_t read;
+ uint32_t crc32;
+
+ myargs args = {
+ .fp_in = stdin,
+ .arg1 = NULL,
+ .options = NULL,
+ };
+
+ argp_parse(&argp, argc, argv, ARGP_IN_ORDER, 0, &args);
+
+ init_crc32_table(crc32_table);
+ crc32 = UBI_CRC32_INIT;
+ while (!feof(args.fp_in)) {
+ read = fread(buf, 1, BUFSIZE, args.fp_in);
+ if (ferror(args.fp_in)) {
+ fprintf(stderr, "I/O Error.");
+ exit(EXIT_FAILURE);
}
- crc = crc32(crc, buf, read);
+ crc32 = clc_crc32(crc32_table, crc32, buf, read);
}
- printf("0x%08x\n", crc);
+ if (args.fp_in != stdin) {
+ fclose(args.fp_in);
+ }
-out_close:
- if (fp != stdin)
- fclose(fp);
- return err;
+ fprintf(stdout, "0x%08x\n", crc32);
+ return rc;
}
diff --git a/ubi-utils/old-tools/src/ubigen.c b/ubi-utils/src/ubigen.c
index 9fcafab..9fcafab 100644
--- a/ubi-utils/old-tools/src/ubigen.c
+++ b/ubi-utils/src/ubigen.c
diff --git a/ubi-utils/old-tools/src/ubigen.h b/ubi-utils/src/ubigen.h
index 07f845f..0f43a46 100644
--- a/ubi-utils/old-tools/src/ubigen.h
+++ b/ubi-utils/src/ubigen.h
@@ -25,7 +25,6 @@
#include <stdio.h> /* FILE */
#include <stdint.h>
#include <mtd/ubi-header.h>
-#include <mtd_swab.h>
#ifdef __cplusplus
extern "C" {
diff --git a/ubi-utils/old-tools/src/ubimirror.c b/ubi-utils/src/ubimirror.c
index 2cc4596..2cc4596 100644
--- a/ubi-utils/old-tools/src/ubimirror.c
+++ b/ubi-utils/src/ubimirror.c
diff --git a/ubi-utils/old-tools/src/ubimirror.h b/ubi-utils/src/ubimirror.h
index d7ae2ad..d7ae2ad 100644
--- a/ubi-utils/old-tools/src/ubimirror.h
+++ b/ubi-utils/src/ubimirror.h
diff --git a/ubi-utils/src/ubimkvol.c b/ubi-utils/src/ubimkvol.c
index 75c180d..bff6068 100644
--- a/ubi-utils/src/ubimkvol.c
+++ b/ubi-utils/src/ubimkvol.c
@@ -19,8 +19,16 @@
/*
* An utility to create UBI volumes.
*
- * Authors: Artem Bityutskiy <dedekind@infradead.org>
- * Frank Haverkamp <haver@vnet.ibm.com>
+ * Author: Artem B. Bityutskiy <dedekind@linutronix.de>
+ * Frank Haverkamp <haver@vnet.ibm.com>
+ *
+ * 1.0 Initial release
+ * 1.1 Does not support erase blocks anymore. This is replaced by
+ * the number of bytes.
+ * 1.2 Reworked the user-interface to use argp.
+ * 1.3 Removed argp because we want to use uClibc.
+ * 1.4 Minor cleanups
+ * 1.5 Use a different libubi
*/
#include <stdio.h>
@@ -28,257 +36,315 @@
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
+#include <config.h>
#include <libubi.h>
-#include "common.h"
-#define PROGRAM_VERSION "1.6"
-#define PROGRAM_NAME "ubimkvol"
+#define PROGRAM_VERSION "1.5"
-/* The variables below are set by command line arguments */
+/*
+ * The variables below are set by command line arguments.
+ */
struct args {
+ int devn;
int vol_id;
int vol_type;
long long bytes;
- int lebs;
int alignment;
- const char *name;
+ char *name;
int nlen;
- const char *node;
+ char node[256];
int maxavs;
+
+ /* special stuff needed to get additional arguments */
+ char *arg1;
+ char **options; /* [STRING...] */
};
-static struct args args = {
+static struct args myargs = {
.vol_type = UBI_DYNAMIC_VOLUME,
- .bytes = -1,
- .lebs = -1,
+ .devn = -1,
+ .bytes = 0,
.alignment = 1,
.vol_id = UBI_VOL_NUM_AUTO,
.name = NULL,
.nlen = 0,
- .node = NULL,
.maxavs = 0,
};
-static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
- " - a tool to create UBI volumes.";
+static int param_sanity_check(struct args *args, libubi_t libubi);
+
+static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
+ "ubinkvol - make UBI Volume.\n";
static const char *optionsstr =
-"-a, --alignment=<alignment> volume alignment (default is 1)\n"
-"-n, --vol_id=<volume ID> UBI volume ID, if not specified, the volume ID\n"
-" will be assigned automatically\n"
-"-N, --name=<name> volume name\n"
-"-s, --size=<bytes> volume size volume size in bytes, kilobytes (KiB)\n"
-" or megabytes (MiB)\n"
-"-S, --lebs=<LEBs count> alternative way to give volume size in logical\n"
-" eraseblocks\n"
-"-m, --maxavsize set volume size to maximum available size\n"
-"-t, --type=<static|dynamic> volume type (dynamic, static), default is dynamic\n"
-"-h, --help print help message\n"
-"-V, --version print program version";
+" -a, --alignment=<alignment> volume alignment (default is 1)\n"
+" -d, --devn=<devn> UBI device\n"
+" -n, --vol_id=<volume id> UBI volume id, if not specified, the volume ID\n"
+" will be assigned automatically\n"
+" -N, --name=<name> volume name\n"
+" -s, --size=<bytes> volume size volume size in bytes, kilobytes (KiB)\n"
+" or megabytes (MiB)\n"
+" -m, --maxavsize set volume size to maximum available size\n"
+" -t, --type=<static|dynamic> volume type (dynamic, static), default is\n"
+" dynamic\n"
+" -?, --help Give this help list\n"
+" --usage Give a short usage message\n"
+" -V, --version Print program version\n";
static const char *usage =
-"Usage: " PROGRAM_NAME " <UBI device node file name> [-h] [-a <alignment>] [-n <volume ID>] [-N <name>]\n"
-"\t\t\t[-s <bytes>] [-S <LEBs>] [-t <static|dynamic>] [-V] [-m]\n"
-"\t\t\t[--alignment=<alignment>][--vol_id=<volume ID>] [--name=<name>]\n"
-"\t\t\t[--size=<bytes>] [--lebs=<LEBs>] [--type=<static|dynamic>] [--help]\n"
-"\t\t\t[--version] [--maxavsize]\n\n"
-"Example: " PROGRAM_NAME "/dev/ubi0 -s 20MiB -N config_data - create a 20 Megabytes volume\n"
-" named \"config_data\" on UBI device /dev/ubi0.";
-
-static const struct option long_options[] = {
+"Usage: ubimkvol [-?V] [-a <alignment>] [-d <devn>] [-n <volume id>]\n"
+" [-N <name>] [-s <bytes>] [-t <static|dynamic>] [-m]\n"
+" [--alignment=<alignment>] [--devn=<devn>] [--vol_id=<volume id>]\n"
+" [--name=<name>] [--size=<bytes>] [--type=<static|dynamic>] [--help]\n"
+" [--usage] [--version] [--maxavsize]\n";
+
+struct option long_options[] = {
{ .name = "alignment", .has_arg = 1, .flag = NULL, .val = 'a' },
- { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' },
- { .name = "name", .has_arg = 1, .flag = NULL, .val = 'N' },
- { .name = "size", .has_arg = 1, .flag = NULL, .val = 's' },
- { .name = "lebs", .has_arg = 1, .flag = NULL, .val = 'S' },
- { .name = "type", .has_arg = 1, .flag = NULL, .val = 't' },
- { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
- { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+ { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' },
+ { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' },
+ { .name = "name", .has_arg = 1, .flag = NULL, .val = 'N' },
+ { .name = "size", .has_arg = 1, .flag = NULL, .val = 's' },
+ { .name = "type", .has_arg = 1, .flag = NULL, .val = 't' },
+ { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' },
+ { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 },
+ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
{ .name = "maxavsize", .has_arg = 0, .flag = NULL, .val = 'm' },
- { NULL, 0, NULL, 0},
+ { NULL, 0, NULL, 0}
};
-static int param_sanity_check(void)
+/*
+ * @brief Parse the arguments passed into the test case.
+ *
+ * @param argc The number of arguments
+ * @param argv The list of arguments
+ * @param args Pointer to argument structure
+ *
+ * @return error
+ *
+ */
+static int
+parse_opt(int argc, char **argv, struct args *args)
{
- int len;
-
- if (args.bytes == -1 && !args.maxavs && args.lebs == -1)
- return errmsg("volume size was not specified (use -h for help)");
-
- if ((args.bytes != -1 && (args.maxavs || args.lebs != -1)) ||
- (args.lebs != -1 && (args.maxavs || args.bytes != -1)) ||
- (args.maxavs && (args.bytes != -1 || args.lebs != -1)))
- return errmsg("size specified with more then one option");
-
- if (args.name == NULL)
- return errmsg("volume name was not specified (use -h for help)");
-
- len = strlen(args.name);
- if (len > UBI_MAX_VOLUME_NAME)
- return errmsg("too long name (%d symbols), max is %d", len, UBI_MAX_VOLUME_NAME);
-
- return 0;
-}
+ char *endp;
-static int parse_opt(int argc, char * const argv[])
-{
while (1) {
int key;
- char *endp;
- key = getopt_long(argc, argv, "a:n:N:s:S:t:hVm", long_options, NULL);
+ key = getopt_long(argc, argv, "a:d:n:N:s:t:?Vm", long_options, NULL);
if (key == -1)
break;
switch (key) {
- case 't':
- if (!strcmp(optarg, "dynamic"))
- args.vol_type = UBI_DYNAMIC_VOLUME;
- else if (!strcmp(optarg, "static"))
- args.vol_type = UBI_STATIC_VOLUME;
- else
- return errmsg("bad volume type: \"%s\"", optarg);
- break;
-
- case 's':
- args.bytes = ubiutils_get_bytes(optarg);
- if (args.bytes <= 0)
- return errmsg("bad volume size: \"%s\"", optarg);
- break;
-
- case 'S':
- args.lebs = strtoull(optarg, &endp, 0);
- if (endp == optarg || args.lebs <= 0 || *endp != '\0')
- return errmsg("bad LEB count: \"%s\"", optarg);
- break;
-
- case 'a':
- args.alignment = strtoul(optarg, &endp, 0);
- if (*endp != '\0' || endp == optarg || args.alignment <= 0)
- return errmsg("bad volume alignment: \"%s\"", optarg);
- break;
-
- case 'n':
- args.vol_id = strtoul(optarg, &endp, 0);
- if (*endp != '\0' || endp == optarg || args.vol_id < 0)
- return errmsg("bad volume ID: " "\"%s\"", optarg);
- break;
-
- case 'N':
- args.name = optarg;
- args.nlen = strlen(args.name);
- break;
-
- case 'h':
- fprintf(stderr, "%s\n\n", doc);
- fprintf(stderr, "%s\n\n", usage);
- fprintf(stderr, "%s\n", optionsstr);
- exit(EXIT_SUCCESS);
+ case 't':
+ if (!strcmp(optarg, "dynamic"))
+ args->vol_type = UBI_DYNAMIC_VOLUME;
+ else if (!strcmp(optarg, "static"))
+ args->vol_type = UBI_STATIC_VOLUME;
+ else {
+ fprintf(stderr,
+ "Bad volume type: \"%s\"\n",
+ optarg);
+ goto out;
+ }
+ break;
+ case 's':
+ args->bytes = strtoull(optarg, &endp, 0);
+ if (endp == optarg || args->bytes < 0) {
+ fprintf(stderr,
+ "Bad volume size: \"%s\"\n",
+ optarg);
+ goto out;
+ }
+ if (endp != '\0') {
+ if (strcmp(endp, "KiB") == 0)
+ args->bytes *= 1024;
+ else if (strcmp(endp, "MiB") == 0)
+ args->bytes *= 1024*1024;
+ }
+ break;
+ case 'a':
+ args->alignment = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg ||
+ args->alignment <= 0) {
+ fprintf(stderr, "Bad volume alignment: "
+ "\"%s\"\n", optarg);
+ goto out;
+ }
+ break;
+ case 'd': /* --devn=<device number> */
+ args->devn = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg ||
+ args->devn < 0) {
+ fprintf(stderr,
+ "Bad UBI device number: "
+ "\"%s\"\n", optarg);
+ goto out;
+ }
+ sprintf(args->node, "/dev/ubi%d", args->devn);
+ break;
+ case 'n': /* --volid=<volume id> */
+ args->vol_id = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' ||
+ endp == optarg ||
+ (args->vol_id < 0 &&
+ args->vol_id != UBI_DYNAMIC_VOLUME)) {
+ fprintf(stderr, "Bad volume ID: "
+ "\"%s\"\n", optarg);
+ goto out;
+ }
+ break;
+ case 'N':
+ args->name = optarg;
+ args->nlen = strlen(args->name);
+ break;
+
+ case ':':
+ fprintf(stderr, "Parameter is missing\n");
+ goto out;
+
+ case '?': /* help */
+ fprintf(stderr,
+ "Usage: ubimkvol [OPTION...]\n");
+ fprintf(stderr, "%s", doc);
+ fprintf(stderr, "%s", optionsstr);
+ fprintf(stderr, "\nReport bugs to %s\n",
+ PACKAGE_BUGREPORT);
+ exit(0);
+ break;
+
+ case 'V':
+ fprintf(stderr, "%s\n", PROGRAM_VERSION);
+ exit(0);
+ break;
+
+ case 'm':
+ args->maxavs = 1;
+ break;
+
+ default:
+ fprintf(stderr, "%s", usage);
+ exit(-1);
+ }
+ }
- case 'V':
- fprintf(stderr, "%s\n", PROGRAM_VERSION);
- exit(EXIT_SUCCESS);
+ return 0;
+ out:
+ return -1;
+}
- case 'm':
- args.maxavs = 1;
- break;
+static int param_sanity_check(struct args *args, libubi_t libubi)
+{
+ int err, len;
+ struct ubi_info ubi;
- case ':':
- return errmsg("parameter is missing");
+ if (args->bytes == 0 && !args->maxavs) {
+ fprintf(stderr, "Volume size was not specified\n");
+ goto out;
+ }
- default:
- fprintf(stderr, "Use -h for help\n");
- return -1;
- }
+ if (args->name == NULL) {
+ fprintf(stderr, "Volume name was not specified\n");
+ goto out;
}
- if (optind == argc)
- return errmsg("UBI device name was not specified (use -h for help)");
- else if (optind != argc - 1)
- return errmsg("more then one UBI device specified (use -h for help)");
+ err = ubi_get_info(libubi, &ubi);
+ if (err)
+ return -1;
- args.node = argv[optind];
+ if (args->devn >= (int)ubi.dev_count) {
+ fprintf(stderr, "Device %d does not exist\n", args->devn);
+ goto out;
+ }
- if (param_sanity_check())
- return -1;
+ len = strlen(args->name);
+ if (len > UBI_MAX_VOLUME_NAME) {
+ fprintf(stderr, "Too long name (%d symbols), max is %d\n",
+ len, UBI_MAX_VOLUME_NAME);
+ goto out;
+ }
return 0;
+out:
+ errno = EINVAL;
+ return -1;
}
int main(int argc, char * const argv[])
{
int err;
libubi_t libubi;
- struct ubi_dev_info dev_info;
- struct ubi_vol_info vol_info;
struct ubi_mkvol_request req;
- err = parse_opt(argc, argv);
- if (err)
- return err;
+ err = parse_opt(argc, (char **)argv, &myargs);
+ if (err) {
+ fprintf(stderr, "Wrong options ...\n");
+ return err == 1 ? 0 : -1;
+ }
- libubi = libubi_open();
- if (!libubi)
- return sys_errmsg("cannot open libubi");
+ if (myargs.devn == -1) {
+ fprintf(stderr, "Device number was not specified\n");
+ fprintf(stderr, "Use -h option for help\n");
+ return -1;
+ }
- err = ubi_node_type(libubi, args.node);
- if (err == 2) {
- errmsg("\"%s\" is an UBI volume node, not an UBI device node",
- args.node);
- goto out_libubi;
- } else if (err < 0) {
- errmsg("\"%s\" is not an UBI device node", args.node);
- goto out_libubi;
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ perror("Cannot open libubi");
+ return -1;
}
- err = ubi_get_dev_info(libubi, args.node, &dev_info);
+ err = param_sanity_check(&myargs, libubi);
if (err) {
- sys_errmsg("cannot get information about UBI device \"%s\"",
- args.node);
+ perror("Input parameters check");
+ fprintf(stderr, "Use -h option for help\n");
goto out_libubi;
}
- if (args.maxavs) {
- args.bytes = dev_info.avail_bytes;
- printf("Set volume size to %lld\n", req.bytes);
- }
+ req.vol_id = myargs.vol_id;
+ req.alignment = myargs.alignment;
- if (args.lebs != -1) {
- args.bytes = dev_info.leb_size;
- args.bytes -= dev_info.leb_size % args.alignment;
- args.bytes *= args.lebs;
- }
+ if (myargs.maxavs) {
+ struct ubi_dev_info ubi_dev;
+
+ err = ubi_get_dev_info1(libubi, myargs.devn, &ubi_dev);
+ if (err) {
+ perror("Can't get UBI device info");
+ goto out_libubi;
+ }
+ req.bytes = ubi_dev.avail_bytes;
+ if (!req.bytes) {
+ fprintf(stderr, "There is no available free space on device!\n");
+ goto out_libubi;
+ }
+ printf("Setting the volume size to %lld\n", req.bytes);
+ } else
+ req.bytes = myargs.bytes;
- req.vol_id = args.vol_id;
- req.alignment = args.alignment;
- req.bytes = args.bytes;
- req.vol_type = args.vol_type;
- req.name = args.name;
+ req.vol_type = myargs.vol_type;
+ req.name = myargs.name;
- err = ubi_mkvol(libubi, args.node, &req);
+ err = ubi_mkvol(libubi, myargs.node, &req);
if (err < 0) {
- sys_errmsg("cannot UBI create volume");
+ perror("Cannot create volume");
+ fprintf(stderr, " err=%d\n", err);
goto out_libubi;
}
- args.vol_id = req.vol_id;
-
- /* Print information about the created device */
- err = ubi_get_vol_info1(libubi, dev_info.dev_num, args.vol_id, &vol_info);
- if (err) {
- sys_errmsg("cannot get information about newly created UBI volume");
- goto out_libubi;
+ /*
+ * This is hacky, but we want to wait until udev has created device
+ * nodes. There is probably better way do do this, though.
+ */
+ if (system("udevsettle")) {
+ /* Well, this is to keep GCC silent */
}
- printf("Volume ID %d, size %d LEBs (", vol_info.vol_id, vol_info.rsvd_lebs);
- ubiutils_print_bytes(vol_info.rsvd_bytes, 0);
- printf("), LEB size ");
- ubiutils_print_bytes(vol_info.leb_size, 1);
- printf(", %s, name \"%s\", alignment %d\n",
- req.vol_type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static",
- vol_info.name, vol_info.alignment);
+ /* printf("Created volume %d, %lld bytes, type %s, name %s\n",
+ vol_id, bytes, vol_type == UBI_DYNAMIC_VOLUME ?
+ "dynamic" : "static", name); */
+ myargs.vol_id = err;
libubi_close(libubi);
return 0;
diff --git a/ubi-utils/src/ubirmvol.c b/ubi-utils/src/ubirmvol.c
index c30446a..6dd16ba 100644
--- a/ubi-utils/src/ubirmvol.c
+++ b/ubi-utils/src/ubirmvol.c
@@ -19,8 +19,13 @@
/*
* An utility to remove UBI volumes.
*
- * Authors: Artem Bityutskiy <dedekind@infradead.org>
- * Frank Haverkamp <haver@vnet.ibm.com>
+ * Author: Artem B. Bityutskiy <dedekind@linutronix.de>
+ * Frank Haverkamp <haver@vnet.ibm.com>
+ *
+ * 1.1 Reworked the userinterface to use argp.
+ * 1.2 Removed argp because we want to use uClibc.
+ * 1.3 Minor cleanups
+ * 1.4 Use a different libubi
*/
#include <stdio.h>
@@ -28,136 +33,190 @@
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
+#include <config.h>
#include <libubi.h>
-#include "common.h"
-#define PROGRAM_VERSION "1.5"
-#define PROGRAM_NAME "ubirmvol"
+#define PROGRAM_VERSION "1.4"
-/* The variables below are set by command line arguments */
+/*
+ * The below variables are set by command line options.
+ */
struct args {
+ int devn;
int vol_id;
- const char *node;
+ char node[256];
+
+ /* special stuff needed to get additional arguments */
+ char *arg1;
+ char **options; /* [STRING...] */
};
-static struct args args = {
+static struct args myargs = {
+ .devn = -1,
.vol_id = -1,
- .node = NULL,
+
+ .arg1 = NULL,
+ .options = NULL,
};
-static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
- " - a tool to remove UBI volumes.";
+static int param_sanity_check(struct args *args, libubi_t libubi);
+
+static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
+ "ubirmvol - make UBI Volume.\n";
static const char *optionsstr =
-" -n, --vol_id=<volume id> volume ID to remove\n"
-" -h, --help print help message\n"
-" -V, --version print program version";
+" -d, --devn=<devn> UBI device\n"
+" -n, --vol_id=<volume id> UBI volume id, if not specified, the volume ID\n"
+" will be assigned automatically\n"
+" -?, --help Give this help list\n"
+" --usage Give a short usage message\n"
+" -V, --version Print program version\n";
static const char *usage =
-"Usage: " PROGRAM_NAME " <UBI device node file name> [-n <volume id>] [--vol_id=<volume id>] [-h] [--help]\n\n"
-"Example: " PROGRAM_NAME "/dev/ubi0 -n 1 - remove UBI volume 1 from UBI device corresponding\n"
-" to the node file /dev/ubi0.";
-
-static const struct option long_options[] = {
- { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' },
- { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
+"Usage: ubirmvol [-?V] [-d <devn>] [-n <volume id>] [--devn=<devn>]\n"
+" [--vol_id=<volume id>] [--help] [--usage] [--version]\n";
+
+struct option long_options[] = {
+ { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' },
+ { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' },
+ { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' },
+ { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 },
{ .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
- { NULL, 0, NULL, 0},
+ { NULL, 0, NULL, 0}
};
-static int param_sanity_check(void)
+/*
+ * @brief Parse the arguments passed into the test case.
+ *
+ * @param argc The number of arguments
+ * @param argv The list of arguments
+ * @param args Pointer to argument structure
+ *
+ * @return error
+ *
+ */
+static int
+parse_opt(int argc, char **argv, struct args *args)
{
- if (args.vol_id == -1) {
- errmsg("volume ID is was not specified");
- return -1;
- }
-
- return 0;
-}
+ char *endp;
-static int parse_opt(int argc, char * const argv[])
-{
while (1) {
int key;
- char *endp;
- key = getopt_long(argc, argv, "n:hV", long_options, NULL);
+ key = getopt_long(argc, argv, "d:n:?V", long_options, NULL);
if (key == -1)
break;
switch (key) {
+ case 'd': /* --devn=<device number> */
+ args->devn = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg ||
+ args->devn < 0) {
+ fprintf(stderr,
+ "Bad UBI device number: "
+ "\"%s\"\n", optarg);
+ goto out;
+ }
+ sprintf(args->node, "/dev/ubi%d", args->devn);
+ break;
+ case 'n': /* --volid=<volume id> */
+ args->vol_id = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg ||
+ (args->vol_id < 0 &&
+ args->vol_id != UBI_DYNAMIC_VOLUME)) {
+ fprintf(stderr, "Bad volume ID: "
+ "\"%s\"\n", optarg);
+ goto out;
+ }
+ break;
+ case ':':
+ fprintf(stderr, "Parameter is missing\n");
+ goto out;
+ case '?': /* help */
+ fprintf(stderr,
+ "Usage: ubirmvol [OPTION...]\n");
+ fprintf(stderr, "%s", doc);
+ fprintf(stderr, "%s", optionsstr);
+ fprintf(stderr, "\nReport bugs to %s\n",
+ PACKAGE_BUGREPORT);
+ exit(0);
+ break;
+ case 'V':
+ fprintf(stderr, "%s\n", PROGRAM_VERSION);
+ exit(0);
+ break;
+ default:
+ fprintf(stderr, "%s", usage);
+ exit(-1);
+ }
+ }
- case 'n':
- args.vol_id = strtoul(optarg, &endp, 0);
- if (*endp != '\0' || endp == optarg || args.vol_id < 0) {
- errmsg("bad volume ID: " "\"%s\"", optarg);
- return -1;
- }
- break;
-
- case 'h':
- fprintf(stderr, "%s\n\n", doc);
- fprintf(stderr, "%s\n\n", usage);
- fprintf(stderr, "%s\n", optionsstr);
- exit(EXIT_SUCCESS);
-
- case 'V':
- fprintf(stderr, "%s\n", PROGRAM_VERSION);
- exit(EXIT_SUCCESS);
+ return 0;
+ out:
+ return -1;
+}
- case ':':
- errmsg("parameter is missing");
- return -1;
+static int param_sanity_check(struct args *args, libubi_t libubi)
+{
+ int err;
+ struct ubi_info ubi;
- default:
- fprintf(stderr, "Use -h for help\n");
- return -1;
- }
+ if (args->vol_id == -1) {
+ fprintf(stderr, "Volume ID was not specified\n");
+ goto out;
}
- if (optind == argc) {
- errmsg("UBI device name was not specified (use -h for help)");
- return -1;
- } else if (optind != argc - 1) {
- errmsg("more then one UBI device specified (use -h for help)");
+ err = ubi_get_info(libubi, &ubi);
+ if (err)
return -1;
- }
- args.node = argv[optind];
-
- if (param_sanity_check())
- return -1;
+ if (args->devn >= (int)ubi.dev_count) {
+ fprintf(stderr, "Device %d does not exist\n", args->devn);
+ goto out;
+ }
return 0;
+
+out:
+ errno = EINVAL;
+ return -1;
}
int main(int argc, char * const argv[])
{
- int err;
+ int err, old_errno;
libubi_t libubi;
- err = parse_opt(argc, argv);
+ err = parse_opt(argc, (char **)argv, &myargs);
if (err)
+ return err == 1 ? 0 : -1;
+
+ if (myargs.devn == -1) {
+ fprintf(stderr, "Device number was not specified\n");
+ fprintf(stderr, "Use -h option for help\n");
return -1;
+ }
libubi = libubi_open();
- if (libubi == NULL)
- return sys_errmsg("cannot open libubi");
+ if (libubi == NULL) {
+ perror("Cannot open libubi");
+ return -1;
+ }
- err = ubi_node_type(libubi, args.node);
- if (err == 2) {
- errmsg("\"%s\" is an UBI volume node, not an UBI device node",
- args.node);
- goto out_libubi;
- } else if (err < 0) {
- errmsg("\"%s\" is not an UBI device node", args.node);
+ err = param_sanity_check(&myargs, libubi);
+ if (err) {
+ perror("Input parameters check");
+ fprintf(stderr, "Use -h option for help\n");
goto out_libubi;
}
- err = ubi_rmvol(libubi, args.node, args.vol_id);
- if (err) {
- sys_errmsg("cannot UBI remove volume");
+ err = ubi_rmvol(libubi, myargs.node, myargs.vol_id);
+ old_errno = errno;
+ if (err < 0) {
+ perror("Cannot remove volume");
+ fprintf(stderr, " err=%d errno=%d\n", err, old_errno);
goto out_libubi;
}
diff --git a/ubi-utils/src/ubiupdatevol.c b/ubi-utils/src/ubiupdatevol.c
new file mode 100644
index 0000000..807b961
--- /dev/null
+++ b/ubi-utils/src/ubiupdatevol.c
@@ -0,0 +1,336 @@
+/*
+ * 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.
+ */
+
+/*
+ * An utility to update UBI volumes.
+ *
+ * Author: Frank Haverkamp
+ * Joshua W. Boyer
+ *
+ * 1.0 Reworked the userinterface to use argp.
+ * 1.1 Removed argp parsing because we want to use uClib.
+ * 1.2 Minor cleanups
+ * 1.3 Use a different libubi
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include <config.h>
+#include <libubi.h>
+
+#define PROGRAM_VERSION "1.3"
+
+#define MAXPATH 1024
+#define BUFSIZE 128 * 1024
+#define MIN(x,y) ((x)<(y)?(x):(y))
+
+struct args {
+ int devn;
+ int vol_id;
+ int truncate;
+ int broken_update;
+ int bufsize;
+
+ /* special stuff needed to get additional arguments */
+ char *arg1;
+ char **options; /* [STRING...] */
+};
+
+static struct args myargs = {
+ .devn = -1,
+ .vol_id = -1,
+ .truncate = 0,
+ .broken_update = 0,
+ .bufsize = BUFSIZE,
+ .arg1 = NULL,
+ .options = NULL,
+};
+
+static int verbose = 0;
+
+static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
+ "ubiupdatevol - write to UBI Volume.\n";
+
+static const char *optionsstr =
+" -B, --broken-update broken update, this is for testing\n"
+" -d, --devn=<devn> UBI device\n"
+" -n, --vol_id=<volume id> UBI volume id\n"
+" -t, --truncate truncate volume\n"
+" -?, --help Give this help list\n"
+" --usage Give a short usage message\n"
+" -V, --version Print program version\n";
+
+static const char *usage =
+"Usage: ubiupdatevol [-Bt?V] [-d <devn>] [-n <volume id>] [--broken-update]\n"
+" [--devn=<devn>] [--vol_id=<volume id>] [--truncate] [--help]\n"
+" [--usage] [--version] <image file>\n";
+
+struct option long_options[] = {
+ { .name = "broken-update", .has_arg = 0, .flag = NULL, .val = 'B' },
+ { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' },
+ { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' },
+ { .name = "truncate", .has_arg = 0, .flag = NULL, .val = 't' },
+ { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' },
+ { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 },
+ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+ { NULL, 0, NULL, 0}
+};
+
+/*
+ * @brief Parse the arguments passed into the test case.
+ */
+static int
+parse_opt(int argc, char **argv, struct args *args)
+{
+ while (1) {
+ int key;
+
+ key = getopt_long(argc, argv, "Bd:n:t?V", long_options, NULL);
+ if (key == -1)
+ break;
+
+ switch (key) {
+ case 'v': /* --verbose=<level> */
+ verbose = strtoul(optarg, (char **)NULL, 0);
+ break;
+
+ case 'n': /* --vol_id=<volume id> */
+ args->vol_id = strtol(optarg, (char **)NULL, 0);
+ break;
+
+ case 'd': /* --devn=<device number> */
+ args->devn = strtol(optarg, (char **)NULL, 0);
+ break;
+
+ case 'b': /* --bufsize=<bufsize> */
+ args->bufsize = strtol(optarg, (char **)NULL, 0);
+ if (args->bufsize <= 0)
+ args->bufsize = BUFSIZE;
+ break;
+
+ case 't': /* --truncate */
+ args->truncate = 1;
+ break;
+
+ case 'B': /* --broken-update */
+ args->broken_update = 1;
+ break;
+
+ case '?': /* help */
+ fprintf(stderr, "Usage: "
+ "ubiupdatevol [OPTION...] <image file>\n%s%s"
+ "\nReport bugs to %s\n",
+ doc, optionsstr, PACKAGE_BUGREPORT);
+ exit(EXIT_SUCCESS);
+ break;
+
+ case 'V':
+ fprintf(stderr, "%s\n", PROGRAM_VERSION);
+ exit(0);
+ break;
+
+ default:
+ fprintf(stderr, "%s", usage);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (optind < argc) {
+ /* only one additional argument required */
+ args->arg1 = argv[optind++];
+ }
+ return 0;
+}
+
+/**
+ * @bytes bytes must be always 0, if not 0 this is a testcase for a
+ * broken volume update where data is promissed to be written, but for
+ * some reason nothing is written. The volume is unusable after this.
+ */
+static int
+ubi_truncate_volume(struct args *args, int64_t bytes,libubi_t libubi)
+{
+ int rc, ofd;
+ char path[MAXPATH];
+ int old_errno;
+
+ snprintf(path, MAXPATH-1, "/dev/ubi%d_%d", args->devn, args->vol_id);
+ path[MAXPATH-1] = '\0';
+
+ ofd = open(path, O_RDWR);
+ if (ofd < 0) {
+ fprintf(stderr, "Cannot open volume %s\n", path);
+ exit(EXIT_FAILURE);
+ }
+ rc = ubi_update_start(libubi, ofd, bytes);
+ old_errno = errno;
+ if (rc < 0) {
+ perror("UBI volume update ioctl");
+ fprintf(stderr, " rc=%d errno=%d\n", rc, old_errno);
+ exit(EXIT_FAILURE);
+ }
+ close(ofd);
+ return 0;
+}
+
+static ssize_t ubi_write(int fd, const void *buf, size_t count)
+{
+ int rc;
+ int len = count;
+
+ while (len) {
+ rc = write(fd, buf, len);
+ if (rc == -1) {
+ if (errno == EINTR)
+ continue; /* try again */
+ perror("write error");
+ return rc;
+ }
+
+ len -= rc;
+ buf += rc;
+ }
+ return count;
+}
+
+static int
+ubi_update_volume(struct args *args, libubi_t libubi)
+{
+ int rc, ofd;
+ FILE *ifp = NULL;
+ struct stat st;
+ int size = 0;
+ char *fname = args->arg1;
+ char path[MAXPATH];
+ char *buf;
+ int64_t bytes = 0;
+ int old_errno;
+
+ buf = malloc(args->bufsize);
+ if (!buf) {
+ perror("Out of memory");
+ exit(EXIT_FAILURE);
+ }
+
+ if (fname == NULL) {
+ fprintf(stderr, "Please specify an existing image file.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ rc = stat(fname, &st);
+ if (rc < 0) {
+ fprintf(stderr, "Cannot stat input file %s\n", fname);
+ exit(EXIT_FAILURE);
+ }
+ bytes = size = st.st_size;
+
+ ifp = fopen(fname, "r");
+ if (!ifp)
+ exit(EXIT_FAILURE);
+
+ snprintf(path, MAXPATH-1, "/dev/ubi%d_%d", args->devn, args->vol_id);
+ path[MAXPATH-1] = '\0';
+
+ ofd = open(path, O_RDWR);
+ if (ofd < 0) {
+ fprintf(stderr, "Cannot open UBI volume %s\n", path);
+ exit(EXIT_FAILURE);
+ }
+
+ rc = ubi_update_start(libubi, ofd, bytes);
+ old_errno = errno;
+ if (rc < 0) {
+ perror("UBI volume update ioctl");
+ fprintf(stderr, " rc=%d errno=%d\n", rc, old_errno);
+ exit(EXIT_FAILURE);
+ }
+
+ while (size > 0) {
+ ssize_t tocopy = MIN(args->bufsize, size);
+
+ rc = fread(buf, tocopy, 1, ifp);
+ if (rc != 1) {
+ perror("Could not read everything.");
+ exit(EXIT_FAILURE);
+ }
+
+ rc = ubi_write(ofd, buf, tocopy);
+ old_errno = errno;
+ if (rc != tocopy) {
+ perror("Could not write to device");
+ fprintf(stderr, " rc=%d errno=%d\n", rc, old_errno);
+ exit(EXIT_FAILURE);
+ }
+ size -= tocopy;
+ }
+
+ free(buf);
+ fclose(ifp);
+ rc = close(ofd);
+ if (rc != 0) {
+ perror("UBI volume close failed");
+ exit(EXIT_FAILURE);
+ }
+ return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int rc;
+ libubi_t libubi;
+
+ parse_opt(argc, argv, &myargs);
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ perror("Cannot open libubi");
+ return -1;
+ }
+
+ if (myargs.truncate) {
+ rc = ubi_truncate_volume(&myargs, 0LL, libubi);
+ if (rc < 0)
+ goto out_libubi;
+ }
+ else if (myargs.broken_update) {
+ rc = ubi_truncate_volume(&myargs, 1LL, libubi);
+ if (rc < 0)
+ goto out_libubi;
+ } else {
+ rc = ubi_update_volume(&myargs, libubi);
+ if (rc < 0)
+ goto out_libubi;
+ }
+
+ libubi_close(libubi);
+ return 0;
+
+out_libubi:
+ libubi_close(libubi);
+ return -1;
+}
diff --git a/ubi-utils/old-tools/src/unubi.c b/ubi-utils/src/unubi.c
index 8a022a3..8a022a3 100644
--- a/ubi-utils/old-tools/src/unubi.c
+++ b/ubi-utils/src/unubi.c
diff --git a/ubi-utils/old-tools/src/unubi_analyze.c b/ubi-utils/src/unubi_analyze.c
index 182100e..182100e 100644
--- a/ubi-utils/old-tools/src/unubi_analyze.c
+++ b/ubi-utils/src/unubi_analyze.c
diff --git a/ubi-utils/old-tools/src/unubi_analyze.h b/ubi-utils/src/unubi_analyze.h
index 8588219..8588219 100644
--- a/ubi-utils/old-tools/src/unubi_analyze.h
+++ b/ubi-utils/src/unubi_analyze.h
diff --git a/ubi-utils/testcases.txt b/ubi-utils/testcases.txt
new file mode 100644
index 0000000..dcc1c35
--- /dev/null
+++ b/ubi-utils/testcases.txt
@@ -0,0 +1,9 @@
+1. Start some large update, but write there byte-by-byte
+
+2. start update for N bytes, write N-x bytes, then write y bytes, y>x.
+ You have to see that at the last write only x bytes were written,
+ but y-x bytes were not. we may vary x a bit. good number would be
+ 1, 128, 128Ki-128...
+
+3. Try to start update for x bytes, write x bytes, then try to write more.
+ Check that it is impossible to write more.
diff --git a/ubi-utils/tests/Makefile b/ubi-utils/tests/Makefile
new file mode 100644
index 0000000..1b17f81
--- /dev/null
+++ b/ubi-utils/tests/Makefile
@@ -0,0 +1,40 @@
+
+INCLUDE1=../inc
+INCLUDE2=../../include
+LIB=.
+
+CC := $(CROSS)gcc
+
+ALL_FILES=libubi.a io_update
+ALL_FILES+=io_paral io_read io_basic mkvol_basic mkvol_bad mkvol_paral rsvol
+ALL_FILES+=integ
+
+CFLAGS += -Wall -I$(INCLUDE1) -I$(INCLUDE2) -L$(LIB) -ggdb
+
+all: $(ALL_FILES)
+
+libubi.a: ../src/libubi.c ../inc/libubi.h ../src/libubi_int.h
+ $(CC) $(CFLAGS) -c ../src/libubi.c -o libubi.o
+ ar cr libubi.a libubi.o
+
+io_paral: io_paral.c common.c
+ $(CC) $(CFLAGS) $^ -lubi -lpthread -o $@
+io_update: io_update.c common.c
+ $(CC) $(CFLAGS) $^ -lubi -o $@
+io_read: io_read.c common.c
+ $(CC) $(CFLAGS) $^ -lubi -o $@
+io_basic: io_basic.c common.c
+ $(CC) $(CFLAGS) $^ -lubi -o $@
+mkvol_basic: mkvol_basic.c common.c
+ $(CC) $(CFLAGS) $^ -lubi -o $@
+mkvol_bad: mkvol_bad.c common.c
+ $(CC) $(CFLAGS) $^ -lubi -o $@
+mkvol_paral: mkvol_paral.c common.c
+ $(CC) $(CFLAGS) $^ -lubi -lpthread -o $@
+rsvol: rsvol.c common.c
+ $(CC) $(CFLAGS) $^ -lubi -o $@
+integ: integ.c
+ $(CC) $(CFLAGS) $^ -lubi -o $@
+
+clean:
+ rm -rf $(ALL_FILES) $(addsuffix .o, $(ALL_FILES))
diff --git a/ubi-utils/tests/README.udev b/ubi-utils/tests/README.udev
new file mode 100644
index 0000000..a4ff9c5
--- /dev/null
+++ b/ubi-utils/tests/README.udev
@@ -0,0 +1,19 @@
+There is a problem with udev: when a volume is created, there is a delay
+before corresponding /dev/ubiX_Y device node is created by udev, so some
+tests fail because of this. The symptom is error messages like
+"cannot open /dev/ubi0_0".
+
+One possible solution of this problem is to pre-create UBI device and volume
+nodes. there is even a script which may be used for this in ubi-utils/scripts/.
+But this is not enough because udev will still remove and re-create the nodes
+and tests will still fail. So you need to stop removing device nodes using
+the following udev rule:
+
+ KERNEL=="ubi*_*", ACTION=="remove", OPTIONS+="ignore_device"
+
+In our Ubuntu distribution we put that to new file:
+/etc/udev/rules.d/50-local.rules
+
+Another possibility is to call udevsettle utility in libubi after the volume
+has been created See src/libubi.c - the call is there but is commented out.
+This is anyway an ugly hack, but works, although makes the tests slower.
diff --git a/ubi-utils/tests/common.c b/ubi-utils/tests/common.c
new file mode 100644
index 0000000..cb63e77
--- /dev/null
+++ b/ubi-utils/tests/common.c
@@ -0,0 +1,336 @@
+/*
+ * 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
+ *
+ * The stuff which is common for many tests.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "libubi.h"
+#include "common.h"
+
+/**
+ * __initial_check - check that common prerequisites which are required to run
+ * tests.
+ *
+ * @test test name
+ * @argc count of command-line arguments
+ * @argv command-line arguments
+ *
+ * This function returns %0 if all is fine and test may be run and %-1 if not.
+ */
+int __initial_check(const char *test, int argc, char * const argv[])
+{
+ libubi_t libubi;
+ struct ubi_dev_info dev_info;
+
+ /*
+ * All tests require UBI character device name as the first parameter,
+ * check this.
+ */
+ if (argc < 2) {
+ __err_msg(test, __FUNCTION__, __LINE__,
+ "UBI character device node is not specified");
+ return -1;
+ }
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ __failed(test, __FUNCTION__, __LINE__, "libubi_open");
+ return -1;
+ }
+
+ if (ubi_get_dev_info(libubi, argv[1], &dev_info)) {
+ __failed(test, __FUNCTION__, __LINE__, "ubi_get_dev_info");
+ goto close;
+ }
+
+ if (dev_info.avail_ebs < MIN_AVAIL_EBS) {
+ __err_msg(test, __FUNCTION__, __LINE__,
+ "insufficient available eraseblocks %d on UBI "
+ "device, required %d",
+ dev_info.avail_ebs, MIN_AVAIL_EBS);
+ goto close;
+ }
+
+ if (dev_info.vol_count != 0) {
+ __err_msg(test, __FUNCTION__, __LINE__,
+ "device %s is not empty", argv[1]);
+ goto close;
+ }
+
+ libubi_close(libubi);
+ return 0;
+
+close:
+ libubi_close(libubi);
+ return -1;
+}
+
+/**
+ * __err_msg - print a message to stderr.
+ *
+ * @test test name
+ * @func function name
+ * @line line number
+ * @fmt format string
+ */
+void __err_msg(const char *test, const char *func, int line,
+ const char *fmt, ...)
+{
+ va_list args;
+
+ fprintf(stderr, "[%s] %s():%d: ", test, func, line);
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+}
+
+/**
+ * __failed - print function fail message.
+ *
+ * @test test name
+ * @func calling function name
+ * @line line number
+ * @failed failed function name
+ */
+void __failed(const char *test, const char *func, int line,
+ const char *failed)
+{
+ fprintf(stderr, "[%s] %s():%d: function %s() failed with error %d (%s)\n",
+ test, func, line, failed, errno, strerror(errno));
+}
+
+/**
+ * __check_volume - check volume information.
+ *
+ * @libubi libubi descriptor
+ * @dev_info UBI device description
+ * @test test name
+ * @func function name
+ * @line line number
+ * @vol_id ID of existing volume to check
+ * @req volume creation request to compare with
+ *
+ * This function checks if a volume created using @req request has exactly the
+ * requested characteristics. Returns 0 in case of success and %-1 in case of
+ * error.
+ */
+int __check_volume(libubi_t libubi, struct ubi_dev_info *dev_info,
+ const char *test, const char *func, int line, int vol_id,
+ const struct ubi_mkvol_request *req)
+{
+ int ret;
+ struct ubi_vol_info vol_info;
+ int eb_size;
+ long long rsvd_bytes;
+
+ ret = ubi_get_vol_info1(libubi, dev_info->dev_num, vol_id, &vol_info);
+ if (ret) {
+ __failed(test, func, line, "ubi_get_vol_info");
+ return -1;
+ }
+
+ if (req->alignment != vol_info.alignment) {
+ __err_msg(test, func, line,
+ "bad alignment: requested %d, got %d",
+ req->alignment, vol_info.alignment);
+ return -1;
+ }
+ if (req->vol_type != vol_info.type) {
+ __err_msg(test, func, line, "bad type: requested %d, got %d",
+ req->vol_type, vol_info.type);
+ return -1;
+ }
+ if (strlen(req->name) != strlen(&vol_info.name[0]) ||
+ strcmp(req->name, &vol_info.name[0]) != 0) {
+ __err_msg(test, func, line,
+ "bad name: requested \"%s\", got \"%s\"",
+ req->name, &vol_info.name[0]);
+ return -1;
+ }
+ if (vol_info.corrupted) {
+ __err_msg(test, func, line, "corrupted new volume");
+ return -1;
+ }
+
+ eb_size = dev_info->eb_size - (dev_info->eb_size % req->alignment);
+ if (eb_size != vol_info.eb_size) {
+ __err_msg(test, func, line,
+ "bad usable LEB size %d, should be %d",
+ vol_info.eb_size, eb_size);
+ return -1;
+ }
+
+ rsvd_bytes = req->bytes;
+ if (rsvd_bytes % eb_size)
+ rsvd_bytes += eb_size - (rsvd_bytes % eb_size);
+
+ if (rsvd_bytes != vol_info.rsvd_bytes) {
+ __err_msg(test, func, line,
+ "bad reserved bytes %lld, should be %lld",
+ vol_info.rsvd_bytes, rsvd_bytes);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * __check_vol_patt - check that volume contains certain data
+ *
+ * @libubi libubi descriptor
+ * @dev_info UBI device description
+ * @test test name
+ * @func function name
+ * @line line number
+ * @node volume character device node
+ * @byte data pattern to check
+ *
+ * This function returns %0 if the volume contains only @byte bytes, and %-1 if
+ * not.
+ */
+int __check_vol_patt(libubi_t libubi, struct ubi_dev_info *dev_info,
+ const char *test, const char *func, int line,
+ const char *node, uint8_t byte)
+{
+ int ret, fd;
+ long long bytes = 0;
+ struct ubi_vol_info vol_info;
+ unsigned char buf[512];
+
+ fd = open(node, O_RDONLY);
+ if (fd == -1) {
+ __failed(test, func, line, "open");
+ __err_msg(test, func, line, "cannot open \"%s\"\n", node);
+ return -1;
+ }
+
+ ret = ubi_get_vol_info(libubi, node, &vol_info);
+ if (ret) {
+ __failed(test, func, line, "ubi_get_vol_info");
+ goto close;
+ }
+
+ while (bytes < vol_info.data_bytes) {
+ int i;
+
+ memset(&buf[0], ~byte, 512);
+ ret = read(fd, &buf[0], 512);
+ if (ret == -1) {
+ __failed(test, func, line, "read");
+ __err_msg(test, func, line, "bytes = %lld, ret = %d",
+ bytes, ret);
+ goto close;
+ }
+
+ if (ret == 0 && bytes + ret < vol_info.data_bytes) {
+ __err_msg(test, func, line,
+ "EOF, but read only %lld bytes of %lld",
+ bytes + ret, vol_info.data_bytes);
+ goto close;
+ }
+
+ for (i = 0; i < ret; i++)
+ if (buf[i] != byte) {
+ __err_msg(test, func, line,
+ "byte at %lld is not %#x but %#x",
+ bytes + i, byte, (int)buf[i]);
+ goto close;
+ }
+
+ bytes += ret;
+ }
+
+ close(fd);
+ return 0;
+
+close:
+ close(fd);
+ return -1;
+}
+
+/**
+ * __update_vol_patt - update volume using a certain byte pattern
+ *
+ * @libubi libubi descriptor
+ * @dev_info UBI device description
+ * @test test name
+ * @func function name
+ * @line line number
+ * @node volume character device node
+ * @byte data pattern to check
+ *
+ * This function returns %0 in case of success, and %-1 if in case of failure.
+ */
+int __update_vol_patt(libubi_t libubi, const char *test, const char *func,
+ int line, const char *node, long long bytes, uint8_t byte)
+{
+ int ret, fd;
+ long long written = 0;
+ unsigned char buf[512];
+
+ fd = open(node, O_RDWR);
+ if (fd == -1) {
+ __failed(test, func, line, "open");
+ __err_msg(test, func, line, "cannot open \"%s\"\n", node);
+ return -1;
+ }
+
+ if (ubi_update_start(libubi, fd, bytes)) {
+ __failed(test, func, line, "ubi_update_start");
+ __err_msg(test, func, line, "bytes = %lld", bytes);
+ goto close;
+ }
+
+ memset(&buf[0], byte, 512);
+
+ while (written != bytes) {
+ ret = write(fd, &buf[0], 512);
+ if (ret == -1) {
+ __failed(test, func, line, "write");
+ __err_msg(test, func, line, "written = %lld, ret = %d",
+ written, ret);
+ goto close;
+ }
+ written += ret;
+
+ if (written > bytes) {
+ __err_msg(test, func, line, "update length %lld bytes, "
+ "but %lld bytes are already written",
+ bytes, written);
+ goto close;
+ }
+ }
+
+ close(fd);
+ return 0;
+
+close:
+ close(fd);
+ return -1;
+}
diff --git a/ubi-utils/tests/common.h b/ubi-utils/tests/common.h
new file mode 100644
index 0000000..3e8ada8
--- /dev/null
+++ b/ubi-utils/tests/common.h
@@ -0,0 +1,103 @@
+/*
+ * 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
+ *
+ * The stuff which is common for many tests.
+ */
+
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define UBI_VOLUME_PATTERN "/dev/ubi%d_%d"
+#define MIN_AVAIL_EBS 5
+#define PAGE_SIZE 4096
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+#define err_msg(fmt, ...) \
+ __err_msg(TESTNAME, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
+
+#define failed(name) \
+ __failed(TESTNAME, __FUNCTION__, __LINE__, name)
+
+#define initial_check(argc, argv) \
+ __initial_check(TESTNAME, argc, argv)
+
+#define check_volume(vol_id, req) \
+ __check_volume(libubi, &dev_info, TESTNAME, __FUNCTION__, \
+ __LINE__, vol_id, req)
+
+#define check_vol_patt(node, byte) \
+ __check_vol_patt(libubi, &dev_info, TESTNAME, __FUNCTION__, __LINE__, \
+ node, byte)
+
+#define update_vol_patt(node, bytes, byte) \
+ __update_vol_patt(libubi, TESTNAME, __FUNCTION__, __LINE__, \
+ node, bytes, byte)
+
+#define check_failed(ret, error, func, fmt, ...) ({ \
+ int __ret; \
+ \
+ if (!ret) { \
+ err_msg("%s() returned success but should have failed", func); \
+ err_msg(fmt, ##__VA_ARGS__); \
+ __ret = -1; \
+ } \
+ if (errno != (error)) { \
+ err_msg("%s failed with error %d (%s), expected %d (%s)", \
+ func, errno, strerror(errno), error, strerror(error)); \
+ err_msg(fmt, ##__VA_ARGS__); \
+ __ret = -1; \
+ } \
+ __ret = 0; \
+})
+
+/* Alignments to test, @s is eraseblock size */
+#define ALIGNMENTS(s) \
+ {3, 5, 27, 666, 512, 1024, 2048, (s)/2-3, (s)/2-2, (s)/2-1, (s)/2+1, \
+ (s)/2+2, (s)/2+3, (s)/3-3, (s)/3-2, (s)/3-1, (s)/3+1, (s)/3+2, \
+ (s)/3+3, (s)/4-3, (s)/4-2, (s)/4-1, (s)/4+1, (s)/4+2, (s)/4+3, \
+ (s)/5-3, (s)/5-2, (s)/5-1, (s)/5+1, (s)/5+2, (s)/5+3, (s)-17, (s)-9, \
+ (s)-8, (s)-6, (s)-4, (s)-1, (s)};
+
+extern void __err_msg(const char *test, const char *func, int line,
+ const char *fmt, ...);
+void __failed(const char *test, const char *func, int line,
+ const char *failed);
+int __initial_check(const char *test, int argc, char * const argv[]);
+int __check_volume(libubi_t libubi, struct ubi_dev_info *dev_info,
+ const char *test, const char *func, int line, int vol_id,
+ const struct ubi_mkvol_request *req);
+int __check_vol_patt(libubi_t libubi, struct ubi_dev_info *dev_info,
+ const char *test, const char *func, int line,
+ const char *node, uint8_t byte);
+int __update_vol_patt(libubi_t libubi, const char *test, const char *func,
+ int line, const char *node, long long bytes,
+ uint8_t byte);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__COMMON_H__ */
diff --git a/ubi-utils/tests/integ.c b/ubi-utils/tests/integ.c
new file mode 100644
index 0000000..4da7121
--- /dev/null
+++ b/ubi-utils/tests/integ.c
@@ -0,0 +1,783 @@
+#define _LARGEFILE64_SOURCE
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include "libubi.h"
+
+struct erase_block_info;
+struct volume_info;
+struct ubi_device_info;
+
+struct write_info
+{
+ struct write_info *next;
+ struct erase_block_info *erase_block;
+ int offset_within_block; /* Offset within erase block */
+ off64_t offset; /* Offset within volume */
+ int size;
+ int random_seed;
+};
+
+struct erase_block_info
+{
+ struct volume_info *volume;
+ int block_number;
+ off64_t offset; /* Offset within volume */
+ off64_t top_of_data;
+ int touched; /* Have we done anything at all with this erase block */
+ int erased; /* This erased block is currently erased */
+ struct write_info *writes;
+};
+
+struct volume_fd
+{
+ struct volume_fd *next;
+ struct volume_info *volume;
+ int fd;
+};
+
+struct volume_info
+{
+ struct volume_info *next;
+ struct ubi_device_info *ubi_device;
+ struct volume_fd *fds;
+ struct erase_block_info *erase_blocks;
+ const char *device_file_name;
+ struct ubi_vol_info info;
+};
+
+struct ubi_device_info
+{
+ struct volume_info *volumes;
+ const char *device_file_name;
+ struct ubi_dev_info info;
+};
+
+struct open_volume_fd
+{
+ struct open_volume_fd *next;
+ struct volume_fd *vol_fd;
+};
+
+#define MAX_UBI_DEVICES 64
+
+static libubi_t libubi;
+
+static struct ubi_info info;
+static struct ubi_device_info ubi_array[MAX_UBI_DEVICES];
+
+static uint64_t total_written = 0;
+static uint64_t total_space = 0;
+
+static struct open_volume_fd *open_volumes;
+static size_t open_volume_count = 0;
+
+static const char *ubi_module_load_string;
+
+static unsigned char *write_buffer = NULL;
+static unsigned char *read_buffer = NULL;
+
+static long long max_ebs_per_vol = 0; /* max number of ebs per vol (zero => no max) */
+
+static unsigned long next_seed = 1;
+
+static unsigned get_next_seed()
+{
+ next_seed = next_seed * 1103515245 + 12345;
+ return ((unsigned) (next_seed / 65536) % 32768);
+}
+
+static void error_exit(const char *msg)
+{
+ int eno = errno;
+ fprintf(stderr,"UBI Integrity Test Error: %s\n",msg);
+ if (eno) {
+ fprintf(stderr, "errno = %d\n", eno);
+ fprintf(stderr, "strerror = %s\n", strerror(eno));
+ }
+ exit(1);
+}
+
+static void *allocate(size_t n)
+{
+ void *p = malloc(n);
+ if (!p)
+ error_exit("Memory allocation failure");
+ memset(p, 0, n);
+ return p;
+}
+
+static unsigned get_random_number(unsigned n)
+{
+ uint64_t r, b;
+
+ if (n < 1)
+ return 0;
+ r = rand();
+ r *= n;
+ b = RAND_MAX;
+ b += 1;
+ r /= b;
+ return r;
+}
+
+static struct volume_fd *open_volume(struct volume_info *vol)
+{
+ struct volume_fd *s;
+ struct open_volume_fd *ofd;
+ int fd;
+
+ if (vol->fds) {
+ /* If already open dup it */
+ fd = dup(vol->fds->fd);
+ if (fd == -1)
+ error_exit("Failed to dup volume device file des");
+ } else {
+ fd = open(vol->device_file_name, O_RDWR | O_LARGEFILE);
+ if (fd == -1)
+ error_exit("Failed to open volume device file");
+ }
+ s = allocate(sizeof(*s));
+ s->fd = fd;
+ s->volume = vol;
+ s->next = vol->fds;
+ vol->fds = s;
+ /* Add to open volumes list */
+ ofd = allocate(sizeof(*ofd));
+ ofd->vol_fd = s;
+ ofd->next = open_volumes;
+ open_volumes = ofd;
+ open_volume_count += 1;
+ return 0;
+}
+
+static void close_volume(struct volume_fd *vol_fd)
+{
+ struct volume_fd *vfd, *vfd_last;
+ struct open_volume_fd *ofd, *ofd_last;
+ int fd = vol_fd->fd;
+
+ /* Remove from open volumes list */
+ ofd_last = NULL;
+ ofd = open_volumes;
+ while (ofd) {
+ if (ofd->vol_fd == vol_fd) {
+ if (ofd_last)
+ ofd_last->next = ofd->next;
+ else
+ open_volumes = ofd->next;
+ free(ofd);
+ open_volume_count -= 1;
+ break;
+ }
+ ofd_last = ofd;
+ ofd = ofd->next;
+ }
+ /* Remove from volume fd list */
+ vfd_last = NULL;
+ vfd = vol_fd->volume->fds;
+ while (vfd) {
+ if (vfd == vol_fd) {
+ if (vfd_last)
+ vfd_last->next = vfd->next;
+ else
+ vol_fd->volume->fds = vfd->next;
+ free(vfd);
+ break;
+ }
+ vfd_last = vfd;
+ vfd = vfd->next;
+ }
+ /* Close volume device file */
+ if (close(fd) == -1)
+ error_exit("Failed to close volume file descriptor");
+}
+
+static void set_random_data(unsigned seed, unsigned char *buf, int size)
+{
+ int i;
+ unsigned r;
+
+ r = rand();
+ srand(seed);
+ for (i = 0; i < size; ++i)
+ buf[i] = rand();
+ srand(r);
+}
+
+#if 0
+static void print_write_info(struct write_info *w)
+{
+ printf("Offset: %lld Size:%d Seed:%u\n", w->offset, w->size, w->random_seed);
+ fflush(stdout);
+}
+#endif
+
+static void check_erase_block(struct erase_block_info *erase_block, int fd)
+{
+ struct write_info *w;
+ off64_t gap_end;
+ int eb_size = erase_block->volume->info.eb_size;
+ ssize_t bytes_read;
+
+ w = erase_block->writes;
+ gap_end = erase_block->offset + eb_size;
+ while (w) {
+ if (w->offset + w->size < gap_end) {
+ /* There is a gap. Check all 0xff */
+ off64_t gap_start = w->offset + w->size;
+ size_t size = gap_end - gap_start;
+ if (lseek64(fd, gap_start, SEEK_SET) != gap_start)
+ error_exit("lseek64 failed");
+ memset(read_buffer, 0 , size);
+ errno = 0;
+ bytes_read = read(fd, read_buffer, size);
+ if (bytes_read != size)
+ error_exit("read failed in gap");
+ while (size)
+ if (read_buffer[--size] != 0xff) {
+ fprintf(stderr, "block no. = %d\n" , erase_block->block_number);
+ fprintf(stderr, "offset = %lld\n" , (long long) gap_start);
+ fprintf(stderr, "size = %ld\n" , (long) bytes_read);
+ error_exit("verify 0xff failed");
+ }
+ }
+ if (lseek64(fd, w->offset, SEEK_SET) != w->offset)
+ error_exit("lseek64 failed");
+ memset(read_buffer, 0 , w->size);
+ errno = 0;
+ bytes_read = read(fd, read_buffer, w->size);
+ if (bytes_read != w->size) {
+ fprintf(stderr, "offset = %lld\n" , (long long) w->offset);
+ fprintf(stderr, "size = %ld\n" , (long) w->size);
+ fprintf(stderr, "bytes_read = %ld\n" , (long) bytes_read);
+ error_exit("read failed");
+ }
+ set_random_data(w->random_seed, write_buffer, w->size);
+ if (memcmp(read_buffer, write_buffer, w->size))
+ error_exit("verify failed");
+ gap_end = w->offset;
+ w = w->next;
+ }
+ if (gap_end > erase_block->offset) {
+ /* Check all 0xff */
+ off64_t gap_start = erase_block->offset;
+ size_t size = gap_end - gap_start;
+ if (lseek64(fd, gap_start, SEEK_SET) != gap_start)
+ error_exit("lseek64 failed");
+ memset(read_buffer, 0 , size);
+ errno = 0;
+ bytes_read = read(fd, read_buffer, size);
+ if (bytes_read != size)
+ error_exit("read failed in gap");
+ while (size)
+ if (read_buffer[--size] != 0xff) {
+ fprintf(stderr, "block no. = %d\n" , erase_block->block_number);
+ fprintf(stderr, "offset = %lld\n" , (long long) gap_start);
+ fprintf(stderr, "size = %ld\n" , (long) bytes_read);
+ error_exit("verify 0xff failed!");
+ }
+ }
+}
+
+static int write_to_erase_block(struct erase_block_info *erase_block, int fd)
+{
+ int page_size = erase_block->volume->ubi_device->info.min_io_size;
+ int eb_size = erase_block->volume->info.eb_size;
+ int next_offset = 0;
+ int space, size;
+ off64_t offset;
+ unsigned seed;
+ struct write_info *w;
+
+ if (erase_block->writes)
+ next_offset = erase_block->writes->offset_within_block + erase_block->writes->size;
+ space = eb_size - next_offset;
+ if (space <= 0)
+ return 0; /* No space */
+ if (!get_random_number(10)) {
+ /* 1 time in 10 leave a gap */
+ next_offset += get_random_number(space);
+ next_offset = (next_offset / page_size) * page_size;
+ space = eb_size - next_offset;
+ }
+ if (get_random_number(2))
+ size = 1 * page_size;
+ else if (get_random_number(2))
+ size = 2 * page_size;
+ else if (get_random_number(2))
+ size = 3 * page_size;
+ else if (get_random_number(2))
+ size = 4 * page_size;
+ else {
+ if (get_random_number(4))
+ size = get_random_number(space);
+ else
+ size = space;
+ size = (size / page_size) * page_size;
+ }
+ if (size == 0 || size > space)
+ size = page_size;
+ if (next_offset + size > eb_size)
+ error_exit("internal error");
+ offset = erase_block->offset + next_offset;
+ if (offset < erase_block->top_of_data)
+ error_exit("internal error!");
+ if (lseek64(fd, offset, SEEK_SET) != offset)
+ error_exit("lseek64 failed");
+ /* Do write */
+ seed = get_next_seed();
+ if (!seed)
+ seed = 1;
+ set_random_data(seed, write_buffer, size);
+ if (write(fd, write_buffer, size) != size)
+ error_exit("write failed");
+ erase_block->top_of_data = offset + size;
+ /* Make write info and add to eb */
+ w = allocate(sizeof(*w));
+ w->offset_within_block = next_offset;
+ w->offset = offset;
+ w->size = size;
+ w->random_seed = seed;
+ w->next = erase_block->writes;
+ erase_block->writes = w;
+ erase_block->touched = 1;
+ erase_block->erased = 0;
+ total_written += size;
+ return 1;
+}
+
+static void erase_erase_block(struct erase_block_info *erase_block, int fd)
+{
+ struct write_info *w;
+ uint32_t eb_no;
+ int res;
+
+ eb_no = erase_block->block_number;
+ res = ioctl(fd, UBI_IOCEBER, &eb_no);
+ if (res)
+ error_exit("Failed to erase an erase block");
+ /* Remove writes from this eb */
+ while (erase_block->writes) {
+ w = erase_block->writes;
+ erase_block->writes = erase_block->writes->next;
+ free(w);
+ }
+ erase_block->erased = 1;
+ erase_block->touched = 1;
+ erase_block->top_of_data = erase_block->offset;
+}
+
+static void operate_on_erase_block(struct erase_block_info *erase_block, int fd)
+{
+ /*
+ Possible operations:
+ read from it and verify
+ write to it
+ erase it
+ */
+ int work_done = 1;
+ static int no_work_done_count = 0;
+
+ if (!get_random_number(10) && no_work_done_count <= 5) {
+ check_erase_block(erase_block, fd);
+ work_done = 0;
+ } else if (get_random_number(100)) {
+ if (!write_to_erase_block(erase_block, fd)) {
+ /* The erase block was full */
+ if (get_random_number(2) || no_work_done_count > 5)
+ erase_erase_block(erase_block, fd);
+ else
+ work_done = 0;
+ }
+ } else
+ erase_erase_block(erase_block, fd);
+ if (work_done)
+ no_work_done_count = 0;
+ else
+ no_work_done_count += 1;
+}
+
+static void operate_on_open_volume(struct volume_fd *vol_fd)
+{
+ /*
+ Possible operations:
+ operate on an erase block
+ close volume
+ */
+ if (get_random_number(100) == 0)
+ close_volume(vol_fd);
+ else {
+ /* Pick an erase block at random */
+ int eb_no = get_random_number(vol_fd->volume->info.rsvd_ebs);
+ operate_on_erase_block(&vol_fd->volume->erase_blocks[eb_no], vol_fd->fd);
+ }
+}
+
+static void operate_on_volume(struct volume_info *vol)
+{
+ /*
+ Possible operations:
+ open it
+ resize it (must close fd's first) <- TODO
+ delete it (must close fd's first) <- TODO
+ */
+ open_volume(vol);
+}
+
+static int ubi_major(const char *device_file_name)
+{
+ struct stat buf;
+ static int maj = 0;
+
+ if (maj)
+ return maj;
+ if (stat(device_file_name, &buf) == -1)
+ error_exit("Failed to stat ubi device file");
+ maj = major(buf.st_rdev);
+ return maj;
+}
+
+static void operate_on_ubi_device(struct ubi_device_info *ubi_device)
+{
+ /*
+ TODO:
+ Possible operations:
+ create a new volume
+ operate on existing volume
+ */
+ /*
+ Simplified operation (i.e. only have 1 volume):
+ If there are no volumes create 1 volumne
+ Then operate on the volume
+ */
+ if (ubi_device->info.vol_count == 0) {
+ /* Create the one-and-only volume we will use */
+ char dev_name[1024];
+ int i, n, maj, fd;
+ struct volume_info *s;
+ struct ubi_mkvol_request req;
+
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.alignment = 1; /* TODO: What is this? */
+ req.bytes = ubi_device->info.eb_size * max_ebs_per_vol;
+ if (req.bytes == 0 || req.bytes > ubi_device->info.avail_bytes)
+ req.bytes = ubi_device->info.avail_bytes;
+ req.vol_type = UBI_DYNAMIC_VOLUME;
+ req.name = "integ-test-vol";
+ if (ubi_mkvol(libubi, ubi_device->device_file_name, &req))
+ error_exit("ubi_mkvol failed");
+ s = allocate(sizeof(*s));
+ s->ubi_device = ubi_device;
+ if (ubi_get_vol_info1(libubi, ubi_device->info.dev_num, req.vol_id, &s->info))
+ error_exit("ubi_get_vol_info failed");
+ n = s->info.rsvd_ebs;
+ s->erase_blocks = allocate(sizeof(struct erase_block_info) * n);
+ for (i = 0; i < n; ++i) {
+ s->erase_blocks[i].volume = s;
+ s->erase_blocks[i].block_number = i;
+ s->erase_blocks[i].offset = i * (off64_t) s->info.eb_size;
+ s->erase_blocks[i].top_of_data = s->erase_blocks[i].offset;
+ }
+ /* FIXME: Correctly get device file name */
+ sprintf(dev_name, "%s_%d", ubi_device->device_file_name, req.vol_id);
+ s->device_file_name = strdup(dev_name);
+ ubi_device->volumes = s;
+ ubi_device->info.vol_count += 1;
+ sleep(1);
+ fd = open(s->device_file_name, O_RDONLY);
+ if (fd == -1) {
+ /* FIXME: Correctly make node */
+ maj = ubi_major(ubi_device->device_file_name);
+ sprintf(dev_name, "mknod %s c %d %d", s->device_file_name, maj, req.vol_id + 1);
+ system(dev_name);
+ } else if (close(fd) == -1)
+ error_exit("Failed to close volume device file");
+ }
+ operate_on_volume(ubi_device->volumes);
+}
+
+static void do_an_operation(void)
+{
+ int too_few = (open_volume_count < info.dev_count * 3);
+ int too_many = (open_volume_count > info.dev_count * 5);
+
+ if (too_many || (!too_few && get_random_number(1000) > 0)) {
+ /* Operate on an open volume */
+ size_t pos;
+ struct open_volume_fd *ofd;
+ pos = get_random_number(open_volume_count);
+ for (ofd = open_volumes; pos && ofd && ofd->next; --pos)
+ ofd = ofd->next;
+ operate_on_open_volume(ofd->vol_fd);
+ } else if (info.dev_count > 0) {
+ /* Operate on a ubi device */
+ size_t ubi_pos = 0;
+ if (info.dev_count > 1)
+ ubi_pos = get_random_number(info.dev_count - 1);
+ operate_on_ubi_device(&ubi_array[ubi_pos]);
+ } else
+ error_exit("Internal error");
+}
+
+static void get_ubi_devices_info(void)
+{
+ int i, ubi_pos = 0;
+ char dev_name[1024];
+ size_t buf_size = 1024 * 128;
+
+ if (ubi_get_info(libubi, &info))
+ error_exit("ubi_get_info failed");
+ if (info.dev_count > MAX_UBI_DEVICES)
+ error_exit("Too many ubi devices");
+ for (i = info.lowest_dev_num; i <= info.highest_dev_num; ++i) {
+ struct ubi_device_info *s;
+ s = &ubi_array[ubi_pos++];
+ if (ubi_get_dev_info1(libubi, i, &s->info))
+ error_exit("ubi_get_dev_info1 failed");
+ if (s->info.vol_count)
+ error_exit("There are existing volumes");
+ /* FIXME: Correctly get device file name */
+ sprintf(dev_name, "/dev/ubi%d", i);
+ s->device_file_name = strdup(dev_name);
+ if (buf_size < s->info.eb_size)
+ buf_size = s->info.eb_size;
+ if (max_ebs_per_vol && s->info.eb_size * max_ebs_per_vol < s->info.avail_bytes)
+ total_space += s->info.eb_size * max_ebs_per_vol;
+ else
+ total_space += s->info.avail_bytes;
+ }
+ write_buffer = allocate(buf_size);
+ read_buffer = allocate(buf_size);
+}
+
+static void load_ubi(void)
+{
+ system("rmmod ubi");
+ if (system(ubi_module_load_string) != 0)
+ error_exit("Failed to load UBI module");
+ sleep(1);
+}
+
+static void do_some_operations(void)
+{
+ unsigned i = 0;
+ total_written = 0;
+ printf("Total space: %llu\n", (unsigned long long) total_space);
+ while (total_written < total_space * 3) {
+ do_an_operation();
+ if (i++ % 10000 == 0)
+ printf("Total written: %llu\n", (unsigned long long) total_written);
+ }
+ printf("Total written: %llu\n", (unsigned long long) total_written);
+}
+
+static void reload_ubi(void)
+{
+ /* Remove module */
+ if (system("rmmod ubi") != 0)
+ error_exit("Failed to remove UBI module");
+ /* Install module */
+ if (system(ubi_module_load_string) != 0)
+ error_exit("Failed to load UBI module");
+ sleep(1);
+}
+
+static void check_volume(struct volume_info *vol)
+{
+ struct erase_block_info *eb = vol->erase_blocks;
+ int pos;
+ int fd;
+
+ fd = open(vol->device_file_name, O_RDWR | O_LARGEFILE);
+ if (fd == -1)
+ error_exit("Failed to open volume device file");
+ for (pos = 0; pos < vol->info.rsvd_ebs; ++pos)
+ check_erase_block(eb++, fd);
+ if (close(fd) == -1)
+ error_exit("Failed to close volume device file");
+}
+
+static void check_ubi_device(struct ubi_device_info *ubi_device)
+{
+ struct volume_info *vol;
+
+ vol = ubi_device->volumes;
+ while (vol) {
+ check_volume(vol);
+ vol = vol->next;
+ }
+}
+
+static void check_ubi(void)
+{
+ int i;
+
+ for (i = 0; i < info.dev_count; ++i)
+ check_ubi_device(&ubi_array[i]);
+}
+
+static int is_all_digits(const char *s)
+{
+ const char *digits = "0123456789";
+ if (!s || !*s)
+ return 0;
+ for (;*s;++s)
+ if (!strchr(digits,*s))
+ return 0;
+ return 1;
+}
+
+static int get_short_arg(int *pos,const char *name,long long *result,int argc,char *argv[])
+{
+ const char *p = NULL;
+ int i = *pos;
+ size_t n = strlen(name);
+
+ if (strlen(argv[i]) > n)
+ p = argv[i] + n;
+ else if (++i < argc)
+ p = argv[i];
+ if (!is_all_digits(p))
+ return 1;
+ *result = atoll(p);
+ *pos = i;
+ return 0;
+}
+
+static int get_long_arg(int *pos,const char *name,long long *result,int argc,char *argv[])
+{
+ const char *p = NULL;
+ int i = *pos;
+ size_t n = strlen(name);
+
+ if (strlen(argv[i]) > n)
+ p = argv[i] + n;
+ else if (++i < argc)
+ p = argv[i];
+ if (p && *p == '=') {
+ p += 1;
+ if (!*p && ++i < argc)
+ p = argv[i];
+ }
+ if (!is_all_digits(p))
+ return 1;
+ *result = atoll(p);
+ *pos = i;
+ return 0;
+}
+
+static int remove_all_volumes(void)
+{
+ int i;
+
+ for (i = 0; i < info.dev_count; ++i) {
+ struct ubi_device_info *ubi_device = &ubi_array[i];
+ struct volume_info *vol;
+ vol = ubi_device->volumes;
+ while (vol) {
+ int res = ubi_rmvol(libubi,
+ ubi_device->device_file_name,
+ vol->info.vol_id);
+ if (res)
+ return res;
+ vol = vol->next;
+ }
+ }
+ return 0;
+}
+
+int main(int argc,char *argv[])
+{
+ int i;
+ long long r, repeat = 1;
+ int initial_seed = 1, args_ok = 1;
+
+ printf("UBI Integrity Test\n");
+
+ /* Get arguments */
+ ubi_module_load_string = 0;
+ for (i = 1; i < argc; ++i) {
+ if (strncmp(argv[i], "-h", 2) == 0)
+ args_ok = 0;
+ else if (strncmp(argv[i], "--help", 6) == 0)
+ args_ok = 0;
+ else if (strncmp(argv[i], "-n", 2) == 0) {
+ if (get_short_arg(&i, "-n", &repeat, argc, argv))
+ args_ok = 0;
+ } else if (strncmp(argv[i], "--repeat", 8) == 0) {
+ if (get_long_arg(&i, "--repeat", &repeat, argc, argv))
+ args_ok = 0;
+ } else if (strncmp(argv[i], "-m", 2) == 0) {
+ if (get_short_arg(&i,"-m", &max_ebs_per_vol, argc, argv))
+ args_ok = 0;
+ } else if (strncmp(argv[i], "--maxebs", 8) == 0) {
+ if (get_long_arg(&i, "--maxebs", &max_ebs_per_vol, argc, argv))
+ args_ok = 0;
+ } else if (!ubi_module_load_string)
+ ubi_module_load_string = argv[i];
+ else
+ args_ok = 0;
+ }
+ if (!args_ok || !ubi_module_load_string) {
+ fprintf(stderr, "Usage is: ubi_integ [<options>] <UBI Module load command>\n");
+ fprintf(stderr, " Options: \n");
+ fprintf(stderr, " -h, --help Help\n");
+ fprintf(stderr, " -n arg, --repeat=arg Repeat test arg times\n");
+ fprintf(stderr, " -m arg, --maxebs=arg Max no. of erase blocks\n");
+ return 1;
+ }
+
+ initial_seed = getpid();
+ printf("Initial seed = %u\n", (unsigned) initial_seed);
+ next_seed = initial_seed;
+ srand(initial_seed);
+ load_ubi();
+
+ libubi = libubi_open();
+ if (!libubi)
+ error_exit("Failed to open libubi");
+
+ get_ubi_devices_info();
+
+ r = 0;
+ while (repeat == 0 || r++ < repeat) {
+ printf("Cycle %lld\n", r);
+ do_some_operations();
+
+ /* Close all volumes */
+ while (open_volumes)
+ close_volume(open_volumes->vol_fd);
+
+ check_ubi();
+
+ libubi_close(libubi);
+
+ reload_ubi();
+
+ libubi = libubi_open();
+ if (!libubi)
+ error_exit("Failed to open libubi");
+
+ check_ubi();
+ }
+
+ if (remove_all_volumes())
+ error_exit("Failed to remove all volumes");
+
+ libubi_close(libubi);
+
+ printf("UBI Integrity Test completed ok\n");
+ return 0;
+}
diff --git a/ubi-utils/tests/io_basic.c b/ubi-utils/tests/io_basic.c
new file mode 100644
index 0000000..2e8809a
--- /dev/null
+++ b/ubi-utils/tests/io_basic.c
@@ -0,0 +1,182 @@
+/*
+ * 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
+ *
+ * Test basic UBI volume I/O capabilities.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "libubi.h"
+#define TESTNAME "io_basic"
+#include "common.h"
+
+static libubi_t libubi;
+static struct ubi_dev_info dev_info;
+const char *node;
+
+static int test_basic(int type);
+static int test_aligned(int type);
+
+int main(int argc, char * const argv[])
+{
+ if (initial_check(argc, argv))
+ return 1;
+
+ node = argv[1];
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ failed("libubi_open");
+ return 1;
+ }
+
+ if (ubi_get_dev_info(libubi, node, &dev_info)) {
+ failed("ubi_get_dev_info");
+ goto close;
+ }
+
+ if (test_basic(UBI_DYNAMIC_VOLUME))
+ goto close;
+ if (test_basic(UBI_STATIC_VOLUME))
+ goto close;
+ if (test_aligned(UBI_DYNAMIC_VOLUME))
+ goto close;
+ if (test_aligned(UBI_STATIC_VOLUME))
+ goto close;
+
+ libubi_close(libubi);
+ return 0;
+
+close:
+ libubi_close(libubi);
+ return 1;
+}
+
+/**
+ * test_basic - check basic volume read and update capabilities.
+ *
+ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+ *
+ * Thus function returns %0 in case of success and %-1 in case of failure.
+ */
+static int test_basic(int type)
+{
+ struct ubi_mkvol_request req;
+ const char *name = TESTNAME ":test_basic()";
+ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
+
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.alignment = 1;
+ req.bytes = dev_info.avail_bytes;
+ req.vol_type = type;
+ req.name = name;
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return -1;
+ }
+
+ sprintf(&vol_node[0], UBI_VOLUME_PATTERN, dev_info.dev_num, req.vol_id);
+
+ /* Make sure newly created volume contains only 0xFF bytes */
+ if (check_vol_patt(&vol_node[0], 0xFF))
+ goto remove;
+
+ /* Write 0xA5 bytes to the volume */
+ if (update_vol_patt(&vol_node[0], dev_info.avail_bytes, 0xA5))
+ goto remove;
+ if (check_vol_patt(&vol_node[0], 0xA5))
+ goto remove;
+
+ if (ubi_rmvol(libubi, node, req.vol_id)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+
+ return 0;
+
+remove:
+ ubi_rmvol(libubi, node, req.vol_id);
+ return -1;
+}
+
+/**
+ * test_aligned - test volume alignment feature.
+ *
+ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+ *
+ * Thus function returns %0 in case of success and %-1 in case of failure.
+ */
+static int test_aligned(int type)
+{
+ int i, ebsz;
+ struct ubi_mkvol_request req;
+ const char *name = TESTNAME ":test_aligned()";
+ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
+ int alignments[] = ALIGNMENTS(dev_info.eb_size);
+
+ req.vol_type = type;
+ req.name = name;
+
+ for (i = 0; i < sizeof(alignments)/sizeof(int); i++) {
+ req.vol_id = UBI_VOL_NUM_AUTO;
+
+ req.alignment = alignments[i];
+ req.alignment -= req.alignment % dev_info.min_io_size;
+ if (req.alignment == 0)
+ req.alignment = dev_info.min_io_size;
+
+ ebsz = dev_info.eb_size - dev_info.eb_size % req.alignment;
+ req.bytes = MIN_AVAIL_EBS * ebsz;
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return -1;
+ }
+
+ sprintf(&vol_node[0], UBI_VOLUME_PATTERN, dev_info.dev_num, req.vol_id);
+
+ /* Make sure newly created volume contains only 0xFF bytes */
+ if (check_vol_patt(&vol_node[0], 0xFF))
+ goto remove;
+
+ /* Write 0xA5 bytes to the volume */
+ if (update_vol_patt(&vol_node[0], req.bytes, 0xA5))
+ goto remove;
+ if (check_vol_patt(&vol_node[0], 0xA5))
+ goto remove;
+
+ if (ubi_rmvol(libubi, node, req.vol_id)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+ }
+
+ return 0;
+
+remove:
+ ubi_rmvol(libubi, node, req.vol_id);
+ return -1;
+}
diff --git a/ubi-utils/tests/io_paral.c b/ubi-utils/tests/io_paral.c
new file mode 100644
index 0000000..4857bf8
--- /dev/null
+++ b/ubi-utils/tests/io_paral.c
@@ -0,0 +1,251 @@
+/*
+ * 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
+ *
+ * This test does a lot of I/O to volumes in parallel.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "libubi.h"
+#define TESTNAME "io_paral"
+#include "common.h"
+
+#define THREADS_NUM 3
+#define ITERATIONS 100
+
+static libubi_t libubi;
+static struct ubi_dev_info dev_info;
+const char *node;
+static int iterations = ITERATIONS;
+int total_bytes;
+
+static void * the_thread(void *ptr);
+
+static long long memory_limit(void)
+{
+ long long result = 0;
+ FILE *f;
+
+ f = fopen("/proc/meminfo", "r");
+ if (!f)
+ return 0;
+ fscanf(f, "%*s %lld", &result);
+ fclose(f);
+ return result * 1024 / 4;
+}
+
+int main(int argc, char * const argv[])
+{
+ int i, ret;
+ pthread_t threads[THREADS_NUM];
+ struct ubi_mkvol_request req;
+ long long mem_limit;
+
+ if (initial_check(argc, argv))
+ return 1;
+
+ node = argv[1];
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ failed("libubi_open");
+ return 1;
+ }
+
+ if (ubi_get_dev_info(libubi, node, &dev_info)) {
+ failed("ubi_get_dev_info");
+ goto close;
+ }
+
+ req.alignment = 1;
+ mem_limit = memory_limit();
+ if (mem_limit && mem_limit < dev_info.avail_bytes)
+ total_bytes = req.bytes =
+ (mem_limit / dev_info.eb_size / THREADS_NUM)
+ * dev_info.eb_size;
+ else
+ total_bytes = req.bytes =
+ ((dev_info.avail_ebs - 3) / THREADS_NUM)
+ * dev_info.eb_size;
+ for (i = 0; i < THREADS_NUM; i++) {
+ char name[100];
+
+ req.vol_id = i;
+ sprintf(&name[0], TESTNAME":%d", i);
+ req.name = &name[0];
+ req.vol_type = (i & 1) ? UBI_STATIC_VOLUME : UBI_DYNAMIC_VOLUME;
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ goto remove;
+ }
+ }
+
+ /* Create one volume with static data to make WL work more */
+ req.vol_id = THREADS_NUM;
+ req.name = TESTNAME ":static";
+ req.vol_type = UBI_DYNAMIC_VOLUME;
+ req.bytes = 3*dev_info.eb_size;
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ goto remove;
+ }
+
+ for (i = 0; i < THREADS_NUM; i++) {
+ ret = pthread_create(&threads[i], NULL, &the_thread, (void*)i);
+ if (ret) {
+ failed("pthread_create");
+ goto remove;
+ }
+ }
+
+ for (i = 0; i < THREADS_NUM; i++)
+ pthread_join(threads[i], NULL);
+
+ for (i = 0; i <= THREADS_NUM; i++) {
+ if (ubi_rmvol(libubi, node, i)) {
+ failed("ubi_rmvol");
+ goto remove;
+ }
+ }
+
+ libubi_close(libubi);
+ return 0;
+
+remove:
+ for (i = 0; i <= THREADS_NUM; i++)
+ ubi_rmvol(libubi, node, i);
+
+close:
+ libubi_close(libubi);
+ return 1;
+}
+
+/**
+ * the_thread - the testing thread.
+ *
+ * @ptr thread number
+ */
+static void * the_thread(void *ptr)
+{
+ int fd, iter = iterations, vol_id = (int)ptr;
+ unsigned char *wbuf, *rbuf;
+ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
+
+ wbuf = malloc(total_bytes);
+ rbuf = malloc(total_bytes);
+ if (!wbuf || !rbuf) {
+ failed("malloc");
+ goto free;
+ }
+
+ sprintf(&vol_node[0], UBI_VOLUME_PATTERN, dev_info.dev_num, vol_id);
+
+ while (iter--) {
+ int i, ret, written = 0, rd = 0;
+ int bytes = (random() % (total_bytes - 1)) + 1;
+
+ fd = open(vol_node, O_RDWR);
+ if (fd == -1) {
+ failed("open");
+ err_msg("cannot open \"%s\"\n", node);
+ goto free;
+ }
+
+ for (i = 0; i < bytes; i++)
+ wbuf[i] = random() % 255;
+ memset(rbuf, '\0', bytes);
+
+ do {
+ ret = ubi_update_start(libubi, fd, bytes);
+ if (ret && errno != EBUSY) {
+ failed("ubi_update_start");
+ err_msg("vol_id %d", vol_id);
+ goto close;
+ }
+ } while (ret);
+
+ while (written < bytes) {
+ int to_write = random() % (bytes - written);
+
+ if (to_write == 0)
+ to_write = 1;
+
+ ret = write(fd, wbuf, to_write);
+ if (ret != to_write) {
+ failed("write");
+ err_msg("failed to write %d bytes at offset %d "
+ "of volume %d", to_write, written,
+ vol_id);
+ err_msg("update: %d bytes", bytes);
+ goto close;
+ }
+
+ written += to_write;
+ }
+
+ close(fd);
+
+ fd = open(vol_node, O_RDONLY);
+ if (fd == -1) {
+ failed("open");
+ err_msg("cannot open \"%s\"\n", node);
+ goto free;
+ }
+
+ /* read data back and check */
+ while (rd < bytes) {
+ int to_read = random() % (bytes - rd);
+
+ if (to_read == 0)
+ to_read = 1;
+
+ ret = read(fd, rbuf, to_read);
+ if (ret != to_read) {
+ failed("read");
+ err_msg("failed to read %d bytes at offset %d "
+ "of volume %d", to_read, rd, vol_id);
+ goto close;
+ }
+
+ rd += to_read;
+ }
+
+ close(fd);
+
+ }
+
+ free(wbuf);
+ free(rbuf);
+ return NULL;
+
+close:
+ close(fd);
+free:
+ free(wbuf);
+ free(rbuf);
+ return NULL;
+}
diff --git a/ubi-utils/tests/io_read.c b/ubi-utils/tests/io_read.c
new file mode 100644
index 0000000..c5d1da7
--- /dev/null
+++ b/ubi-utils/tests/io_read.c
@@ -0,0 +1,398 @@
+/*
+ * 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
+ *
+ * Test UBI volume read.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "libubi.h"
+#define TESTNAME "io_basic"
+#include "common.h"
+
+static libubi_t libubi;
+static struct ubi_dev_info dev_info;
+const char *node;
+
+static int test_static(void);
+static int test_read(int type);
+
+int main(int argc, char * const argv[])
+{
+ if (initial_check(argc, argv))
+ return 1;
+
+ node = argv[1];
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ failed("libubi_open");
+ return 1;
+ }
+
+ if (ubi_get_dev_info(libubi, node, &dev_info)) {
+ failed("ubi_get_dev_info");
+ goto close;
+ }
+
+ if (test_static())
+ goto close;
+ if (test_read(UBI_DYNAMIC_VOLUME))
+ goto close;
+ if (test_read(UBI_STATIC_VOLUME))
+ goto close;
+
+ libubi_close(libubi);
+ return 0;
+
+close:
+ libubi_close(libubi);
+ return 1;
+}
+
+/**
+ * test_static - test static volume-specific features.
+ *
+ * Thus function returns %0 in case of success and %-1 in case of failure.
+ */
+static int test_static(void)
+{
+ struct ubi_mkvol_request req;
+ const char *name = TESTNAME ":io_basic()";
+ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
+ struct ubi_vol_info vol_info;
+ int fd, ret;
+ char buf[20];
+
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.alignment = 1;
+ req.bytes = dev_info.avail_bytes;
+ req.vol_type = UBI_STATIC_VOLUME;
+ req.name = name;
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return -1;
+ }
+
+ sprintf(&vol_node[0], UBI_VOLUME_PATTERN, dev_info.dev_num, req.vol_id);
+
+ fd = open(vol_node, O_RDWR);
+ if (fd == -1) {
+ failed("open");
+ err_msg("cannot open \"%s\"\n", node);
+ goto remove;
+ }
+
+ if (ubi_get_vol_info(libubi, vol_node, &vol_info)) {
+ failed("ubi_get_vol_info");
+ goto close;
+ }
+
+ /* Make sure new static volume contains no data */
+ if (vol_info.data_bytes != 0) {
+ err_msg("data_bytes = %lld, not zero", vol_info.data_bytes);
+ goto close;
+ }
+
+ /* Ensure read returns EOF */
+ ret = read(fd, &buf[0], 1);
+ if (ret < 0) {
+ failed("read");
+ goto close;
+ }
+ if (ret != 0) {
+ err_msg("read data from free static volume");
+ goto close;
+ }
+
+ if (ubi_update_start(libubi, fd, 10)) {
+ failed("ubi_update_start");
+ goto close;
+ }
+
+ ret = write(fd, &buf[0], 10);
+ if (ret < 0) {
+ failed("write");
+ goto close;
+ }
+ if (ret != 10) {
+ err_msg("written %d bytes", ret);
+ goto close;
+ }
+
+ if (lseek(fd, 0, SEEK_SET) != 0) {
+ failed("seek");
+ goto close;
+ }
+ ret = read(fd, &buf[0], 20);
+ if (ret < 0) {
+ failed("read");
+ goto close;
+ }
+ if (ret != 10) {
+ err_msg("read %d bytes", ret);
+ goto close;
+ }
+
+ close(fd);
+ if (ubi_rmvol(libubi, node, req.vol_id)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+
+ return 0;
+
+close:
+ close(fd);
+remove:
+ ubi_rmvol(libubi, node, req.vol_id);
+ return -1;
+}
+
+static int test_read1(struct ubi_vol_info *vol_info);
+
+/**
+ * test_read - test UBI volume reading from different offsets.
+ *
+ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+ *
+ * Thus function returns %0 in case of success and %-1 in case of failure.
+ */
+static int test_read(int type)
+{
+ const char *name = TESTNAME ":test_read()";
+ int alignments[] = ALIGNMENTS(dev_info.eb_size);
+ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
+ struct ubi_mkvol_request req;
+ int i;
+
+ for (i = 0; i < sizeof(alignments)/sizeof(int); i++) {
+ int eb_size;
+ struct ubi_vol_info vol_info;
+
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.vol_type = type;
+ req.name = name;
+
+ req.alignment = alignments[i];
+ req.alignment -= req.alignment % dev_info.min_io_size;
+ if (req.alignment == 0)
+ req.alignment = dev_info.min_io_size;
+
+ eb_size = dev_info.eb_size - dev_info.eb_size % req.alignment;
+ req.bytes = MIN_AVAIL_EBS * eb_size;
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return -1;
+ }
+
+ sprintf(&vol_node[0], UBI_VOLUME_PATTERN, dev_info.dev_num,
+ req.vol_id);
+
+ if (ubi_get_vol_info(libubi, vol_node, &vol_info)) {
+ failed("ubi_get_vol_info");
+ goto remove;
+ }
+
+ if (test_read1(&vol_info)) {
+ err_msg("alignment = %d", req.alignment);
+ goto remove;
+ }
+
+ if (ubi_rmvol(libubi, node, req.vol_id)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+ }
+
+ return 0;
+
+remove:
+ ubi_rmvol(libubi, node, req.vol_id);
+ return -1;
+}
+
+static int test_read2(const struct ubi_vol_info *vol_info, int len);
+
+static int fd;
+
+/* Data lengthes to test, @io - minimal I/O unit size, @s - eraseblock size */
+#define LENGTHES(io, s) \
+ {1, (io), (io)+1, 2*(io), 3*(io)-1, 3*(io), \
+ PAGE_SIZE-1, PAGE_SIZE-(io), 2*PAGE_SIZE, 2*PAGE_SIZE-(io), \
+ (s)/2-1, (s)/2, (s)/2+1, (s)-1, (s), (s)+1, 2*(s)-(io), 2*(s), \
+ 2*(s)+(io), 3*(s), 3*(s)+(io)};
+
+/*
+ * A helper function for test_read().
+ */
+static int test_read1(struct ubi_vol_info *vol_info)
+{
+ int i, written = 0;
+ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
+ int lengthes[] = LENGTHES(dev_info.min_io_size, vol_info->eb_size);
+
+ sprintf(&vol_node[0], UBI_VOLUME_PATTERN, dev_info.dev_num,
+ vol_info->vol_id);
+
+ fd = open(vol_node, O_RDWR);
+ if (fd == -1) {
+ failed("open");
+ err_msg("cannot open \"%s\"\n", node);
+ return -1;
+ }
+
+ /* Write some pattern to the volume */
+ if (ubi_update_start(libubi, fd, vol_info->rsvd_bytes)) {
+ failed("ubi_update_start");
+ err_msg("bytes = %lld", vol_info->rsvd_bytes);
+ goto close;
+ }
+
+ while (written < vol_info->rsvd_bytes) {
+ int i, ret;
+ unsigned char buf[512];
+
+ for (i = 0; i < 512; i++)
+ buf[i] = (unsigned char)(written + i);
+
+ ret = write(fd, &buf[0], 512);
+ if (ret == -1) {
+ failed("write");
+ err_msg("written = %d, ret = %d", written, ret);
+ goto close;
+ }
+ written += ret;
+ }
+
+ close(fd);
+
+ if (ubi_get_vol_info(libubi, vol_node, vol_info)) {
+ failed("ubi_get_vol_info");
+ return -1;
+ }
+
+ fd = open(vol_node, O_RDONLY);
+ if (fd == -1) {
+ failed("open");
+ err_msg("cannot open \"%s\"\n", node);
+ return -1;
+ }
+
+ for (i = 0; i < sizeof(lengthes)/sizeof(int); i++) {
+ if (test_read2(vol_info, lengthes[i])) {
+ err_msg("length = %d", lengthes[i]);
+ goto close;
+ }
+ }
+
+ close(fd);
+ return 0;
+
+close:
+ close(fd);
+ return -1;
+}
+
+static int test_read3(const struct ubi_vol_info *vol_info, int len, off_t off);
+
+/*
+ * Offsets to test, @io - minimal I/O unit size, @s - eraseblock size, @sz -
+ * volume size.
+ */
+#define OFFSETS(io, s, sz) \
+ {0, (io)-1, (io), (io)+1, 2*(io)-1, 2*(io), 3*(io)-1, 3*(io), \
+ PAGE_SIZE-1, PAGE_SIZE-(io), 2*PAGE_SIZE, 2*PAGE_SIZE-(io), \
+ (s)/2-1, (s)/2, (s)/2+1, (s)-1, (s), (s)+1, 2*(s)-(io), 2*(s), \
+ 2*(s)+(io), 3*(s), (sz)-(s)-1, (sz)-(io)-1, (sz)-PAGE_SIZE-1};
+
+/*
+ * A helper function for test_read1().
+ */
+static int test_read2(const struct ubi_vol_info *vol_info, int len)
+{
+ int i;
+ off_t offsets[] = OFFSETS(dev_info.min_io_size, vol_info->eb_size,
+ vol_info->data_bytes);
+
+ for (i = 0; i < sizeof(offsets)/sizeof(off_t); i++) {
+ if (test_read3(vol_info, len, offsets[i])) {
+ err_msg("offset = %d", offsets[i]);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * A helper function for test_read2().
+ */
+static int test_read3(const struct ubi_vol_info *vol_info, int len, off_t off)
+{
+ int i, len1;
+ unsigned char ck_buf[len], buf[len];
+ off_t new_off;
+
+ if (off + len > vol_info->data_bytes)
+ len1 = vol_info->data_bytes - off;
+ else
+ len1 = len;
+
+ if (lseek(fd, off, SEEK_SET) != off) {
+ failed("seek");
+ err_msg("len = %d", len);
+ return -1;
+ }
+ if (read(fd, &buf[0], len) != len1) {
+ failed("read");
+ err_msg("len = %d", len);
+ return -1;
+ }
+
+ new_off = lseek(fd, 0, SEEK_CUR);
+ if (new_off != off + len1) {
+ if (new_off == -1)
+ failed("lseek");
+ else
+ err_msg("read %d bytes from %lld, but resulting "
+ "offset is %lld", len1, (long long) off, (long long) new_off);
+ return -1;
+ }
+
+ for (i = 0; i < len1; i++)
+ ck_buf[i] = (unsigned char)(off + i);
+
+ if (memcmp(&buf[0], &ck_buf[0], len1)) {
+ err_msg("incorrect data read from offset %lld",
+ (long long)off);
+ err_msg("len = %d", len);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/ubi-utils/tests/io_update.c b/ubi-utils/tests/io_update.c
new file mode 100644
index 0000000..2e3422a
--- /dev/null
+++ b/ubi-utils/tests/io_update.c
@@ -0,0 +1,370 @@
+/*
+ * 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
+ *
+ * Test UBI volume update.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "libubi.h"
+#define TESTNAME "io_update"
+#include "common.h"
+
+static libubi_t libubi;
+static struct ubi_dev_info dev_info;
+const char *node;
+
+static int test_update(int type);
+static int test_update_ff(void);
+
+int main(int argc, char * const argv[])
+{
+ if (initial_check(argc, argv))
+ return 1;
+
+ node = argv[1];
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ failed("libubi_open");
+ return 1;
+ }
+
+ if (ubi_get_dev_info(libubi, node, &dev_info)) {
+ failed("ubi_get_dev_info");
+ goto close;
+ }
+
+ if (test_update(UBI_DYNAMIC_VOLUME))
+ goto close;
+ if (test_update(UBI_STATIC_VOLUME))
+ goto close;
+ if (test_update_ff())
+ goto close;
+
+ libubi_close(libubi);
+ return 0;
+
+close:
+ libubi_close(libubi);
+ return 1;
+}
+
+static int test_update1(struct ubi_vol_info *vol_info);
+
+/**
+ * test_update - check volume update capabilities.
+ *
+ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int test_update(int type)
+{
+ struct ubi_mkvol_request req;
+ const char *name = TESTNAME ":io_update()";
+ int alignments[] = ALIGNMENTS(dev_info.eb_size);
+ struct ubi_vol_info vol_info;
+ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
+ int i;
+
+ for (i = 0; i < sizeof(alignments)/sizeof(int); i++) {
+ int eb_size;
+
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.vol_type = type;
+ req.name = name;
+
+ req.alignment = alignments[i];
+ req.alignment -= req.alignment % dev_info.min_io_size;
+ if (req.alignment == 0)
+ req.alignment = dev_info.min_io_size;
+
+ eb_size = dev_info.eb_size - dev_info.eb_size % req.alignment;
+ req.bytes = MIN_AVAIL_EBS * eb_size;
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return -1;
+ }
+
+ sprintf(&vol_node[0], UBI_VOLUME_PATTERN, dev_info.dev_num,
+ req.vol_id);
+ if (ubi_get_vol_info(libubi, vol_node, &vol_info)) {
+ failed("ubi_get_vol_info");
+ goto remove;
+ }
+
+ if (test_update1(&vol_info)) {
+ err_msg("alignment = %d", req.alignment);
+ goto remove;
+ }
+
+ if (ubi_rmvol(libubi, node, req.vol_id)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+ }
+
+ return 0;
+
+remove:
+ ubi_rmvol(libubi, node, req.vol_id);
+ return -1;
+}
+
+#define SEQUENCES(io, s) { \
+ {3*(s)-(io)-1, 1}, \
+ {512}, \
+ {666}, \
+ {2048}, \
+ {(io), (io), PAGE_SIZE}, \
+ {(io)+1, (io)+1, PAGE_SIZE}, \
+ {PAGE_SIZE}, \
+ {PAGE_SIZE-1}, \
+ {PAGE_SIZE+(io)}, \
+ {(s)}, \
+ {(s)-1}, \
+ {(s)+1}, \
+ {(io), (s)+1}, \
+ {(s)+(io), PAGE_SIZE}, \
+ {2*(s), PAGE_SIZE}, \
+ {PAGE_SIZE, 2*(s), 1}, \
+ {PAGE_SIZE, 2*(s)}, \
+ {2*(s)-1, 2*(s)-1}, \
+ {3*(s), PAGE_SIZE + 1}, \
+ {1, PAGE_SIZE}, \
+ {(io), (s)} \
+}
+#define SEQ_SZ 21
+
+/*
+ * test_update1 - helper function for test_update().
+ */
+static int test_update1(struct ubi_vol_info *vol_info)
+{
+ int sequences[SEQ_SZ][3] = SEQUENCES(dev_info.min_io_size,
+ vol_info->eb_size);
+ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
+ unsigned char buf[vol_info->rsvd_bytes];
+ int fd, i, j;
+
+ sprintf(&vol_node[0], UBI_VOLUME_PATTERN, dev_info.dev_num,
+ vol_info->vol_id);
+
+ for (i = 0; i < vol_info->rsvd_bytes; i++)
+ buf[i] = (unsigned char)i;
+
+ fd = open(vol_node, O_RDWR);
+ if (fd == -1) {
+ failed("open");
+ err_msg("cannot open \"%s\"\n", node);
+ return -1;
+ }
+
+ for (i = 0; i < SEQ_SZ; i++) {
+ int ret, stop = 0, len;
+ off_t off = 0;
+ unsigned char buf1[vol_info->rsvd_bytes];
+
+ if (ubi_update_start(libubi, fd, vol_info->rsvd_bytes)) {
+ failed("ubi_update_start");
+ goto close;
+ }
+
+ for (j = 0; off < vol_info->rsvd_bytes; j++) {
+ if (!stop) {
+ if (sequences[i][j] != 0)
+ len = sequences[i][j];
+ else
+ stop = 1;
+ }
+
+ ret = write(fd, &buf[off], len);
+ if (ret < 0) {
+ failed("write");
+ err_msg("failed to write %d bytes at offset "
+ "%lld", len, (long long) off);
+ goto close;
+ }
+ if (off + len > vol_info->rsvd_bytes)
+ len = vol_info->rsvd_bytes - off;
+ if (ret != len) {
+ err_msg("failed to write %d bytes at offset "
+ "%lld, wrote %d", len, (long long) off, ret);
+ goto close;
+ }
+ off += len;
+ }
+
+ /* Check data */
+ if ((ret = lseek(fd, SEEK_SET, 0)) != 0) {
+ if (ret < 0)
+ failed("lseek");
+ err_msg("cannot seek to 0");
+ goto close;
+ }
+ memset(&buf1[0], 0x01, vol_info->rsvd_bytes);
+ ret = read(fd, &buf1[0], vol_info->rsvd_bytes + 1);
+ if (ret < 0) {
+ failed("read");
+ err_msg("failed to read %d bytes",
+ vol_info->rsvd_bytes + 1);
+ goto close;
+ }
+ if (ret != vol_info->rsvd_bytes) {
+ err_msg("failed to read %d bytes, read %d",
+ vol_info->rsvd_bytes, ret);
+ goto close;
+ }
+ if (memcmp(&buf[0], &buf1[0], vol_info->rsvd_bytes)) {
+ err_msg("data corruption");
+ goto close;
+ }
+ }
+
+ close(fd);
+ return 0;
+
+close:
+ close(fd);
+ return -1;
+}
+
+/**
+ * test_update_ff - check volume with 0xFF data
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int test_update_ff(void)
+{
+ struct ubi_mkvol_request req;
+ const char *name = TESTNAME ":io_update()";
+ struct ubi_vol_info vol_info;
+ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
+ int i, fd, ret, types[2];
+ int upd_len = MIN_AVAIL_EBS * dev_info.eb_size;
+ char buf[upd_len], buf1[upd_len];
+
+ for(i = 0; i < MIN_AVAIL_EBS; i++) {
+ if (i % 1)
+ memset(&buf[0], 0xAB, upd_len);
+ else
+ memset(&buf[0], 0xFF, upd_len);
+ }
+
+ types[0] = UBI_DYNAMIC_VOLUME;
+ types[1] = UBI_STATIC_VOLUME;
+
+ for (i = 0; i < 2; i++) {
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.vol_type = types[i];
+ req.name = name;
+
+ req.alignment = 1;
+ req.bytes = upd_len;
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return -1;
+ }
+
+ sprintf(&vol_node[0], UBI_VOLUME_PATTERN, dev_info.dev_num,
+ req.vol_id);
+ if (ubi_get_vol_info(libubi, vol_node, &vol_info)) {
+ failed("ubi_get_vol_info");
+ goto remove;
+ }
+
+ fd = open(vol_node, O_RDWR);
+ if (fd == -1) {
+ failed("open");
+ err_msg("cannot open \"%s\"\n", node);
+ goto remove;
+ }
+
+ if (ubi_update_start(libubi, fd, upd_len)) {
+ failed("ubi_update_start");
+ goto close;
+ }
+
+
+ ret = write(fd, &buf[0], upd_len);
+ if (ret < 0 || ret != upd_len) {
+ failed("write");
+ err_msg("failed to write %d bytes", upd_len);
+ goto close;
+ }
+
+ /* Check data */
+ if ((ret = lseek(fd, SEEK_SET, 0)) != 0) {
+ if (ret < 0)
+ failed("lseek");
+ err_msg("cannot seek to 0");
+ goto close;
+ }
+
+ close(fd);
+
+ fd = open(vol_node, O_RDWR);
+ if (fd == -1) {
+ failed("open");
+ err_msg("cannot open \"%s\"\n", node);
+ goto remove;
+ }
+
+ memset(&buf1[0], 0x00, upd_len);
+ ret = read(fd, &buf1[0], upd_len);
+ if (ret < 0) {
+ failed("read");
+ err_msg("failed to read %d bytes", upd_len);
+ goto close;
+ }
+ if (ret != upd_len) {
+ err_msg("failed to read %d bytes, read %d",
+ upd_len, ret);
+ goto close;
+ }
+ if (memcmp(&buf[0], &buf1[0], upd_len)) {
+ err_msg("data corruption");
+ goto close;
+ }
+
+ close(fd);
+
+ if (ubi_rmvol(libubi, node, req.vol_id)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+ }
+
+ return 0;
+
+close:
+ close(fd);
+remove:
+ ubi_rmvol(libubi, node, req.vol_id);
+ return -1;
+}
diff --git a/ubi-utils/tests/mkvol_bad.c b/ubi-utils/tests/mkvol_bad.c
new file mode 100644
index 0000000..023b06b
--- /dev/null
+++ b/ubi-utils/tests/mkvol_bad.c
@@ -0,0 +1,304 @@
+/*
+ * 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
+ *
+ * Test UBI volume creation and deletion ioctl()s with bad input and in case of
+ * incorrect usage.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include "libubi.h"
+#define TESTNAME "mkvol_bad"
+#include "common.h"
+
+static libubi_t libubi;
+static struct ubi_dev_info dev_info;
+const char *node;
+
+static int test_mkvol(void);
+static int test_rmvol(void);
+
+int main(int argc, char * const argv[])
+{
+ if (initial_check(argc, argv))
+ return 1;
+
+ node = argv[1];
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ failed("libubi_open");
+ return 1;
+ }
+
+ if (ubi_get_dev_info(libubi, node, &dev_info)) {
+ failed("ubi_get_dev_info");
+ goto close;
+ }
+
+ if (test_mkvol())
+ goto close;
+
+ if (test_rmvol())
+ goto close;
+
+ libubi_close(libubi);
+ return 0;
+
+close:
+ libubi_close(libubi);
+ return 1;
+}
+
+/**
+ * test_mkvol - test that UBI mkvol ioctl rejects bad input parameters.
+ *
+ * This function returns %0 if the test passed and %-1 if not.
+ */
+static int test_mkvol(void)
+{
+ int ret, i;
+ struct ubi_mkvol_request req;
+ const char *name = TESTNAME ":test_mkvol()";
+
+ req.alignment = 1;
+ req.bytes = dev_info.avail_bytes;
+ req.vol_type = UBI_DYNAMIC_VOLUME;
+ req.name = name;
+
+ /* Bad volume ID */
+ req.vol_id = -2;
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, EINVAL, "ubi_mkvol", "vol_id = %d", req.vol_id))
+ return -1;
+
+ req.vol_id = dev_info.max_vol_count;
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, EINVAL, "ubi_mkvol", "vol_id = %d", req.vol_id))
+ return -1;
+
+ /* Bad alignment */
+ req.vol_id = 0;
+ req.alignment = 0;
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, EINVAL, "ubi_mkvol", "alignment = %d",
+ req.alignment))
+ return -1;
+
+ req.alignment = -1;
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, EINVAL, "ubi_mkvol", "alignment = %d",
+ req.alignment))
+ return -1;
+
+ req.alignment = dev_info.eb_size + 1;
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, EINVAL, "ubi_mkvol", "alignment = %d",
+ req.alignment))
+ return -1;
+
+ if (dev_info.min_io_size > 1) {
+ req.alignment = dev_info.min_io_size + 1;
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, EINVAL, "ubi_mkvol", "alignment = %d",
+ req.alignment))
+ return -1;
+ }
+
+ /* Bad bytes */
+ req.alignment = 1;
+ req.bytes = -1;
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, EINVAL, "ubi_mkvol", "bytes = %lld", req.bytes))
+ return -1;
+
+ req.bytes = 0;
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, EINVAL, "ubi_mkvol", "bytes = %lld", req.bytes))
+ return -1;
+
+ req.bytes = dev_info.avail_bytes + 1;
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, ENOSPC, "ubi_mkvol", "bytes = %lld", req.bytes))
+ return -1;
+
+ req.alignment = dev_info.eb_size - dev_info.min_io_size;
+ req.bytes = (dev_info.eb_size - dev_info.eb_size % req.alignment) *
+ dev_info.avail_ebs + 1;
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, ENOSPC, "ubi_mkvol", "bytes = %lld", req.bytes))
+ return -1;
+
+ /* Bad vol_type */
+ req.alignment = 1;
+ req.bytes = dev_info.eb_size;
+ req.vol_type = UBI_DYNAMIC_VOLUME + UBI_STATIC_VOLUME;
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, EINVAL, "ubi_mkvol", "vol_type = %d",
+ req.vol_type))
+ return -1;
+
+ req.vol_type = UBI_DYNAMIC_VOLUME;
+
+ /* Too long name */
+ {
+ char name[UBI_VOL_NAME_MAX + 5];
+
+ memset(&name[0], 'x', UBI_VOL_NAME_MAX + 1);
+ name[UBI_VOL_NAME_MAX + 1] = '\0';
+
+ req.name = &name[0];
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, EINVAL, "ubi_mkvol", "name_len = %d",
+ UBI_VOL_NAME_MAX + 1))
+ return -1;
+ }
+
+ /* Try to create 2 volumes with the same ID and name */
+ req.name = name;
+ req.vol_id = 0;
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return -1;
+ }
+
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, EEXIST, "ubi_mkvol",
+ "volume with ID 0 created twice"))
+ return -1;
+
+ req.vol_id = 1;
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, EEXIST, "ubi_mkvol",
+ "volume with name \"%s\" created twice", name))
+ return -1;
+
+ if (ubi_rmvol(libubi, node, 0)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+
+ /* Try to use too much space */
+ req.vol_id = 0;
+ req.bytes = dev_info.avail_bytes;
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return -1;
+ }
+
+ req.bytes = 1;
+ req.vol_id = 1;
+ ret = ubi_mkvol(libubi, node, &req);
+ if (check_failed(ret, EEXIST, "ubi_mkvol",
+ "created volume of maximum size %lld, but still "
+ "can create more volumes", dev_info.avail_bytes))
+ return -1;
+
+ if (ubi_rmvol(libubi, node, 0)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+
+ /* Try to create too many volumes */
+ for (i = 0; i < dev_info.max_vol_count; i++) {
+ char nm[strlen(name) + 50];
+
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.alignment = 1;
+ req.bytes = 1;
+ req.vol_type = UBI_STATIC_VOLUME;
+
+ sprintf(&nm[0], "%s:%d", name, i);
+ req.name = &nm[0];
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ /*
+ * Note, because of gluebi we may be unable to create
+ * dev_info.max_vol_count devices (MTD restrictions).
+ */
+ if (errno == ENFILE)
+ break;
+ failed("ubi_mkvol");
+ err_msg("vol_id %d", i);
+ goto remove;
+ }
+ }
+
+ for (i = 0; i < dev_info.max_vol_count + 1; i++)
+ ubi_rmvol(libubi, node, i);
+
+ return 0;
+
+remove:
+ for (i = 0; i < dev_info.max_vol_count + 1; i++)
+ ubi_rmvol(libubi, node, i);
+ return -1;
+}
+
+/**
+ * test_rmvol - test that UBI rmvol ioctl rejects bad input parameters.
+ *
+ * This function returns %0 if the test passed and %-1 if not.
+ */
+static int test_rmvol(void)
+{
+ int ret;
+ struct ubi_mkvol_request req;
+ const char *name = TESTNAME ":test_rmvol()";
+
+ /* Bad vol_id */
+ ret = ubi_rmvol(libubi, node, -1);
+ if (check_failed(ret, EINVAL, "ubi_rmvol", "vol_id = -1"))
+ return -1;
+
+ ret = ubi_rmvol(libubi, node, dev_info.max_vol_count);
+ if (check_failed(ret, EINVAL, "ubi_rmvol", "vol_id = %d",
+ dev_info.max_vol_count))
+ return -1;
+
+ /* Try to remove non-existing volume */
+ ret = ubi_rmvol(libubi, node, 0);
+ if (check_failed(ret, ENODEV, "ubi_rmvol",
+ "removed non-existing volume 0"))
+ return -1;
+
+ /* Try to remove volume twice */
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.alignment = 1;
+ req.bytes = dev_info.avail_bytes;
+ req.vol_type = UBI_DYNAMIC_VOLUME;
+ req.name = name;
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return -1;
+ }
+
+ if (ubi_rmvol(libubi, node, req.vol_id)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+
+ ret = ubi_rmvol(libubi, node, req.vol_id);
+ if (check_failed(ret, ENODEV, "ubi_rmvol", "volume %d removed twice",
+ req.vol_id))
+ return -1;
+
+ return 0;
+}
diff --git a/ubi-utils/tests/mkvol_basic.c b/ubi-utils/tests/mkvol_basic.c
new file mode 100644
index 0000000..e2120e9
--- /dev/null
+++ b/ubi-utils/tests/mkvol_basic.c
@@ -0,0 +1,253 @@
+/*
+ * 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
+ *
+ * Test test checks basic volume creation and deletion capabilities.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include "libubi.h"
+#define TESTNAME "mkvol_basic"
+#include "common.h"
+
+static libubi_t libubi;
+static struct ubi_dev_info dev_info;
+const char *node;
+
+static int mkvol_basic(void);
+static int mkvol_alignment(void);
+static int mkvol_multiple(void);
+
+int main(int argc, char * const argv[])
+{
+ if (initial_check(argc, argv))
+ return 1;
+
+ node = argv[1];
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ failed("libubi_open");
+ return 1;
+ }
+
+ if (ubi_get_dev_info(libubi, node, &dev_info)) {
+ failed("ubi_get_dev_info");
+ goto close;
+ }
+
+ if (mkvol_basic())
+ goto close;
+
+ if (mkvol_alignment())
+ goto close;
+
+ if (mkvol_multiple())
+ goto close;
+
+ libubi_close(libubi);
+ return 0;
+
+close:
+ libubi_close(libubi);
+ return 1;
+}
+
+/**
+ * mkvol_alignment - create volumes with different alignments.
+ *
+ * Thus function returns %0 in case of success and %-1 in case of failure.
+ */
+static int mkvol_alignment(void)
+{
+ struct ubi_mkvol_request req;
+ int i, vol_id, ebsz;
+ const char *name = TESTNAME ":mkvol_alignment()";
+ int alignments[] = ALIGNMENTS(dev_info.eb_size);
+
+ for (i = 0; i < sizeof(alignments)/sizeof(int); i++) {
+ req.vol_id = UBI_VOL_NUM_AUTO;
+
+ /* Alignment should actually be multiple of min. I/O size */
+ req.alignment = alignments[i];
+ req.alignment -= req.alignment % dev_info.min_io_size;
+ if (req.alignment == 0)
+ req.alignment = dev_info.min_io_size;
+
+ /* Bear in mind alignment reduces EB size */
+ ebsz = dev_info.eb_size - dev_info.eb_size % req.alignment;
+ req.bytes = dev_info.avail_ebs * ebsz;
+
+ req.vol_type = UBI_DYNAMIC_VOLUME;
+ req.name = name;
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ err_msg("alignment %d", req.alignment);
+ return -1;
+ }
+
+ vol_id = req.vol_id;
+ if (check_volume(vol_id, &req))
+ goto remove;
+
+ if (ubi_rmvol(libubi, node, vol_id)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+ }
+
+ return 0;
+
+remove:
+ ubi_rmvol(libubi, node, vol_id);
+ return -1;
+}
+
+/**
+ * mkvol_basic - simple test that checks basic volume creation capability.
+ *
+ * Thus function returns %0 in case of success and %-1 in case of failure.
+ */
+static int mkvol_basic(void)
+{
+ struct ubi_mkvol_request req;
+ struct ubi_vol_info vol_info;
+ int vol_id, ret;
+ const char *name = TESTNAME ":mkvol_basic()";
+
+ /* Create dynamic volume of maximum size */
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.alignment = 1;
+ req.bytes = dev_info.avail_bytes;
+ req.vol_type = UBI_DYNAMIC_VOLUME;
+ req.name = name;
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return -1;
+ }
+
+ vol_id = req.vol_id;
+ if (check_volume(vol_id, &req))
+ goto remove;
+
+ if (ubi_rmvol(libubi, node, vol_id)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+
+ /* Create static volume of maximum size */
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.alignment = 1;
+ req.bytes = dev_info.avail_bytes;
+ req.vol_type = UBI_STATIC_VOLUME;
+ req.name = name;
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return -1;
+ }
+
+ vol_id = req.vol_id;
+ if (check_volume(vol_id, &req))
+ goto remove;
+
+ if (ubi_rmvol(libubi, node, vol_id)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+
+ /* Make sure volume does not exist */
+ ret = ubi_get_vol_info1(libubi, dev_info.dev_num, vol_id, &vol_info);
+ if (ret == 0) {
+ err_msg("removed volume %d exists", vol_id);
+ goto remove;
+ }
+
+ return 0;
+
+remove:
+ ubi_rmvol(libubi, node, vol_id);
+ return -1;
+}
+
+/**
+ * mkvol_multiple - test multiple volumes creation
+ *
+ * Thus function returns %0 if the test passed and %-1 if not.
+ */
+static int mkvol_multiple(void)
+{
+ struct ubi_mkvol_request req;
+ int i, ret, max = dev_info.max_vol_count;
+ const char *name = TESTNAME ":mkvol_multiple()";
+
+ /* Create maximum number of volumes */
+ for (i = 0; i < max; i++) {
+ char nm[strlen(name) + 50];
+
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.alignment = 1;
+ req.bytes = 1;
+ req.vol_type = UBI_STATIC_VOLUME;
+
+ sprintf(&nm[0], "%s:%d", name, i);
+ req.name = &nm[0];
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ if (errno == ENFILE) {
+ max = i;
+ break;
+ }
+ failed("ubi_mkvol");
+ err_msg("vol_id %d", i);
+ goto remove;
+ }
+
+ if (check_volume(req.vol_id, &req)) {
+ err_msg("vol_id %d", i);
+ goto remove;
+ }
+ }
+
+ for (i = 0; i < max; i++) {
+ struct ubi_vol_info vol_info;
+
+ if (ubi_rmvol(libubi, node, i)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+
+ /* Make sure volume does not exist */
+ ret = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info);
+ if (ret == 0) {
+ err_msg("removed volume %d exists", i);
+ goto remove;
+ }
+ }
+
+ return 0;
+
+remove:
+ for (i = 0; i < dev_info.max_vol_count + 1; i++)
+ ubi_rmvol(libubi, node, i);
+ return -1;
+}
diff --git a/ubi-utils/tests/mkvol_paral.c b/ubi-utils/tests/mkvol_paral.c
new file mode 100644
index 0000000..faf085c
--- /dev/null
+++ b/ubi-utils/tests/mkvol_paral.c
@@ -0,0 +1,112 @@
+/*
+ * 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
+ *
+ * This test creates and deletes volumes in parallel.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include "libubi.h"
+#define TESTNAME "mkvol_paral"
+#include "common.h"
+
+#define THREADS_NUM 4
+#define ITERATIONS 500
+
+static libubi_t libubi;
+static struct ubi_dev_info dev_info;
+const char *node;
+static int iterations = ITERATIONS;
+
+static void * the_thread(void *ptr);
+
+int main(int argc, char * const argv[])
+{
+ int i, ret;
+ pthread_t threads[THREADS_NUM];
+
+ if (initial_check(argc, argv))
+ return 1;
+
+ node = argv[1];
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ failed("libubi_open");
+ return 1;
+ }
+
+ if (ubi_get_dev_info(libubi, node, &dev_info)) {
+ failed("ubi_get_dev_info");
+ goto close;
+ }
+
+ for (i = 0; i < THREADS_NUM; i++) {
+ ret = pthread_create(&threads[i], NULL, &the_thread, (void*)i);
+ if (ret) {
+ failed("pthread_create");
+ goto close;
+ }
+ }
+
+ for (i = 0; i < THREADS_NUM; i++)
+ pthread_join(threads[i], NULL);
+
+ libubi_close(libubi);
+ return 0;
+
+close:
+ libubi_close(libubi);
+ return 1;
+}
+
+/**
+ * the_thread - the testing thread.
+ *
+ * @ptr thread number
+ */
+static void * the_thread(void *ptr)
+{
+ int n = (int)ptr, iter = iterations;
+ struct ubi_mkvol_request req;
+ const char *name = TESTNAME ":the_thread()";
+ char nm[strlen(name) + 50];
+
+ req.alignment = 1;
+ req.bytes = dev_info.avail_bytes/ITERATIONS;
+ req.vol_type = UBI_DYNAMIC_VOLUME;
+ sprintf(&nm[0], "%s:%d", name, n);
+ req.name = &nm[0];
+
+ while (iter--) {
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return NULL;
+ }
+ if (ubi_rmvol(libubi, node, req.vol_id)) {
+ failed("ubi_rmvol");
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
diff --git a/ubi-utils/tests/rsvol.c b/ubi-utils/tests/rsvol.c
new file mode 100644
index 0000000..7a9e5ea
--- /dev/null
+++ b/ubi-utils/tests/rsvol.c
@@ -0,0 +1,310 @@
+/*
+ * 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
+ *
+ * Tes UBI volume re-size.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "libubi.h"
+#define TESTNAME "rsvol"
+#include "common.h"
+
+static libubi_t libubi;
+static struct ubi_dev_info dev_info;
+const char *node;
+
+static int test_basic(int type);
+static int test_rsvol(int type);
+
+int main(int argc, char * const argv[])
+{
+ if (initial_check(argc, argv))
+ return 1;
+
+ node = argv[1];
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ failed("libubi_open");
+ return 1;
+ }
+
+ if (ubi_get_dev_info(libubi, node, &dev_info)) {
+ failed("ubi_get_dev_info");
+ goto close;
+ }
+
+ if (test_basic(UBI_DYNAMIC_VOLUME))
+ goto close;
+ if (test_basic(UBI_STATIC_VOLUME))
+ goto close;
+ if (test_rsvol(UBI_DYNAMIC_VOLUME))
+ goto close;
+ if (test_rsvol(UBI_STATIC_VOLUME))
+ goto close;
+
+ libubi_close(libubi);
+ return 0;
+
+close:
+ libubi_close(libubi);
+ return 1;
+}
+
+/**
+ * test_basic - check volume re-size capability.
+ *
+ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+ *
+ * Thus function returns %0 in case of success and %-1 in case of failure.
+ */
+static int test_basic(int type)
+{
+ struct ubi_mkvol_request req;
+ const char *name = TESTNAME ":test_basic()";
+
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.alignment = 1;
+ req.bytes = MIN_AVAIL_EBS * dev_info.eb_size;
+ req.vol_type = type;
+ req.name = name;
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return -1;
+ }
+
+ req.bytes = dev_info.eb_size;
+ if (ubi_rsvol(libubi, node, req.vol_id, req.bytes)) {
+ failed("ubi_rsvol");
+ goto remove;
+ }
+
+ if (check_volume(req.vol_id, &req))
+ goto remove;
+
+ req.bytes = (MIN_AVAIL_EBS + 1) * dev_info.eb_size;
+ if (ubi_rsvol(libubi, node, req.vol_id, req.bytes)) {
+ failed("ubi_rsvol");
+ goto remove;
+ }
+
+ if (check_volume(req.vol_id, &req))
+ goto remove;
+
+ req.bytes -= 1;
+ if (ubi_rsvol(libubi, node, req.vol_id, req.bytes)) {
+ failed("ubi_rsvol");
+ goto remove;
+ }
+
+ if (check_volume(req.vol_id, &req))
+ goto remove;
+
+ if (ubi_rmvol(libubi, node, req.vol_id)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+
+ return 0;
+
+remove:
+ ubi_rmvol(libubi, node, req.vol_id);
+ return -1;
+}
+
+static int test_rsvol1(struct ubi_vol_info *vol_info);
+
+/**
+ * test_rsvol - test UBI volume re-size.
+ *
+ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+ *
+ * Thus function returns %0 in case of success and %-1 in case of failure.
+ */
+static int test_rsvol(int type)
+{
+ const char *name = TESTNAME "test_rsvol:()";
+ int alignments[] = ALIGNMENTS(dev_info.eb_size);
+ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
+ struct ubi_mkvol_request req;
+ int i;
+
+ for (i = 0; i < sizeof(alignments)/sizeof(int); i++) {
+ int eb_size;
+ struct ubi_vol_info vol_info;
+
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.vol_type = type;
+ req.name = name;
+
+ req.alignment = alignments[i];
+ req.alignment -= req.alignment % dev_info.min_io_size;
+ if (req.alignment == 0)
+ req.alignment = dev_info.min_io_size;
+
+ eb_size = dev_info.eb_size - dev_info.eb_size % req.alignment;
+ req.bytes = MIN_AVAIL_EBS * eb_size;
+
+ if (ubi_mkvol(libubi, node, &req)) {
+ failed("ubi_mkvol");
+ return -1;
+ }
+
+ sprintf(&vol_node[0], UBI_VOLUME_PATTERN, dev_info.dev_num,
+ req.vol_id);
+
+ if (ubi_get_vol_info(libubi, vol_node, &vol_info)) {
+ failed("ubi_get_vol_info");
+ goto remove;
+ }
+
+ if (test_rsvol1(&vol_info)) {
+ err_msg("alignment = %d", req.alignment);
+ goto remove;
+ }
+
+ if (ubi_rmvol(libubi, node, req.vol_id)) {
+ failed("ubi_rmvol");
+ return -1;
+ }
+ }
+
+ return 0;
+
+remove:
+ ubi_rmvol(libubi, node, req.vol_id);
+ return -1;
+}
+
+/*
+ * Helper function for test_rsvol().
+ */
+static int test_rsvol1(struct ubi_vol_info *vol_info)
+{
+ long long bytes;
+ struct ubi_vol_info vol_info1;
+ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
+ unsigned char buf[vol_info->rsvd_bytes];
+ int fd, i, ret;
+
+ /* Make the volume smaller and check basic volume I/O */
+ bytes = vol_info->rsvd_bytes - vol_info->eb_size;
+ if (ubi_rsvol(libubi, node, vol_info->vol_id, bytes - 1)) {
+ failed("ubi_rsvol");
+ return -1;
+ }
+
+ if (ubi_get_vol_info1(libubi, vol_info->dev_num, vol_info->vol_id,
+ &vol_info1)) {
+ failed("ubi_get_vol_info");
+ return -1;
+ }
+
+ if (vol_info1.rsvd_bytes != bytes) {
+ err_msg("rsvd_bytes %lld, must be %lld",
+ vol_info1.rsvd_bytes, bytes);
+ return -1;
+ }
+
+ if (vol_info1.rsvd_ebs != vol_info->rsvd_ebs - 1) {
+ err_msg("rsvd_ebs %d, must be %d",
+ vol_info1.rsvd_ebs, vol_info->rsvd_ebs - 1);
+ return -1;
+ }
+
+ /* Write data to the volume */
+ sprintf(&vol_node[0], UBI_VOLUME_PATTERN, dev_info.dev_num,
+ vol_info->vol_id);
+
+ fd = open(vol_node, O_RDWR);
+ if (fd == -1) {
+ failed("open");
+ err_msg("cannot open \"%s\"\n", vol_node);
+ return -1;
+ }
+
+ bytes = vol_info->rsvd_bytes - vol_info->eb_size - 1;
+ if (ubi_update_start(libubi, fd, bytes)) {
+ failed("ubi_update_start");
+ goto close;
+ }
+
+ for (i = 0; i < bytes; i++)
+ buf[i] = (unsigned char)i;
+
+ ret = write(fd, &buf[0], bytes);
+ if (ret != bytes) {
+ failed("write");
+ goto close;
+ }
+
+ close(fd);
+
+ if (ubi_rsvol(libubi, node, vol_info->vol_id, bytes)) {
+ failed("ubi_rsvol");
+ return -1;
+ }
+
+ if (ubi_rsvol(libubi, node, vol_info->vol_id,
+ vol_info->eb_size * dev_info.avail_ebs)) {
+ failed("ubi_rsvol");
+ return -1;
+ }
+
+ fd = open(vol_node, O_RDWR);
+ if (fd == -1) {
+ failed("open");
+ err_msg("cannot open \"%s\"\n", vol_node);
+ return -1;
+ }
+
+ /* Read data back */
+ if (lseek(fd, 0, SEEK_SET) != 0) {
+ failed("seek");
+ goto close;
+ }
+ memset(&buf[0], 0, bytes);
+ ret = read(fd, &buf[0], bytes);
+ if (ret != bytes) {
+ failed("read");
+ goto close;
+ }
+
+ for (i = 0; i < bytes; i++) {
+ if (buf[i] != (unsigned char)i) {
+ err_msg("bad data");
+ goto close;
+ }
+ }
+
+ close(fd);
+ return 0;
+
+close:
+ close(fd);
+ return -1;
+}
diff --git a/ubi-utils/tests/runtests.pl b/ubi-utils/tests/runtests.pl
new file mode 100755
index 0000000..8005716
--- /dev/null
+++ b/ubi-utils/tests/runtests.pl
@@ -0,0 +1,30 @@
+#!/usr/bin/perl -w
+
+sub usage;
+
+my @tests = ("mkvol_basic", "mkvol_bad", "mkvol_paral", "rsvol",
+ "io_basic", "io_read", "io_update", "io_paral");
+
+if (not defined @ARGV) {
+ usage();
+ exit;
+}
+
+foreach (@ARGV) {
+ -c or die "Error: $_ is not character device\n";
+}
+
+my $dev;
+foreach $dev (@ARGV) {
+ foreach (@tests) {
+ print "Running: $_ $dev";
+ system "./$_ $dev" and die;
+ print "\tSUCCESS\n";
+ }
+}
+
+sub usage
+{
+ print "Usage:\n";
+ print "$0 <UBI device 1> <UBI device 2> ...\n";
+}
diff --git a/ubi-utils/tests/runtests.sh b/ubi-utils/tests/runtests.sh
new file mode 100755
index 0000000..f993bc0
--- /dev/null
+++ b/ubi-utils/tests/runtests.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+ubidev="$1"
+ubiloadcmd="$2"
+tests="mkvol_basic mkvol_bad mkvol_paral rsvol io_basic io_read io_update io_paral"
+
+if test -z "$ubidev" || test -z "$ubiloadcmd";
+then
+ echo "Usage:"
+ echo "$0 <UBI device> <ubi module load command>"
+ exit 1
+fi
+
+ubiname=`echo $ubidev | cut -d/ -f3`
+
+major=`cat /sys/class/ubi/$ubiname/dev | cut -d: -f1`
+
+for minor in `seq 0 4`; do
+ if test ! -e ${ubidev}_${minor} ;
+ then
+ mknod ${ubidev}_${minor} c $major $(($minor + 1))
+ fi
+done
+
+if ! test -c "$ubidev";
+then
+ echo "Error: $ubidev is not character device"
+ exit 1
+fi
+
+for t in `echo $tests`;
+do
+ echo "Running $t $ubidev"
+ "./$t" "$ubidev" || exit 1
+done
+
+./integ "$ubiloadcmd" || exit 1
+
+echo SUCCESS
+
+exit 0